mesa: create/use a fallback texture when bound texture is incomplete
authorBrian Paul <brianp@vmware.com>
Fri, 1 May 2009 15:30:32 +0000 (09:30 -0600)
committerBrian Paul <brianp@vmware.com>
Fri, 1 May 2009 15:30:32 +0000 (09:30 -0600)
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?

src/mesa/main/mtypes.h
src/mesa/main/texobj.c
src/mesa/main/texobj.h
src/mesa/main/texstate.c

index 30c7cca3b5a3762cf39e5617ee91406b2957252b..38c3b1bb40d892e7f7f322d40fe64b7d21370ae9 100644 (file)
@@ -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. 
index b63f747fe8d3936cd2b5e40e246ac77e524d3fcb..0024efc0e64cab1ce8a5d5685d795a8b4c4e9472 100644 (file)
@@ -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;
+}
+
+
+
 /*@}*/
 
 
index d5374c5d6c4fd1034bb97eb5b66e07753101f5b0..2599c0816a9c867a4ae194b9fdf77466e6862c76 100644 (file)
@@ -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 );
 
index 73f8a5339ecbd1ab09daec9573365d0be259ba20..32d55ba8d58ed5e18f062204dfa8fe26600c4dd3 100644 (file)
@@ -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 */