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