mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
Images which are too large for the system they're loaded on use a checkerboard pattern instead of erroring
This commit is contained in:
@@ -45,6 +45,7 @@ Image::Image(love::image::ImageData *data)
|
|||||||
, mipmapSharpness(defaultMipmapSharpness)
|
, mipmapSharpness(defaultMipmapSharpness)
|
||||||
, mipmapsCreated(false)
|
, mipmapsCreated(false)
|
||||||
, compressed(false)
|
, compressed(false)
|
||||||
|
, usingDefaultTexture(false)
|
||||||
{
|
{
|
||||||
data->retain();
|
data->retain();
|
||||||
preload();
|
preload();
|
||||||
@@ -59,6 +60,7 @@ Image::Image(love::image::CompressedData *cdata)
|
|||||||
, mipmapSharpness(defaultMipmapSharpness)
|
, mipmapSharpness(defaultMipmapSharpness)
|
||||||
, mipmapsCreated(false)
|
, mipmapsCreated(false)
|
||||||
, compressed(true)
|
, compressed(true)
|
||||||
|
, usingDefaultTexture(false)
|
||||||
{
|
{
|
||||||
cdata->retain();
|
cdata->retain();
|
||||||
preload();
|
preload();
|
||||||
@@ -246,7 +248,7 @@ void Image::createMipmaps()
|
|||||||
|
|
||||||
void Image::checkMipmapsCreated()
|
void Image::checkMipmapsCreated()
|
||||||
{
|
{
|
||||||
if (mipmapsCreated || filter.mipmap == FILTER_NONE)
|
if (mipmapsCreated || filter.mipmap == FILTER_NONE || usingDefaultTexture)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isCompressed() && cdata && hasCompressedTextureSupport(cdata->getType()))
|
if (isCompressed() && cdata && hasCompressedTextureSupport(cdata->getType()))
|
||||||
@@ -263,8 +265,15 @@ void Image::setFilter(const Image::Filter &f)
|
|||||||
{
|
{
|
||||||
filter = f;
|
filter = f;
|
||||||
|
|
||||||
|
// We don't want filtering or (attempted) mipmaps on the default texture.
|
||||||
|
if (usingDefaultTexture)
|
||||||
|
{
|
||||||
|
filter.mipmap = FILTER_NONE;
|
||||||
|
filter.min = filter.mag = FILTER_NEAREST;
|
||||||
|
}
|
||||||
|
|
||||||
bind();
|
bind();
|
||||||
filter.anisotropy = gl.setTextureFilter(f);
|
filter.anisotropy = gl.setTextureFilter(filter);
|
||||||
checkMipmapsCreated();
|
checkMipmapsCreated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,18 +362,6 @@ void Image::unload()
|
|||||||
|
|
||||||
bool Image::loadVolatile()
|
bool Image::loadVolatile()
|
||||||
{
|
{
|
||||||
// glTexImage2D is guaranteed to throw an error in this case.
|
|
||||||
if (width > gl.getMaxTextureSize())
|
|
||||||
{
|
|
||||||
throw love::Exception("Cannot create image: "
|
|
||||||
"width of %d pixels is too large for this system.", (int) width);
|
|
||||||
}
|
|
||||||
else if (height > gl.getMaxTextureSize())
|
|
||||||
{
|
|
||||||
throw love::Exception("Cannot create image:"
|
|
||||||
"height of %d pixels is too large for this system.", (int) height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCompressed() && cdata && !hasCompressedTextureSupport(cdata->getType()))
|
if (isCompressed() && cdata && !hasCompressedTextureSupport(cdata->getType()))
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str;
|
||||||
@@ -400,6 +397,13 @@ bool Image::loadVolatilePOT()
|
|||||||
float s = width/p2width;
|
float s = width/p2width;
|
||||||
float t = height/p2height;
|
float t = height/p2height;
|
||||||
|
|
||||||
|
// Use a default texture if the size is too big for the system.
|
||||||
|
if (p2width > gl.getMaxTextureSize() || p2height > gl.getMaxTextureSize())
|
||||||
|
{
|
||||||
|
uploadDefaultTexture();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
vertices[1].t = t;
|
vertices[1].t = t;
|
||||||
vertices[2].t = t;
|
vertices[2].t = t;
|
||||||
vertices[2].s = s;
|
vertices[2].s = s;
|
||||||
@@ -450,9 +454,11 @@ bool Image::loadVolatilePOT()
|
|||||||
data->getData());
|
data->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glGetError() != GL_NO_ERROR)
|
GLenum glerr = glGetError();
|
||||||
throw love::Exception("Cannot create image: size may be too large for this system.");
|
if (glerr != GL_NO_ERROR)
|
||||||
|
throw love::Exception("Cannot create image (error code 0x%x)", glerr);
|
||||||
|
|
||||||
|
usingDefaultTexture = false;
|
||||||
mipmapsCreated = false;
|
mipmapsCreated = false;
|
||||||
checkMipmapsCreated();
|
checkMipmapsCreated();
|
||||||
|
|
||||||
@@ -468,6 +474,13 @@ bool Image::loadVolatileNPOT()
|
|||||||
gl.setTextureWrap(wrap);
|
gl.setTextureWrap(wrap);
|
||||||
setMipmapSharpness(mipmapSharpness);
|
setMipmapSharpness(mipmapSharpness);
|
||||||
|
|
||||||
|
// Use a default texture if the size is too big for the system.
|
||||||
|
if (width > gl.getMaxTextureSize() || height > gl.getMaxTextureSize())
|
||||||
|
{
|
||||||
|
uploadDefaultTexture();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// We want this lock to potentially cover mipmap creation as well.
|
// We want this lock to potentially cover mipmap creation as well.
|
||||||
love::thread::EmptyLock lock;
|
love::thread::EmptyLock lock;
|
||||||
|
|
||||||
@@ -499,9 +512,11 @@ bool Image::loadVolatileNPOT()
|
|||||||
data->getData());
|
data->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glGetError() != GL_NO_ERROR)
|
GLenum glerr = glGetError();
|
||||||
throw love::Exception("Cannot create image: size may be too large for this system.");
|
if (glerr != GL_NO_ERROR)
|
||||||
|
throw love::Exception("Cannot create image (error code 0x%x)", glerr);
|
||||||
|
|
||||||
|
usingDefaultTexture = false;
|
||||||
mipmapsCreated = false;
|
mipmapsCreated = false;
|
||||||
checkMipmapsCreated();
|
checkMipmapsCreated();
|
||||||
|
|
||||||
@@ -524,6 +539,10 @@ bool Image::refresh()
|
|||||||
if (texture == 0)
|
if (texture == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (gl.getMaxTextureSize())
|
||||||
|
|
||||||
|
while (glGetError() != GL_NO_ERROR); // clear errors
|
||||||
|
|
||||||
// We want this lock to potentially cover mipmap creation as well.
|
// We want this lock to potentially cover mipmap creation as well.
|
||||||
love::thread::EmptyLock lock;
|
love::thread::EmptyLock lock;
|
||||||
|
|
||||||
@@ -554,12 +573,31 @@ bool Image::refresh()
|
|||||||
data->getData());
|
data->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (glGetError() != GL_NO_ERROR)
|
||||||
|
uploadDefaultTexture();
|
||||||
|
else
|
||||||
|
usingDefaultTexture = false;
|
||||||
|
|
||||||
mipmapsCreated = false;
|
mipmapsCreated = false;
|
||||||
checkMipmapsCreated();
|
checkMipmapsCreated();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Image::uploadDefaultTexture()
|
||||||
|
{
|
||||||
|
usingDefaultTexture = true;
|
||||||
|
|
||||||
|
bind();
|
||||||
|
setFilter(filter);
|
||||||
|
|
||||||
|
// A nice friendly checkerboard to signify invalid textures...
|
||||||
|
GLubyte px[] = {0xFF,0xFF,0xFF,0xFF, 0x20,0x20,0x20,0xFF,
|
||||||
|
0x20,0x20,0x20,0xFF, 0xFF,0xFF,0xFF,0xFF};
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, px);
|
||||||
|
}
|
||||||
|
|
||||||
love::Vector Image::getTexCoordScale() const
|
love::Vector Image::getTexCoordScale() const
|
||||||
{
|
{
|
||||||
// FIXME: this should be changed if Image::loadVolatilePOT changes.
|
// FIXME: this should be changed if Image::loadVolatilePOT changes.
|
||||||
|
|||||||
@@ -146,6 +146,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
vertex *scaleNPOT(const vertex *v, size_t count) const;
|
vertex *scaleNPOT(const vertex *v, size_t count) const;
|
||||||
|
void uploadDefaultTexture();
|
||||||
|
|
||||||
void drawv(const Matrix &t, const vertex *v, GLsizei count = 4, GLenum mode = GL_QUADS, const uint16 *e = 0, GLsizei ecount = 0) const;
|
void drawv(const Matrix &t, const vertex *v, GLsizei count = 4, GLenum mode = GL_QUADS, const uint16 *e = 0, GLsizei ecount = 0) const;
|
||||||
|
|
||||||
friend class Shader;
|
friend class Shader;
|
||||||
@@ -180,6 +182,10 @@ private:
|
|||||||
// Whether this Image is using a compressed texture.
|
// Whether this Image is using a compressed texture.
|
||||||
bool compressed;
|
bool compressed;
|
||||||
|
|
||||||
|
// True if the image wasn't able to be properly created and it had to fall
|
||||||
|
// back to a default texture.
|
||||||
|
bool usingDefaultTexture;
|
||||||
|
|
||||||
// The image's filter mode
|
// The image's filter mode
|
||||||
Image::Filter filter;
|
Image::Filter filter;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user