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