ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

texobj.c
Go to the documentation of this file.
00001 
00006 /*
00007  * Mesa 3-D graphics library
00008  * Version:  7.1
00009  *
00010  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
00011  *
00012  * Permission is hereby granted, free of charge, to any person obtaining a
00013  * copy of this software and associated documentation files (the "Software"),
00014  * to deal in the Software without restriction, including without limitation
00015  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00016  * and/or sell copies of the Software, and to permit persons to whom the
00017  * Software is furnished to do so, subject to the following conditions:
00018  *
00019  * The above copyright notice and this permission notice shall be included
00020  * in all copies or substantial portions of the Software.
00021  *
00022  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00023  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00024  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00025  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00026  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00027  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00028  */
00029 
00030 
00031 #include "glheader.h"
00032 #if FEATURE_colortable
00033 #include "colortab.h"
00034 #endif
00035 #include "context.h"
00036 #include "enums.h"
00037 #include "fbobject.h"
00038 #include "hash.h"
00039 #include "imports.h"
00040 #include "macros.h"
00041 #include "teximage.h"
00042 #include "texstate.h"
00043 #include "texobj.h"
00044 #include "mtypes.h"
00045 
00046 
00047 /**********************************************************************/
00050 
00051 
00055 struct gl_texture_object *
00056 _mesa_lookup_texture(GLcontext *ctx, GLuint id)
00057 {
00058    return (struct gl_texture_object *)
00059       _mesa_HashLookup(ctx->Shared->TexObjects, id);
00060 }
00061 
00062 
00063 
00079 struct gl_texture_object *
00080 _mesa_new_texture_object( GLcontext *ctx, GLuint name, GLenum target )
00081 {
00082    struct gl_texture_object *obj;
00083    (void) ctx;
00084    obj = MALLOC_STRUCT(gl_texture_object);
00085    _mesa_initialize_texture_object(obj, name, target);
00086    return obj;
00087 }
00088 
00089 
00096 void
00097 _mesa_initialize_texture_object( struct gl_texture_object *obj,
00098                                  GLuint name, GLenum target )
00099 {
00100    ASSERT(target == 0 ||
00101           target == GL_TEXTURE_1D ||
00102           target == GL_TEXTURE_2D ||
00103           target == GL_TEXTURE_3D ||
00104           target == GL_TEXTURE_CUBE_MAP_ARB ||
00105           target == GL_TEXTURE_RECTANGLE_NV ||
00106           target == GL_TEXTURE_1D_ARRAY_EXT ||
00107           target == GL_TEXTURE_2D_ARRAY_EXT);
00108 
00109    _mesa_bzero(obj, sizeof(*obj));
00110    /* init the non-zero fields */
00111    _glthread_INIT_MUTEX(obj->Mutex);
00112    obj->RefCount = 1;
00113    obj->Name = name;
00114    obj->Target = target;
00115    obj->Priority = 1.0F;
00116    if (target == GL_TEXTURE_RECTANGLE_NV) {
00117       obj->WrapS = GL_CLAMP_TO_EDGE;
00118       obj->WrapT = GL_CLAMP_TO_EDGE;
00119       obj->WrapR = GL_CLAMP_TO_EDGE;
00120       obj->MinFilter = GL_LINEAR;
00121    }
00122    else {
00123       obj->WrapS = GL_REPEAT;
00124       obj->WrapT = GL_REPEAT;
00125       obj->WrapR = GL_REPEAT;
00126       obj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
00127    }
00128    obj->MagFilter = GL_LINEAR;
00129    obj->MinLod = -1000.0;
00130    obj->MaxLod = 1000.0;
00131    obj->LodBias = 0.0;
00132    obj->BaseLevel = 0;
00133    obj->MaxLevel = 1000;
00134    obj->MaxAnisotropy = 1.0;
00135    obj->CompareFlag = GL_FALSE;                      /* SGIX_shadow */
00136    obj->CompareOperator = GL_TEXTURE_LEQUAL_R_SGIX;  /* SGIX_shadow */
00137    obj->CompareMode = GL_NONE;         /* ARB_shadow */
00138    obj->CompareFunc = GL_LEQUAL;       /* ARB_shadow */
00139    obj->DepthMode = GL_LUMINANCE;      /* ARB_depth_texture */
00140    obj->ShadowAmbient = 0.0F;          /* ARB/SGIX_shadow_ambient */
00141 }
00142 
00143 
00148 static void
00149 finish_texture_init(GLcontext *ctx, GLenum target,
00150                     struct gl_texture_object *obj)
00151 {
00152    assert(obj->Target == 0);
00153 
00154    if (target == GL_TEXTURE_RECTANGLE_NV) {
00155       /* have to init wrap and filter state here - kind of klunky */
00156       obj->WrapS = GL_CLAMP_TO_EDGE;
00157       obj->WrapT = GL_CLAMP_TO_EDGE;
00158       obj->WrapR = GL_CLAMP_TO_EDGE;
00159       obj->MinFilter = GL_LINEAR;
00160       if (ctx->Driver.TexParameter) {
00161          static const GLfloat fparam_wrap[1] = {(GLfloat) GL_CLAMP_TO_EDGE};
00162          static const GLfloat fparam_filter[1] = {(GLfloat) GL_LINEAR};
00163          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_S, fparam_wrap);
00164          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_T, fparam_wrap);
00165          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_R, fparam_wrap);
00166          ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_MIN_FILTER, fparam_filter);
00167       }
00168    }
00169 }
00170 
00171 
00180 void
00181 _mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
00182 {
00183    GLuint i, face;
00184 
00185    (void) ctx;
00186 
00187    /* Set Target to an invalid value.  With some assertions elsewhere
00188     * we can try to detect possible use of deleted textures.
00189     */
00190    texObj->Target = 0x99;
00191 
00192 #if FEATURE_colortable
00193    _mesa_free_colortable_data(&texObj->Palette);
00194 #endif
00195 
00196    /* free the texture images */
00197    for (face = 0; face < 6; face++) {
00198       for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
00199      if (texObj->Image[face][i]) {
00200         _mesa_delete_texture_image( ctx, texObj->Image[face][i] );
00201      }
00202       }
00203    }
00204 
00205    /* destroy the mutex -- it may have allocated memory (eg on bsd) */
00206    _glthread_DESTROY_MUTEX(texObj->Mutex);
00207 
00208    /* free this object */
00209    _mesa_free(texObj);
00210 }
00211 
00212 
00213 
00214 
00222 void
00223 _mesa_copy_texture_object( struct gl_texture_object *dest,
00224                            const struct gl_texture_object *src )
00225 {
00226    dest->Target = src->Target;
00227    dest->Name = src->Name;
00228    dest->Priority = src->Priority;
00229    dest->BorderColor[0] = src->BorderColor[0];
00230    dest->BorderColor[1] = src->BorderColor[1];
00231    dest->BorderColor[2] = src->BorderColor[2];
00232    dest->BorderColor[3] = src->BorderColor[3];
00233    dest->WrapS = src->WrapS;
00234    dest->WrapT = src->WrapT;
00235    dest->WrapR = src->WrapR;
00236    dest->MinFilter = src->MinFilter;
00237    dest->MagFilter = src->MagFilter;
00238    dest->MinLod = src->MinLod;
00239    dest->MaxLod = src->MaxLod;
00240    dest->LodBias = src->LodBias;
00241    dest->BaseLevel = src->BaseLevel;
00242    dest->MaxLevel = src->MaxLevel;
00243    dest->MaxAnisotropy = src->MaxAnisotropy;
00244    dest->CompareFlag = src->CompareFlag;
00245    dest->CompareOperator = src->CompareOperator;
00246    dest->ShadowAmbient = src->ShadowAmbient;
00247    dest->CompareMode = src->CompareMode;
00248    dest->CompareFunc = src->CompareFunc;
00249    dest->DepthMode = src->DepthMode;
00250    dest->_MaxLevel = src->_MaxLevel;
00251    dest->_MaxLambda = src->_MaxLambda;
00252    dest->GenerateMipmap = src->GenerateMipmap;
00253    dest->Palette = src->Palette;
00254    dest->_Complete = src->_Complete;
00255 }
00256 
00257 
00262 static GLboolean
00263 valid_texture_object(const struct gl_texture_object *tex)
00264 {
00265    switch (tex->Target) {
00266    case 0:
00267    case GL_TEXTURE_1D:
00268    case GL_TEXTURE_2D:
00269    case GL_TEXTURE_3D:
00270    case GL_TEXTURE_CUBE_MAP_ARB:
00271    case GL_TEXTURE_RECTANGLE_NV:
00272    case GL_TEXTURE_1D_ARRAY_EXT:
00273    case GL_TEXTURE_2D_ARRAY_EXT:
00274       return GL_TRUE;
00275    case 0x99:
00276       _mesa_problem(NULL, "invalid reference to a deleted texture object");
00277       return GL_FALSE;
00278    default:
00279       _mesa_problem(NULL, "invalid texture object Target value");
00280       return GL_FALSE;
00281    }
00282 }
00283 
00284 
00290 void
00291 _mesa_reference_texobj(struct gl_texture_object **ptr,
00292                        struct gl_texture_object *tex)
00293 {
00294    assert(ptr);
00295    if (*ptr == tex) {
00296       /* no change */
00297       return;
00298    }
00299 
00300    if (*ptr) {
00301       /* Unreference the old texture */
00302       GLboolean deleteFlag = GL_FALSE;
00303       struct gl_texture_object *oldTex = *ptr;
00304 
00305       assert(valid_texture_object(oldTex));
00306 
00307       _glthread_LOCK_MUTEX(oldTex->Mutex);
00308       ASSERT(oldTex->RefCount > 0);
00309       oldTex->RefCount--;
00310 
00311       deleteFlag = (oldTex->RefCount == 0);
00312       _glthread_UNLOCK_MUTEX(oldTex->Mutex);
00313 
00314       if (deleteFlag) {
00315          GET_CURRENT_CONTEXT(ctx);
00316          if (ctx)
00317             ctx->Driver.DeleteTexture(ctx, oldTex);
00318          else
00319             _mesa_problem(NULL, "Unable to delete texture, no context");
00320       }
00321 
00322       *ptr = NULL;
00323    }
00324    assert(!*ptr);
00325 
00326    if (tex) {
00327       /* reference new texture */
00328       assert(valid_texture_object(tex));
00329       _glthread_LOCK_MUTEX(tex->Mutex);
00330       if (tex->RefCount == 0) {
00331          /* this texture's being deleted (look just above) */
00332          /* Not sure this can every really happen.  Warn if it does. */
00333          _mesa_problem(NULL, "referencing deleted texture object");
00334          *ptr = NULL;
00335       }
00336       else {
00337          tex->RefCount++;
00338          *ptr = tex;
00339       }
00340       _glthread_UNLOCK_MUTEX(tex->Mutex);
00341    }
00342 }
00343 
00344 
00345 
00354 #if 0
00355 static void
00356 incomplete(const struct gl_texture_object *t, const char *why)
00357 {
00358    _mesa_printf("Texture Obj %d incomplete because: %s\n", t->Name, why);
00359 }
00360 #else
00361 #define incomplete(t, why)
00362 #endif
00363 
00364 
00377 void
00378 _mesa_test_texobj_completeness( const GLcontext *ctx,
00379                                 struct gl_texture_object *t )
00380 {
00381    const GLint baseLevel = t->BaseLevel;
00382    GLint maxLog2 = 0, maxLevels = 0;
00383 
00384    t->_Complete = GL_TRUE;  /* be optimistic */
00385 
00386    /* Detect cases where the application set the base level to an invalid
00387     * value.
00388     */
00389    if ((baseLevel < 0) || (baseLevel > MAX_TEXTURE_LEVELS)) {
00390       char s[100];
00391       _mesa_sprintf(s, "obj %p (%d) base level = %d is invalid",
00392               (void *) t, t->Name, baseLevel);
00393       incomplete(t, s);
00394       t->_Complete = GL_FALSE;
00395       return;
00396    }
00397 
00398    /* Always need the base level image */
00399    if (!t->Image[0][baseLevel]) {
00400       char s[100];
00401       _mesa_sprintf(s, "obj %p (%d) Image[baseLevel=%d] == NULL",
00402               (void *) t, t->Name, baseLevel);
00403       incomplete(t, s);
00404       t->_Complete = GL_FALSE;
00405       return;
00406    }
00407 
00408    /* Check width/height/depth for zero */
00409    if (t->Image[0][baseLevel]->Width == 0 ||
00410        t->Image[0][baseLevel]->Height == 0 ||
00411        t->Image[0][baseLevel]->Depth == 0) {
00412       incomplete(t, "texture width = 0");
00413       t->_Complete = GL_FALSE;
00414       return;
00415    }
00416 
00417    /* Compute _MaxLevel */
00418    if ((t->Target == GL_TEXTURE_1D) ||
00419        (t->Target == GL_TEXTURE_1D_ARRAY_EXT)) {
00420       maxLog2 = t->Image[0][baseLevel]->WidthLog2;
00421       maxLevels = ctx->Const.MaxTextureLevels;
00422    }
00423    else if ((t->Target == GL_TEXTURE_2D) ||
00424         (t->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
00425       maxLog2 = MAX2(t->Image[0][baseLevel]->WidthLog2,
00426                      t->Image[0][baseLevel]->HeightLog2);
00427       maxLevels = ctx->Const.MaxTextureLevels;
00428    }
00429    else if (t->Target == GL_TEXTURE_3D) {
00430       GLint max = MAX2(t->Image[0][baseLevel]->WidthLog2,
00431                        t->Image[0][baseLevel]->HeightLog2);
00432       maxLog2 = MAX2(max, (GLint)(t->Image[0][baseLevel]->DepthLog2));
00433       maxLevels = ctx->Const.Max3DTextureLevels;
00434    }
00435    else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
00436       maxLog2 = MAX2(t->Image[0][baseLevel]->WidthLog2,
00437                      t->Image[0][baseLevel]->HeightLog2);
00438       maxLevels = ctx->Const.MaxCubeTextureLevels;
00439    }
00440    else if (t->Target == GL_TEXTURE_RECTANGLE_NV) {
00441       maxLog2 = 0;  /* not applicable */
00442       maxLevels = 1;  /* no mipmapping */
00443    }
00444    else {
00445       _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness");
00446       return;
00447    }
00448 
00449    ASSERT(maxLevels > 0);
00450 
00451    t->_MaxLevel = baseLevel + maxLog2;
00452    t->_MaxLevel = MIN2(t->_MaxLevel, t->MaxLevel);
00453    t->_MaxLevel = MIN2(t->_MaxLevel, maxLevels - 1);
00454 
00455    /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */
00456    t->_MaxLambda = (GLfloat) (t->_MaxLevel - t->BaseLevel);
00457 
00458    if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
00459       /* make sure that all six cube map level 0 images are the same size */
00460       const GLuint w = t->Image[0][baseLevel]->Width2;
00461       const GLuint h = t->Image[0][baseLevel]->Height2;
00462       GLuint face;
00463       for (face = 1; face < 6; face++) {
00464      if (t->Image[face][baseLevel] == NULL ||
00465          t->Image[face][baseLevel]->Width2 != w ||
00466          t->Image[face][baseLevel]->Height2 != h) {
00467         t->_Complete = GL_FALSE;
00468         incomplete(t, "Non-quare cubemap image");
00469         return;
00470      }
00471       }
00472    }
00473 
00474    /* extra checking for mipmaps */
00475    if (t->MinFilter != GL_NEAREST && t->MinFilter != GL_LINEAR) {
00476       /*
00477        * Mipmapping: determine if we have a complete set of mipmaps
00478        */
00479       GLint i;
00480       GLint minLevel = baseLevel;
00481       GLint maxLevel = t->_MaxLevel;
00482 
00483       if (minLevel > maxLevel) {
00484          t->_Complete = GL_FALSE;
00485          incomplete(t, "minLevel > maxLevel");
00486          return;
00487       }
00488 
00489       /* Test dimension-independent attributes */
00490       for (i = minLevel; i <= maxLevel; i++) {
00491          if (t->Image[0][i]) {
00492             if (t->Image[0][i]->TexFormat != t->Image[0][baseLevel]->TexFormat) {
00493                t->_Complete = GL_FALSE;
00494                incomplete(t, "Format[i] != Format[baseLevel]");
00495                return;
00496             }
00497             if (t->Image[0][i]->Border != t->Image[0][baseLevel]->Border) {
00498                t->_Complete = GL_FALSE;
00499                incomplete(t, "Border[i] != Border[baseLevel]");
00500                return;
00501             }
00502          }
00503       }
00504 
00505       /* Test things which depend on number of texture image dimensions */
00506       if ((t->Target == GL_TEXTURE_1D) ||
00507           (t->Target == GL_TEXTURE_1D_ARRAY_EXT)) {
00508          /* Test 1-D mipmaps */
00509          GLuint width = t->Image[0][baseLevel]->Width2;
00510          for (i = baseLevel + 1; i < maxLevels; i++) {
00511             if (width > 1) {
00512                width /= 2;
00513             }
00514             if (i >= minLevel && i <= maxLevel) {
00515                if (!t->Image[0][i]) {
00516                   t->_Complete = GL_FALSE;
00517                   incomplete(t, "1D Image[0][i] == NULL");
00518                   return;
00519                }
00520                if (t->Image[0][i]->Width2 != width ) {
00521                   t->_Complete = GL_FALSE;
00522                   incomplete(t, "1D Image[0][i] bad width");
00523                   return;
00524                }
00525             }
00526             if (width == 1) {
00527                return;  /* found smallest needed mipmap, all done! */
00528             }
00529          }
00530       }
00531       else if ((t->Target == GL_TEXTURE_2D) ||
00532                (t->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
00533          /* Test 2-D mipmaps */
00534          GLuint width = t->Image[0][baseLevel]->Width2;
00535          GLuint height = t->Image[0][baseLevel]->Height2;
00536          for (i = baseLevel + 1; i < maxLevels; i++) {
00537             if (width > 1) {
00538                width /= 2;
00539             }
00540             if (height > 1) {
00541                height /= 2;
00542             }
00543             if (i >= minLevel && i <= maxLevel) {
00544                if (!t->Image[0][i]) {
00545                   t->_Complete = GL_FALSE;
00546                   incomplete(t, "2D Image[0][i] == NULL");
00547                   return;
00548                }
00549                if (t->Image[0][i]->Width2 != width) {
00550                   t->_Complete = GL_FALSE;
00551                   incomplete(t, "2D Image[0][i] bad width");
00552                   return;
00553                }
00554                if (t->Image[0][i]->Height2 != height) {
00555                   t->_Complete = GL_FALSE;
00556                   incomplete(t, "2D Image[0][i] bad height");
00557                   return;
00558                }
00559                if (width==1 && height==1) {
00560                   return;  /* found smallest needed mipmap, all done! */
00561                }
00562             }
00563          }
00564       }
00565       else if (t->Target == GL_TEXTURE_3D) {
00566          /* Test 3-D mipmaps */
00567          GLuint width = t->Image[0][baseLevel]->Width2;
00568          GLuint height = t->Image[0][baseLevel]->Height2;
00569          GLuint depth = t->Image[0][baseLevel]->Depth2;
00570      for (i = baseLevel + 1; i < maxLevels; i++) {
00571             if (width > 1) {
00572                width /= 2;
00573             }
00574             if (height > 1) {
00575                height /= 2;
00576             }
00577             if (depth > 1) {
00578                depth /= 2;
00579             }
00580             if (i >= minLevel && i <= maxLevel) {
00581                if (!t->Image[0][i]) {
00582                   incomplete(t, "3D Image[0][i] == NULL");
00583                   t->_Complete = GL_FALSE;
00584                   return;
00585                }
00586                if (t->Image[0][i]->_BaseFormat == GL_DEPTH_COMPONENT) {
00587                   t->_Complete = GL_FALSE;
00588                   incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex");
00589                   return;
00590                }
00591                if (t->Image[0][i]->Width2 != width) {
00592                   t->_Complete = GL_FALSE;
00593                   incomplete(t, "3D Image[0][i] bad width");
00594                   return;
00595                }
00596                if (t->Image[0][i]->Height2 != height) {
00597                   t->_Complete = GL_FALSE;
00598                   incomplete(t, "3D Image[0][i] bad height");
00599                   return;
00600                }
00601                if (t->Image[0][i]->Depth2 != depth) {
00602                   t->_Complete = GL_FALSE;
00603                   incomplete(t, "3D Image[0][i] bad depth");
00604                   return;
00605                }
00606             }
00607             if (width == 1 && height == 1 && depth == 1) {
00608                return;  /* found smallest needed mipmap, all done! */
00609             }
00610          }
00611       }
00612       else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
00613          /* make sure 6 cube faces are consistant */
00614          GLuint width = t->Image[0][baseLevel]->Width2;
00615          GLuint height = t->Image[0][baseLevel]->Height2;
00616      for (i = baseLevel + 1; i < maxLevels; i++) {
00617             if (width > 1) {
00618                width /= 2;
00619             }
00620             if (height > 1) {
00621                height /= 2;
00622             }
00623             if (i >= minLevel && i <= maxLevel) {
00624            GLuint face;
00625            for (face = 0; face < 6; face++) {
00626           /* check that we have images defined */
00627           if (!t->Image[face][i]) {
00628              t->_Complete = GL_FALSE;
00629              incomplete(t, "CubeMap Image[n][i] == NULL");
00630              return;
00631           }
00632           /* Don't support GL_DEPTH_COMPONENT for cube maps */
00633           if (t->Image[face][i]->_BaseFormat == GL_DEPTH_COMPONENT) {
00634              t->_Complete = GL_FALSE;
00635              incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex");
00636              return;
00637           }
00638           /* check that all six images have same size */
00639           if (t->Image[face][i]->Width2!=width || 
00640               t->Image[face][i]->Height2!=height) {
00641              t->_Complete = GL_FALSE;
00642              incomplete(t, "CubeMap Image[n][i] bad size");
00643              return;
00644           }
00645            }
00646         }
00647         if (width == 1 && height == 1) {
00648            return;  /* found smallest needed mipmap, all done! */
00649             }
00650          }
00651       }
00652       else if (t->Target == GL_TEXTURE_RECTANGLE_NV) {
00653          /* XXX special checking? */
00654       }
00655       else {
00656          /* Target = ??? */
00657          _mesa_problem(ctx, "Bug in gl_test_texture_object_completeness\n");
00658       }
00659    }
00660 }
00661 
00665 /***********************************************************************/
00668 
00669 
00682 void GLAPIENTRY
00683 _mesa_GenTextures( GLsizei n, GLuint *textures )
00684 {
00685    GET_CURRENT_CONTEXT(ctx);
00686    GLuint first;
00687    GLint i;
00688    ASSERT_OUTSIDE_BEGIN_END(ctx);
00689 
00690    if (n < 0) {
00691       _mesa_error( ctx, GL_INVALID_VALUE, "glGenTextures" );
00692       return;
00693    }
00694 
00695    if (!textures)
00696       return;
00697 
00698    /*
00699     * This must be atomic (generation and allocation of texture IDs)
00700     */
00701    _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
00702 
00703    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
00704 
00705    /* Allocate new, empty texture objects */
00706    for (i = 0; i < n; i++) {
00707       struct gl_texture_object *texObj;
00708       GLuint name = first + i;
00709       GLenum target = 0;
00710       texObj = (*ctx->Driver.NewTextureObject)( ctx, name, target);
00711       if (!texObj) {
00712          _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
00713          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures");
00714          return;
00715       }
00716 
00717       /* insert into hash table */
00718       _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj);
00719 
00720       textures[i] = name;
00721    }
00722 
00723    _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
00724 }
00725 
00726 
00731 static void
00732 unbind_texobj_from_fbo(GLcontext *ctx, struct gl_texture_object *texObj)
00733 {
00734    const GLuint n = (ctx->DrawBuffer == ctx->ReadBuffer) ? 1 : 2;
00735    GLuint i;
00736 
00737    for (i = 0; i < n; i++) {
00738       struct gl_framebuffer *fb = (i == 0) ? ctx->DrawBuffer : ctx->ReadBuffer;
00739       if (fb->Name) {
00740          GLuint j;
00741          for (j = 0; j < BUFFER_COUNT; j++) {
00742             if (fb->Attachment[j].Type == GL_TEXTURE &&
00743                 fb->Attachment[j].Texture == texObj) {
00744                _mesa_remove_attachment(ctx, fb->Attachment + j);         
00745             }
00746          }
00747       }
00748    }
00749 }
00750 
00751 
00756 static void
00757 unbind_texobj_from_texunits(GLcontext *ctx, struct gl_texture_object *texObj)
00758 {
00759    GLuint u, tex;
00760 
00761    for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
00762       struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
00763       for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
00764          if (texObj == unit->CurrentTex[tex]) {
00765             _mesa_reference_texobj(&unit->CurrentTex[tex],
00766                                    ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]);
00767             ASSERT(unit->CurrentTex[tex]);
00768             break;
00769          }
00770       }
00771    }
00772 }
00773 
00774 
00789 void GLAPIENTRY
00790 _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
00791 {
00792    GET_CURRENT_CONTEXT(ctx);
00793    GLint i;
00794    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */
00795 
00796    if (!textures)
00797       return;
00798 
00799    for (i = 0; i < n; i++) {
00800       if (textures[i] > 0) {
00801          struct gl_texture_object *delObj
00802             = _mesa_lookup_texture(ctx, textures[i]);
00803 
00804          if (delObj) {
00805         _mesa_lock_texture(ctx, delObj);
00806 
00807             /* Check if texture is bound to any framebuffer objects.
00808              * If so, unbind.
00809              * See section 4.4.2.3 of GL_EXT_framebuffer_object.
00810              */
00811             unbind_texobj_from_fbo(ctx, delObj);
00812 
00813             /* Check if this texture is currently bound to any texture units.
00814              * If so, unbind it.
00815              */
00816             unbind_texobj_from_texunits(ctx, delObj);
00817 
00818         _mesa_unlock_texture(ctx, delObj);
00819 
00820             ctx->NewState |= _NEW_TEXTURE;
00821 
00822             /* The texture _name_ is now free for re-use.
00823              * Remove it from the hash table now.
00824              */
00825             _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
00826             _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
00827             _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
00828 
00829             /* Unreference the texobj.  If refcount hits zero, the texture
00830              * will be deleted.
00831              */
00832             _mesa_reference_texobj(&delObj, NULL);
00833          }
00834       }
00835    }
00836 }
00837 
00838 
00844 static GLint
00845 target_enum_to_index(GLenum target)
00846 {
00847    switch (target) {
00848    case GL_TEXTURE_1D:
00849       return TEXTURE_1D_INDEX;
00850    case GL_TEXTURE_2D:
00851       return TEXTURE_2D_INDEX;
00852    case GL_TEXTURE_3D:
00853       return TEXTURE_3D_INDEX;
00854    case GL_TEXTURE_CUBE_MAP_ARB:
00855       return TEXTURE_CUBE_INDEX;
00856    case GL_TEXTURE_RECTANGLE_NV:
00857       return TEXTURE_RECT_INDEX;
00858    case GL_TEXTURE_1D_ARRAY_EXT:
00859       return TEXTURE_1D_ARRAY_INDEX;
00860    case GL_TEXTURE_2D_ARRAY_EXT:
00861       return TEXTURE_2D_ARRAY_INDEX;
00862    default:
00863       return -1;
00864    }
00865 }
00866 
00867 
00883 void GLAPIENTRY
00884 _mesa_BindTexture( GLenum target, GLuint texName )
00885 {
00886    GET_CURRENT_CONTEXT(ctx);
00887    const GLuint unit = ctx->Texture.CurrentUnit;
00888    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
00889    struct gl_texture_object *newTexObj = NULL, *defaultTexObj = NULL;
00890    GLint targetIndex;
00891    ASSERT_OUTSIDE_BEGIN_END(ctx);
00892 
00893    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
00894       _mesa_debug(ctx, "glBindTexture %s %d\n",
00895                   _mesa_lookup_enum_by_nr(target), (GLint) texName);
00896 
00897    targetIndex = target_enum_to_index(target);
00898    if (targetIndex < 0) {
00899       _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target)");
00900       return;
00901    }
00902    assert(targetIndex < NUM_TEXTURE_TARGETS);
00903    defaultTexObj = ctx->Shared->DefaultTex[targetIndex];
00904 
00905    /*
00906     * Get pointer to new texture object (newTexObj)
00907     */
00908    if (texName == 0) {
00909       newTexObj = defaultTexObj;
00910    }
00911    else {
00912       /* non-default texture object */
00913       newTexObj = _mesa_lookup_texture(ctx, texName);
00914       if (newTexObj) {
00915          /* error checking */
00916          if (newTexObj->Target != 0 && newTexObj->Target != target) {
00917             /* the named texture object's target doesn't match the given target */
00918             _mesa_error( ctx, GL_INVALID_OPERATION,
00919                          "glBindTexture(target mismatch)" );
00920             return;
00921          }
00922          if (newTexObj->Target == 0) {
00923             finish_texture_init(ctx, target, newTexObj);
00924          }
00925       }
00926       else {
00927          /* if this is a new texture id, allocate a texture object now */
00928      newTexObj = (*ctx->Driver.NewTextureObject)(ctx, texName, target);
00929          if (!newTexObj) {
00930             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
00931             return;
00932          }
00933 
00934          /* and insert it into hash table */
00935          _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
00936          _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj);
00937          _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
00938       }
00939       newTexObj->Target = target;
00940    }
00941 
00942    assert(valid_texture_object(newTexObj));
00943 
00944    /* flush before changing binding */
00945    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
00946 
00947    /* Do the actual binding.  The refcount on the previously bound
00948     * texture object will be decremented.  It'll be deleted if the
00949     * count hits zero.
00950     */
00951    _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], newTexObj);
00952    ASSERT(texUnit->CurrentTex[targetIndex]);
00953 
00954    /* Pass BindTexture call to device driver */
00955    if (ctx->Driver.BindTexture)
00956       (*ctx->Driver.BindTexture)( ctx, target, newTexObj );
00957 }
00958 
00959 
00972 void GLAPIENTRY
00973 _mesa_PrioritizeTextures( GLsizei n, const GLuint *texName,
00974                           const GLclampf *priorities )
00975 {
00976    GET_CURRENT_CONTEXT(ctx);
00977    GLint i;
00978    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
00979 
00980    if (n < 0) {
00981       _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
00982       return;
00983    }
00984 
00985    if (!priorities)
00986       return;
00987 
00988    for (i = 0; i < n; i++) {
00989       if (texName[i] > 0) {
00990          struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]);
00991          if (t) {
00992             t->Priority = CLAMP( priorities[i], 0.0F, 1.0F );
00993         if (ctx->Driver.PrioritizeTexture)
00994            ctx->Driver.PrioritizeTexture( ctx, t, t->Priority );
00995          }
00996       }
00997    }
00998 
00999    ctx->NewState |= _NEW_TEXTURE;
01000 }
01001 
01016 GLboolean GLAPIENTRY
01017 _mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
01018                           GLboolean *residences)
01019 {
01020    GET_CURRENT_CONTEXT(ctx);
01021    GLboolean allResident = GL_TRUE;
01022    GLint i, j;
01023    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
01024 
01025    if (n < 0) {
01026       _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
01027       return GL_FALSE;
01028    }
01029 
01030    if (!texName || !residences)
01031       return GL_FALSE;
01032 
01033    for (i = 0; i < n; i++) {
01034       struct gl_texture_object *t;
01035       if (texName[i] == 0) {
01036          _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
01037          return GL_FALSE;
01038       }
01039       t = _mesa_lookup_texture(ctx, texName[i]);
01040       if (!t) {
01041          _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
01042          return GL_FALSE;
01043       }
01044       if (!ctx->Driver.IsTextureResident ||
01045           ctx->Driver.IsTextureResident(ctx, t)) {
01046          /* The texture is resident */
01047      if (!allResident)
01048         residences[i] = GL_TRUE;
01049       }
01050       else {
01051          /* The texture is not resident */
01052          if (allResident) {
01053         allResident = GL_FALSE;
01054         for (j = 0; j < i; j++)
01055            residences[j] = GL_TRUE;
01056      }
01057      residences[i] = GL_FALSE;
01058       }
01059    }
01060    
01061    return allResident;
01062 }
01063 
01076 GLboolean GLAPIENTRY
01077 _mesa_IsTexture( GLuint texture )
01078 {
01079    struct gl_texture_object *t;
01080    GET_CURRENT_CONTEXT(ctx);
01081    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
01082 
01083    if (!texture)
01084       return GL_FALSE;
01085 
01086    t = _mesa_lookup_texture(ctx, texture);
01087 
01088    /* IsTexture is true only after object has been bound once. */
01089    return t && t->Target;
01090 }
01091 
01092 
01105 void
01106 _mesa_lock_context_textures( GLcontext *ctx )
01107 {
01108    _glthread_LOCK_MUTEX(ctx->Shared->TexMutex);
01109 
01110    if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) {
01111       ctx->NewState |= _NEW_TEXTURE;
01112       ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp;
01113    }
01114 }
01115 
01116 
01117 void
01118 _mesa_unlock_context_textures( GLcontext *ctx )
01119 {
01120    assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp);
01121    _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex);
01122 }
01123 

Generated on Sun May 27 2012 04:20:31 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.