|
@@ -106,9 +106,8 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
|
|
return status;
|
|
return status;
|
|
}
|
|
}
|
|
|
|
|
|
-static bool newRenderbuffer(int width, int height, int &samples, PixelFormat pixelformat, GLuint &buffer)
|
|
|
|
|
|
+static GLenum newRenderbuffer(int width, int height, int &samples, PixelFormat pixelformat, GLuint &buffer)
|
|
{
|
|
{
|
|
- int reqsamples = samples;
|
|
|
|
bool unusedSRGB = false;
|
|
bool unusedSRGB = false;
|
|
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, true, unusedSRGB);
|
|
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, true, unusedSRGB);
|
|
|
|
|
|
@@ -145,13 +144,16 @@ static bool newRenderbuffer(int width, int height, int &samples, PixelFormat pix
|
|
}
|
|
}
|
|
|
|
|
|
if (samples > 1)
|
|
if (samples > 1)
|
|
|
|
+ {
|
|
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
|
|
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
|
|
|
|
+ samples = std::max(1, samples);
|
|
|
|
+ }
|
|
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
|
|
|
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
|
|
|
|
- if (status == GL_FRAMEBUFFER_COMPLETE && (reqsamples <= 1 || samples > 1))
|
|
|
|
|
|
+ if (status == GL_FRAMEBUFFER_COMPLETE)
|
|
{
|
|
{
|
|
if (isPixelFormatDepthStencil(pixelformat))
|
|
if (isPixelFormatDepthStencil(pixelformat))
|
|
{
|
|
{
|
|
@@ -183,7 +185,7 @@ static bool newRenderbuffer(int width, int height, int &samples, PixelFormat pix
|
|
gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, current_fbo);
|
|
gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, current_fbo);
|
|
gl.deleteFramebuffer(fbo);
|
|
gl.deleteFramebuffer(fbo);
|
|
|
|
|
|
- return status == GL_FRAMEBUFFER_COMPLETE;
|
|
|
|
|
|
+ return status;
|
|
}
|
|
}
|
|
|
|
|
|
Texture::Texture(const Settings &settings, const Slices *data)
|
|
Texture::Texture(const Settings &settings, const Slices *data)
|
|
@@ -193,11 +195,19 @@ Texture::Texture(const Settings &settings, const Slices *data)
|
|
, texture(0)
|
|
, texture(0)
|
|
, renderbuffer(0)
|
|
, renderbuffer(0)
|
|
, framebufferStatus(GL_FRAMEBUFFER_COMPLETE)
|
|
, framebufferStatus(GL_FRAMEBUFFER_COMPLETE)
|
|
|
|
+ , textureGLError(GL_NO_ERROR)
|
|
, actualSamples(1)
|
|
, actualSamples(1)
|
|
{
|
|
{
|
|
if (data != nullptr)
|
|
if (data != nullptr)
|
|
slices = *data;
|
|
slices = *data;
|
|
- loadVolatile();
|
|
|
|
|
|
+
|
|
|
|
+ if (!loadVolatile())
|
|
|
|
+ {
|
|
|
|
+ if (framebufferStatus != GL_FRAMEBUFFER_COMPLETE)
|
|
|
|
+ throw love::Exception("Cannot create Texture (OpenGL framebuffer error: %s)", OpenGL::framebufferStatusString(framebufferStatus));
|
|
|
|
+ if (textureGLError != GL_NO_ERROR)
|
|
|
|
+ throw love::Exception("Cannot create Texture (OpenGL error: %s)", OpenGL::errorString(textureGLError));
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
Texture::~Texture()
|
|
Texture::~Texture()
|
|
@@ -205,7 +215,7 @@ Texture::~Texture()
|
|
unloadVolatile();
|
|
unloadVolatile();
|
|
}
|
|
}
|
|
|
|
|
|
-bool Texture::createTexture()
|
|
|
|
|
|
+void Texture::createTexture()
|
|
{
|
|
{
|
|
// The base class handles some validation. For example, if ImageData is
|
|
// The base class handles some validation. For example, if ImageData is
|
|
// given then it must exist for all mip levels, a render target can't use
|
|
// given then it must exist for all mip levels, a render target can't use
|
|
@@ -235,7 +245,7 @@ bool Texture::createTexture()
|
|
for (int slice = 0; slice < slices; slice++)
|
|
for (int slice = 0; slice < slices; slice++)
|
|
uploadByteData(PIXELFORMAT_RGBA8_UNORM, px, sizeof(px), 0, slice, rect, nullptr);
|
|
uploadByteData(PIXELFORMAT_RGBA8_UNORM, px, sizeof(px), 0, slice, rect, nullptr);
|
|
|
|
|
|
- return true;
|
|
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
GLenum gltype = OpenGL::getGLTextureType(texType);
|
|
GLenum gltype = OpenGL::getGLTextureType(texType);
|
|
@@ -254,6 +264,11 @@ bool Texture::createTexture()
|
|
else if (texType == TEXTURE_CUBE)
|
|
else if (texType == TEXTURE_CUBE)
|
|
slicecount = 6;
|
|
slicecount = 6;
|
|
|
|
|
|
|
|
+ // For a couple flimsy reasons, we don't initialize the texture here if it's
|
|
|
|
+ // compressed. I need to verify that getPixelFormatSliceSize will return the
|
|
|
|
+ // correct value for all compressed texture formats, and I also vaguely
|
|
|
|
+ // remember some driver issues on some old Android systems, maybe...
|
|
|
|
+ // For now, the base class enforces data on init for compressed textures.
|
|
if (!isCompressed())
|
|
if (!isCompressed())
|
|
gl.rawTexStorage(texType, mipcount, format, sRGB, pixelWidth, pixelHeight, texType == TEXTURE_VOLUME ? depth : layers);
|
|
gl.rawTexStorage(texType, mipcount, format, sRGB, pixelWidth, pixelHeight, texType == TEXTURE_VOLUME ? depth : layers);
|
|
|
|
|
|
@@ -322,16 +337,6 @@ bool Texture::createTexture()
|
|
// so generateMipmaps here is fine - when they aren't already initialized.
|
|
// so generateMipmaps here is fine - when they aren't already initialized.
|
|
if (getMipmapCount() > 1 && slices.getMipmapCount() <= 1)
|
|
if (getMipmapCount() > 1 && slices.getMipmapCount() <= 1)
|
|
generateMipmaps();
|
|
generateMipmaps();
|
|
-
|
|
|
|
- return true;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-bool Texture::createRenderbuffer()
|
|
|
|
-{
|
|
|
|
- if (isReadable() && actualSamples <= 1)
|
|
|
|
- return true;
|
|
|
|
-
|
|
|
|
- return newRenderbuffer(pixelWidth, pixelHeight, actualSamples, format, renderbuffer);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
bool Texture::loadVolatile()
|
|
bool Texture::loadVolatile()
|
|
@@ -353,21 +358,24 @@ bool Texture::loadVolatile()
|
|
|
|
|
|
while (glGetError() != GL_NO_ERROR); // Clear errors.
|
|
while (glGetError() != GL_NO_ERROR); // Clear errors.
|
|
|
|
|
|
- try
|
|
|
|
|
|
+ framebufferStatus = GL_FRAMEBUFFER_COMPLETE;
|
|
|
|
+ textureGLError = GL_NO_ERROR;
|
|
|
|
+
|
|
|
|
+ if (isReadable())
|
|
|
|
+ createTexture();
|
|
|
|
+
|
|
|
|
+ if (!usingDefaultTexture && framebufferStatus == GL_FRAMEBUFFER_COMPLETE
|
|
|
|
+ && (!isReadable() || actualSamples > 1))
|
|
{
|
|
{
|
|
- if (isReadable())
|
|
|
|
- createTexture();
|
|
|
|
- if (!isReadable() || actualSamples > 1)
|
|
|
|
- createRenderbuffer();
|
|
|
|
-
|
|
|
|
- GLenum glerr = glGetError();
|
|
|
|
- if (glerr != GL_NO_ERROR)
|
|
|
|
- throw love::Exception("Cannot create texture (OpenGL error: %s)", OpenGL::errorString(glerr));
|
|
|
|
|
|
+ framebufferStatus = newRenderbuffer(pixelWidth, pixelHeight, actualSamples, format, renderbuffer);
|
|
}
|
|
}
|
|
- catch (love::Exception &)
|
|
|
|
|
|
+
|
|
|
|
+ textureGLError = glGetError();
|
|
|
|
+
|
|
|
|
+ if (framebufferStatus != GL_FRAMEBUFFER_COMPLETE || textureGLError != GL_NO_ERROR)
|
|
{
|
|
{
|
|
unloadVolatile();
|
|
unloadVolatile();
|
|
- throw;
|
|
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
|
|
|
|
int64 memsize = 0;
|
|
int64 memsize = 0;
|