mesa: add #define FEATURE_ARB_pixel_buffer_object
[mesa.git] / src / mesa / main / texobj.c
index ac70e5a22ec0e1bfc105ce1c4e7763da03137f5c..b63f747fe8d3936cd2b5e40e246ac77e524d3fcb 100644 (file)
@@ -5,9 +5,9 @@
 
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  7.1
  *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  */
 
 
-#include "glheader.h"
+#include "mfeatures.h"
+#if FEATURE_colortable
 #include "colortab.h"
+#endif
 #include "context.h"
 #include "enums.h"
 #include "fbobject.h"
@@ -40,6 +42,8 @@
 #include "texstate.h"
 #include "texobj.h"
 #include "mtypes.h"
+#include "shader/prog_instruction.h"
+
 
 
 /**********************************************************************/
@@ -130,12 +134,43 @@ _mesa_initialize_texture_object( struct gl_texture_object *obj,
    obj->BaseLevel = 0;
    obj->MaxLevel = 1000;
    obj->MaxAnisotropy = 1.0;
-   obj->CompareFlag = GL_FALSE;                      /* SGIX_shadow */
-   obj->CompareOperator = GL_TEXTURE_LEQUAL_R_SGIX;  /* SGIX_shadow */
    obj->CompareMode = GL_NONE;         /* ARB_shadow */
    obj->CompareFunc = GL_LEQUAL;       /* ARB_shadow */
+   obj->CompareFailValue = 0.0F;       /* ARB_shadow_ambient */
    obj->DepthMode = GL_LUMINANCE;      /* ARB_depth_texture */
-   obj->ShadowAmbient = 0.0F;          /* ARB/SGIX_shadow_ambient */
+   obj->Swizzle[0] = GL_RED;
+   obj->Swizzle[1] = GL_GREEN;
+   obj->Swizzle[2] = GL_BLUE;
+   obj->Swizzle[3] = GL_ALPHA;
+   obj->_Swizzle = SWIZZLE_NOOP;
+}
+
+
+/**
+ * Some texture initialization can't be finished until we know which
+ * target it's getting bound to (GL_TEXTURE_1D/2D/etc).
+ */
+static void
+finish_texture_init(GLcontext *ctx, GLenum target,
+                    struct gl_texture_object *obj)
+{
+   assert(obj->Target == 0);
+
+   if (target == GL_TEXTURE_RECTANGLE_NV) {
+      /* have to init wrap and filter state here - kind of klunky */
+      obj->WrapS = GL_CLAMP_TO_EDGE;
+      obj->WrapT = GL_CLAMP_TO_EDGE;
+      obj->WrapR = GL_CLAMP_TO_EDGE;
+      obj->MinFilter = GL_LINEAR;
+      if (ctx->Driver.TexParameter) {
+         static const GLfloat fparam_wrap[1] = {(GLfloat) GL_CLAMP_TO_EDGE};
+         static const GLfloat fparam_filter[1] = {(GLfloat) GL_LINEAR};
+         ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_S, fparam_wrap);
+         ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_T, fparam_wrap);
+         ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_R, fparam_wrap);
+         ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_MIN_FILTER, fparam_filter);
+      }
+   }
 }
 
 
