home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / texobj.cpp < prev    next >
C/C++ Source or Header  |  2002-10-24  |  28KB  |  865 lines

  1. /* $Id: texobj.c,v 1.62 2002/10/24 23:57:21 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  4.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27. #include "glheader.h"
  28. #include "colortab.h"
  29. #include "context.h"
  30. #include "enums.h"
  31. #include "hash.h"
  32. #include "imports.h"
  33. #include "macros.h"
  34. #include "teximage.h"
  35. #include "texstate.h"
  36. #include "texobj.h"
  37. #include "mtypes.h"
  38.  
  39.  
  40. /*
  41.  * Allocate a new texture object and add it to the linked list of texture
  42.  * objects.  If name>0 then also insert the new texture object into the hash
  43.  * table.
  44.  * Input:  shared - the shared GL state structure to contain the texture object
  45.  *         name - integer name for the texture object
  46.  *         target - either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D,
  47.  *                  GL_TEXTURE_CUBE_MAP_ARB or GL_TEXTURE_RECTANGLE_NV
  48.  *                      zero is ok for the sake of GenTextures()
  49.  * Return:  pointer to new texture object
  50.  */
  51. struct gl_texture_object *
  52. _mesa_alloc_texture_object( struct gl_shared_state *shared,
  53.                 GLuint name, GLenum target )
  54. {
  55.    struct gl_texture_object *obj;
  56.  
  57.    ASSERT(target == 0 ||
  58.           target == GL_TEXTURE_1D ||
  59.           target == GL_TEXTURE_2D ||
  60.           target == GL_TEXTURE_3D ||
  61.           target == GL_TEXTURE_CUBE_MAP_ARB ||
  62.           target == GL_TEXTURE_RECTANGLE_NV);
  63.  
  64.    obj = CALLOC_STRUCT(gl_texture_object);
  65.  
  66.    if (obj) {
  67.       /* init the non-zero fields */
  68.       _glthread_INIT_MUTEX(obj->Mutex);
  69.       obj->RefCount = 1;
  70.       obj->Name = name;
  71.       obj->Target = target;
  72.       obj->Priority = 1.0F;
  73.       if (target == GL_TEXTURE_RECTANGLE_NV) {
  74.          obj->WrapS = GL_CLAMP_TO_EDGE;
  75.          obj->WrapT = GL_CLAMP_TO_EDGE;
  76.          obj->WrapR = GL_CLAMP_TO_EDGE;
  77.          obj->MinFilter = GL_LINEAR;
  78.       }
  79.       else {
  80.          obj->WrapS = GL_REPEAT;
  81.          obj->WrapT = GL_REPEAT;
  82.          obj->WrapR = GL_REPEAT;
  83.          obj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
  84.       }
  85.       obj->MagFilter = GL_LINEAR;
  86.       obj->MinLod = -1000.0;
  87.       obj->MaxLod = 1000.0;
  88.       obj->BaseLevel = 0;
  89.       obj->MaxLevel = 1000;
  90.       obj->MaxAnisotropy = 1.0;
  91.       obj->CompareFlag = GL_FALSE;                      /* SGIX_shadow */
  92.       obj->CompareOperator = GL_TEXTURE_LEQUAL_R_SGIX;  /* SGIX_shadow */
  93.       obj->CompareMode = GL_LUMINANCE;    /* ARB_shadow */
  94.       obj->CompareFunc = GL_LEQUAL;       /* ARB_shadow */
  95.       obj->DepthMode = GL_LUMINANCE;      /* ARB_depth_texture */
  96.       obj->ShadowAmbient = 0.0F;          /* ARB/SGIX_shadow_ambient */
  97.       _mesa_init_colortable(&obj->Palette);
  98.  
  99.       /* insert into linked list */
  100.       if (shared) {
  101.          _glthread_LOCK_MUTEX(shared->Mutex);
  102.          obj->Next = shared->TexObjectList;
  103.          shared->TexObjectList = obj;
  104.          _glthread_UNLOCK_MUTEX(shared->Mutex);
  105.       }
  106.  
  107.       if (name > 0) {
  108.          /* insert into hash table */
  109.          _mesa_HashInsert(shared->TexObjects, name, obj);
  110.       }
  111.    }
  112.    return obj;
  113. }
  114.  
  115.  
  116. /*
  117.  * Deallocate a texture object struct and remove it from the given
  118.  * shared GL state.
  119.  * Input:  shared - the shared GL state to which the object belongs
  120.  *         t - the texture object to delete
  121.  */
  122. void _mesa_free_texture_object( struct gl_shared_state *shared,
  123.                                 struct gl_texture_object *t )
  124. {
  125.    struct gl_texture_object *tprev, *tcurr;
  126.  
  127.    assert(t);
  128.  
  129.    /* unlink t from the linked list */
  130.    if (shared) {
  131.       _glthread_LOCK_MUTEX(shared->Mutex);
  132.       tprev = NULL;
  133.       tcurr = shared->TexObjectList;
  134.       while (tcurr) {
  135.          if (tcurr==t) {
  136.             if (tprev) {
  137.                tprev->Next = t->Next;
  138.             }
  139.             else {
  140.                shared->TexObjectList = t->Next;
  141.             }
  142.             break;
  143.          }
  144.          tprev = tcurr;
  145.          tcurr = tcurr->Next;
  146.       }
  147.       _glthread_UNLOCK_MUTEX(shared->Mutex);
  148.    }
  149.  
  150.    if (t->Name) {
  151.       /* remove from hash table */
  152.       _mesa_HashRemove(shared->TexObjects, t->Name);
  153.    }
  154.  
  155.    _mesa_free_colortable_data(&t->Palette);
  156.  
  157.    /* free the texture images */
  158.    {
  159.       GLuint i;
  160.       for (i=0;i<MAX_TEXTURE_LEVELS;i++) {
  161.          if (t->Image[i]) {
  162.             _mesa_free_texture_image( t->Image[i] );
  163.          }
  164.       }
  165.    }
  166.  
  167.    /* free this object */
  168.    FREE( t );
  169. }
  170.  
  171.  
  172. /*
  173.  * Copy texture object state from one texture object to another.
  174.  */
  175. void
  176. _mesa_copy_texture_object( struct gl_texture_object *dest,
  177.                            const struct gl_texture_object *src )
  178. {
  179.    dest->Name = src->Name;
  180.    dest->Priority = src->Priority;
  181.    dest->BorderColor[0] = src->BorderColor[0];
  182.    dest->BorderColor[1] = src->BorderColor[1];
  183.    dest->BorderColor[2] = src->BorderColor[2];
  184.    dest->BorderColor[3] = src->BorderColor[3];
  185.    dest->WrapS = src->WrapS;
  186.    dest->WrapT = src->WrapT;
  187.    dest->WrapR = src->WrapR;
  188.    dest->MinFilter = src->MinFilter;
  189.    dest->MagFilter = src->MagFilter;
  190.    dest->MinLod = src->MinLod;
  191.    dest->MaxLod = src->MaxLod;
  192.    dest->BaseLevel = src->BaseLevel;
  193.    dest->MaxLevel = src->MaxLevel;
  194.    dest->MaxAnisotropy = src->MaxAnisotropy;
  195.    dest->CompareFlag = src->CompareFlag;
  196.    dest->CompareOperator = src->CompareOperator;
  197.    dest->ShadowAmbient = src->ShadowAmbient;
  198.    dest->CompareMode = src->CompareMode;
  199.    dest->CompareFunc = src->CompareFunc;
  200.    dest->DepthMode = src->DepthMode;
  201.    dest->_MaxLevel = src->_MaxLevel;
  202.    dest->_MaxLambda = src->_MaxLambda;
  203.    dest->GenerateMipmap = src->GenerateMipmap;
  204.    dest->Palette = src->Palette;
  205.    dest->Complete = src->Complete;
  206. }
  207.  
  208.  
  209. /*
  210.  * Report why a texture object is incomplete.  (for debug only)
  211.  */
  212. #if 0
  213. static void
  214. incomplete(const struct gl_texture_object *t, const char *why)
  215. {
  216.    _mesa_printf("Texture Obj %d incomplete because: %s\n", t->Name, why);
  217. }
  218. #else
  219. #define incomplete(a, b)
  220. #endif
  221.  
  222.  
  223. /*
  224.  * Examine a texture object to determine if it is complete.
  225.  * The t->Complete flag will be set to GL_TRUE or GL_FALSE accordingly.
  226.  */
  227. void
  228. _mesa_test_texobj_completeness( const GLcontext *ctx,
  229.                                 struct gl_texture_object *t )
  230. {
  231.    const GLint baseLevel = t->BaseLevel;
  232.    GLint maxLog2 = 0, maxLevels = 0;
  233.  
  234.    t->Complete = GL_TRUE;  /* be optimistic */
  235.  
  236.    /* Always need the base level image */
  237.    if (!t->Image[baseLevel]) {
  238.       incomplete(t, "Image[baseLevel] == NULL");
  239.       t->Complete = GL_FALSE;
  240.       return;
  241.    }
  242.  
  243.    /* Compute _MaxLevel */
  244.    if (t->Target == GL_TEXTURE_1D) {
  245.       maxLog2 = t->Image[baseLevel]->WidthLog2;
  246.       maxLevels = ctx->Const.MaxTextureLevels;
  247.    }
  248.    else if (t->Target == GL_TEXTURE_2D) {
  249.       maxLog2 = MAX2(t->Image[baseLevel]->WidthLog2,
  250.                      t->Image[baseLevel]->HeightLog2);
  251.       maxLevels = ctx->Const.MaxTextureLevels;
  252.    }
  253.    else if (t->Target == GL_TEXTURE_3D) {
  254.       GLint max = MAX2(t->Image[baseLevel]->WidthLog2,
  255.                        t->Image[baseLevel]->HeightLog2);
  256.       maxLog2 = MAX2(max, (GLint)(t->Image[baseLevel]->DepthLog2));
  257.       maxLevels = ctx->Const.Max3DTextureLevels;
  258.    }
  259.    else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
  260.       maxLog2 = MAX2(t->Image[baseLevel]->WidthLog2,
  261.                      t->Image[baseLevel]->HeightLog2);
  262.       maxLevels = ctx->Const.MaxCubeTextureLevels;
  263.    }
  264.    else if (t->Target == GL_TEXTURE_RECTANGLE_NV) {
  265.       maxLog2 = 0;  /* not applicable */
  266.       maxLevels = 1;  /* no mipmapping */
  267.    }
  268.    else {
  269.       _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness");
  270.       return;
  271.    }
  272.  
  273.    ASSERT(maxLevels > 0);
  274.  
  275.    t->_MaxLevel = baseLevel + maxLog2;
  276.    t->_MaxLevel = MIN2(t->_MaxLevel, t->MaxLevel);
  277.    t->_MaxLevel = MIN2(t->_MaxLevel, maxLevels - 1);
  278.  
  279.    /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */
  280.    t->_MaxLambda = (GLfloat) (t->_MaxLevel - t->BaseLevel);
  281.  
  282.    if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
  283.       /* make sure that all six cube map level 0 images are the same size */
  284.       const GLuint w = t->Image[baseLevel]->Width2;
  285.       const GLuint h = t->Image[baseLevel]->Height2;
  286.       if (!t->NegX[baseLevel] ||
  287.           t->NegX[baseLevel]->Width2 != w ||
  288.           t->NegX[baseLevel]->Height2 != h ||
  289.           !t->PosY[baseLevel] ||
  290.           t->PosY[baseLevel]->Width2 != w ||
  291.           t->PosY[baseLevel]->Height2 != h ||
  292.           !t->NegY[baseLevel] ||
  293.           t->NegY[baseLevel]->Width2 != w ||
  294.           t->NegY[baseLevel]->Height2 != h ||
  295.           !t->PosZ[baseLevel] ||
  296.           t->PosZ[baseLevel]->Width2 != w ||
  297.           t->PosZ[baseLevel]->Height2 != h ||
  298.           !t->NegZ[baseLevel] ||
  299.           t->NegZ[baseLevel]->Width2 != w ||
  300.           t->NegZ[baseLevel]->Height2 != h) {
  301.          t->Complete = GL_FALSE;
  302.          incomplete(t, "Non-quare cubemap image");
  303.          return;
  304.       }
  305.    }
  306.  
  307.    if (t->MinFilter != GL_NEAREST && t->MinFilter != GL_LINEAR) {
  308.       /*
  309.        * Mipmapping: determine if we have a complete set of mipmaps
  310.        */
  311.       GLint i;
  312.       GLint minLevel = baseLevel;
  313.       GLint maxLevel = t->_MaxLevel;
  314.  
  315.       if (minLevel > maxLevel) {
  316.          t->Complete = GL_FALSE;
  317.          incomplete(t, "minLevel > maxLevel");
  318.          return;
  319.       }
  320.  
  321.       /* Test dimension-independent attributes */
  322.       for (i = minLevel; i <= maxLevel; i++) {
  323.          if (t->Image[i]) {
  324.             if (t->Image[i]->TexFormat != t->Image[baseLevel]->TexFormat) {
  325.                t->Complete = GL_FALSE;
  326.                incomplete(t, "Format[i] != Format[baseLevel]");
  327.                return;
  328.             }
  329.             if (t->Image[i]->Border != t->Image[baseLevel]->Border) {
  330.                t->Complete = GL_FALSE;
  331.                incomplete(t, "Border[i] != Border[baseLevel]");
  332.                return;
  333.             }
  334.          }
  335.       }
  336.  
  337.       /* Test things which depend on number of texture image dimensions */
  338.       if (t->Target == GL_TEXTURE_1D) {
  339.          /* Test 1-D mipmaps */
  340.          GLuint width = t->Image[baseLevel]->Width2;
  341.          for (i = baseLevel + 1; i < maxLevels; i++) {
  342.             if (width > 1) {
  343.                width /= 2;
  344.             }
  345.             if (i >= minLevel && i <= maxLevel) {
  346.                if (!t->Image[i]) {
  347.                   t->Complete = GL_FALSE;
  348.                   incomplete(t, "1D Image[i] == NULL");
  349.                   return;
  350.                }
  351.                if (t->Image[i]->Width2 != width ) {
  352.                   t->Complete = GL_FALSE;
  353.                   incomplete(t, "1D Image[i] bad width");
  354.                   return;
  355.                }
  356.             }
  357.             if (width == 1) {
  358.                return;  /* found smallest needed mipmap, all done! */
  359.             }
  360.          }
  361.       }
  362.       else if (t->Target == GL_TEXTURE_2D) {
  363.          /* Test 2-D mipmaps */
  364.          GLuint width = t->Image[baseLevel]->Width2;
  365.          GLuint height = t->Image[baseLevel]->Height2;
  366.          for (i = baseLevel + 1; i < maxLevels; i++) {
  367.             if (width > 1) {
  368.                width /= 2;
  369.             }
  370.             if (height > 1) {
  371.                height /= 2;
  372.             }
  373.             if (i >= minLevel && i <= maxLevel) {
  374.                if (!t->Image[i]) {
  375.                   t->Complete = GL_FALSE;
  376.                   incomplete(t, "2D Image[i] == NULL");
  377.                   return;
  378.                }
  379.                if (t->Image[i]->Width2 != width) {
  380.                   t->Complete = GL_FALSE;
  381.                   incomplete(t, "2D Image[i] bad width");
  382.                   return;
  383.                }
  384.                if (t->Image[i]->Height2 != height) {
  385.                   t->Complete = GL_FALSE;
  386.                   incomplete(t, "2D Image[i] bad height");
  387.                   return;
  388.                }
  389.                if (width==1 && height==1) {
  390.                   return;  /* found smallest needed mipmap, all done! */
  391.                }
  392.             }
  393.          }
  394.       }
  395.       else if (t->Target == GL_TEXTURE_3D) {
  396.          /* Test 3-D mipmaps */
  397.          GLuint width = t->Image[baseLevel]->Width2;
  398.          GLuint height = t->Image[baseLevel]->Height2;
  399.          GLuint depth = t->Image[baseLevel]->Depth2;
  400.      for (i = baseLevel + 1; i < maxLevels; i++) {
  401.             if (width > 1) {
  402.                width /= 2;
  403.             }
  404.             if (height > 1) {
  405.                height /= 2;
  406.             }
  407.             if (depth > 1) {
  408.                depth /= 2;
  409.             }
  410.             if (i >= minLevel && i <= maxLevel) {
  411.                if (!t->Image[i]) {
  412.                   incomplete(t, "3D Image[i] == NULL");
  413.                   t->Complete = GL_FALSE;
  414.                   return;
  415.                }
  416.                if (t->Image[i]->Format == GL_DEPTH_COMPONENT) {
  417.                   t->Complete = GL_FALSE;
  418.                   incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex");
  419.                   return;
  420.                }
  421.                if (t->Image[i]->Width2 != width) {
  422.                   t->Complete = GL_FALSE;
  423.                   incomplete(t, "3D Image[i] bad width");
  424.                   return;
  425.                }
  426.                if (t->Image[i]->Height2 != height) {
  427.                   t->Complete = GL_FALSE;
  428.                   incomplete(t, "3D Image[i] bad height");
  429.                   return;
  430.                }
  431.                if (t->Image[i]->Depth2 != depth) {
  432.                   t->Complete = GL_FALSE;
  433.                   incomplete(t, "3D Image[i] bad depth");
  434.                   return;
  435.                }
  436.             }
  437.             if (width == 1 && height == 1 && depth == 1) {
  438.                return;  /* found smallest needed mipmap, all done! */
  439.             }
  440.          }
  441.       }
  442.       else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
  443.          /* make sure 6 cube faces are consistant */
  444.          GLuint width = t->Image[baseLevel]->Width2;
  445.          GLuint height = t->Image[baseLevel]->Height2;
  446.      for (i = baseLevel + 1; i < maxLevels; i++) {
  447.             if (width > 1) {
  448.                width /= 2;
  449.             }
  450.             if (height > 1) {
  451.                height /= 2;
  452.             }
  453.             if (i >= minLevel && i <= maxLevel) {
  454.                /* Don't support GL_DEPTH_COMPONENT for cube maps */
  455.                if (t->Image[i]->Format == GL_DEPTH_COMPONENT) {
  456.                   t->Complete = GL_FALSE;
  457.                   incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex");
  458.                   return;
  459.                }
  460.                /* check that we have images defined */
  461.                if (!t->Image[i] || !t->NegX[i] ||
  462.                    !t->PosY[i]  || !t->NegY[i] ||
  463.                    !t->PosZ[i]  || !t->NegZ[i]) {
  464.                   t->Complete = GL_FALSE;
  465.                   incomplete(t, "CubeMap Image[i] == NULL");
  466.                   return;
  467.                }
  468.                /* check that all six images have same size */
  469.                if (t->NegX[i]->Width2!=width || t->NegX[i]->Height2!=height ||
  470.                    t->PosY[i]->Width2!=width || t->PosY[i]->Height2!=height ||
  471.                    t->NegY[i]->Width2!=width || t->NegY[i]->Height2!=height ||
  472.                    t->PosZ[i]->Width2!=width || t->PosZ[i]->Height2!=height ||
  473.                    t->NegZ[i]->Width2!=width || t->NegZ[i]->Height2!=height) {
  474.                   t->Complete = GL_FALSE;
  475.                   incomplete(t, "CubeMap Image[i] bad size");
  476.                   return;
  477.                }
  478.             }
  479.             if (width == 1 && height == 1) {
  480.                return;  /* found smallest needed mipmap, all done! */
  481.             }
  482.          }
  483.       }
  484.       else if (t->Target == GL_TEXTURE_RECTANGLE_NV) {
  485.          /* XXX special checking? */
  486.  
  487.       }
  488.       else {
  489.          /* Target = ??? */
  490.          _mesa_problem(ctx, "Bug in gl_test_texture_object_completeness\n");
  491.       }
  492.    }
  493. }
  494.  
  495.  
  496. _glthread_DECLARE_STATIC_MUTEX(GenTexturesLock);
  497.  
  498.  
  499. /*
  500.  * Execute glGenTextures
  501.  */
  502. void
  503. _mesa_GenTextures( GLsizei n, GLuint *texName )
  504. {
  505.    GET_CURRENT_CONTEXT(ctx);
  506.    GLuint first;
  507.    GLint i;
  508.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  509.  
  510.    if (n < 0) {
  511.       _mesa_error( ctx, GL_INVALID_VALUE, "glGenTextures" );
  512.       return;
  513.    }
  514.  
  515.    if (!texName)
  516.       return;
  517.  
  518.    /*
  519.     * This must be atomic (generation and allocation of texture IDs)
  520.     */
  521.    _glthread_LOCK_MUTEX(GenTexturesLock);
  522.  
  523.    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
  524.  
  525.    /* Return the texture names */
  526.    for (i=0;i<n;i++) {
  527.       texName[i] = first + i;
  528.    }
  529.  
  530.    /* Allocate new, empty texture objects */
  531.    for (i=0;i<n;i++) {
  532.       GLuint name = first + i;
  533.       GLenum target = 0;
  534.       (void) _mesa_alloc_texture_object( ctx->Shared, name, target);
  535.    }
  536.  
  537.    _glthread_UNLOCK_MUTEX(GenTexturesLock);
  538. }
  539.  
  540.  
  541.  
  542. /*
  543.  * Execute glDeleteTextures
  544.  */
  545. void
  546. _mesa_DeleteTextures( GLsizei n, const GLuint *texName)
  547. {
  548.    GET_CURRENT_CONTEXT(ctx);
  549.    GLint i;
  550.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */
  551.  
  552.    if (!texName)
  553.       return;
  554.  
  555.    for (i=0;i<n;i++) {
  556.       if (texName[i] > 0) {
  557.          struct gl_texture_object *delObj = (struct gl_texture_object *)
  558.             _mesa_HashLookup(ctx->Shared->TexObjects, texName[i]);
  559.          if (delObj) {
  560.             /* First check if this texture is currently bound.
  561.              * If so, unbind it and decrement the reference count.
  562.              */
  563.             GLuint u;
  564.             for (u = 0; u < MAX_TEXTURE_UNITS; u++) {
  565.                struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
  566.                if (delObj == unit->Current1D) {
  567.                   unit->Current1D = ctx->Shared->Default1D;
  568.                   ctx->Shared->Default1D->RefCount++;
  569.                   delObj->RefCount--;
  570.                   if (delObj == unit->_Current)
  571.                      unit->_Current = unit->Current1D;
  572.                }
  573.                else if (delObj == unit->Current2D) {
  574.                   unit->Current2D = ctx->Shared->Default2D;
  575.                   ctx->Shared->Default2D->RefCount++;
  576.                   delObj->RefCount--;
  577.                   if (delObj == unit->_Current)
  578.                      unit->_Current = unit->Current2D;
  579.                }
  580.                else if (delObj == unit->Current3D) {
  581.                   unit->Current3D = ctx->Shared->Default3D;
  582.                   ctx->Shared->Default3D->RefCount++;
  583.                   delObj->RefCount--;
  584.                   if (delObj == unit->_Current)
  585.                      unit->_Current = unit->Current3D;
  586.                }
  587.                else if (delObj == unit->CurrentCubeMap) {
  588.                   unit->CurrentCubeMap = ctx->Shared->DefaultCubeMap;
  589.                   ctx->Shared->DefaultCubeMap->RefCount++;
  590.                   delObj->RefCount--;
  591.                   if (delObj == unit->_Current)
  592.                      unit->_Current = unit->CurrentCubeMap;
  593.                }
  594.                else if (delObj == unit->CurrentRect) {
  595.                   unit->CurrentRect = ctx->Shared->DefaultRect;
  596.                   ctx->Shared->DefaultRect->RefCount++;
  597.                   delObj->RefCount--;
  598.                   if (delObj == unit->_Current)
  599.                      unit->_Current = unit->CurrentRect;
  600.                }
  601.             }
  602.             ctx->NewState |= _NEW_TEXTURE;
  603.  
  604.             /* Decrement reference count and delete if zero */
  605.             delObj->RefCount--;
  606.             ASSERT(delObj->RefCount >= 0);
  607.  
  608.             if (delObj->RefCount == 0) {
  609.                ASSERT(delObj->Name != 0);
  610.                if (ctx->Driver.DeleteTexture)
  611.                   (*ctx->Driver.DeleteTexture)( ctx, delObj );
  612.                _mesa_free_texture_object(ctx->Shared, delObj);
  613.             }
  614.          }
  615.       }
  616.    }
  617. }
  618.  
  619.  
  620.  
  621. /*
  622.  * Execute glBindTexture
  623.  */
  624. void
  625. _mesa_BindTexture( GLenum target, GLuint texName )
  626. {
  627.    GET_CURRENT_CONTEXT(ctx);
  628.    GLuint unit = ctx->Texture.CurrentUnit;
  629.    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
  630.    struct gl_texture_object *oldTexObj;
  631.    struct gl_texture_object *newTexObj = 0;
  632.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  633.  
  634.    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
  635.       _mesa_debug(ctx, "glBindTexture %s %d\n",
  636.                   _mesa_lookup_enum_by_nr(target), (GLint) texName);
  637.  
  638.    switch (target) {
  639.       case GL_TEXTURE_1D:
  640.          oldTexObj = texUnit->Current1D;
  641.          break;
  642.       case GL_TEXTURE_2D:
  643.          oldTexObj = texUnit->Current2D;
  644.          break;
  645.       case GL_TEXTURE_3D:
  646.          oldTexObj = texUnit->Current3D;
  647.          break;
  648.       case GL_TEXTURE_CUBE_MAP_ARB:
  649.          if (!ctx->Extensions.ARB_texture_cube_map) {
  650.             _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
  651.             return;
  652.          }
  653.          oldTexObj = texUnit->CurrentCubeMap;
  654.          break;
  655.       case GL_TEXTURE_RECTANGLE_NV:
  656.          if (!ctx->Extensions.NV_texture_rectangle) {
  657.             _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
  658.             return;
  659.          }
  660.          oldTexObj = texUnit->CurrentRect;
  661.          break;
  662.       default:
  663.          _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
  664.          return;
  665.    }
  666.  
  667.    if (oldTexObj->Name == texName)
  668.       return;   /* rebinding the same texture- no change */
  669.  
  670.    /*
  671.     * Get pointer to new texture object (newTexObj)
  672.     */
  673.    if (texName == 0) {
  674.       /* newTexObj = a default texture object */
  675.       switch (target) {
  676.          case GL_TEXTURE_1D:
  677.             newTexObj = ctx->Shared->Default1D;
  678.             break;
  679.          case GL_TEXTURE_2D:
  680.             newTexObj = ctx->Shared->Default2D;
  681.             break;
  682.          case GL_TEXTURE_3D:
  683.             newTexObj = ctx->Shared->Default3D;
  684.             break;
  685.          case GL_TEXTURE_CUBE_MAP_ARB:
  686.             newTexObj = ctx->Shared->DefaultCubeMap;
  687.             break;
  688.          case GL_TEXTURE_RECTANGLE_NV:
  689.             newTexObj = ctx->Shared->DefaultRect;
  690.             break;
  691.          default:
  692.             ; /* Bad targets are caught above */
  693.       }
  694.    }
  695.    else {
  696.       /* non-default texture object */
  697.       const struct _mesa_HashTable *hash = ctx->Shared->TexObjects;
  698.       newTexObj = (struct gl_texture_object *) _mesa_HashLookup(hash, texName);
  699.       if (newTexObj) {
  700.          /* error checking */
  701.          if (newTexObj->Target != 0 && newTexObj->Target != target) {
  702.             /* the named texture object's dimensions don't match the target */
  703.             _mesa_error( ctx, GL_INVALID_OPERATION,
  704.                          "glBindTexture(wrong dimensionality)" );
  705.             return;
  706.          }
  707.          if (newTexObj->Target == 0 && target == GL_TEXTURE_RECTANGLE_NV) {
  708.             /* have to init wrap and filter state here - kind of klunky */
  709.             newTexObj->WrapS = GL_CLAMP_TO_EDGE;
  710.             newTexObj->WrapT = GL_CLAMP_TO_EDGE;
  711.             newTexObj->WrapR = GL_CLAMP_TO_EDGE;
  712.             newTexObj->MinFilter = GL_LINEAR;
  713.          }
  714.       }
  715.       else {
  716.          /* if this is a new texture id, allocate a texture object now */
  717.      newTexObj = _mesa_alloc_texture_object( ctx->Shared, texName,
  718.                          target);
  719.          if (!newTexObj) {
  720.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
  721.             return;
  722.          }
  723.       }
  724.       newTexObj->Target = target;
  725.    }
  726.  
  727.    newTexObj->RefCount++;
  728.  
  729.    /* do the actual binding, but first flush outstanding vertices:
  730.     */
  731.    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
  732.  
  733.    switch (target) {
  734.       case GL_TEXTURE_1D:
  735.          texUnit->Current1D = newTexObj;
  736.          break;
  737.       case GL_TEXTURE_2D:
  738.          texUnit->Current2D = newTexObj;
  739.          break;
  740.       case GL_TEXTURE_3D:
  741.          texUnit->Current3D = newTexObj;
  742.          break;
  743.       case GL_TEXTURE_CUBE_MAP_ARB:
  744.          texUnit->CurrentCubeMap = newTexObj;
  745.          break;
  746.       case GL_TEXTURE_RECTANGLE_NV:
  747.          texUnit->CurrentRect = newTexObj;
  748.          break;
  749.       default:
  750.          _mesa_problem(ctx, "bad target in BindTexture");
  751.          return;
  752.    }
  753.  
  754.    /* Pass BindTexture call to device driver */
  755.    if (ctx->Driver.BindTexture)
  756.       (*ctx->Driver.BindTexture)( ctx, target, newTexObj );
  757.  
  758.    oldTexObj->RefCount--;
  759.    assert(oldTexObj->RefCount >= 0);
  760.    if (oldTexObj->RefCount == 0) {
  761.       assert(oldTexObj->Name != 0);
  762.       if (ctx->Driver.DeleteTexture) {
  763.          (*ctx->Driver.DeleteTexture)( ctx, oldTexObj );
  764.       }
  765.       _mesa_free_texture_object(ctx->Shared, oldTexObj);
  766.    }
  767. }
  768.  
  769.  
  770.  
  771. /*
  772.  * Execute glPrioritizeTextures
  773.  */
  774. void
  775. _mesa_PrioritizeTextures( GLsizei n, const GLuint *texName,
  776.                           const GLclampf *priorities )
  777. {
  778.    GET_CURRENT_CONTEXT(ctx);
  779.    GLint i;
  780.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  781.  
  782.    if (n < 0) {
  783.       _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
  784.       return;
  785.    }
  786.  
  787.    if (!priorities)
  788.       return;
  789.  
  790.    for (i = 0; i < n; i++) {
  791.       if (texName[i] > 0) {
  792.          struct gl_texture_object *t = (struct gl_texture_object *)
  793.             _mesa_HashLookup(ctx->Shared->TexObjects, texName[i]);
  794.          if (t) {
  795.             t->Priority = CLAMP( priorities[i], 0.0F, 1.0F );
  796.         if (ctx->Driver.PrioritizeTexture)
  797.            ctx->Driver.PrioritizeTexture( ctx, t, t->Priority );
  798.          }
  799.       }
  800.    }
  801.  
  802.    ctx->NewState |= _NEW_TEXTURE;
  803. }
  804.  
  805.  
  806.  
  807. /*
  808.  * Execute glAreTexturesResident
  809.  */
  810. GLboolean
  811. _mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
  812.                           GLboolean *residences)
  813. {
  814.    GET_CURRENT_CONTEXT(ctx);
  815.    GLboolean allResident = GL_TRUE;
  816.    GLint i;
  817.    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
  818.  
  819.    if (n < 0) {
  820.       _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
  821.       return GL_FALSE;
  822.    }
  823.  
  824.    if (!texName || !residences)
  825.       return GL_FALSE;
  826.  
  827.    for (i = 0; i < n; i++) {
  828.       struct gl_texture_object *t;
  829.       if (texName[i] == 0) {
  830.          _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)");
  831.          return GL_FALSE;
  832.       }
  833.       t = (struct gl_texture_object *)
  834.          _mesa_HashLookup(ctx->Shared->TexObjects, texName[i]);
  835.       if (t) {
  836.      if (ctx->Driver.IsTextureResident) {
  837.         residences[i] = ctx->Driver.IsTextureResident(ctx, t);
  838.             if (!residences[i])
  839.                allResident = GL_FALSE;
  840.          }
  841.      else {
  842.         residences[i] = GL_TRUE;
  843.          }
  844.       }
  845.       else {
  846.          _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)");
  847.          return GL_FALSE;
  848.       }
  849.    }
  850.    return allResident;
  851. }
  852.  
  853.  
  854.  
  855. /*
  856.  * Execute glIsTexture
  857.  */
  858. GLboolean
  859. _mesa_IsTexture( GLuint texture )
  860. {
  861.    GET_CURRENT_CONTEXT(ctx);
  862.    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
  863.    return texture > 0 && _mesa_HashLookup(ctx->Shared->TexObjects, texture);
  864. }
  865.