Commits

Alex Szpakowski committed a27c328

Images which are too large for the system they're loaded on use a checkerboard pattern instead of erroring

Comments (0)

Files changed (2)

src/modules/graphics/opengl/Image.cpp

 	, mipmapSharpness(defaultMipmapSharpness)
 	, mipmapsCreated(false)
 	, compressed(false)
+	, usingDefaultTexture(false)
 {
 	data->retain();
 	preload();
 	, mipmapSharpness(defaultMipmapSharpness)
 	, mipmapsCreated(false)
 	, compressed(true)
+	, usingDefaultTexture(false)
 {
 	cdata->retain();
 	preload();
 
 void Image::checkMipmapsCreated()
 {
-	if (mipmapsCreated || filter.mipmap == FILTER_NONE)
+	if (mipmapsCreated || filter.mipmap == FILTER_NONE || usingDefaultTexture)
 		return;
 
 	if (isCompressed() && cdata && hasCompressedTextureSupport(cdata->getType()))
 {
 	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();
-	filter.anisotropy = gl.setTextureFilter(f);
+	filter.anisotropy = gl.setTextureFilter(filter);
 	checkMipmapsCreated();
 }
 
 
 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()))
 	{
 		const char *str;
 	float s = width/p2width;
 	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[2].t = t;
 	vertices[2].s = s;
 		                data->getData());
 	}
 
-	if (glGetError() != GL_NO_ERROR)
-		throw love::Exception("Cannot create image: size may be too large for this system.");
+	GLenum glerr = glGetError();
+	if (glerr != GL_NO_ERROR)
+		throw love::Exception("Cannot create image (error code 0x%x)", glerr);
 
+	usingDefaultTexture = false;
 	mipmapsCreated = false;
 	checkMipmapsCreated();
 
 	gl.setTextureWrap(wrap);
 	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.
 	love::thread::EmptyLock lock;
 
 		             data->getData());
 	}
 
-	if (glGetError() != GL_NO_ERROR)
-		throw love::Exception("Cannot create image: size may be too large for this system.");
+	GLenum glerr = glGetError();
+	if (glerr != GL_NO_ERROR)
+		throw love::Exception("Cannot create image (error code 0x%x)", glerr);
 
+	usingDefaultTexture = false;
 	mipmapsCreated = false;
 	checkMipmapsCreated();
 
 	if (texture == 0)
 		return false;
 
+	if (gl.getMaxTextureSize())
+
+	while (glGetError() != GL_NO_ERROR); // clear errors
+
 	// We want this lock to potentially cover mipmap creation as well.
 	love::thread::EmptyLock lock;
 
 		                data->getData());
 	}
 
+	if (glGetError() != GL_NO_ERROR)
+		uploadDefaultTexture();
+	else
+		usingDefaultTexture = false;
+
 	mipmapsCreated = false;
 	checkMipmapsCreated();
 
 	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
 {
 	// FIXME: this should be changed if Image::loadVolatilePOT changes.

src/modules/graphics/opengl/Image.h

 private:
 
 	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;
 
 	friend class Shader;
 	// Whether this Image is using a compressed texture.
 	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
 	Image::Filter filter;