@@ -145,17 +180,13 @@ _mesa_initialize_texture_object( struct gl_texture_object *obj,
  * Called via ctx->Driver.DeleteTexture() if not overriden by a driver.
  *
  * \param shared the shared GL state to which the object belongs.
- * \param texOjb the texture object to delete.
+ * \param texObj the texture object to delete.
  */
 void
 _mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
 {
    GLuint i, face;
 
-   /*
-   printf("TEX DELETE %p (%u)\n", (void*) texObj, texObj->Name);
-   */
-
    (void) ctx;
 
    /* Set Target to an invalid value.  With some assertions elsewhere
@@ -163,7 +194,9 @@ _mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
     */
    texObj->Target = 0x99;
 
+#if FEATURE_colortable
    _mesa_free_colortable_data(&texObj->Palette);
+#endif
 
    /* free the texture images */
    for (face = 0; face < 6; face++) {
@@ -195,6 +228,7 @@ void
 _mesa_copy_texture_object( struct gl_texture_object *dest,
                            const struct gl_texture_object *src )
 {
+   dest->Target = src->Target;
    dest->Name = src->Name;
    dest->Priority = src->Priority;
    dest->BorderColor[0] = src->BorderColor[0];
@@ -212,17 +246,17 @@ _mesa_copy_texture_object( struct gl_texture_object *dest,
    dest->BaseLevel = src->BaseLevel;
    dest->MaxLevel = src->MaxLevel;
    dest->MaxAnisotropy = src->MaxAnisotropy;
-   dest->CompareFlag = src->CompareFlag;
-   dest->CompareOperator = src->CompareOperator;
-   dest->ShadowAmbient = src->ShadowAmbient;
    dest->CompareMode = src->CompareMode;
    dest->CompareFunc = src->CompareFunc;
+   dest->CompareFailValue = src->CompareFailValue;
    dest->DepthMode = src->DepthMode;
    dest->_MaxLevel = src->_MaxLevel;
    dest->_MaxLambda = src->_MaxLambda;
    dest->GenerateMipmap = src->GenerateMipmap;
    dest->Palette = src->Palette;
    dest->_Complete = src->_Complete;
+   COPY_4V(dest->Swizzle, src->Swizzle);
+   dest->_Swizzle = src->_Swizzle;
 }
 
 
@@ -278,16 +312,16 @@ _mesa_reference_texobj(struct gl_texture_object **ptr,
       _glthread_LOCK_MUTEX(oldTex->Mutex);
       ASSERT(oldTex->RefCount > 0);
       oldTex->RefCount--;
-      /*
-      printf("TEX DECR %p (%u) to %d\n",
-             (void*) oldTex, oldTex->Name, oldTex->RefCount);
-      */
+
       deleteFlag = (oldTex->RefCount == 0);
       _glthread_UNLOCK_MUTEX(oldTex->Mutex);
 
       if (deleteFlag) {
          GET_CURRENT_CONTEXT(ctx);
-         ctx->Driver.DeleteTexture(ctx, oldTex);
+         if (ctx)
+            ctx->Driver.DeleteTexture(ctx, oldTex);
+         else
+            _mesa_problem(NULL, "Unable to delete texture, no context");
       }
 
       *ptr = NULL;
@@ -306,10 +340,6 @@ _mesa_reference_texobj(struct gl_texture_object **ptr,
       }
       else {
          tex->RefCount++;
-         /*
-           printf("TEX INCR %p (%u) to %d\n",
-           (void*) tex, tex->Name, tex->RefCount);
-         */
          *ptr = tex;
       }
       _glthread_UNLOCK_MUTEX(tex->Mutex);
@@ -358,11 +388,21 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
 
    t->_Complete = GL_TRUE;  /* be optimistic */
 
+   /* Detect cases where the application set the base level to an invalid
+    * value.
+    */
+   if ((baseLevel < 0) || (baseLevel > MAX_TEXTURE_LEVELS)) {
+      char s[100];
+      _mesa_sprintf(s, "base level = %d is invalid", baseLevel);
+      incomplete(t, s);
+      t->_Complete = GL_FALSE;
+      return;
+   }
+
    /* Always need the base level image */
    if (!t->Image[0][baseLevel]) {
       char s[100];
-      _mesa_sprintf(s, "obj %p (%d) Image[baseLevel=%d] == NULL",
-              (void *) t, t->Name, baseLevel);
+      _mesa_sprintf(s, "Image[baseLevel=%d] == NULL", baseLevel);
       incomplete(t, s);
       t->_Complete = GL_FALSE;
       return;
@@ -719,30 +759,17 @@ unbind_texobj_from_fbo(GLcontext *ctx, struct gl_texture_object *texObj)
 static void
 unbind_texobj_from_texunits(GLcontext *ctx, struct gl_texture_object *texObj)
 {
-   GLuint u;
+   GLuint u, tex;
 
    for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
       struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
-      if (texObj == unit->Current1D) {
-         _mesa_reference_texobj(&unit->Current1D, ctx->Shared->Default1D);
-      }
-      else if (texObj == unit->Current2D) {
-         _mesa_reference_texobj(&unit->Current2D, ctx->Shared->Default2D);
-      }
-      else if (texObj == unit->Current3D) {
-         _mesa_reference_texobj(&unit->Current3D, ctx->Shared->Default3D);
-      }
-      else if (texObj == unit->CurrentCubeMap) {
-         _mesa_reference_texobj(&unit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
-      }
-      else if (texObj == unit->CurrentRect) {
-         _mesa_reference_texobj(&unit->CurrentRect, ctx->Shared->DefaultRect);
-      }
-      else if (texObj == unit->Current1DArray) {
-         _mesa_reference_texobj(&unit->Current1DArray, ctx->Shared->Default1DArray);
-      }
-      else if (texObj == unit->Current2DArray) {
-         _mesa_reference_texobj(&unit->Current2DArray, ctx->Shared->Default2DArray);
+      for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+         if (texObj == unit->CurrentTex[tex]) {
+            _mesa_reference_texobj(&unit->CurrentTex[tex],
+                                   ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]);
+            ASSERT(unit->CurrentTex[tex]);
+            break;
+         }
       }
    }
 }
@@ -802,7 +829,7 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
             _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
             _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
 
-            /* Unrefernce the texobj.  If refcount hits zero, the texture
+            /* Unreference the texobj.  If refcount hits zero, the texture
              * will be deleted.
              */
             _mesa_reference_texobj(&delObj, NULL);
@@ -812,6 +839,35 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
 }
 
 
+/**
+ * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D
+ * into the corresponding Mesa texture target index.
+ * Return -1 if target is invalid.
+ */
+static GLint
+target_enum_to_index(GLenum target)
+{
+   switch (target) {
+   case GL_TEXTURE_1D:
+      return TEXTURE_1D_INDEX;
+   case GL_TEXTURE_2D:
+      return TEXTURE_2D_INDEX;
+   case GL_TEXTURE_3D:
+      return TEXTURE_3D_INDEX;
+   case GL_TEXTURE_CUBE_MAP_ARB:
+      return TEXTURE_CUBE_INDEX;
+   case GL_TEXTURE_RECTANGLE_NV:
+      return TEXTURE_RECT_INDEX;
+   case GL_TEXTURE_1D_ARRAY_EXT:
+      return TEXTURE_1D_ARRAY_INDEX;
+   case GL_TEXTURE_2D_ARRAY_EXT:
+      return TEXTURE_2D_ARRAY_INDEX;
+   default:
+      return -1;
+   }
+}
+
+
 /**
  * Bind a named texture to a texturing target.
  * 
@@ -833,43 +889,27 @@ _mesa_BindTexture( GLenum target, GLuint texName )
    GET_CURRENT_CONTEXT(ctx);
    const GLuint unit = ctx->Texture.CurrentUnit;
    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
-   struct gl_texture_object *newTexObj = NULL;
+   struct gl_texture_object *newTexObj = NULL, *defaultTexObj = NULL;
+   GLint targetIndex;
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
       _mesa_debug(ctx, "glBindTexture %s %d\n",
                   _mesa_lookup_enum_by_nr(target), (GLint) texName);
 
+   targetIndex = target_enum_to_index(target);
+   if (targetIndex < 0) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target)");
+      return;
+   }
+   assert(targetIndex < NUM_TEXTURE_TARGETS);
+   defaultTexObj = ctx->Shared->DefaultTex[targetIndex];
+
    /*
     * Get pointer to new texture object (newTexObj)
     */
    if (texName == 0) {
-      /* newTexObj = a default texture object */
-      switch (target) {
-         case GL_TEXTURE_1D:
-            newTexObj = ctx->Shared->Default1D;
-            break;
-         case GL_TEXTURE_2D:
-            newTexObj = ctx->Shared->Default2D;
-            break;
-         case GL_TEXTURE_3D:
-            newTexObj = ctx->Shared->Default3D;
-            break;
-         case GL_TEXTURE_CUBE_MAP_ARB:
-            newTexObj = ctx->Shared->DefaultCubeMap;
-            break;
-         case GL_TEXTURE_RECTANGLE_NV:
-            newTexObj = ctx->Shared->DefaultRect;
-            break;
-         case GL_TEXTURE_1D_ARRAY_EXT:
-            newTexObj = ctx->Shared->Default1DArray;
-            break;
-         case GL_TEXTURE_2D_ARRAY_EXT:
-            newTexObj = ctx->Shared->Default2DArray;
-            break;
-         default:
-            ; /* Bad targets are caught above */
-      }
+      newTexObj = defaultTexObj;
    }
    else {
       /* non-default texture object */
@@ -877,25 +917,13 @@ _mesa_BindTexture( GLenum target, GLuint texName )
       if (newTexObj) {
          /* error checking */
          if (newTexObj->Target != 0 && newTexObj->Target != target) {
-            /* the named texture object's dimensions don't match the target */
+            /* the named texture object's target doesn't match the given target */
             _mesa_error( ctx, GL_INVALID_OPERATION,
-                         "glBindTexture(wrong dimensionality)" );
+                         "glBindTexture(target mismatch)" );
             return;
          }
-         if (newTexObj->Target == 0 && target == GL_TEXTURE_RECTANGLE_NV) {
-            /* have to init wrap and filter state here - kind of klunky */
-            newTexObj->WrapS = GL_CLAMP_TO_EDGE;
-            newTexObj->WrapT = GL_CLAMP_TO_EDGE;
-            newTexObj->WrapR = GL_CLAMP_TO_EDGE;
-            newTexObj->MinFilter = GL_LINEAR;
-            if (ctx->Driver.TexParameter) {
-               static const GLfloat fparam_wrap[1] = {(GLfloat) GL_CLAMP_TO_EDGE};
-               static const GLfloat fparam_filter[1] = {(GLfloat) GL_LINEAR};
-               (*ctx->Driver.TexParameter)( ctx, target, newTexObj, GL_TEXTURE_WRAP_S, fparam_wrap );
-               (*ctx->Driver.TexParameter)( ctx, target, newTexObj, GL_TEXTURE_WRAP_T, fparam_wrap );
-               (*ctx->Driver.TexParameter)( ctx, target, newTexObj, GL_TEXTURE_WRAP_R, fparam_wrap );
-               (*ctx->Driver.TexParameter)( ctx, target, newTexObj, GL_TEXTURE_MIN_FILTER, fparam_filter );
-            }
+         if (newTexObj->Target == 0) {
+            finish_texture_init(ctx, target, newTexObj);
          }
       }
       else {
@@ -923,32 +951,8 @@ _mesa_BindTexture( GLenum target, GLuint texName )
     * texture object will be decremented.  It'll be deleted if the
     * count hits zero.
     */
-   switch (target) {
-      case GL_TEXTURE_1D:
-         _mesa_reference_texobj(&texUnit->Current1D, newTexObj);
-         break;
-      case GL_TEXTURE_2D:
-         _mesa_reference_texobj(&texUnit->Current2D, newTexObj);
-         break;
-      case GL_TEXTURE_3D:
-         _mesa_reference_texobj(&texUnit->Current3D, newTexObj);
-         break;
-      case GL_TEXTURE_CUBE_MAP_ARB:
-         _mesa_reference_texobj(&texUnit->CurrentCubeMap, newTexObj);
-         break;
-      case GL_TEXTURE_RECTANGLE_NV:
-         _mesa_reference_texobj(&texUnit->CurrentRect, newTexObj);
-         break;
-      case GL_TEXTURE_1D_ARRAY_EXT:
-         texUnit->Current1DArray = newTexObj;
-         break;
-      case GL_TEXTURE_2D_ARRAY_EXT:
-         texUnit->Current2DArray = newTexObj;
-         break;
-      default:
-         _mesa_problem(ctx, "bad target in BindTexture");
-         return;
-   }
+   _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], newTexObj);
+   ASSERT(texUnit->CurrentTex[targetIndex]);
 
    /* Pass BindTexture call to device driver */
    if (ctx->Driver.BindTexture)