[Mesa-dev] [PATCH] mesa: fix _mesa_get_fallback_texture() to handle all texture targets

Brian Paul brianp at vmware.com
Wed Jan 4 13:55:32 PST 2012


Previously, this function only handled 2D textures.

The fallback texture is used when we try to sample from an incomplete
texture object.  GLSL says sampling an incomplete texture should return
(0,0,0,1).
---
 src/mesa/main/mtypes.h   |    2 +-
 src/mesa/main/shared.c   |    8 ++-
 src/mesa/main/texobj.c   |  115 ++++++++++++++++++++++++++++++++++++----------
 src/mesa/main/texobj.h   |    4 +-
 src/mesa/main/texstate.c |   10 +++-
 5 files changed, 107 insertions(+), 32 deletions(-)

diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 107371e..5158100 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2419,7 +2419,7 @@ struct gl_shared_state
    struct gl_texture_object *DefaultTex[NUM_TEXTURE_TARGETS];
 
    /** Fallback texture used when a bound texture is incomplete */
-   struct gl_texture_object *FallbackTex;
+   struct gl_texture_object *FallbackTex[NUM_TEXTURE_TARGETS];
 
    /**
     * \name Thread safety and statechange notification for texture
diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c
index 276fac1..f889abe 100644
--- a/src/mesa/main/shared.c
+++ b/src/mesa/main/shared.c
@@ -307,9 +307,11 @@ free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared)
 {
    GLuint i;
 
-   /* Free the dummy/fallback texture object */
-   if (shared->FallbackTex)
-      ctx->Driver.DeleteTexture(ctx, shared->FallbackTex);
+   /* Free the dummy/fallback texture objects */
+   for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
+      if (shared->FallbackTex[i])
+         ctx->Driver.DeleteTexture(ctx, shared->FallbackTex[i]);
+   }
 
    /*
     * Free display lists
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
index 7ee2005..112d58a 100644
--- a/src/mesa/main/texobj.c
+++ b/src/mesa/main/texobj.c
@@ -757,59 +757,126 @@ _mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj,
 
 
 /**
- * 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
+ * Return pointer to a default/fallback texture of the given type/target.
+ * The texture is an RGBA texture with all texels = (0,0,0,1).
+ * That's the value a GLSL sampler should get when sampling from an
  * incomplete texture.
  */
 struct gl_texture_object *
