Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /**
  2.  * \file texobj.c
  3.  * Texture object management.
  4.  */
  5.  
  6. /*
  7.  * Mesa 3-D graphics library
  8.  * Version:  7.1
  9.  *
  10.  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  11.  *
  12.  * Permission is hereby granted, free of charge, to any person obtaining a
  13.  * copy of this software and associated documentation files (the "Software"),
  14.  * to deal in the Software without restriction, including without limitation
  15.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  16.  * and/or sell copies of the Software, and to permit persons to whom the
  17.  * Software is furnished to do so, subject to the following conditions:
  18.  *
  19.  * The above copyright notice and this permission notice shall be included
  20.  * in all copies or substantial portions of the Software.
  21.  *
  22.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  23.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  25.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  26.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  27.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28.  */
  29.  
  30.  
  31. #include "mfeatures.h"
  32. #include "colortab.h"
  33. #include "context.h"
  34. #include "enums.h"
  35. #include "fbobject.h"
  36. #include "formats.h"
  37. #include "hash.h"
  38. #include "imports.h"
  39. #include "macros.h"
  40. #include "teximage.h"
  41. #include "texobj.h"
  42. #include "mtypes.h"
  43. #include "program/prog_instruction.h"
  44.  
  45.  
  46.  
  47. /**********************************************************************/
  48. /** \name Internal functions */
  49. /*@{*/
  50.  
  51.  
  52. /**
  53.  * Return the gl_texture_object for a given ID.
  54.  */
  55. struct gl_texture_object *
  56. _mesa_lookup_texture(struct gl_context *ctx, GLuint id)
  57. {
  58.    return (struct gl_texture_object *)
  59.       _mesa_HashLookup(ctx->Shared->TexObjects, id);
  60. }
  61.  
  62.  
  63.  
  64. /**
  65.  * Allocate and initialize a new texture object.  But don't put it into the
  66.  * texture object hash table.
  67.  *
  68.  * Called via ctx->Driver.NewTextureObject, unless overridden by a device
  69.  * driver.
  70.  *
  71.  * \param shared the shared GL state structure to contain the texture object
  72.  * \param name integer name for the texture object
  73.  * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D,
  74.  * GL_TEXTURE_CUBE_MAP_ARB or GL_TEXTURE_RECTANGLE_NV.  zero is ok for the sake
  75.  * of GenTextures()
  76.  *
  77.  * \return pointer to new texture object.
  78.  */
  79. struct gl_texture_object *
  80. _mesa_new_texture_object( struct gl_context *ctx, GLuint name, GLenum target )
  81. {
  82.    struct gl_texture_object *obj;
  83.    (void) ctx;
  84.    obj = MALLOC_STRUCT(gl_texture_object);
  85.    _mesa_initialize_texture_object(obj, name, target);
  86.    return obj;
  87. }
  88.  
  89.  
  90. /**
  91.  * Initialize a new texture object to default values.
  92.  * \param obj  the texture object
  93.  * \param name  the texture name
  94.  * \param target  the texture target
  95.  */
  96. void
  97. _mesa_initialize_texture_object( struct gl_texture_object *obj,
  98.                                  GLuint name, GLenum target )
  99. {
  100.    ASSERT(target == 0 ||
  101.           target == GL_TEXTURE_1D ||
  102.           target == GL_TEXTURE_2D ||
  103.           target == GL_TEXTURE_3D ||
  104.           target == GL_TEXTURE_CUBE_MAP_ARB ||
  105.           target == GL_TEXTURE_RECTANGLE_NV ||
  106.           target == GL_TEXTURE_1D_ARRAY_EXT ||
  107.           target == GL_TEXTURE_2D_ARRAY_EXT);
  108.  
  109.    memset(obj, 0, sizeof(*obj));
  110.    /* init the non-zero fields */
  111.    _glthread_INIT_MUTEX(obj->Mutex);
  112.    obj->RefCount = 1;
  113.    obj->Name = name;
  114.    obj->Target = target;
  115.    obj->Priority = 1.0F;
  116.    if (target == GL_TEXTURE_RECTANGLE_NV) {
  117.       obj->WrapS = GL_CLAMP_TO_EDGE;
  118.       obj->WrapT = GL_CLAMP_TO_EDGE;
  119.       obj->WrapR = GL_CLAMP_TO_EDGE;
  120.       obj->MinFilter = GL_LINEAR;
  121.    }
  122.    else {
  123.       obj->WrapS = GL_REPEAT;
  124.       obj->WrapT = GL_REPEAT;
  125.       obj->WrapR = GL_REPEAT;
  126.       obj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
  127.    }
  128.    obj->MagFilter = GL_LINEAR;
  129.    obj->MinLod = -1000.0;
  130.    obj->MaxLod = 1000.0;
  131.    obj->LodBias = 0.0;
  132.    obj->BaseLevel = 0;
  133.    obj->MaxLevel = 1000;
  134.    obj->MaxAnisotropy = 1.0;
  135.    obj->CompareMode = GL_NONE;         /* ARB_shadow */
  136.    obj->CompareFunc = GL_LEQUAL;       /* ARB_shadow */
  137.    obj->CompareFailValue = 0.0F;       /* ARB_shadow_ambient */
  138.    obj->DepthMode = GL_LUMINANCE;      /* ARB_depth_texture */
  139.    obj->Swizzle[0] = GL_RED;
  140.    obj->Swizzle[1] = GL_GREEN;
  141.    obj->Swizzle[2] = GL_BLUE;
  142.    obj->Swizzle[3] = GL_ALPHA;
  143.    obj->_Swizzle = SWIZZLE_NOOP;
  144. }
  145.  
  146.  
  147. /**
  148.  * Some texture initialization can't be finished until we know which
  149.  * target it's getting bound to (GL_TEXTURE_1D/2D/etc).
  150.  */
  151. static void
  152. finish_texture_init(struct gl_context *ctx, GLenum target,
  153.                     struct gl_texture_object *obj)
  154. {
  155.    assert(obj->Target == 0);
  156.  
  157.    if (target == GL_TEXTURE_RECTANGLE_NV) {
  158.       /* have to init wrap and filter state here - kind of klunky */
  159.       obj->WrapS = GL_CLAMP_TO_EDGE;
  160.       obj->WrapT = GL_CLAMP_TO_EDGE;
  161.       obj->WrapR = GL_CLAMP_TO_EDGE;
  162.       obj->MinFilter = GL_LINEAR;
  163.       if (ctx->Driver.TexParameter) {
  164.          static const GLfloat fparam_wrap[1] = {(GLfloat) GL_CLAMP_TO_EDGE};
  165.          static const GLfloat fparam_filter[1] = {(GLfloat) GL_LINEAR};
  166.          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_S, fparam_wrap);
  167.          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_T, fparam_wrap);
  168.          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_R, fparam_wrap);
  169.          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_MIN_FILTER, fparam_filter);
  170.       }
  171.    }
  172. }
  173.  
  174.  
  175. /**
  176.  * Deallocate a texture object struct.  It should have already been
  177.  * removed from the texture object pool.
  178.  * Called via ctx->Driver.DeleteTexture() if not overriden by a driver.
  179.  *
  180.  * \param shared the shared GL state to which the object belongs.
  181.  * \param texObj the texture object to delete.
  182.  */
  183. void
  184. _mesa_delete_texture_object(struct gl_context *ctx,
  185.                             struct gl_texture_object *texObj)
  186. {
  187.    GLuint i, face;
  188.  
  189.    /* Set Target to an invalid value.  With some assertions elsewhere
  190.     * we can try to detect possible use of deleted textures.
  191.     */
  192.    texObj->Target = 0x99;
  193.  
  194.    _mesa_free_colortable_data(&texObj->Palette);
  195.  
  196.    /* free the texture images */
  197.    for (face = 0; face < 6; face++) {
  198.       for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
  199.          if (texObj->Image[face][i]) {
  200.             _mesa_delete_texture_image( ctx, texObj->Image[face][i] );
  201.          }
  202.       }
  203.    }
  204.  
  205.    /* destroy the mutex -- it may have allocated memory (eg on bsd) */
  206.    _glthread_DESTROY_MUTEX(texObj->Mutex);
  207.  
  208.    /* free this object */
  209.    free(texObj);
  210. }
  211.  
  212.  
  213.  
  214. /**
  215.  * Copy texture object state from one texture object to another.
  216.  * Use for glPush/PopAttrib.
  217.  *
  218.  * \param dest destination texture object.
  219.  * \param src source texture object.
  220.  */
  221. void
  222. _mesa_copy_texture_object( struct gl_texture_object *dest,
  223.                            const struct gl_texture_object *src )
  224. {
  225.    dest->Target = src->Target;
  226.    dest->Name = src->Name;
  227.    dest->Priority = src->Priority;
  228.    dest->BorderColor.f[0] = src->BorderColor.f[0];
  229.    dest->BorderColor.f[1] = src->BorderColor.f[1];
  230.    dest->BorderColor.f[2] = src->BorderColor.f[2];
  231.    dest->BorderColor.f[3] = src->BorderColor.f[3];
  232.    dest->WrapS = src->WrapS;
  233.    dest->WrapT = src->WrapT;
  234.    dest->WrapR = src->WrapR;
  235.    dest->MinFilter = src->MinFilter;
  236.    dest->MagFilter = src->MagFilter;
  237.    dest->MinLod = src->MinLod;
  238.    dest->MaxLod = src->MaxLod;
  239.    dest->LodBias = src->LodBias;
  240.    dest->BaseLevel = src->BaseLevel;
  241.    dest->MaxLevel = src->MaxLevel;
  242.    dest->MaxAnisotropy = src->MaxAnisotropy;
  243.    dest->CompareMode = src->CompareMode;
  244.    dest->CompareFunc = src->CompareFunc;
  245.    dest->CompareFailValue = src->CompareFailValue;
  246.    dest->DepthMode = src->DepthMode;
  247.    dest->_MaxLevel = src->_MaxLevel;
  248.    dest->_MaxLambda = src->_MaxLambda;
  249.    dest->GenerateMipmap = src->GenerateMipmap;
  250.    dest->Palette = src->Palette;
  251.    dest->_Complete = src->_Complete;
  252.    COPY_4V(dest->Swizzle, src->Swizzle);
  253.    dest->_Swizzle = src->_Swizzle;
  254. }
  255.  
  256.  
  257. /**
  258.  * Free all texture images of the given texture object.
  259.  *
  260.  * \param ctx GL context.
  261.  * \param t texture object.
  262.  *
  263.  * \sa _mesa_clear_texture_image().
  264.  */
  265. void
  266. _mesa_clear_texture_object(struct gl_context *ctx,
  267.                            struct gl_texture_object *texObj)
  268. {
  269.    GLuint i, j;
  270.  
  271.    if (texObj->Target == 0)
  272.       return;
  273.  
  274.    for (i = 0; i < MAX_FACES; i++) {
  275.       for (j = 0; j < MAX_TEXTURE_LEVELS; j++) {
  276.          struct gl_texture_image *texImage = texObj->Image[i][j];
  277.          if (texImage)
  278.             _mesa_clear_texture_image(ctx, texImage);
  279.       }
  280.    }
  281. }
  282.  
  283.  
  284. /**
  285.  * Check if the given texture object is valid by examining its Target field.
  286.  * For debugging only.
  287.  */
  288. static GLboolean
  289. valid_texture_object(const struct gl_texture_object *tex)
  290. {
  291.    switch (tex->Target) {
  292.    case 0:
  293.    case GL_TEXTURE_1D:
  294.    case GL_TEXTURE_2D:
  295.    case GL_TEXTURE_3D:
  296.    case GL_TEXTURE_CUBE_MAP_ARB:
  297.    case GL_TEXTURE_RECTANGLE_NV:
  298.    case GL_TEXTURE_1D_ARRAY_EXT:
  299.    case GL_TEXTURE_2D_ARRAY_EXT:
  300.       return GL_TRUE;
  301.    case 0x99:
  302.       _mesa_problem(NULL, "invalid reference to a deleted texture object");
  303.       return GL_FALSE;
  304.    default:
  305.       _mesa_problem(NULL, "invalid texture object Target 0x%x, Id = %u",
  306.                     tex->Target, tex->Name);
  307.       return GL_FALSE;
  308.    }
  309. }
  310.  
  311.  
  312. /**
  313.  * Reference (or unreference) a texture object.
  314.  * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero).
  315.  * If 'tex' is non-null, increment its refcount.
  316.  */
  317. void
  318. _mesa_reference_texobj(struct gl_texture_object **ptr,
  319.                        struct gl_texture_object *tex)
  320. {
  321.    assert(ptr);
  322.    if (*ptr == tex) {
  323.       /* no change */
  324.       return;
  325.    }
  326.  
  327.    if (*ptr) {
  328.       /* Unreference the old texture */
  329.       GLboolean deleteFlag = GL_FALSE;
  330.       struct gl_texture_object *oldTex = *ptr;
  331.  
  332.       ASSERT(valid_texture_object(oldTex));
  333.       (void) valid_texture_object; /* silence warning in release builds */
  334.  
  335.       _glthread_LOCK_MUTEX(oldTex->Mutex);
  336.       ASSERT(oldTex->RefCount > 0);
  337.       oldTex->RefCount--;
  338.  
  339.       deleteFlag = (oldTex->RefCount == 0);
  340.       _glthread_UNLOCK_MUTEX(oldTex->Mutex);
  341.  
  342.       if (deleteFlag) {
  343.          GET_CURRENT_CONTEXT(ctx);
  344.          if (ctx)
  345.             ctx->Driver.DeleteTexture(ctx, oldTex);
  346.          else
  347.             _mesa_problem(NULL, "Unable to delete texture, no context");
  348.       }
  349.  
  350.       *ptr = NULL;
  351.    }
  352.    assert(!*ptr);
  353.  
  354.    if (tex) {
  355.       /* reference new texture */
  356.       ASSERT(valid_texture_object(tex));
  357.       _glthread_LOCK_MUTEX(tex->Mutex);
  358.       if (tex->RefCount == 0) {
  359.          /* this texture's being deleted (look just above) */
  360.          /* Not sure this can every really happen.  Warn if it does. */
  361.          _mesa_problem(NULL, "referencing deleted texture object");
  362.          *ptr = NULL;
  363.       }
  364.       else {
  365.          tex->RefCount++;
  366.          *ptr = tex;
  367.       }
  368.       _glthread_UNLOCK_MUTEX(tex->Mutex);
  369.    }
  370. }
  371.  
  372.  
  373.  
  374. /**
  375.  * Mark a texture object as incomplete.
  376.  * \param t  texture object
  377.  * \param fmt...  string describing why it's incomplete (for debugging).
  378.  */
  379. static void
  380. incomplete(struct gl_texture_object *t, const char *fmt, ...)
  381. {
  382. #if 0
  383.    va_list args;
  384.    char s[100];
  385.  
  386.    va_start(args, fmt);
  387.    vsnprintf(s, sizeof(s), fmt, args);
  388.    va_end(args);
  389.  
  390.    printf("Texture Obj %d incomplete because: %s\n", t->Name, s);
  391. #endif
  392.    t->_Complete = GL_FALSE;
  393. }
  394.  
  395.  
  396. /**
  397.  * Examine a texture object to determine if it is complete.
  398.  *
  399.  * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE
  400.  * accordingly.
  401.  *
  402.  * \param ctx GL context.
  403.  * \param t texture object.
  404.  *
  405.  * According to the texture target, verifies that each of the mipmaps is
  406.  * present and has the expected size.
  407.  */
  408. void
  409. _mesa_test_texobj_completeness( const struct gl_context *ctx,
  410.                                 struct gl_texture_object *t )
  411. {
  412.    const GLint baseLevel = t->BaseLevel;
  413.    GLint maxLog2 = 0, maxLevels = 0;
  414.  
  415.    t->_Complete = GL_TRUE;  /* be optimistic */
  416.  
  417.    /* Detect cases where the application set the base level to an invalid
  418.     * value.
  419.     */
  420.    if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS)) {
  421.       incomplete(t, "base level = %d is invalid", baseLevel);
  422.       return;
  423.    }
  424.  
  425.    /* Always need the base level image */
  426.    if (!t->Image[0][baseLevel]) {
  427.       incomplete(t, "Image[baseLevel=%d] == NULL", baseLevel);
  428.       return;
  429.    }
  430.  
  431.    /* Check width/height/depth for zero */
  432.    if (t->Image[0][baseLevel]->Width == 0 ||
  433.        t->Image[0][baseLevel]->Height == 0 ||
  434.        t->Image[0][baseLevel]->Depth == 0) {
  435.       incomplete(t, "texture width = 0");
  436.       return;
  437.    }
  438.  
  439.    /* Compute _MaxLevel */
  440.    if ((t->Target == GL_TEXTURE_1D) ||
  441.        (t->Target == GL_TEXTURE_1D_ARRAY_EXT)) {
  442.       maxLog2 = t->Image[0][baseLevel]->WidthLog2;
  443.       maxLevels = ctx->Const.MaxTextureLevels;
  444.    }
  445.    else if ((t->Target == GL_TEXTURE_2D) ||
  446.             (t->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
  447.       maxLog2 = MAX2(t->Image[0][baseLevel]->WidthLog2,
  448.                      t->Image[0][baseLevel]->HeightLog2);
  449.       maxLevels = ctx->Const.MaxTextureLevels;
  450.    }
  451.    else if (t->Target == GL_TEXTURE_3D) {
  452.       GLint max = MAX2(t->Image[0][baseLevel]->WidthLog2,
  453.                        t->Image[0][baseLevel]->HeightLog2);
  454.       maxLog2 = MAX2(max, (GLint)(t->Image[0][baseLevel]->DepthLog2));
  455.       maxLevels = ctx->Const.Max3DTextureLevels;
  456.    }
  457.    else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
  458.       maxLog2 = MAX2(t->Image[0][baseLevel]->WidthLog2,
  459.                      t->Image[0][baseLevel]->HeightLog2);
  460.       maxLevels = ctx->Const.MaxCubeTextureLevels;
  461.    }
  462.    else if (t->Target == GL_TEXTURE_RECTANGLE_NV) {
  463.       maxLog2 = 0;  /* not applicable */
  464.       maxLevels = 1;  /* no mipmapping */
  465.    }
  466.    else {
  467.       _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness");
  468.       return;
  469.    }
  470.  
  471.    ASSERT(maxLevels > 0);
  472.  
  473.    t->_MaxLevel = baseLevel + maxLog2;
  474.    t->_MaxLevel = MIN2(t->_MaxLevel, t->MaxLevel);
  475.    t->_MaxLevel = MIN2(t->_MaxLevel, maxLevels - 1);
  476.  
  477.    /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */
  478.    t->_MaxLambda = (GLfloat) (t->_MaxLevel - t->BaseLevel);
  479.  
  480.    if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
  481.       /* make sure that all six cube map level 0 images are the same size */
  482.       const GLuint w = t->Image[0][baseLevel]->Width2;
  483.       const GLuint h = t->Image[0][baseLevel]->Height2;
  484.       GLuint face;
  485.       for (face = 1; face < 6; face++) {
  486.          if (t->Image[face][baseLevel] == NULL ||
  487.              t->Image[face][baseLevel]->Width2 != w ||
  488.              t->Image[face][baseLevel]->Height2 != h) {
  489.             incomplete(t, "Cube face missing or mismatched size");
  490.             return;
  491.          }
  492.       }
  493.    }
  494.  
  495.    /* extra checking for mipmaps */
  496.    if (t->MinFilter != GL_NEAREST && t->MinFilter != GL_LINEAR) {
  497.       /*
  498.        * Mipmapping: determine if we have a complete set of mipmaps
  499.        */
  500.       GLint i;
  501.       GLint minLevel = baseLevel;
  502.       GLint maxLevel = t->_MaxLevel;
  503.  
  504.       if (minLevel > maxLevel) {
  505.          incomplete(t, "minLevel > maxLevel");
  506.          return;
  507.       }
  508.  
  509.       /* Test dimension-independent attributes */
  510.       for (i = minLevel; i <= maxLevel; i++) {
  511.          if (t->Image[0][i]) {
  512.             if (t->Image[0][i]->TexFormat != t->Image[0][baseLevel]->TexFormat) {
  513.                incomplete(t, "Format[i] != Format[baseLevel]");
  514.                return;
  515.             }
  516.             if (t->Image[0][i]->Border != t->Image[0][baseLevel]->Border) {
  517.                incomplete(t, "Border[i] != Border[baseLevel]");
  518.                return;
  519.             }
  520.          }
  521.       }
  522.  
  523.       /* Test things which depend on number of texture image dimensions */
  524.       if ((t->Target == GL_TEXTURE_1D) ||
  525.           (t->Target == GL_TEXTURE_1D_ARRAY_EXT)) {
  526.          /* Test 1-D mipmaps */
  527.          GLuint width = t->Image[0][baseLevel]->Width2;
  528.          for (i = baseLevel + 1; i < maxLevels; i++) {
  529.             if (width > 1) {
  530.                width /= 2;
  531.             }
  532.             if (i >= minLevel && i <= maxLevel) {
  533.                if (!t->Image[0][i]) {
  534.                   incomplete(t, "1D Image[0][i] == NULL");
  535.                   return;
  536.                }
  537.                if (t->Image[0][i]->Width2 != width ) {
  538.                   incomplete(t, "1D Image[0][i] bad width");
  539.                   return;
  540.                }
  541.             }
  542.             if (width == 1) {
  543.                return;  /* found smallest needed mipmap, all done! */
  544.             }
  545.          }
  546.       }
  547.       else if ((t->Target == GL_TEXTURE_2D) ||
  548.                (t->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
  549.          /* Test 2-D mipmaps */
  550.          GLuint width = t->Image[0][baseLevel]->Width2;
  551.          GLuint height = t->Image[0][baseLevel]->Height2;
  552.          for (i = baseLevel + 1; i < maxLevels; i++) {
  553.             if (width > 1) {
  554.                width /= 2;
  555.             }
  556.             if (height > 1) {
  557.                height /= 2;
  558.             }
  559.             if (i >= minLevel && i <= maxLevel) {
  560.                if (!t->Image[0][i]) {
  561.                   incomplete(t, "2D Image[0][i] == NULL");
  562.                   return;
  563.                }
  564.                if (t->Image[0][i]->Width2 != width) {
  565.                   incomplete(t, "2D Image[0][i] bad width");
  566.                   return;
  567.                }
  568.                if (t->Image[0][i]->Height2 != height) {
  569.                   incomplete(t, "2D Image[0][i] bad height");
  570.                   return;
  571.                }
  572.                if (width==1 && height==1) {
  573.                   return;  /* found smallest needed mipmap, all done! */
  574.                }
  575.             }
  576.          }
  577.       }
  578.       else if (t->Target == GL_TEXTURE_3D) {
  579.          /* Test 3-D mipmaps */
  580.          GLuint width = t->Image[0][baseLevel]->Width2;
  581.          GLuint height = t->Image[0][baseLevel]->Height2;
  582.          GLuint depth = t->Image[0][baseLevel]->Depth2;
  583.          for (i = baseLevel + 1; i < maxLevels; i++) {
  584.             if (width > 1) {
  585.                width /= 2;
  586.             }
  587.             if (height > 1) {
  588.                height /= 2;
  589.             }
  590.             if (depth > 1) {
  591.                depth /= 2;
  592.             }
  593.             if (i >= minLevel && i <= maxLevel) {
  594.                if (!t->Image[0][i]) {
  595.                   incomplete(t, "3D Image[0][i] == NULL");
  596.                   return;
  597.                }
  598.                if (t->Image[0][i]->_BaseFormat == GL_DEPTH_COMPONENT) {
  599.                   incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex");
  600.                   return;
  601.                }
  602.                if (t->Image[0][i]->Width2 != width) {
  603.                   incomplete(t, "3D Image[0][i] bad width");
  604.                   return;
  605.                }
  606.                if (t->Image[0][i]->Height2 != height) {
  607.                   incomplete(t, "3D Image[0][i] bad height");
  608.                   return;
  609.                }
  610.                if (t->Image[0][i]->Depth2 != depth) {
  611.                   incomplete(t, "3D Image[0][i] bad depth");
  612.                   return;
  613.                }
  614.             }
  615.             if (width == 1 && height == 1 && depth == 1) {
  616.                return;  /* found smallest needed mipmap, all done! */
  617.             }
  618.          }
  619.       }
  620.       else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
  621.          /* make sure 6 cube faces are consistant */
  622.          GLuint width = t->Image[0][baseLevel]->Width2;
  623.          GLuint height = t->Image[0][baseLevel]->Height2;
  624.          for (i = baseLevel + 1; i < maxLevels; i++) {
  625.             if (width > 1) {
  626.                width /= 2;
  627.             }
  628.             if (height > 1) {
  629.                height /= 2;
  630.             }
  631.             if (i >= minLevel && i <= maxLevel) {
  632.                GLuint face;
  633.                for (face = 0; face < 6; face++) {
  634.                   /* check that we have images defined */
  635.                   if (!t->Image[face][i]) {
  636.                      incomplete(t, "CubeMap Image[n][i] == NULL");
  637.                      return;
  638.                   }
  639.                   /* Don't support GL_DEPTH_COMPONENT for cube maps */
  640.                   if (t->Image[face][i]->_BaseFormat == GL_DEPTH_COMPONENT) {
  641.                      incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex");
  642.                      return;
  643.                   }
  644.                   /* check that all six images have same size */
  645.                   if (t->Image[face][i]->Width2 != width ||
  646.                       t->Image[face][i]->Height2 != height) {
  647.                      incomplete(t, "CubeMap Image[n][i] bad size");
  648.                      return;
  649.                   }
  650.                }
  651.             }
  652.             if (width == 1 && height == 1) {
  653.                return;  /* found smallest needed mipmap, all done! */
  654.             }
  655.          }
  656.       }
  657.       else if (t->Target == GL_TEXTURE_RECTANGLE_NV) {
  658.          /* XXX special checking? */
  659.       }
  660.       else {
  661.          /* Target = ??? */
  662.          _mesa_problem(ctx, "Bug in gl_test_texture_object_completeness\n");
  663.       }
  664.    }
  665. }
  666.  
  667.  
  668. /**
  669.  * Check if the given cube map texture is "cube complete" as defined in
  670.  * the OpenGL specification.
  671.  */
  672. GLboolean
  673. _mesa_cube_complete(const struct gl_texture_object *texObj)
  674. {
  675.    const GLint baseLevel = texObj->BaseLevel;
  676.    const struct gl_texture_image *img0, *img;
  677.    GLuint face;
  678.  
  679.    if (texObj->Target != GL_TEXTURE_CUBE_MAP)
  680.       return GL_FALSE;
  681.  
  682.    if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS))
  683.       return GL_FALSE;
  684.  
  685.    /* check first face */
  686.    img0 = texObj->Image[0][baseLevel];
  687.    if (!img0 ||
  688.        img0->Width < 1 ||
  689.        img0->Width != img0->Height)
  690.       return GL_FALSE;
  691.  
  692.    /* check remaining faces vs. first face */
  693.    for (face = 1; face < 6; face++) {
  694.       img = texObj->Image[face][baseLevel];
  695.       if (!img ||
  696.           img->Width != img0->Width ||
  697.           img->Height != img0->Height ||
  698.           img->TexFormat != img0->TexFormat)
  699.          return GL_FALSE;
  700.    }
  701.  
  702.    return GL_TRUE;
  703. }
  704.  
  705.  
  706. /**
  707.  * Mark a texture object dirty.  It forces the object to be incomplete
  708.  * and optionally forces the context to re-validate its state.
  709.  *
  710.  * \param ctx GL context.
  711.  * \param texObj texture object.
  712.  * \param invalidate_state also invalidate context state.
  713.  */
  714. void
  715. _mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj,
  716.                    GLboolean invalidate_state)
  717. {
  718.    texObj->_Complete = GL_FALSE;
  719.    if (invalidate_state)
  720.       ctx->NewState |= _NEW_TEXTURE;
  721. }
  722.  
  723.  
  724. /**
  725.  * Return pointer to a default/fallback texture.
  726.  * The texture is a 2D 8x8 RGBA texture with all texels = (0,0,0,1).
  727.  * That's the value a sampler should get when sampling from an
  728.  * incomplete texture.
  729.  */
  730. struct gl_texture_object *
  731. _mesa_get_fallback_texture(struct gl_context *ctx)
  732. {
  733.    if (!ctx->Shared->FallbackTex) {
  734.       /* create fallback texture now */
  735.       static GLubyte texels[8 * 8][4];
  736.       struct gl_texture_object *texObj;
  737.       struct gl_texture_image *texImage;
  738.       gl_format texFormat;
  739.       GLuint i;
  740.  
  741.       for (i = 0; i < 8 * 8; i++) {
  742.          texels[i][0] =
  743.          texels[i][1] =
  744.          texels[i][2] = 0x0;
  745.          texels[i][3] = 0xff;
  746.       }
  747.  
  748.       /* create texture object */
  749.       texObj = ctx->Driver.NewTextureObject(ctx, 0, GL_TEXTURE_2D);
  750.       assert(texObj->RefCount == 1);
  751.       texObj->MinFilter = GL_NEAREST;
  752.       texObj->MagFilter = GL_NEAREST;
  753.  
  754.       /* create level[0] texture image */
  755.       texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, 0);
  756.  
  757.       texFormat = ctx->Driver.ChooseTextureFormat(ctx, GL_RGBA, GL_RGBA,
  758.                                                   GL_UNSIGNED_BYTE);
  759.  
  760.       /* init the image fields */
  761.       _mesa_init_teximage_fields(ctx, GL_TEXTURE_2D, texImage,
  762.                                  8, 8, 1, 0, GL_RGBA, texFormat);
  763.  
  764.       ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
  765.  
  766.       /* set image data */
  767.       ctx->Driver.TexImage2D(ctx, GL_TEXTURE_2D, 0, GL_RGBA,
  768.                              8, 8, 0,
  769.                              GL_RGBA, GL_UNSIGNED_BYTE, texels,
  770.                              &ctx->DefaultPacking, texObj, texImage);
  771.  
  772.       _mesa_test_texobj_completeness(ctx, texObj);
  773.       assert(texObj->_Complete);
  774.  
  775.       ctx->Shared->FallbackTex = texObj;
  776.    }
  777.    return ctx->Shared->FallbackTex;
  778. }
  779.  
  780.  
  781. /*@}*/
  782.  
  783.  
  784. /***********************************************************************/
  785. /** \name API functions */
  786. /*@{*/
  787.  
  788.  
  789. /**
  790.  * Generate texture names.
  791.  *
  792.  * \param n number of texture names to be generated.
  793.  * \param textures an array in which will hold the generated texture names.
  794.  *
  795.  * \sa glGenTextures().
  796.  *
  797.  * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture
  798.  * IDs which are stored in \p textures.  Corresponding empty texture
  799.  * objects are also generated.
  800.  */
  801. void GLAPIENTRY
  802. _mesa_GenTextures( GLsizei n, GLuint *textures )
  803. {
  804.    GET_CURRENT_CONTEXT(ctx);
  805.    GLuint first;
  806.    GLint i;
  807.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  808.  
  809.    if (n < 0) {
  810.       _mesa_error( ctx, GL_INVALID_VALUE, "glGenTextures" );
  811.       return;
  812.    }
  813.  
  814.    if (!textures)
  815.       return;
  816.  
  817.    /*
  818.     * This must be atomic (generation and allocation of texture IDs)
  819.     */
  820.    _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
  821.  
  822.    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
  823.  
  824.    /* Allocate new, empty texture objects */
  825.    for (i = 0; i < n; i++) {
  826.       struct gl_texture_object *texObj;
  827.       GLuint name = first + i;
  828.       GLenum target = 0;
  829.       texObj = (*ctx->Driver.NewTextureObject)( ctx, name, target);
  830.       if (!texObj) {
  831.          _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
  832.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures");
  833.          return;
  834.       }
  835.  
  836.       /* insert into hash table */
  837.       _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj);
  838.  
  839.       textures[i] = name;
  840.    }
  841.  
  842.    _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
  843. }
  844.  
  845.  
  846. /**
  847.  * Check if the given texture object is bound to the current draw or
  848.  * read framebuffer.  If so, Unbind it.
  849.  */
  850. static void
  851. unbind_texobj_from_fbo(struct gl_context *ctx,
  852.                        struct gl_texture_object *texObj)
  853. {
  854.    const GLuint n = (ctx->DrawBuffer == ctx->ReadBuffer) ? 1 : 2;
  855.    GLuint i;
  856.  
  857.    for (i = 0; i < n; i++) {
  858.       struct gl_framebuffer *fb = (i == 0) ? ctx->DrawBuffer : ctx->ReadBuffer;
  859.       if (fb->Name) {
  860.          GLuint j;
  861.          for (j = 0; j < BUFFER_COUNT; j++) {
  862.             if (fb->Attachment[j].Type == GL_TEXTURE &&
  863.                 fb->Attachment[j].Texture == texObj) {
  864.                _mesa_remove_attachment(ctx, fb->Attachment + j);        
  865.             }
  866.          }
  867.       }
  868.    }
  869. }
  870.  
  871.  
  872. /**
  873.  * Check if the given texture object is bound to any texture image units and
  874.  * unbind it if so (revert to default textures).
  875.  */
  876. static void
  877. unbind_texobj_from_texunits(struct gl_context *ctx,
  878.                             struct gl_texture_object *texObj)
  879. {
  880.    GLuint u, tex;
  881.  
  882.    for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
  883.       struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
  884.       for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
  885.          if (texObj == unit->CurrentTex[tex]) {
  886.             _mesa_reference_texobj(&unit->CurrentTex[tex],
  887.                                    ctx->Shared->DefaultTex[tex]);
  888.             ASSERT(unit->CurrentTex[tex]);
  889.             break;
  890.          }
  891.       }
  892.    }
  893. }
  894.  
  895.  
  896. /**
  897.  * Delete named textures.
  898.  *
  899.  * \param n number of textures to be deleted.
  900.  * \param textures array of texture IDs to be deleted.
  901.  *
  902.  * \sa glDeleteTextures().
  903.  *
  904.  * If we're about to delete a texture that's currently bound to any
  905.  * texture unit, unbind the texture first.  Decrement the reference
  906.  * count on the texture object and delete it if it's zero.
  907.  * Recall that texture objects can be shared among several rendering
  908.  * contexts.
  909.  */
  910. void GLAPIENTRY
  911. _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
  912. {
  913.    GET_CURRENT_CONTEXT(ctx);
  914.    GLint i;
  915.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */
  916.  
  917.    if (!textures)
  918.       return;
  919.  
  920.    for (i = 0; i < n; i++) {
  921.       if (textures[i] > 0) {
  922.          struct gl_texture_object *delObj
  923.             = _mesa_lookup_texture(ctx, textures[i]);
  924.  
  925.          if (delObj) {
  926.             _mesa_lock_texture(ctx, delObj);
  927.  
  928.             /* Check if texture is bound to any framebuffer objects.
  929.              * If so, unbind.
  930.              * See section 4.4.2.3 of GL_EXT_framebuffer_object.
  931.              */
  932.             unbind_texobj_from_fbo(ctx, delObj);
  933.  
  934.             /* Check if this texture is currently bound to any texture units.
  935.              * If so, unbind it.
  936.              */
  937.             unbind_texobj_from_texunits(ctx, delObj);
  938.  
  939.             _mesa_unlock_texture(ctx, delObj);
  940.  
  941.             ctx->NewState |= _NEW_TEXTURE;
  942.  
  943.             /* The texture _name_ is now free for re-use.
  944.              * Remove it from the hash table now.
  945.              */
  946.             _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
  947.             _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
  948.             _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
  949.  
  950.             /* Unreference the texobj.  If refcount hits zero, the texture
  951.              * will be deleted.
  952.              */
  953.             _mesa_reference_texobj(&delObj, NULL);
  954.          }
  955.       }
  956.    }
  957. }
  958.  
  959.  
  960. /**
  961.  * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D
  962.  * into the corresponding Mesa texture target index.
  963.  * Note that proxy targets are not valid here.
  964.  * \return TEXTURE_x_INDEX or -1 if target is invalid
  965.  */
  966. static GLint
  967. target_enum_to_index(GLenum target)
  968. {
  969.    switch (target) {
  970.    case GL_TEXTURE_1D:
  971.       return TEXTURE_1D_INDEX;
  972.    case GL_TEXTURE_2D:
  973.       return TEXTURE_2D_INDEX;
  974.    case GL_TEXTURE_3D:
  975.       return TEXTURE_3D_INDEX;
  976.    case GL_TEXTURE_CUBE_MAP_ARB:
  977.       return TEXTURE_CUBE_INDEX;
  978.    case GL_TEXTURE_RECTANGLE_NV:
  979.       return TEXTURE_RECT_INDEX;
  980.    case GL_TEXTURE_1D_ARRAY_EXT:
  981.       return TEXTURE_1D_ARRAY_INDEX;
  982.    case GL_TEXTURE_2D_ARRAY_EXT:
  983.       return TEXTURE_2D_ARRAY_INDEX;
  984.    default:
  985.       return -1;
  986.    }
  987. }
  988.  
  989.  
  990. /**
  991.  * Bind a named texture to a texturing target.
  992.  *
  993.  * \param target texture target.
  994.  * \param texName texture name.
  995.  *
  996.  * \sa glBindTexture().
  997.  *
  998.  * Determines the old texture object bound and returns immediately if rebinding
  999.  * the same texture.  Get the current texture which is either a default texture
  1000.  * if name is null, a named texture from the hash, or a new texture if the
  1001.  * given texture name is new. Increments its reference count, binds it, and
  1002.  * calls dd_function_table::BindTexture. Decrements the old texture reference
  1003.  * count and deletes it if it reaches zero.
  1004.  */
  1005. void GLAPIENTRY
  1006. _mesa_BindTexture( GLenum target, GLuint texName )
  1007. {
  1008.    GET_CURRENT_CONTEXT(ctx);
  1009.    const GLuint unit = ctx->Texture.CurrentUnit;
  1010.    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
  1011.    struct gl_texture_object *newTexObj = NULL, *defaultTexObj = NULL;
  1012.    GLint targetIndex;
  1013.    GLboolean early_out = GL_FALSE;
  1014.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  1015.  
  1016.    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
  1017.       _mesa_debug(ctx, "glBindTexture %s %d\n",
  1018.                   _mesa_lookup_enum_by_nr(target), (GLint) texName);
  1019.  
  1020.    targetIndex = target_enum_to_index(target);
  1021.    if (targetIndex < 0) {
  1022.       _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target)");
  1023.       return;
  1024.    }
  1025.    assert(targetIndex < NUM_TEXTURE_TARGETS);
  1026.    defaultTexObj = ctx->Shared->DefaultTex[targetIndex];
  1027.  
  1028.    /*
  1029.     * Get pointer to new texture object (newTexObj)
  1030.     */
  1031.    if (texName == 0) {
  1032.       newTexObj = defaultTexObj;
  1033.    }
  1034.    else {
  1035.       /* non-default texture object */
  1036.       newTexObj = _mesa_lookup_texture(ctx, texName);
  1037.       if (newTexObj) {
  1038.          /* error checking */
  1039.          if (newTexObj->Target != 0 && newTexObj->Target != target) {
  1040.             /* the named texture object's target doesn't match the given target */
  1041.             _mesa_error( ctx, GL_INVALID_OPERATION,
  1042.                          "glBindTexture(target mismatch)" );
  1043.             return;
  1044.          }
  1045.          if (newTexObj->Target == 0) {
  1046.             finish_texture_init(ctx, target, newTexObj);
  1047.          }
  1048.       }
  1049.       else {
  1050.          /* if this is a new texture id, allocate a texture object now */
  1051.          newTexObj = (*ctx->Driver.NewTextureObject)(ctx, texName, target);
  1052.          if (!newTexObj) {
  1053.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
  1054.             return;
  1055.          }
  1056.  
  1057.          /* and insert it into hash table */
  1058.          _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
  1059.          _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj);
  1060.          _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
  1061.       }
  1062.       newTexObj->Target = target;
  1063.    }
  1064.  
  1065.    assert(valid_texture_object(newTexObj));
  1066.  
  1067.    _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
  1068.    if ((ctx->Shared->RefCount == 1)
  1069.        && (newTexObj == texUnit->CurrentTex[targetIndex])) {
  1070.       early_out = GL_TRUE;
  1071.    }
  1072.    _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
  1073.  
  1074.    if (early_out) {
  1075.       return;
  1076.    }
  1077.  
  1078.    /* flush before changing binding */
  1079.    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
  1080.  
  1081.    /* Do the actual binding.  The refcount on the previously bound
  1082.     * texture object will be decremented.  It'll be deleted if the
  1083.     * count hits zero.
  1084.     */
  1085.    _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], newTexObj);
  1086.    ASSERT(texUnit->CurrentTex[targetIndex]);
  1087.  
  1088.    /* Pass BindTexture call to device driver */
  1089.    if (ctx->Driver.BindTexture)
  1090.       (*ctx->Driver.BindTexture)( ctx, target, newTexObj );
  1091. }
  1092.  
  1093.  
  1094. /**
  1095.  * Set texture priorities.
  1096.  *
  1097.  * \param n number of textures.
  1098.  * \param texName texture names.
  1099.  * \param priorities corresponding texture priorities.
  1100.  *
  1101.  * \sa glPrioritizeTextures().
  1102.  *
  1103.  * Looks up each texture in the hash, clamps the corresponding priority between
  1104.  * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture.
  1105.  */
  1106. void GLAPIENTRY
  1107. _mesa_PrioritizeTextures( GLsizei n, const GLuint *texName,
  1108.                           const GLclampf *priorities )
  1109. {
  1110.    GET_CURRENT_CONTEXT(ctx);
  1111.    GLint i;
  1112.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  1113.  
  1114.    if (n < 0) {
  1115.       _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
  1116.       return;
  1117.    }
  1118.  
  1119.    if (!priorities)
  1120.       return;
  1121.  
  1122.    for (i = 0; i < n; i++) {
  1123.       if (texName[i] > 0) {
  1124.          struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]);
  1125.          if (t) {
  1126.             t->Priority = CLAMP( priorities[i], 0.0F, 1.0F );
  1127.          }
  1128.       }
  1129.    }
  1130.  
  1131.    ctx->NewState |= _NEW_TEXTURE;
  1132. }
  1133.  
  1134.  
  1135.  
  1136. /**
  1137.  * See if textures are loaded in texture memory.
  1138.  *
  1139.  * \param n number of textures to query.
  1140.  * \param texName array with the texture names.
  1141.  * \param residences array which will hold the residence status.
  1142.  *
  1143.  * \return GL_TRUE if all textures are resident and \p residences is left unchanged,
  1144.  *
  1145.  * \sa glAreTexturesResident().
  1146.  *
  1147.  * Looks up each texture in the hash and calls
  1148.  * dd_function_table::IsTextureResident.
  1149.  */
  1150. GLboolean GLAPIENTRY
  1151. _mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
  1152.                           GLboolean *residences)
  1153. {
  1154.    GET_CURRENT_CONTEXT(ctx);
  1155.    GLboolean allResident = GL_TRUE;
  1156.    GLint i, j;
  1157.    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
  1158.  
  1159.    if (n < 0) {
  1160.       _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
  1161.       return GL_FALSE;
  1162.    }
  1163.  
  1164.    if (!texName || !residences)
  1165.       return GL_FALSE;
  1166.  
  1167.    for (i = 0; i < n; i++) {
  1168.       struct gl_texture_object *t;
  1169.       if (texName[i] == 0) {
  1170.          _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
  1171.          return GL_FALSE;
  1172.       }
  1173.       t = _mesa_lookup_texture(ctx, texName[i]);
  1174.       if (!t) {
  1175.          _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
  1176.          return GL_FALSE;
  1177.       }
  1178.       if (!ctx->Driver.IsTextureResident ||
  1179.           ctx->Driver.IsTextureResident(ctx, t)) {
  1180.          /* The texture is resident */
  1181.          if (!allResident)
  1182.             residences[i] = GL_TRUE;
  1183.       }
  1184.       else {
  1185.          /* The texture is not resident */
  1186.          if (allResident) {
  1187.             allResident = GL_FALSE;
  1188.             for (j = 0; j < i; j++)
  1189.                residences[j] = GL_TRUE;
  1190.          }
  1191.          residences[i] = GL_FALSE;
  1192.       }
  1193.    }
  1194.    
  1195.    return allResident;
  1196. }
  1197.  
  1198.  
  1199. /**
  1200.  * See if a name corresponds to a texture.
  1201.  *
  1202.  * \param texture texture name.
  1203.  *
  1204.  * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE
  1205.  * otherwise.
  1206.  *
  1207.  * \sa glIsTexture().
  1208.  *
  1209.  * Calls _mesa_HashLookup().
  1210.  */
  1211. GLboolean GLAPIENTRY
  1212. _mesa_IsTexture( GLuint texture )
  1213. {
  1214.    struct gl_texture_object *t;
  1215.    GET_CURRENT_CONTEXT(ctx);
  1216.    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
  1217.  
  1218.    if (!texture)
  1219.       return GL_FALSE;
  1220.  
  1221.    t = _mesa_lookup_texture(ctx, texture);
  1222.  
  1223.    /* IsTexture is true only after object has been bound once. */
  1224.    return t && t->Target;
  1225. }
  1226.  
  1227.  
  1228. /**
  1229.  * Simplest implementation of texture locking: grab the shared tex
  1230.  * mutex.  Examine the shared context state timestamp and if there has
  1231.  * been a change, set the appropriate bits in ctx->NewState.
  1232.  *
  1233.  * This is used to deal with synchronizing things when a texture object
  1234.  * is used/modified by different contexts (or threads) which are sharing
  1235.  * the texture.
  1236.  *
  1237.  * See also _mesa_lock/unlock_texture() in teximage.h
  1238.  */
  1239. void
  1240. _mesa_lock_context_textures( struct gl_context *ctx )
  1241. {
  1242.    _glthread_LOCK_MUTEX(ctx->Shared->TexMutex);
  1243.  
  1244.    if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) {
  1245.       ctx->NewState |= _NEW_TEXTURE;
  1246.       ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp;
  1247.    }
  1248. }
  1249.  
  1250.  
  1251. void
  1252. _mesa_unlock_context_textures( struct gl_context *ctx )
  1253. {
  1254.    assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp);
  1255.    _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex);
  1256. }
  1257.  
  1258. /*@}*/
  1259.