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_EXTERNAL_OES || 111 target == GL_TEXTURE_BUFFER); 112 113 memset(obj, 0, sizeof(*obj)); 114 /* init the non-zero fields */ 115 _glthread_INIT_MUTEX(obj->Mutex); 116 obj->RefCount = 1; 117 obj->Name = name; 118 obj->Target = target; 119 obj->Priority = 1.0F; 120 obj->BaseLevel = 0; 121 obj->MaxLevel = 1000; 122 123 /* must be one; no support for (YUV) planes in separate buffers */ 124 obj->RequiredTextureImageUnits = 1; 125 126 /* sampler state */ 127 if (target == GL_TEXTURE_RECTANGLE_NV || 128 target == GL_TEXTURE_EXTERNAL_OES) { 129 obj->Sampler.WrapS = GL_CLAMP_TO_EDGE; 130 obj->Sampler.WrapT = GL_CLAMP_TO_EDGE; 131 obj->Sampler.WrapR = GL_CLAMP_TO_EDGE; 132 obj->Sampler.MinFilter = GL_LINEAR; 133 } 134 else { 135 obj->Sampler.WrapS = GL_REPEAT; 136 obj->Sampler.WrapT = GL_REPEAT; 137 obj->Sampler.WrapR = GL_REPEAT; 138 obj->Sampler.MinFilter = GL_NEAREST_MIPMAP_LINEAR; 139 } 140 obj->Sampler.MagFilter = GL_LINEAR; 141 obj->Sampler.MinLod = -1000.0; 142 obj->Sampler.MaxLod = 1000.0; 143 obj->Sampler.LodBias = 0.0; 144 obj->Sampler.MaxAnisotropy = 1.0; 145 obj->Sampler.CompareMode = GL_NONE; /* ARB_shadow */ 146 obj->Sampler.CompareFunc = GL_LEQUAL; /* ARB_shadow */ 147 obj->DepthMode = GL_LUMINANCE; 148 obj->Sampler.CubeMapSeamless = GL_FALSE; 149 obj->Swizzle[0] = GL_RED; 150 obj->Swizzle[1] = GL_GREEN; 151 obj->Swizzle[2] = GL_BLUE; 152 obj->Swizzle[3] = GL_ALPHA; 153 obj->_Swizzle = SWIZZLE_NOOP; 154 obj->Sampler.sRGBDecode = GL_DECODE_EXT; 155 obj->BufferObjectFormat = GL_LUMINANCE8; 156 obj->_BufferObjectFormat = MESA_FORMAT_L8; 157} 158 159 160/** 161 * Some texture initialization can't be finished until we know which 162 * target it's getting bound to (GL_TEXTURE_1D/2D/etc). 163 */ 164static void 165finish_texture_init(struct gl_context *ctx, GLenum target, 166 struct gl_texture_object *obj) 167{ 168 assert(obj->Target == 0); 169 170 if (target == GL_TEXTURE_RECTANGLE_NV || 171 target == GL_TEXTURE_EXTERNAL_OES) { 172 /* have to init wrap and filter state here - kind of klunky */ 173 obj->Sampler.WrapS = GL_CLAMP_TO_EDGE; 174 obj->Sampler.WrapT = GL_CLAMP_TO_EDGE; 175 obj->Sampler.WrapR = GL_CLAMP_TO_EDGE; 176 obj->Sampler.MinFilter = GL_LINEAR; 177 if (ctx->Driver.TexParameter) { 178 static const GLfloat fparam_wrap[1] = {(GLfloat) GL_CLAMP_TO_EDGE}; 179 static const GLfloat fparam_filter[1] = {(GLfloat) GL_LINEAR}; 180 ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_S, fparam_wrap); 181 ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_T, fparam_wrap); 182 ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_R, fparam_wrap); 183 ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_MIN_FILTER, fparam_filter); 184 } 185 } 186} 187 188 189/** 190 * Deallocate a texture object struct. It should have already been 191 * removed from the texture object pool. 192 * Called via ctx->Driver.DeleteTexture() if not overriden by a driver. 193 * 194 * \param shared the shared GL state to which the object belongs. 195 * \param texObj the texture object to delete. 196 */ 197void 198_mesa_delete_texture_object(struct gl_context *ctx, 199 struct gl_texture_object *texObj) 200{ 201 GLuint i, face; 202 203 /* Set Target to an invalid value. With some assertions elsewhere 204 * we can try to detect possible use of deleted textures. 205 */ 206 texObj->Target = 0x99; 207 208 /* free the texture images */ 209 for (face = 0; face < 6; face++) { 210 for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { 211 if (texObj->Image[face][i]) { 212 ctx->Driver.DeleteTextureImage(ctx, texObj->Image[face][i]); 213 } 214 } 215 } 216 217 _mesa_reference_buffer_object(ctx, &texObj->BufferObject, NULL); 218 219 /* destroy the mutex -- it may have allocated memory (eg on bsd) */ 220 _glthread_DESTROY_MUTEX(texObj->Mutex); 221 222 /* free this object */ 223 free(texObj); 224} 225 226 227 228/** 229 * Copy texture object state from one texture object to another. 230 * Use for glPush/PopAttrib. 231 * 232 * \param dest destination texture object. 233 * \param src source texture object. 234 */ 235void 236_mesa_copy_texture_object( struct gl_texture_object *dest, 237 const struct gl_texture_object *src ) 238{ 239 dest->Target = src->Target; 240 dest->Name = src->Name; 241 dest->Priority = src->Priority; 242 dest->Sampler.BorderColor.f[0] = src->Sampler.BorderColor.f[0]; 243 dest->Sampler.BorderColor.f[1] = src->Sampler.BorderColor.f[1]; 244 dest->Sampler.BorderColor.f[2] = src->Sampler.BorderColor.f[2]; 245 dest->Sampler.BorderColor.f[3] = src->Sampler.BorderColor.f[3]; 246 dest->Sampler.WrapS = src->Sampler.WrapS; 247 dest->Sampler.WrapT = src->Sampler.WrapT; 248 dest->Sampler.WrapR = src->Sampler.WrapR; 249 dest->Sampler.MinFilter = src->Sampler.MinFilter; 250 dest->Sampler.MagFilter = src->Sampler.MagFilter; 251 dest->Sampler.MinLod = src->Sampler.MinLod; 252 dest->Sampler.MaxLod = src->Sampler.MaxLod; 253 dest->Sampler.LodBias = src->Sampler.LodBias; 254 dest->BaseLevel = src->BaseLevel; 255 dest->MaxLevel = src->MaxLevel; 256 dest->Sampler.MaxAnisotropy = src->Sampler.MaxAnisotropy; 257 dest->Sampler.CompareMode = src->Sampler.CompareMode; 258 dest->Sampler.CompareFunc = src->Sampler.CompareFunc; 259 dest->Sampler.CubeMapSeamless = src->Sampler.CubeMapSeamless; 260 dest->DepthMode = src->DepthMode; 261 dest->Sampler.sRGBDecode = src->Sampler.sRGBDecode; 262 dest->_MaxLevel = src->_MaxLevel; 263 dest->_MaxLambda = src->_MaxLambda; 264 dest->GenerateMipmap = src->GenerateMipmap; 265 dest->_BaseComplete = src->_BaseComplete; 266 dest->_MipmapComplete = src->_MipmapComplete; 267 COPY_4V(dest->Swizzle, src->Swizzle); 268 dest->_Swizzle = src->_Swizzle; 269 270 dest->RequiredTextureImageUnits = src->RequiredTextureImageUnits; 271} 272 273 274/** 275 * Free all texture images of the given texture object. 276 * 277 * \param ctx GL context. 278 * \param t texture object. 279 * 280 * \sa _mesa_clear_texture_image(). 281 */ 282void 283_mesa_clear_texture_object(struct gl_context *ctx, 284 struct gl_texture_object *texObj) 285{ 286 GLuint i, j; 287 288 if (texObj->Target == 0) 289 return; 290 291 for (i = 0; i < MAX_FACES; i++) { 292 for (j = 0; j < MAX_TEXTURE_LEVELS; j++) { 293 struct gl_texture_image *texImage = texObj->Image[i][j]; 294 if (texImage) 295 _mesa_clear_texture_image(ctx, texImage); 296 } 297 } 298} 299 300 301/** 302 * Check if the given texture object is valid by examining its Target field. 303 * For debugging only. 304 */ 305static GLboolean 306valid_texture_object(const struct gl_texture_object *tex) 307{ 308 switch (tex->Target) { 309 case 0: 310 case GL_TEXTURE_1D: 311 case GL_TEXTURE_2D: 312 case GL_TEXTURE_3D: 313 case GL_TEXTURE_CUBE_MAP_ARB: 314 case GL_TEXTURE_RECTANGLE_NV: 315 case GL_TEXTURE_1D_ARRAY_EXT: 316 case GL_TEXTURE_2D_ARRAY_EXT: 317 case GL_TEXTURE_BUFFER: 318 case GL_TEXTURE_EXTERNAL_OES: 319 return GL_TRUE; 320 case 0x99: 321 _mesa_problem(NULL, "invalid reference to a deleted texture object"); 322 return GL_FALSE; 323 default: 324 _mesa_problem(NULL, "invalid texture object Target 0x%x, Id = %u", 325 tex->Target, tex->Name); 326 return GL_FALSE; 327 } 328} 329 330 331/** 332 * Reference (or unreference) a texture object. 333 * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero). 334 * If 'tex' is non-null, increment its refcount. 335 * This is normally only called from the _mesa_reference_texobj() macro 336 * when there's a real pointer change. 337 */ 338void 339_mesa_reference_texobj_(struct gl_texture_object **ptr, 340 struct gl_texture_object *tex) 341{ 342 assert(ptr); 343 344 if (*ptr) { 345 /* Unreference the old texture */ 346 GLboolean deleteFlag = GL_FALSE; 347 struct gl_texture_object *oldTex = *ptr; 348 349 ASSERT(valid_texture_object(oldTex)); 350 (void) valid_texture_object; /* silence warning in release builds */ 351 352 _glthread_LOCK_MUTEX(oldTex->Mutex); 353 ASSERT(oldTex->RefCount > 0); 354 oldTex->RefCount--; 355 356 deleteFlag = (oldTex->RefCount == 0); 357 _glthread_UNLOCK_MUTEX(oldTex->Mutex); 358 359 if (deleteFlag) { 360 GET_CURRENT_CONTEXT(ctx); 361 if (ctx) 362 ctx->Driver.DeleteTexture(ctx, oldTex); 363 else 364 _mesa_problem(NULL, "Unable to delete texture, no context"); 365 } 366 367 *ptr = NULL; 368 } 369 assert(!*ptr); 370 371 if (tex) { 372 /* reference new texture */ 373 ASSERT(valid_texture_object(tex)); 374 _glthread_LOCK_MUTEX(tex->Mutex); 375 if (tex->RefCount == 0) { 376 /* this texture's being deleted (look just above) */ 377 /* Not sure this can every really happen. Warn if it does. */ 378 _mesa_problem(NULL, "referencing deleted texture object"); 379 *ptr = NULL; 380 } 381 else { 382 tex->RefCount++; 383 *ptr = tex; 384 } 385 _glthread_UNLOCK_MUTEX(tex->Mutex); 386 } 387} 388 389 390enum base_mipmap { BASE, MIPMAP }; 391 392 393/** 394 * Mark a texture object as incomplete. There are actually three kinds of 395 * (in)completeness: 396 * 1. "base incomplete": the base level of the texture is invalid so no 397 * texturing is possible. 398 * 2. "mipmap incomplete": a non-base level of the texture is invalid so 399 * mipmap filtering isn't possible, but non-mipmap filtering is. 400 * 3. "texture incompleteness": some combination of texture state and 401 * sampler state renders the texture incomplete. 402 * 403 * \param t texture object 404 * \param bm either BASE or MIPMAP to indicate what's incomplete 405 * \param fmt... string describing why it's incomplete (for debugging). 406 */ 407static void 408incomplete(struct gl_texture_object *t, enum base_mipmap bm, 409 const char *fmt, ...) 410{ 411 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_TEXTURE) { 412 va_list args; 413 char s[100]; 414 415 va_start(args, fmt); 416 vsnprintf(s, sizeof(s), fmt, args); 417 va_end(args); 418 419 _mesa_debug(NULL, "Texture Obj %d incomplete because: %s\n", t->Name, s); 420 } 421 422 if (bm == BASE) 423 t->_BaseComplete = GL_FALSE; 424 t->_MipmapComplete = GL_FALSE; 425} 426 427 428/** 429 * Examine a texture object to determine if it is complete. 430 * 431 * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE 432 * accordingly. 433 * 434 * \param ctx GL context. 435 * \param t texture object. 436 * 437 * According to the texture target, verifies that each of the mipmaps is 438 * present and has the expected size. 439 */ 440void 441_mesa_test_texobj_completeness( const struct gl_context *ctx, 442 struct gl_texture_object *t ) 443{ 444 const GLint baseLevel = t->BaseLevel; 445 const struct gl_texture_image *baseImage; 446 GLint maxLog2 = 0, maxLevels = 0; 447 448 /* We'll set these to FALSE if tests fail below */ 449 t->_BaseComplete = GL_TRUE; 450 t->_MipmapComplete = GL_TRUE; 451 452 if (t->Target == GL_TEXTURE_BUFFER) { 453 /* Buffer textures are always considered complete. The obvious case where 454 * they would be incomplete (no BO attached) is actually specced to be 455 * undefined rendering results. 456 */ 457 return; 458 } 459 460 /* Detect cases where the application set the base level to an invalid 461 * value. 462 */ 463 if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS)) { 464 incomplete(t, BASE, "base level = %d is invalid", baseLevel); 465 return; 466 } 467 468 if (t->MaxLevel < baseLevel) { 469 incomplete(t, BASE, "MAX_LEVEL (%d) < BASE_LEVEL (%d)", 470 t->MaxLevel, baseLevel); 471 return; 472 } 473 474 baseImage = t->Image[0][baseLevel]; 475 476 /* Always need the base level image */ 477 if (!baseImage) { 478 incomplete(t, BASE, "Image[baseLevel=%d] == NULL", baseLevel); 479 return; 480 } 481 482 /* Check width/height/depth for zero */ 483 if (baseImage->Width == 0 || 484 baseImage->Height == 0 || 485 baseImage->Depth == 0) { 486 incomplete(t, BASE, "texture width or height or depth = 0"); 487 return; 488 } 489 490 /* Check if the texture values are integer */ 491 { 492 GLenum datatype = _mesa_get_format_datatype(baseImage->TexFormat); 493 t->_IsIntegerFormat = datatype == GL_INT || datatype == GL_UNSIGNED_INT; 494 } 495 496 /* Compute _MaxLevel (the maximum mipmap level we'll sample from given the 497 * mipmap image sizes and GL_TEXTURE_MAX_LEVEL state). 498 */ 499 switch (t->Target) { 500 case GL_TEXTURE_1D: 501 case GL_TEXTURE_1D_ARRAY_EXT: 502 maxLog2 = baseImage->WidthLog2; 503 maxLevels = ctx->Const.MaxTextureLevels; 504 break; 505 case GL_TEXTURE_2D: 506 case GL_TEXTURE_2D_ARRAY_EXT: 507 maxLog2 = MAX2(baseImage->WidthLog2, 508 baseImage->HeightLog2); 509 maxLevels = ctx->Const.MaxTextureLevels; 510 break; 511 case GL_TEXTURE_3D: 512 maxLog2 = MAX3(baseImage->WidthLog2, 513 baseImage->HeightLog2, 514 baseImage->DepthLog2); 515 maxLevels = ctx->Const.Max3DTextureLevels; 516 break; 517 case GL_TEXTURE_CUBE_MAP_ARB: 518 maxLog2 = MAX2(baseImage->WidthLog2, 519 baseImage->HeightLog2); 520 maxLevels = ctx->Const.MaxCubeTextureLevels; 521 break; 522 case GL_TEXTURE_RECTANGLE_NV: 523 case GL_TEXTURE_BUFFER: 524 case GL_TEXTURE_EXTERNAL_OES: 525 maxLog2 = 0; /* not applicable */ 526 maxLevels = 1; /* no mipmapping */ 527 break; 528 default: 529 _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness"); 530 return; 531 } 532 533 ASSERT(maxLevels > 0); 534 535 t->_MaxLevel = baseLevel + maxLog2; /* 'p' in the GL spec */ 536 t->_MaxLevel = MIN2(t->_MaxLevel, t->MaxLevel); 537 t->_MaxLevel = MIN2(t->_MaxLevel, maxLevels - 1); /* 'q' in the GL spec */ 538 539 /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */ 540 t->_MaxLambda = (GLfloat) (t->_MaxLevel - baseLevel); 541 542 if (t->Immutable) { 543 /* This texture object was created with glTexStorage1/2/3D() so we 544 * know that all the mipmap levels are the right size and all cube 545 * map faces are the same size. 546 * We don't need to do any of the additional checks below. 547 */ 548 return; 549 } 550 551 if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) { 552 /* Make sure that all six cube map level 0 images are the same size. 553 * Note: we know that the image's width==height (we enforce that 554 * at glTexImage time) so we only need to test the width here. 555 */ 556 GLuint face; 557 assert(baseImage->Width2 == baseImage->Height); 558 for (face = 1; face < 6; face++) { 559 assert(t->Image[face][baseLevel] == NULL || 560 t->Image[face][baseLevel]->Width2 == 561 t->Image[face][baseLevel]->Height2); 562 if (t->Image[face][baseLevel] == NULL || 563 t->Image[face][baseLevel]->Width2 != baseImage->Width2) { 564 incomplete(t, BASE, "Cube face missing or mismatched size"); 565 return; 566 } 567 } 568 } 569 570 /* 571 * Do mipmap consistency checking. 572 * Note: we don't care about the current texture sampler state here. 573 * To determine texture completeness we'll either look at _BaseComplete 574 * or _MipmapComplete depending on the current minification filter mode. 575 */ 576 { 577 GLint i; 578 const GLint minLevel = baseLevel; 579 const GLint maxLevel = t->_MaxLevel; 580 const GLuint numFaces = _mesa_num_tex_faces(t->Target); 581 GLuint width, height, depth, face; 582 583 if (minLevel > maxLevel) { 584 incomplete(t, BASE, "minLevel > maxLevel"); 585 return; 586 } 587 588 /* Get the base image's dimensions */ 589 width = baseImage->Width2; 590 height = baseImage->Height2; 591 depth = baseImage->Depth2; 592 593 /* Note: this loop will be a no-op for RECT, BUFFER, EXTERNAL textures */ 594 for (i = baseLevel + 1; i < maxLevels; i++) { 595 /* Compute the expected size of image at level[i] */ 596 if (width > 1) { 597 width /= 2; 598 } 599 if (height > 1 && t->Target != GL_TEXTURE_1D_ARRAY) { 600 height /= 2; 601 } 602 if (depth > 1 && t->Target != GL_TEXTURE_2D_ARRAY) { 603 depth /= 2; 604 } 605 606 /* loop over cube faces (or single face otherwise) */ 607 for (face = 0; face < numFaces; face++) { 608 if (i >= minLevel && i <= maxLevel) { 609 const struct gl_texture_image *img = t->Image[face][i]; 610 611 if (!img) { 612 incomplete(t, MIPMAP, "TexImage[%d] is missing", i); 613 return; 614 } 615 if (img->TexFormat != baseImage->TexFormat) { 616 incomplete(t, MIPMAP, "Format[i] != Format[baseLevel]"); 617 return; 618 } 619 if (img->Border != baseImage->Border) { 620 incomplete(t, MIPMAP, "Border[i] != Border[baseLevel]"); 621 return; 622 } 623 if (img->Width2 != width) { 624 incomplete(t, MIPMAP, "TexImage[%d] bad width %u", i, img->Width2); 625 return; 626 } 627 if (img->Height2 != height) { 628 incomplete(t, MIPMAP, "TexImage[%d] bad height %u", i, img->Height2); 629 return; 630 } 631 if (img->Depth2 != depth) { 632 incomplete(t, MIPMAP, "TexImage[%d] bad depth %u", i, img->Depth2); 633 return; 634 } 635 636 /* Extra checks for cube textures */ 637 if (face > 0) { 638 /* check that cube faces are the same size */ 639 if (img->Width2 != t->Image[0][i]->Width2 || 640 img->Height2 != t->Image[0][i]->Height2) { 641 incomplete(t, MIPMAP, "CubeMap Image[n][i] bad size"); 642 return; 643 } 644 } 645 } 646 } 647 648 if (width == 1 && height == 1 && depth == 1) { 649 return; /* found smallest needed mipmap, all done! */ 650 } 651 } 652 } 653} 654 655 656/** 657 * Check if the given cube map texture is "cube complete" as defined in 658 * the OpenGL specification. 659 */ 660GLboolean 661_mesa_cube_complete(const struct gl_texture_object *texObj) 662{ 663 const GLint baseLevel = texObj->BaseLevel; 664 const struct gl_texture_image *img0, *img; 665 GLuint face; 666 667 if (texObj->Target != GL_TEXTURE_CUBE_MAP) 668 return GL_FALSE; 669 670 if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS)) 671 return GL_FALSE; 672 673 /* check first face */ 674 img0 = texObj->Image[0][baseLevel]; 675 if (!img0 || 676 img0->Width < 1 || 677 img0->Width != img0->Height) 678 return GL_FALSE; 679 680 /* check remaining faces vs. first face */ 681 for (face = 1; face < 6; face++) { 682 img = texObj->Image[face][baseLevel]; 683 if (!img || 684 img->Width != img0->Width || 685 img->Height != img0->Height || 686 img->TexFormat != img0->TexFormat) 687 return GL_FALSE; 688 } 689 690 return GL_TRUE; 691} 692 693 694/** 695 * Mark a texture object dirty. It forces the object to be incomplete 696 * and optionally forces the context to re-validate its state. 697 * 698 * \param ctx GL context. 699 * \param texObj texture object. 700 * \param invalidate_state also invalidate context state. 701 */ 702void 703_mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj, 704 GLboolean invalidate_state) 705{ 706 texObj->_BaseComplete = GL_FALSE; 707 texObj->_MipmapComplete = GL_FALSE; 708 if (invalidate_state) 709 ctx->NewState |= _NEW_TEXTURE; 710} 711 712 713/** 714 * Return pointer to a default/fallback texture of the given type/target. 715 * The texture is an RGBA texture with all texels = (0,0,0,1). 716 * That's the value a GLSL sampler should get when sampling from an 717 * incomplete texture. 718 */ 719struct gl_texture_object * 720_mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex) 721{ 722 if (!ctx->Shared->FallbackTex[tex]) { 723 /* create fallback texture now */ 724 const GLsizei width = 1, height = 1, depth = 1; 725 GLubyte texel[4]; 726 struct gl_texture_object *texObj; 727 struct gl_texture_image *texImage; 728 gl_format texFormat; 729 GLuint dims, face, numFaces = 1; 730 GLenum target; 731 732 texel[0] = 733 texel[1] = 734 texel[2] = 0x0; 735 texel[3] = 0xff; 736 737 switch (tex) { 738 case TEXTURE_2D_ARRAY_INDEX: 739 dims = 3; 740 target = GL_TEXTURE_2D_ARRAY; 741 break; 742 case TEXTURE_1D_ARRAY_INDEX: 743 dims = 2; 744 target = GL_TEXTURE_1D_ARRAY; 745 break; 746 case TEXTURE_CUBE_INDEX: 747 dims = 2; 748 target = GL_TEXTURE_CUBE_MAP; 749 numFaces = 6; 750 break; 751 case TEXTURE_3D_INDEX: 752 dims = 3; 753 target = GL_TEXTURE_3D; 754 break; 755 case TEXTURE_RECT_INDEX: 756 dims = 2; 757 target = GL_TEXTURE_RECTANGLE; 758 break; 759 case TEXTURE_2D_INDEX: 760 dims = 2; 761 target = GL_TEXTURE_2D; 762 break; 763 case TEXTURE_1D_INDEX: 764 dims = 1; 765 target = GL_TEXTURE_1D; 766 break; 767 case TEXTURE_BUFFER_INDEX: 768 dims = 0; 769 target = GL_TEXTURE_BUFFER; 770 break; 771 case TEXTURE_EXTERNAL_INDEX: 772 dims = 2; 773 target = GL_TEXTURE_EXTERNAL_OES; 774 break; 775 default: 776 /* no-op */ 777 return NULL; 778 } 779 780 /* create texture object */ 781 texObj = ctx->Driver.NewTextureObject(ctx, 0, target); 782 if (!texObj) 783 return NULL; 784 785 assert(texObj->RefCount == 1); 786 texObj->Sampler.MinFilter = GL_NEAREST; 787 texObj->Sampler.MagFilter = GL_NEAREST; 788 789 texFormat = ctx->Driver.ChooseTextureFormat(ctx, target, 790 GL_RGBA, GL_RGBA, 791 GL_UNSIGNED_BYTE); 792 793 /* need a loop here just for cube maps */ 794 for (face = 0; face < numFaces; face++) { 795 GLenum faceTarget; 796 797 if (target == GL_TEXTURE_CUBE_MAP) 798 faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; 799 else 800 faceTarget = target; 801 802 /* initialize level[0] texture image */ 803 texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, 0); 804 805 _mesa_init_teximage_fields(ctx, texImage, 806 width, 807 (dims > 1) ? height : 1, 808 (dims > 2) ? depth : 1, 809 0, /* border */ 810 GL_RGBA, texFormat); 811 812 ctx->Driver.TexImage(ctx, dims, texImage, 813 GL_RGBA, GL_UNSIGNED_BYTE, texel, 814 &ctx->DefaultPacking); 815 } 816 817 _mesa_test_texobj_completeness(ctx, texObj); 818 assert(texObj->_BaseComplete); 819 assert(texObj->_MipmapComplete); 820 821 ctx->Shared->FallbackTex[tex] = texObj; 822 } 823 return ctx->Shared->FallbackTex[tex]; 824} 825 826 827/** 828 * Compute the size of the given texture object, in bytes. 829 */ 830static GLuint 831texture_size(const struct gl_texture_object *texObj) 832{ 833 const GLuint numFaces = _mesa_num_tex_faces(texObj->Target); 834 GLuint face, level, size = 0; 835 836 for (face = 0; face < numFaces; face++) { 837 for (level = 0; level < MAX_TEXTURE_LEVELS; level++) { 838 const struct gl_texture_image *img = texObj->Image[face][level]; 839 if (img) { 840 GLuint sz = _mesa_format_image_size(img->TexFormat, img->Width, 841 img->Height, img->Depth); 842 size += sz; 843 } 844 } 845 } 846 847 return size; 848} 849 850 851/** 852 * Callback called from _mesa_HashWalk() 853 */ 854static void 855count_tex_size(GLuint key, void *data, void *userData) 856{ 857 const struct gl_texture_object *texObj = 858 (const struct gl_texture_object *) data; 859 GLuint *total = (GLuint *) userData; 860 861 *total = *total + texture_size(texObj); 862} 863 864 865/** 866 * Compute total size (in bytes) of all textures for the given context. 867 * For debugging purposes. 868 */ 869GLuint 870_mesa_total_texture_memory(struct gl_context *ctx) 871{ 872 GLuint tgt, total = 0; 873 874 _mesa_HashWalk(ctx->Shared->TexObjects, count_tex_size, &total); 875 876 /* plus, the default texture objects */ 877 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { 878 total += texture_size(ctx->Shared->DefaultTex[tgt]); 879 } 880 881 return total; 882} 883 884static struct gl_texture_object * 885invalidate_tex_image_error_check(struct gl_context *ctx, GLuint texture, 886 GLint level, const char *name) 887{ 888 /* The GL_ARB_invalidate_subdata spec says: 889 * 890 * "If <texture> is zero or is not the name of a texture, the error 891 * INVALID_VALUE is generated." 892 * 893 * This performs the error check in a different order than listed in the 894 * spec. We have to get the texture object before we can validate the 895 * other parameters against values in the texture object. 896 */ 897 struct gl_texture_object *const t = _mesa_lookup_texture(ctx, texture); 898 if (texture == 0 || t == NULL) { 899 _mesa_error(ctx, GL_INVALID_VALUE, "%s(texture)", name); 900 return NULL; 901 } 902 903 /* The GL_ARB_invalidate_subdata spec says: 904 * 905 * "If <level> is less than zero or greater than the base 2 logarithm 906 * of the maximum texture width, height, or depth, the error 907 * INVALID_VALUE is generated." 908 */ 909 if (level < 0 || level > t->MaxLevel) { 910 _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name); 911 return NULL; 912 } 913 914 /* The GL_ARB_invalidate_subdata spec says: 915 * 916 * "If the target of <texture> is TEXTURE_RECTANGLE, TEXTURE_BUFFER, 917 * TEXTURE_2D_MULTISAMPLE, or TEXTURE_2D_MULTISAMPLE_ARRAY, and <level> 918 * is not zero, the error INVALID_VALUE is generated." 919 */ 920 if (level != 0) { 921 switch (t->Target) { 922 case GL_TEXTURE_RECTANGLE: 923 case GL_TEXTURE_BUFFER: 924 case GL_TEXTURE_2D_MULTISAMPLE: 925 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 926 _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name); 927 return NULL; 928 929 default: 930 break; 931 } 932 } 933 934 return t; 935} 936 937/*@}*/ 938 939 940/***********************************************************************/ 941/** \name API functions */ 942/*@{*/ 943 944 945/** 946 * Generate texture names. 947 * 948 * \param n number of texture names to be generated. 949 * \param textures an array in which will hold the generated texture names. 950 * 951 * \sa glGenTextures(). 952 * 953 * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture 954 * IDs which are stored in \p textures. Corresponding empty texture 955 * objects are also generated. 956 */ 957void GLAPIENTRY 958_mesa_GenTextures( GLsizei n, GLuint *textures ) 959{ 960 GET_CURRENT_CONTEXT(ctx); 961 GLuint first; 962 GLint i; 963 ASSERT_OUTSIDE_BEGIN_END(ctx); 964 965 if (n < 0) { 966 _mesa_error( ctx, GL_INVALID_VALUE, "glGenTextures" ); 967 return; 968 } 969 970 if (!textures) 971 return; 972 973 /* 974 * This must be atomic (generation and allocation of texture IDs) 975 */ 976 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 977 978 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n); 979 980 /* Allocate new, empty texture objects */ 981 for (i = 0; i < n; i++) { 982 struct gl_texture_object *texObj; 983 GLuint name = first + i; 984 GLenum target = 0; 985 texObj = ctx->Driver.NewTextureObject(ctx, name, target); 986 if (!texObj) { 987 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 988 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures"); 989 return; 990 } 991 992 /* insert into hash table */ 993 _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj); 994 995 textures[i] = name; 996 } 997 998 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 999} 1000 1001 1002/** 1003 * Check if the given texture object is bound to the current draw or 1004 * read framebuffer. If so, Unbind it. 1005 */ 1006static void 1007unbind_texobj_from_fbo(struct gl_context *ctx, 1008 struct gl_texture_object *texObj) 1009{ 1010 const GLuint n = (ctx->DrawBuffer == ctx->ReadBuffer) ? 1 : 2; 1011 GLuint i; 1012 1013 for (i = 0; i < n; i++) { 1014 struct gl_framebuffer *fb = (i == 0) ? ctx->DrawBuffer : ctx->ReadBuffer; 1015 if (_mesa_is_user_fbo(fb)) { 1016 GLuint j; 1017 for (j = 0; j < BUFFER_COUNT; j++) { 1018 if (fb->Attachment[j].Type == GL_TEXTURE && 1019 fb->Attachment[j].Texture == texObj) { 1020 /* Vertices are already flushed by _mesa_DeleteTextures */ 1021 ctx->NewState |= _NEW_BUFFERS; 1022 _mesa_remove_attachment(ctx, fb->Attachment + j); 1023 } 1024 } 1025 } 1026 } 1027} 1028 1029 1030/** 1031 * Check if the given texture object is bound to any texture image units and 1032 * unbind it if so (revert to default textures). 1033 */ 1034static void 1035unbind_texobj_from_texunits(struct gl_context *ctx, 1036 struct gl_texture_object *texObj) 1037{ 1038 GLuint u, tex; 1039 1040 for (u = 0; u < Elements(ctx->Texture.Unit); u++) { 1041 struct gl_texture_unit *unit = &ctx->Texture.Unit[u]; 1042 for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) { 1043 if (texObj == unit->CurrentTex[tex]) { 1044 _mesa_reference_texobj(&unit->CurrentTex[tex], 1045 ctx->Shared->DefaultTex[tex]); 1046 ASSERT(unit->CurrentTex[tex]); 1047 break; 1048 } 1049 } 1050 } 1051} 1052 1053 1054/** 1055 * Delete named textures. 1056 * 1057 * \param n number of textures to be deleted. 1058 * \param textures array of texture IDs to be deleted. 1059 * 1060 * \sa glDeleteTextures(). 1061 * 1062 * If we're about to delete a texture that's currently bound to any 1063 * texture unit, unbind the texture first. Decrement the reference 1064 * count on the texture object and delete it if it's zero. 1065 * Recall that texture objects can be shared among several rendering 1066 * contexts. 1067 */ 1068void GLAPIENTRY 1069_mesa_DeleteTextures( GLsizei n, const GLuint *textures) 1070{ 1071 GET_CURRENT_CONTEXT(ctx); 1072 GLint i; 1073 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */ 1074 1075 if (!textures) 1076 return; 1077 1078 for (i = 0; i < n; i++) { 1079 if (textures[i] > 0) { 1080 struct gl_texture_object *delObj 1081 = _mesa_lookup_texture(ctx, textures[i]); 1082 1083 if (delObj) { 1084 _mesa_lock_texture(ctx, delObj); 1085 1086 /* Check if texture is bound to any framebuffer objects. 1087 * If so, unbind. 1088 * See section 4.4.2.3 of GL_EXT_framebuffer_object. 1089 */ 1090 unbind_texobj_from_fbo(ctx, delObj); 1091 1092 /* Check if this texture is currently bound to any texture units. 1093 * If so, unbind it. 1094 */ 1095 unbind_texobj_from_texunits(ctx, delObj); 1096 1097 _mesa_unlock_texture(ctx, delObj); 1098 1099 ctx->NewState |= _NEW_TEXTURE; 1100 1101 /* The texture _name_ is now free for re-use. 1102 * Remove it from the hash table now. 1103 */ 1104 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 1105 _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name); 1106 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 1107 1108 /* Unreference the texobj. If refcount hits zero, the texture 1109 * will be deleted. 1110 */ 1111 _mesa_reference_texobj(&delObj, NULL); 1112 } 1113 } 1114 } 1115} 1116 1117 1118/** 1119 * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D 1120 * into the corresponding Mesa texture target index. 1121 * Note that proxy targets are not valid here. 1122 * \return TEXTURE_x_INDEX or -1 if target is invalid 1123 */ 1124static GLint 1125target_enum_to_index(struct gl_context *ctx, GLenum target) 1126{ 1127 switch (target) { 1128 case GL_TEXTURE_1D: 1129 return _mesa_is_desktop_gl(ctx) ? TEXTURE_1D_INDEX : -1; 1130 case GL_TEXTURE_2D: 1131 return TEXTURE_2D_INDEX; 1132 case GL_TEXTURE_3D: 1133 return TEXTURE_3D_INDEX; 1134 case GL_TEXTURE_CUBE_MAP_ARB: 1135 return ctx->Extensions.ARB_texture_cube_map 1136 ? TEXTURE_CUBE_INDEX : -1; 1137 case GL_TEXTURE_RECTANGLE_NV: 1138 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle 1139 ? TEXTURE_RECT_INDEX : -1; 1140 case GL_TEXTURE_1D_ARRAY_EXT: 1141 return _mesa_is_desktop_gl(ctx) 1142 && (ctx->Extensions.EXT_texture_array 1143 || ctx->Extensions.MESA_texture_array) 1144 ? TEXTURE_1D_ARRAY_INDEX : -1; 1145 case GL_TEXTURE_2D_ARRAY_EXT: 1146 return (_mesa_is_desktop_gl(ctx) 1147 && (ctx->Extensions.EXT_texture_array 1148 || ctx->Extensions.MESA_texture_array)) 1149 || _mesa_is_gles3(ctx) 1150 ? TEXTURE_2D_ARRAY_INDEX : -1; 1151 case GL_TEXTURE_BUFFER_ARB: 1152 return _mesa_is_desktop_gl(ctx) 1153 && ctx->Extensions.ARB_texture_buffer_object 1154 ? TEXTURE_BUFFER_INDEX : -1; 1155 case GL_TEXTURE_EXTERNAL_OES: 1156 return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external 1157 ? TEXTURE_EXTERNAL_INDEX : -1; 1158 default: 1159 return -1; 1160 } 1161} 1162 1163 1164/** 1165 * Bind a named texture to a texturing target. 1166 * 1167 * \param target texture target. 1168 * \param texName texture name. 1169 * 1170 * \sa glBindTexture(). 1171 * 1172 * Determines the old texture object bound and returns immediately if rebinding 1173 * the same texture. Get the current texture which is either a default texture 1174 * if name is null, a named texture from the hash, or a new texture if the 1175 * given texture name is new. Increments its reference count, binds it, and 1176 * calls dd_function_table::BindTexture. Decrements the old texture reference 1177 * count and deletes it if it reaches zero. 1178 */ 1179void GLAPIENTRY 1180_mesa_BindTexture( GLenum target, GLuint texName ) 1181{ 1182 GET_CURRENT_CONTEXT(ctx); 1183 struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); 1184 struct gl_texture_object *newTexObj = NULL; 1185 GLint targetIndex; 1186 ASSERT_OUTSIDE_BEGIN_END(ctx); 1187 1188 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 1189 _mesa_debug(ctx, "glBindTexture %s %d\n", 1190 _mesa_lookup_enum_by_nr(target), (GLint) texName); 1191 1192 targetIndex = target_enum_to_index(ctx, target); 1193 if (targetIndex < 0) { 1194 _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target)"); 1195 return; 1196 } 1197 assert(targetIndex < NUM_TEXTURE_TARGETS); 1198 1199 /* 1200 * Get pointer to new texture object (newTexObj) 1201 */ 1202 if (texName == 0) { 1203 /* Use a default texture object */ 1204 newTexObj = ctx->Shared->DefaultTex[targetIndex]; 1205 } 1206 else { 1207 /* non-default texture object */ 1208 newTexObj = _mesa_lookup_texture(ctx, texName); 1209 if (newTexObj) { 1210 /* error checking */ 1211 if (newTexObj->Target != 0 && newTexObj->Target != target) { 1212 /* the named texture object's target doesn't match the given target */ 1213 _mesa_error( ctx, GL_INVALID_OPERATION, 1214 "glBindTexture(target mismatch)" ); 1215 return; 1216 } 1217 if (newTexObj->Target == 0) { 1218 finish_texture_init(ctx, target, newTexObj); 1219 } 1220 } 1221 else { 1222 if (ctx->API == API_OPENGL_CORE) { 1223 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindTexture"); 1224 return; 1225 } 1226 1227 /* if this is a new texture id, allocate a texture object now */ 1228 newTexObj = ctx->Driver.NewTextureObject(ctx, texName, target); 1229 if (!newTexObj) { 1230 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture"); 1231 return; 1232 } 1233 1234 /* and insert it into hash table */ 1235 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 1236 _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj); 1237 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 1238 } 1239 newTexObj->Target = target; 1240 } 1241 1242 assert(valid_texture_object(newTexObj)); 1243 1244 /* Check if this texture is only used by this context and is already bound. 1245 * If so, just return. 1246 */ 1247 { 1248 GLboolean early_out; 1249 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 1250 early_out = ((ctx->Shared->RefCount == 1) 1251 && (newTexObj == texUnit->CurrentTex[targetIndex])); 1252 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 1253 if (early_out) { 1254 return; 1255 } 1256 } 1257 1258 /* flush before changing binding */ 1259 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 1260 1261 /* Do the actual binding. The refcount on the previously bound 1262 * texture object will be decremented. It'll be deleted if the 1263 * count hits zero. 1264 */ 1265 _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], newTexObj); 1266 ASSERT(texUnit->CurrentTex[targetIndex]); 1267 1268 /* Pass BindTexture call to device driver */ 1269 if (ctx->Driver.BindTexture) 1270 ctx->Driver.BindTexture(ctx, target, newTexObj); 1271} 1272 1273 1274/** 1275 * Set texture priorities. 1276 * 1277 * \param n number of textures. 1278 * \param texName texture names. 1279 * \param priorities corresponding texture priorities. 1280 * 1281 * \sa glPrioritizeTextures(). 1282 * 1283 * Looks up each texture in the hash, clamps the corresponding priority between 1284 * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture. 1285 */ 1286void GLAPIENTRY 1287_mesa_PrioritizeTextures( GLsizei n, const GLuint *texName, 1288 const GLclampf *priorities ) 1289{ 1290 GET_CURRENT_CONTEXT(ctx); 1291 GLint i; 1292 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1293 1294 if (n < 0) { 1295 _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" ); 1296 return; 1297 } 1298 1299 if (!priorities) 1300 return; 1301 1302 for (i = 0; i < n; i++) { 1303 if (texName[i] > 0) { 1304 struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]); 1305 if (t) { 1306 t->Priority = CLAMP( priorities[i], 0.0F, 1.0F ); 1307 } 1308 } 1309 } 1310 1311 ctx->NewState |= _NEW_TEXTURE; 1312} 1313 1314 1315 1316/** 1317 * See if textures are loaded in texture memory. 1318 * 1319 * \param n number of textures to query. 1320 * \param texName array with the texture names. 1321 * \param residences array which will hold the residence status. 1322 * 1323 * \return GL_TRUE if all textures are resident and \p residences is left unchanged, 1324 * 1325 * Note: we assume all textures are always resident 1326 */ 1327GLboolean GLAPIENTRY 1328_mesa_AreTexturesResident(GLsizei n, const GLuint *texName, 1329 GLboolean *residences) 1330{ 1331 GET_CURRENT_CONTEXT(ctx); 1332 GLboolean allResident = GL_TRUE; 1333 GLint i; 1334 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 1335 1336 if (n < 0) { 1337 _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)"); 1338 return GL_FALSE; 1339 } 1340 1341 if (!texName || !residences) 1342 return GL_FALSE; 1343 1344 /* We only do error checking on the texture names */ 1345 for (i = 0; i < n; i++) { 1346 struct gl_texture_object *t; 1347 if (texName[i] == 0) { 1348 _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident"); 1349 return GL_FALSE; 1350 } 1351 t = _mesa_lookup_texture(ctx, texName[i]); 1352 if (!t) { 1353 _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident"); 1354 return GL_FALSE; 1355 } 1356 } 1357 1358 return allResident; 1359} 1360 1361 1362/** 1363 * See if a name corresponds to a texture. 1364 * 1365 * \param texture texture name. 1366 * 1367 * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE 1368 * otherwise. 1369 * 1370 * \sa glIsTexture(). 1371 * 1372 * Calls _mesa_HashLookup(). 1373 */ 1374GLboolean GLAPIENTRY 1375_mesa_IsTexture( GLuint texture ) 1376{ 1377 struct gl_texture_object *t; 1378 GET_CURRENT_CONTEXT(ctx); 1379 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 1380 1381 if (!texture) 1382 return GL_FALSE; 1383 1384 t = _mesa_lookup_texture(ctx, texture); 1385 1386 /* IsTexture is true only after object has been bound once. */ 1387 return t && t->Target; 1388} 1389 1390 1391/** 1392 * Simplest implementation of texture locking: grab the shared tex 1393 * mutex. Examine the shared context state timestamp and if there has 1394 * been a change, set the appropriate bits in ctx->NewState. 1395 * 1396 * This is used to deal with synchronizing things when a texture object 1397 * is used/modified by different contexts (or threads) which are sharing 1398 * the texture. 1399 * 1400 * See also _mesa_lock/unlock_texture() in teximage.h 1401 */ 1402void 1403_mesa_lock_context_textures( struct gl_context *ctx ) 1404{ 1405 _glthread_LOCK_MUTEX(ctx->Shared->TexMutex); 1406 1407 if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) { 1408 ctx->NewState |= _NEW_TEXTURE; 1409 ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp; 1410 } 1411} 1412 1413 1414void 1415_mesa_unlock_context_textures( struct gl_context *ctx ) 1416{ 1417 assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp); 1418 _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex); 1419} 1420 1421void GLAPIENTRY 1422_mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset, 1423 GLint yoffset, GLint zoffset, GLsizei width, 1424 GLsizei height, GLsizei depth) 1425{ 1426 struct gl_texture_object *t; 1427 struct gl_texture_image *image; 1428 GET_CURRENT_CONTEXT(ctx); 1429 1430 ASSERT_OUTSIDE_BEGIN_END(ctx); 1431 1432 t = invalidate_tex_image_error_check(ctx, texture, level, 1433 "glInvalidateTexSubImage"); 1434 1435 /* The GL_ARB_invalidate_subdata spec says: 1436 * 1437 * "...the specified subregion must be between -<b> and <dim>+<b> where 1438 * <dim> is the size of the dimension of the texture image, and <b> is 1439 * the size of the border of that texture image, otherwise 1440 * INVALID_VALUE is generated (border is not applied to dimensions that 1441 * don't exist in a given texture target)." 1442 */ 1443 image = t->Image[0][level]; 1444 if (image) { 1445 int xBorder; 1446 int yBorder; 1447 int zBorder; 1448 int imageWidth; 1449 int imageHeight; 1450 int imageDepth; 1451 1452 /* The GL_ARB_invalidate_subdata spec says: 1453 * 1454 * "For texture targets that don't have certain dimensions, this 1455 * command treats those dimensions as having a size of 1. For 1456 * example, to invalidate a portion of a two-dimensional texture, 1457 * the application would use <zoffset> equal to zero and <depth> 1458 * equal to one." 1459 */ 1460 switch (t->Target) { 1461 case GL_TEXTURE_BUFFER: 1462 xBorder = 0; 1463 yBorder = 0; 1464 zBorder = 0; 1465 imageWidth = 1; 1466 imageHeight = 1; 1467 imageDepth = 1; 1468 break; 1469 case GL_TEXTURE_1D: 1470 xBorder = image->Border; 1471 yBorder = 0; 1472 zBorder = 0; 1473 imageWidth = image->Width; 1474 imageHeight = 1; 1475 imageDepth = 1; 1476 break; 1477 case GL_TEXTURE_1D_ARRAY: 1478 xBorder = image->Border; 1479 yBorder = 0; 1480 zBorder = 0; 1481 imageWidth = image->Width; 1482 imageHeight = image->Height; 1483 imageDepth = 1; 1484 break; 1485 case GL_TEXTURE_2D: 1486 case GL_TEXTURE_CUBE_MAP: 1487 case GL_TEXTURE_RECTANGLE: 1488 case GL_TEXTURE_2D_MULTISAMPLE: 1489 xBorder = image->Border; 1490 yBorder = image->Border; 1491 zBorder = 0; 1492 imageWidth = image->Width; 1493 imageHeight = image->Height; 1494 imageDepth = 1; 1495 break; 1496 case GL_TEXTURE_2D_ARRAY: 1497 case GL_TEXTURE_CUBE_MAP_ARRAY: 1498 xBorder = image->Border; 1499 yBorder = image->Border; 1500 zBorder = 0; 1501 imageWidth = image->Width; 1502 imageHeight = image->Height; 1503 imageDepth = image->Depth; 1504 break; 1505 case GL_TEXTURE_3D: 1506 xBorder = image->Border; 1507 yBorder = image->Border; 1508 zBorder = image->Border; 1509 imageWidth = image->Width; 1510 imageHeight = image->Height; 1511 imageDepth = image->Depth; 1512 break; 1513 default: 1514 assert(!"Should not get here."); 1515 xBorder = 0; 1516 yBorder = 0; 1517 zBorder = 0; 1518 imageWidth = 0; 1519 imageHeight = 0; 1520 imageDepth = 0; 1521 break; 1522 } 1523 1524 if (xoffset < -xBorder) { 1525 _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(xoffset)"); 1526 return; 1527 } 1528 1529 if (xoffset + width > imageWidth + xBorder) { 1530 _mesa_error(ctx, GL_INVALID_VALUE, 1531 "glInvalidateSubTexImage(xoffset+width)"); 1532 return; 1533 } 1534 1535 if (yoffset < -yBorder) { 1536 _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(yoffset)"); 1537 return; 1538 } 1539 1540 if (yoffset + height > imageHeight + yBorder) { 1541 _mesa_error(ctx, GL_INVALID_VALUE, 1542 "glInvalidateSubTexImage(yoffset+height)"); 1543 return; 1544 } 1545 1546 if (zoffset < -zBorder) { 1547 _mesa_error(ctx, GL_INVALID_VALUE, 1548 "glInvalidateSubTexImage(zoffset)"); 1549 return; 1550 } 1551 1552 if (zoffset + depth > imageDepth + zBorder) { 1553 _mesa_error(ctx, GL_INVALID_VALUE, 1554 "glInvalidateSubTexImage(zoffset+depth)"); 1555 return; 1556 } 1557 } 1558 1559 /* We don't actually do anything for this yet. Just return after 1560 * validating the parameters and generating the required errors. 1561 */ 1562 return; 1563} 1564 1565void GLAPIENTRY 1566_mesa_InvalidateTexImage(GLuint texture, GLint level) 1567{ 1568 GET_CURRENT_CONTEXT(ctx); 1569 1570 ASSERT_OUTSIDE_BEGIN_END(ctx); 1571 1572 invalidate_tex_image_error_check(ctx, texture, level, 1573 "glInvalidateTexImage"); 1574 1575 /* We don't actually do anything for this yet. Just return after 1576 * validating the parameters and generating the required errors. 1577 */ 1578 return; 1579} 1580 1581/*@}*/ 1582