fixed pointer arithmetic error in glCopyPixels
[mesa.git] / src / mesa / main / texobj.c
index 8881083e4876a343516082390e31a112327537b1..39f65940b5d608b927c7205a2294a01f897987d7 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: texobj.c,v 1.41 2001/02/26 18:25:25 brianp Exp $ */
+/* $Id: texobj.c,v 1.52 2002/02/15 16:32:06 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.5
+ * Version:  4.1
  *
- * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2002  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"),
@@ -54,7 +54,7 @@
  * Return:  pointer to new texture object
  */
 struct gl_texture_object *
-_mesa_alloc_texture_object( struct gl_shared_state *shared, 
+_mesa_alloc_texture_object( struct gl_shared_state *shared,
                            GLuint name, GLuint dimensions )
 {
    struct gl_texture_object *obj;
@@ -79,9 +79,13 @@ _mesa_alloc_texture_object( struct gl_shared_state *shared,
       obj->MaxLod = 1000.0;
       obj->BaseLevel = 0;
       obj->MaxLevel = 1000;
-      obj->CompareFlag = GL_FALSE;
-      obj->CompareOperator = GL_TEXTURE_LEQUAL_R_SGIX;
-      obj->ShadowAmbient = 0;
+      obj->MaxAnisotropy = 1.0;
+      obj->CompareFlag = GL_FALSE;                      /* SGIX_shadow */
+      obj->CompareOperator = GL_TEXTURE_LEQUAL_R_SGIX;  /* SGIX_shadow */
+      obj->CompareMode = GL_LUMINANCE;    /* ARB_shadow */
+      obj->CompareFunc = GL_LEQUAL;       /* ARB_shadow */
+      obj->DepthMode = GL_LUMINANCE;      /* ARB_depth_texture */
+      obj->ShadowAmbient = 0;             /* ARB/SGIX_shadow_ambient */
       _mesa_init_colortable(&obj->Palette);
 
       /* insert into linked list */
@@ -180,7 +184,7 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
                                 struct gl_texture_object *t )
 {
    const GLint baseLevel = t->BaseLevel;
-   GLint maxLog2 = 0;
+   GLint maxLog2 = 0, maxLevels = 0;
 
    t->Complete = GL_TRUE;  /* be optimistic */
 
@@ -194,28 +198,38 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
    /* Compute _MaxLevel */
    if (t->Dimensions == 1) {
       maxLog2 = t->Image[baseLevel]->WidthLog2;
+      maxLevels = ctx->Const.MaxTextureLevels;
    }
    else if (t->Dimensions == 2 || t->Dimensions == 6) {
       maxLog2 = MAX2(t->Image[baseLevel]->WidthLog2,
                      t->Image[baseLevel]->HeightLog2);
+      maxLevels = (t->Dimensions == 2) ?
+         ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels;
    }
    else if (t->Dimensions == 3) {
       GLint max = MAX2(t->Image[baseLevel]->WidthLog2,
                        t->Image[baseLevel]->HeightLog2);
       maxLog2 = MAX2(max, (GLint)(t->Image[baseLevel]->DepthLog2));
+      maxLevels = ctx->Const.Max3DTextureLevels;
+   }
+   else {
+      _mesa_problem(ctx, "Bad t->Dimension in _mesa_test_texobj_completeness");
+      return;
    }
 
+   ASSERT(maxLevels > 0);
+
    t->_MaxLevel = baseLevel + maxLog2;
    t->_MaxLevel = MIN2(t->_MaxLevel, t->MaxLevel);
-   t->_MaxLevel = MIN2(t->_MaxLevel, ctx->Const.MaxTextureLevels - 1);
+   t->_MaxLevel = MIN2(t->_MaxLevel, maxLevels - 1);
 
    /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */
    t->_MaxLambda = (GLfloat) (t->_MaxLevel - t->BaseLevel);
 
    if (t->Dimensions == 6) {
       /* make sure that all six cube map level 0 images are the same size */
-      const GLint w = t->Image[baseLevel]->Width2;
-      const GLint h = t->Image[baseLevel]->Height2;
+      const GLuint w = t->Image[baseLevel]->Width2;
+      const GLuint h = t->Image[baseLevel]->Height2;
       if (!t->NegX[baseLevel] ||
           t->NegX[baseLevel]->Width2 != w ||
           t->NegX[baseLevel]->Height2 != h ||
@@ -254,7 +268,7 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
       /* Test dimension-independent attributes */
       for (i = minLevel; i <= maxLevel; i++) {
          if (t->Image[i]) {
-            if (t->Image[i]->Format != t->Image[baseLevel]->Format) {
+            if (t->Image[i]->TexFormat != t->Image[baseLevel]->TexFormat) {
                t->Complete = GL_FALSE;
                incomplete(t, "Format[i] != Format[baseLevel]");
                return;
@@ -271,7 +285,7 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
       if (t->Dimensions == 1) {
          /* Test 1-D mipmaps */
          GLuint width = t->Image[baseLevel]->Width2;
-         for (i = baseLevel + 1; i < ctx->Const.MaxTextureLevels; i++) {
+         for (i = baseLevel + 1; i < maxLevels; i++) {
             if (width > 1) {
                width /= 2;
             }
@@ -296,7 +310,7 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
          /* Test 2-D mipmaps */
          GLuint width = t->Image[baseLevel]->Width2;
          GLuint height = t->Image[baseLevel]->Height2;
-         for (i = baseLevel + 1; i < ctx->Const.MaxTextureLevels; i++) {
+         for (i = baseLevel + 1; i < maxLevels; i++) {
             if (width > 1) {
                width /= 2;
             }
@@ -330,7 +344,7 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
          GLuint width = t->Image[baseLevel]->Width2;
          GLuint height = t->Image[baseLevel]->Height2;
          GLuint depth = t->Image[baseLevel]->Depth2;
-        for (i = baseLevel + 1; i < ctx->Const.MaxTextureLevels; i++) {
+        for (i = baseLevel + 1; i < maxLevels; i++) {
             if (width > 1) {
                width /= 2;
             }
@@ -346,6 +360,11 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
                   t->Complete = GL_FALSE;
                   return;
                }
+               if (t->Image[i]->Format == GL_DEPTH_COMPONENT) {
+                  t->Complete = GL_FALSE;
+                  incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex");
+                  return;
+               }
                if (t->Image[i]->Width2 != width) {
                   t->Complete = GL_FALSE;
                   incomplete(t, "3D Image[i] bad width");
@@ -371,7 +390,7 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
          /* make sure 6 cube faces are consistant */
          GLuint width = t->Image[baseLevel]->Width2;
          GLuint height = t->Image[baseLevel]->Height2;
-        for (i = baseLevel + 1; i < ctx->Const.MaxTextureLevels; i++) {
+        for (i = baseLevel + 1; i < maxLevels; i++) {
             if (width > 1) {
                width /= 2;
             }
@@ -379,6 +398,12 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
                height /= 2;
             }
             if (i >= minLevel && i <= maxLevel) {
+               /* Don't support GL_DEPTH_COMPONENT for cube maps */
+               if (t->Image[i]->Format == GL_DEPTH_COMPONENT) {
+                  t->Complete = GL_FALSE;
+                  incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex");
+                  return;
+               }
                /* check that we have images defined */
                if (!t->Image[i] || !t->NegX[i] ||
                    !t->PosY[i]  || !t->NegY[i] ||
@@ -405,7 +430,7 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
       }
       else {
          /* Dimensions = ??? */
-         gl_problem(ctx, "Bug in gl_test_texture_object_completeness\n");
+         _mesa_problem(ctx, "Bug in gl_test_texture_object_completeness\n");
       }
    }
 }
@@ -426,7 +451,7 @@ _mesa_GenTextures( GLsizei n, GLuint *texName )
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (n < 0) {
-      gl_error( ctx, GL_INVALID_VALUE, "glGenTextures" );
+      _mesa_error( ctx, GL_INVALID_VALUE, "glGenTextures" );
       return;
    }
 
@@ -484,26 +509,36 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *texName)
                if (delObj == unit->Current1D) {
                   unit->Current1D = ctx->Shared->Default1D;
                   ctx->Shared->Default1D->RefCount++;
+                  if (delObj == unit->_Current)
+                     unit->_Current = unit->Current1D;
                }
                else if (delObj == unit->Current2D) {
                   unit->Current2D = ctx->Shared->Default2D;
                   ctx->Shared->Default2D->RefCount++;
+                  if (delObj == unit->_Current)
+                     unit->_Current = unit->Current2D;
                }
                else if (delObj == unit->Current3D) {
                   unit->Current3D = ctx->Shared->Default3D;
                   ctx->Shared->Default3D->RefCount++;
+                  if (delObj == unit->_Current)
+                     unit->_Current = unit->Current3D;
                }
                else if (delObj == unit->CurrentCubeMap) {
                   unit->CurrentCubeMap = ctx->Shared->DefaultCubeMap;
                   ctx->Shared->DefaultCubeMap->RefCount++;
+                  if (delObj == unit->_Current)
+                     unit->_Current = unit->CurrentCubeMap;
                }
             }
             ctx->NewState |= _NEW_TEXTURE;
 
             /* Decrement reference count and delete if zero */
             delObj->RefCount--;
-            ASSERT( delObj->RefCount >= 0 );
+            ASSERT(delObj->RefCount >= 0);
+
             if (delObj->RefCount == 0) {
+               ASSERT(delObj->Name != 0);
                if (ctx->Driver.DeleteTexture)
                   (*ctx->Driver.DeleteTexture)( ctx, delObj );
                _mesa_free_texture_object(ctx->Shared, delObj);
@@ -531,7 +566,7 @@ _mesa_BindTexture( GLenum target, GLuint texName )
 
    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
       fprintf(stderr, "glBindTexture %s %d\n",
-             gl_lookup_enum_by_nr(target), (GLint) texName);
+             _mesa_lookup_enum_by_nr(target), (GLint) texName);
 
    switch (target) {
       case GL_TEXTURE_1D:
@@ -554,7 +589,7 @@ _mesa_BindTexture( GLenum target, GLuint texName )
          }
          /* fallthrough */
       default:
-         gl_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
+         _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
          return;
    }
 
@@ -591,7 +626,8 @@ _mesa_BindTexture( GLenum target, GLuint texName )
          /* error checking */
          if (newTexObj->Dimensions > 0 && newTexObj->Dimensions != targetDim) {
             /* the named texture object's dimensions don't match the target */
-            gl_error( ctx, GL_INVALID_OPERATION, "glBindTexture" );
+            _mesa_error( ctx, GL_INVALID_OPERATION,
+                         "glBindTexture(wrong dimensionality)" );
             return;
          }
       }
@@ -600,7 +636,7 @@ _mesa_BindTexture( GLenum target, GLuint texName )
         newTexObj = _mesa_alloc_texture_object( ctx->Shared, texName,
                                                 targetDim);
          if (!newTexObj) {
-            gl_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
             return;
          }
       }
@@ -609,7 +645,6 @@ _mesa_BindTexture( GLenum target, GLuint texName )
 
    newTexObj->RefCount++;
 
-   
    /* do the actual binding, but first flush outstanding vertices:
     */
    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
@@ -628,22 +663,21 @@ _mesa_BindTexture( GLenum target, GLuint texName )
          texUnit->CurrentCubeMap = newTexObj;
          break;
       default:
-         gl_problem(ctx, "bad target in BindTexture");
+         _mesa_problem(ctx, "bad target in BindTexture");
    }
 
    /* Pass BindTexture call to device driver */
    if (ctx->Driver.BindTexture)
       (*ctx->Driver.BindTexture)( ctx, target, newTexObj );
 
-   if (oldTexObj->Name > 0) {
-      /* never delete default (id=0) texture objects */
-      oldTexObj->RefCount--;
-      if (oldTexObj->RefCount <= 0) {
-         if (ctx->Driver.DeleteTexture) {
-           (*ctx->Driver.DeleteTexture)( ctx, oldTexObj );
-        }
-         _mesa_free_texture_object(ctx->Shared, oldTexObj);
+   oldTexObj->RefCount--;
+   assert(oldTexObj->RefCount >= 0);
+   if (oldTexObj->RefCount == 0) {
+      assert(oldTexObj->Name != 0);
+      if (ctx->Driver.DeleteTexture) {
+         (*ctx->Driver.DeleteTexture)( ctx, oldTexObj );
       }
+      _mesa_free_texture_object(ctx->Shared, oldTexObj);
    }
 }
 
@@ -661,7 +695,7 @@ _mesa_PrioritizeTextures( GLsizei n, const GLuint *texName,
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
    if (n < 0) {
-      gl_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
+      _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
       return;
    }
 
@@ -698,7 +732,7 @@ _mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
 
    if (n < 0) {
-      gl_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
+      _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
       return GL_FALSE;
    }
 
@@ -708,7 +742,7 @@ _mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
    for (i = 0; i < n; i++) {
       struct gl_texture_object *t;
       if (texName[i] == 0) {
-         gl_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)");
+         _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)");
          return GL_FALSE;
       }
       t = (struct gl_texture_object *)
@@ -724,7 +758,7 @@ _mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
          }
       }
       else {
-         gl_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)");
+         _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)");
          return GL_FALSE;
       }
    }
@@ -743,4 +777,3 @@ _mesa_IsTexture( GLuint texture )
    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
    return texture > 0 && _mesa_HashLookup(ctx->Shared->TexObjects, texture);
 }
-