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)
committerIan Romanick <ian.d.romanick@intel.com>
Mon, 22 Jun 2009 22:15:19 +0000 (15:15 -0700)
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?
(cherry picked from commit 3f25219c7bf0f090502489928f0f018e62c4f6cf)

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

index 8872c8963f5492f0707be3088400c536b31c119b..b9cb972e5f4aa7f5771acdc9004347c2d1e55428 100644 (file)
@@ -2053,6 +2053,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 9b8d3777fb100c7ac0d0a580dccefc0290ed43e1..89ee69770e4c03bf0868680ec0e557d0c4e2ed9f 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 cef58d7a496fee9b0476048bbd7bf32f7206a2a0..89da4335a2e888c92ea1727f6e4bca891441b8ae 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 */