summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2009-05-01 09:30:32 -0600
committerBrian Paul <brianp@vmware.com>2009-05-01 09:30:32 -0600
commit3f25219c7bf0f090502489928f0f018e62c4f6cf (patch)
tree22005061c8d17bc1c57a08af1a93b36b499beb38
parent7ca04273387fb1af1b67d1359f2b0da4874a0e4c (diff)
mesa: create/use a fallback texture when bound texture is incomplete
When a GLSL sampler reads from an incomplete texture it should return (0,0,0,1). Instead of jumping through hoops in all the drivers to make this happen, just create/install a fallback texture with those texel values. Fixes piglit/fp-incomplete-tex on i965 and more importantly, fixes some GPU lockups when trying to sample from missing surfaces. If a binding table entry is NULL, it seems that sampling sometimes works, but not always (lockup). Todo: create a fallback texture for each type of texture target?
-rw-r--r--src/mesa/main/mtypes.h3
-rw-r--r--src/mesa/main/texobj.c53
-rw-r--r--src/mesa/main/texobj.h3
-rw-r--r--src/mesa/main/texstate.c9
4 files changed, 66 insertions, 2 deletions
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 30c7cca3b5..38c3b1bb40 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2050,6 +2050,9 @@ struct gl_shared_state
/** Default texture objects (shared by all texture units) */
struct gl_texture_object *DefaultTex[NUM_TEXTURE_TARGETS];
+ /** Fallback texture used when a bound texture is incomplete */
+ struct gl_texture_object *FallbackTex;
+
/**
* \name Thread safety and statechange notification for texture
* objects.
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
index b63f747fe8..0024efc0e6 100644
--- a/src/mesa/main/texobj.c
+++ b/src/mesa/main/texobj.c
@@ -662,6 +662,59 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
}
}
+
+/**
+ * Return pointer to a default/fallback texture.
+ * The texture is a 2D 8x8 RGBA texture with all texels = (0,0,0,1).
+ * That's the value a sampler should get when sampling from an
+ * incomplete texture.
+ */
+struct gl_texture_object *
+_mesa_get_fallback_texture(GLcontext *ctx)
+{
+ if (!ctx->Shared->FallbackTex) {
+ /* create fallback texture now */
+ static GLubyte texels[8 * 8][4];
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLuint i;
+
+ for (i = 0; i < 8 * 8; i++) {
+ texels[i][0] =
+ texels[i][1] =
+ texels[i][2] = 0x0;
+ texels[i][3] = 0xff;
+ }
+
+ /* create texture object */
+ texObj = ctx->Driver.NewTextureObject(ctx, 0, GL_TEXTURE_2D);
+ assert(texObj->RefCount == 1);
+ texObj->MinFilter = GL_NEAREST;
+ texObj->MagFilter = GL_NEAREST;
+
+ /* create level[0] texture image */
+ texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, 0);
+
+ /* init the image fields */
+ _mesa_init_teximage_fields(ctx, GL_TEXTURE_2D, texImage,
+ 8, 8, 1, 0, GL_RGBA);
+
+ /* set image data */
+ ctx->Driver.TexImage2D(ctx, GL_TEXTURE_2D, 0, GL_RGBA,
+ 8, 8, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texels,
+ &ctx->DefaultPacking, texObj, texImage);
+
+ _mesa_test_texobj_completeness(ctx, texObj);
+ assert(texObj->_Complete);
+
+ ctx->Shared->FallbackTex = texObj;
+ }
+ return ctx->Shared->FallbackTex;
+}
+
+
+
/*@}*/
diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h
index d5374c5d6c..2599c0816a 100644
--- a/src/mesa/main/texobj.h
+++ b/src/mesa/main/texobj.h
@@ -65,6 +65,9 @@ extern void
_mesa_test_texobj_completeness( const GLcontext *ctx,
struct gl_texture_object *obj );
+extern struct gl_texture_object *
+_mesa_get_fallback_texture(GLcontext *ctx);
+
extern void
_mesa_unlock_context_textures( GLcontext *ctx );
diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index 73f8a5339e..32d55ba8d5 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -561,8 +561,13 @@ update_texture_state( GLcontext *ctx )
}
if (!texUnit->_ReallyEnabled) {
- _mesa_reference_texobj(&texUnit->_Current, NULL);
- continue;
+ /* If we get here it means the shader (or fixed-function state)
+ * is expecting a texture object, but there isn't one (or it's
+ * incomplete). Use the fallback texture.
+ */
+ struct gl_texture_object *texObj = _mesa_get_fallback_texture(ctx);
+ texUnit->_ReallyEnabled = 1 << TEXTURE_2D_INDEX;
+ _mesa_reference_texobj(&texUnit->_Current, texObj);
}
/* if we get here, we know this texture unit is enabled */