mesa: fix _mesa_get_fallback_texture() to handle all texture targets
authorBrian Paul <brianp@vmware.com>
Wed, 4 Jan 2012 21:55:32 +0000 (14:55 -0700)
committerBrian Paul <brianp@vmware.com>
Wed, 15 Feb 2012 21:07:43 +0000 (14:07 -0700)
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).

v2: use a 1-texel texture image, per José.

Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
src/mesa/main/mtypes.h
src/mesa/main/shared.c
src/mesa/main/texobj.c
src/mesa/main/texobj.h
src/mesa/main/texstate.c

index 5ef97c8..9200f3f 100644 (file)
@@ -2483,7 +2483,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
index c07ce82..2269476 100644 (file)
@@ -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
index 1b61d3a..5905948 100644 (file)
@@ -759,59 +759,127 @@ _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 = 1, height = 1, depth = 1;
+      GLubyte texel[4];
       struct gl_texture_object *texObj;
       struct gl_texture_image *texImage;
       gl_format texFormat;
-      GLuint i;
-
-      for (i = 0; i < 8 * 8; i++) {
-         texels[i][0] =
-         texels[i][1] =
-         texels[i][2] = 0x0;
-         texels[i][3] = 0xff;
+      GLuint dims, face, numFaces = 1;
+      GLenum target;
+
+      texel[0] =
+      texel[1] =
+      texel[2] = 0x0;
+      texel[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);
+      if (!texObj)
+         return NULL;
+
       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, texel,
+                                   &ctx->DefaultPacking);
+            break;
+         case 2:
+            ctx->Driver.TexImage2D(ctx, texImage, GL_RGBA,
+                                   width, height, 0,
+                                   GL_RGBA, GL_UNSIGNED_BYTE, texel,
+                                   &ctx->DefaultPacking);
+            break;
+         case 3:
+            ctx->Driver.TexImage3D(ctx, texImage, GL_RGBA,
+                                   width, height, depth, 0,
+                                   GL_RGBA, GL_UNSIGNED_BYTE, texel,
+                                   &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];
 }
 
 
index 9ca7a4c..03dfbe3 100644 (file)
@@ -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 );
index cc49916..187ec9c 100644 (file)
@@ -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) (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 */