Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentexobj.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
1.7.6.1
|