-_mesa_get_fallback_texture(struct gl_context *ctx)
+_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex)
 {
-   if (!ctx->Shared->FallbackTex) {
+   if (!ctx->Shared->FallbackTex[tex]) {
       /* create fallback texture now */
-      static GLubyte texels[8 * 8][4];
+      const GLsizei width = 4, height = 4, depth = 4;
+      GLubyte texels[width * height * depth][4];
       struct gl_texture_object *texObj;
       struct gl_texture_image *texImage;
       gl_format texFormat;
-      GLuint i;
+      GLuint i, dims, face, numFaces = 1;
+      GLenum target;
 
-      for (i = 0; i < 8 * 8; i++) {
+      for (i = 0; i < width * height * depth; i++) {
          texels[i][0] =
          texels[i][1] =
          texels[i][2] = 0x0;
          texels[i][3] = 0xff;
       }
 
+      switch (tex) {
+      case TEXTURE_2D_ARRAY_INDEX:
+         dims = 3;
+         target = GL_TEXTURE_2D_ARRAY;
+         break;
+      case TEXTURE_1D_ARRAY_INDEX:
+         dims = 2;
+         target = GL_TEXTURE_1D_ARRAY;
+         break;
+      case TEXTURE_CUBE_INDEX:
+         dims = 2;
+         target = GL_TEXTURE_CUBE_MAP;
+         numFaces = 6;
+         break;
+      case TEXTURE_3D_INDEX:
+         dims = 3;
+         target = GL_TEXTURE_3D;
+         break;
+      case TEXTURE_RECT_INDEX:
+         dims = 2;
+         target = GL_TEXTURE_RECTANGLE;
+         break;
+      case TEXTURE_2D_INDEX:
+         dims = 2;
+         target = GL_TEXTURE_2D;
+         break;
+      case TEXTURE_1D_INDEX:
+         dims = 1;
+         target = GL_TEXTURE_1D;
+         break;
+      case TEXTURE_BUFFER_INDEX:
+      case TEXTURE_EXTERNAL_INDEX:
+      default:
+         /* no-op */
+         return NULL;
+      }
+
       /* create texture object */
-      texObj = ctx->Driver.NewTextureObject(ctx, 0, GL_TEXTURE_2D);
+      texObj = ctx->Driver.NewTextureObject(ctx, 0, target);
       assert(texObj->RefCount == 1);
       texObj->Sampler.MinFilter = GL_NEAREST;
       texObj->Sampler.MagFilter = GL_NEAREST;
 
-      /* create level[0] texture image */
-      texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, 0);
-
       texFormat = ctx->Driver.ChooseTextureFormat(ctx, GL_RGBA, GL_RGBA,
                                                   GL_UNSIGNED_BYTE);
 
-      /* init the image fields */
-      _mesa_init_teximage_fields(ctx, texImage,
-                                 8, 8, 1, 0, GL_RGBA, texFormat); 
+      /* need a loop here just for cube maps */
+      for (face = 0; face < numFaces; face++) {
+         GLenum faceTarget;
 
-      ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
-
-      /* set image data */
-      ctx->Driver.TexImage2D(ctx, texImage, GL_RGBA,
-                             8, 8, 0,
-                             GL_RGBA, GL_UNSIGNED_BYTE, texels,
-                             &ctx->DefaultPacking);
+         if (target == GL_TEXTURE_CUBE_MAP)
+            faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
+         else
+            faceTarget = target;
+
+         /* initialize level[0] texture image */
+         texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, 0);
+
+         _mesa_init_teximage_fields(ctx, texImage,
+                                    width,
+                                    (dims > 1) ? height : 1,
+                                    (dims > 2) ? depth : 1,
+                                    0, /* border */
+                                    GL_RGBA, texFormat);
+
+         switch (dims) {
+         case 1:
+            ctx->Driver.TexImage1D(ctx, texImage, GL_RGBA,
+                                   width, 0,
+                                   GL_RGBA, GL_UNSIGNED_BYTE, texels,
+                                   &ctx->DefaultPacking);
+            break;
+         case 2:
+            ctx->Driver.TexImage2D(ctx, texImage, GL_RGBA,
+                                   width, height, 0,
+                                   GL_RGBA, GL_UNSIGNED_BYTE, texels,
+                                   &ctx->DefaultPacking);
+            break;
+         case 3:
+            ctx->Driver.TexImage3D(ctx, texImage, GL_RGBA,
+                                   width, height, depth, 0,
+                                   GL_RGBA, GL_UNSIGNED_BYTE, texels,
+                                   &ctx->DefaultPacking);
+            break;
+         default:
+            _mesa_problem(ctx, "bad dims in _mesa_get_fallback_texture()");
+         }
+      }
 
       _mesa_test_texobj_completeness(ctx, texObj);
       assert(texObj->_Complete);
 
-      ctx->Shared->FallbackTex = texObj;
+      ctx->Shared->FallbackTex[tex] = texObj;
    }
-   return ctx->Shared->FallbackTex;
+   return ctx->Shared->FallbackTex[tex];
 }
 
 
diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h
index 9ca7a4c..03dfbe3 100644
--- a/src/mesa/main/texobj.h
+++ b/src/mesa/main/texobj.h
@@ -34,8 +34,8 @@
 
 #include "compiler.h"
 #include "glheader.h"
+#include "mtypes.h"
 
-struct gl_context;
 
 /**
  * \name Internal functions
@@ -89,7 +89,7 @@ _mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj,
                    GLboolean invalidate_state);
 
 extern struct gl_texture_object *
-_mesa_get_fallback_texture(struct gl_context *ctx);
+_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex);
 
 extern void
 _mesa_unlock_context_textures( struct gl_context *ctx );
diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index 7cd2858..351a556 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -586,9 +586,15 @@ update_texture_state( struct gl_context *ctx )
              * 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;
+            struct gl_texture_object *texObj;
+            gl_texture_index texTarget;
+
+            assert(_mesa_bitcount(enabledTargets) == 1);
+
+            texTarget = (gl_texture_index) (_mesa_ffs(enabledTargets) - 1);
+            texObj = _mesa_get_fallback_texture(ctx, texTarget);
             _mesa_reference_texobj(&texUnit->_Current, texObj);
+            texUnit->_ReallyEnabled = 1 << texTarget;
          }
          else {
             /* fixed-function: texture unit is really disabled */
-- 
1.7.3.4



More information about the mesa-dev mailing list