texobj.c revision d47a6ada9ca9670c60fc141fabadf40c63031c08
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 default: 773 /* no-op */ 774 return NULL; 775 } 776 777 /* create texture object */ 778 texObj = ctx->Driver.NewTextureObject(ctx, 0, target); 779 if (!texObj) 780 return NULL; 781 782 assert(texObj->RefCount == 1); 783 texObj->Sampler.MinFilter = GL_NEAREST; 784 texObj->Sampler.MagFilter = GL_NEAREST; 785 786 texFormat = ctx->Driver.ChooseTextureFormat(ctx, target, 787 GL_RGBA, GL_RGBA, 788 GL_UNSIGNED_BYTE); 789 790 /* need a loop here just for cube maps */ 791 for (face = 0; face < numFaces; face++) { 792 GLenum faceTarget; 793 794 if (target == GL_TEXTURE_CUBE_MAP) 795 faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; 796 else 797 faceTarget = target; 798 799 /* initialize level[0] texture image */ 800 texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, 0); 801 802 _mesa_init_teximage_fields(ctx, texImage, 803 width, 804 (dims > 1) ? height : 1, 805 (dims > 2) ? depth : 1, 806 0, /* border */ 807 GL_RGBA, texFormat); 808 809 ctx->Driver.TexImage(ctx, dims, texImage, 810 GL_RGBA, GL_UNSIGNED_BYTE, texel, 811 &ctx->DefaultPacking); 812 } 813 814 _mesa_test_texobj_completeness(ctx, texObj); 815 assert(texObj->_BaseComplete); 816 assert(texObj->_MipmapComplete); 817 818 ctx->Shared->FallbackTex[tex] = texObj; 819 } 820 return ctx->Shared->FallbackTex[tex]; 821} 822 823 824/** 825 * Compute the size of the given texture object, in bytes. 826 */ 827static GLuint 828texture_size(const struct gl_texture_object *texObj) 829{ 830 const GLuint numFaces = _mesa_num_tex_faces(texObj->Target); 831 GLuint face, level, size = 0; 832 833 for (face = 0; face < numFaces; face++) { 834 for (level = 0; level < MAX_TEXTURE_LEVELS; level++) { 835 const struct gl_texture_image *img = texObj->Image[face][level]; 836 if (img) { 837 GLuint sz = _mesa_format_image_size(img->TexFormat, img->Width, 838 img->Height, img->Depth); 839 size += sz; 840 } 841 } 842 } 843 844 return size; 845} 846 847 848/** 849 * Callback called from _mesa_HashWalk() 850 */ 851static void 852count_tex_size(GLuint key, void *data, void *userData) 853{ 854 const struct gl_texture_object *texObj = 855 (const struct gl_texture_object *) data; 856 GLuint *total = (GLuint *) userData; 857 858 *total = *total + texture_size(texObj); 859} 860 861 862/** 863 * Compute total size (in bytes) of all textures for the given context. 864 * For debugging purposes. 865 */ 866GLuint 867_mesa_total_texture_memory(struct gl_context *ctx) 868{ 869 GLuint tgt, total = 0; 870 871 _mesa_HashWalk(ctx->Shared->TexObjects, count_tex_size, &total); 872 873 /* plus, the default texture objects */ 874 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { 875 total += texture_size(ctx->Shared->DefaultTex[tgt]); 876 } 877 878 return total; 879} 880 881static struct gl_texture_object * 882invalidate_tex_image_error_check(struct gl_context *ctx, GLuint texture, 883 GLint level, const char *name) 884{ 885 /* The GL_ARB_invalidate_subdata spec says: 886 * 887 * "If <texture> is zero or is not the name of a texture, the error 888 * INVALID_VALUE is generated." 889 * 890 * This performs the error check in a different order than listed in the 891 * spec. We have to get the texture object before we can validate the 892 * other parameters against values in the texture object. 893 */ 894 struct gl_texture_object *const t = _mesa_lookup_texture(ctx, texture); 895 if (texture == 0 || t == NULL) { 896 _mesa_error(ctx, GL_INVALID_VALUE, "%s(texture)", name); 897 return NULL; 898 } 899 900 /* The GL_ARB_invalidate_subdata spec says: 901 * 902 * "If <level> is less than zero or greater than the base 2 logarithm 903 * of the maximum texture width, height, or depth, the error 904 * INVALID_VALUE is generated." 905 */ 906 if (level < 0 || level > t->MaxLevel) { 907 _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name); 908 return NULL; 909 } 910 911 /* The GL_ARB_invalidate_subdata spec says: 912 * 913 * "If the target of <texture> is TEXTURE_RECTANGLE, TEXTURE_BUFFER, 914 * TEXTURE_2D_MULTISAMPLE, or TEXTURE_2D_MULTISAMPLE_ARRAY, and <level> 915 * is not zero, the error INVALID_VALUE is generated." 916 */ 917 if (level != 0) { 918 switch (t->Target) { 919 case GL_TEXTURE_RECTANGLE: 920 case GL_TEXTURE_BUFFER: 921 case GL_TEXTURE_2D_MULTISAMPLE: 922 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 923 _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name); 924 return NULL; 925 926 default: 927 break; 928 } 929 } 930 931 return t; 932} 933 934/*@}*/ 935 936 937/***********************************************************************/ 938/** \name API functions */ 939/*@{*/ 940 941 942/** 943 * Generate texture names. 944 * 945 * \param n number of texture names to be generated. 946 * \param textures an array in which will hold the generated texture names. 947 * 948 * \sa glGenTextures(). 949 * 950 * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture 951 * IDs which are stored in \p textures. Corresponding empty texture 952 * objects are also generated. 953 */ 954void GLAPIENTRY 955_mesa_GenTextures( GLsizei n, GLuint *textures ) 956{ 957 GET_CURRENT_CONTEXT(ctx); 958 GLuint first; 959 GLint i; 960 ASSERT_OUTSIDE_BEGIN_END(ctx); 961 962 if (n < 0) { 963 _mesa_error( ctx, GL_INVALID_VALUE, "glGenTextures" ); 964 return; 965 } 966 967 if (!textures) 968 return; 969 970 /* 971 * This must be atomic (generation and allocation of texture IDs) 972 */ 973 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 974 975 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n); 976 977 /* Allocate new, empty texture objects */ 978 for (i = 0; i < n; i++) { 979 struct gl_texture_object *texObj; 980 GLuint name = first + i; 981 GLenum target = 0; 982 texObj = ctx->Driver.NewTextureObject(ctx, name, target); 983 if (!texObj) { 984 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 985 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures"); 986 return; 987 } 988 989 /* insert into hash table */ 990 _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj); 991 992 textures[i] = name; 993 } 994 995 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 996} 997 998 999/** 1000 * Check if the given texture object is bound to the current draw or 1001 * read framebuffer. If so, Unbind it. 1002 */ 1003static void 1004unbind_texobj_from_fbo(struct gl_context *ctx, 1005 struct gl_texture_object *texObj) 1006{ 1007 const GLuint n = (ctx->DrawBuffer == ctx->ReadBuffer) ? 1 : 2; 1008 GLuint i; 1009 1010 for (i = 0; i < n; i++) { 1011 struct gl_framebuffer *fb = (i == 0) ? ctx->DrawBuffer : ctx->ReadBuffer; 1012 if (_mesa_is_user_fbo(fb)) { 1013 GLuint j; 1014 for (j = 0; j < BUFFER_COUNT; j++) { 1015 if (fb->Attachment[j].Type == GL_TEXTURE && 1016 fb->Attachment[j].Texture == texObj) { 1017 /* Vertices are already flushed by _mesa_DeleteTextures */ 1018 ctx->NewState |= _NEW_BUFFERS; 1019 _mesa_remove_attachment(ctx, fb->Attachment + j); 1020 } 1021 } 1022 } 1023 } 1024} 1025 1026 1027/** 1028 * Check if the given texture object is bound to any texture image units and 1029 * unbind it if so (revert to default textures). 1030 */ 1031static void 1032unbind_texobj_from_texunits(struct gl_context *ctx, 1033 struct gl_texture_object *texObj) 1034{ 1035 GLuint u, tex; 1036 1037 for (u = 0; u < Elements(ctx->Texture.Unit); u++) { 1038 struct gl_texture_unit *unit = &ctx->Texture.Unit[u]; 1039 for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) { 1040 if (texObj == unit->CurrentTex[tex]) { 1041 _mesa_reference_texobj(&unit->CurrentTex[tex], 1042 ctx->Shared->DefaultTex[tex]); 1043 ASSERT(unit->CurrentTex[tex]); 1044 break; 1045 } 1046 } 1047 } 1048} 1049 1050 1051/** 1052 * Delete named textures. 1053 * 1054 * \param n number of textures to be deleted. 1055 * \param textures array of texture IDs to be deleted. 1056 * 1057 * \sa glDeleteTextures(). 1058 * 1059 * If we're about to delete a texture that's currently bound to any 1060 * texture unit, unbind the texture first. Decrement the reference 1061 * count on the texture object and delete it if it's zero. 1062 * Recall that texture objects can be shared among several rendering 1063 * contexts. 1064 */ 1065void GLAPIENTRY 1066_mesa_DeleteTextures( GLsizei n, const GLuint *textures) 1067{ 1068 GET_CURRENT_CONTEXT(ctx); 1069 GLint i; 1070 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */ 1071 1072 if (!textures) 1073 return; 1074 1075 for (i = 0; i < n; i++) { 1076 if (textures[i] > 0) { 1077 struct gl_texture_object *delObj 1078 = _mesa_lookup_texture(ctx, textures[i]); 1079 1080 if (delObj) { 1081 _mesa_lock_texture(ctx, delObj); 1082 1083 /* Check if texture is bound to any framebuffer objects. 1084 * If so, unbind. 1085 * See section 4.4.2.3 of GL_EXT_framebuffer_object. 1086 */ 1087 unbind_texobj_from_fbo(ctx, delObj); 1088 1089 /* Check if this texture is currently bound to any texture units. 1090 * If so, unbind it. 1091 */ 1092 unbind_texobj_from_texunits(ctx, delObj); 1093 1094 _mesa_unlock_texture(ctx, delObj); 1095 1096 ctx->NewState |= _NEW_TEXTURE; 1097 1098 /* The texture _name_ is now free for re-use. 1099 * Remove it from the hash table now. 1100 */ 1101 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 1102 _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name); 1103 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 1104 1105 /* Unreference the texobj. If refcount hits zero, the texture 1106 * will be deleted. 1107 */ 1108 _mesa_reference_texobj(&delObj, NULL); 1109 } 1110 } 1111 } 1112} 1113 1114 1115/** 1116 * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D 1117 * into the corresponding Mesa texture target index. 1118 * Note that proxy targets are not valid here. 1119 * \return TEXTURE_x_INDEX or -1 if target is invalid 1120 */ 1121static GLint 1122target_enum_to_index(struct gl_context *ctx, GLenum target) 1123{ 1124 switch (target) { 1125 case GL_TEXTURE_1D: 1126 return _mesa_is_desktop_gl(ctx) ? TEXTURE_1D_INDEX : -1; 1127 case GL_TEXTURE_2D: 1128 return TEXTURE_2D_INDEX; 1129 case GL_TEXTURE_3D: 1130 return TEXTURE_3D_INDEX; 1131 case GL_TEXTURE_CUBE_MAP_ARB: 1132 return ctx->Extensions.ARB_texture_cube_map 1133 ? TEXTURE_CUBE_INDEX : -1; 1134 case GL_TEXTURE_RECTANGLE_NV: 1135 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle 1136 ? TEXTURE_RECT_INDEX : -1; 1137 case GL_TEXTURE_1D_ARRAY_EXT: 1138 return _mesa_is_desktop_gl(ctx) 1139 && (ctx->Extensions.EXT_texture_array 1140 || ctx->Extensions.MESA_texture_array) 1141 ? TEXTURE_1D_ARRAY_INDEX : -1; 1142 case GL_TEXTURE_2D_ARRAY_EXT: 1143 return (_mesa_is_desktop_gl(ctx) 1144 && (ctx->Extensions.EXT_texture_array 1145 || ctx->Extensions.MESA_texture_array)) 1146 || _mesa_is_gles3(ctx) 1147 ? TEXTURE_2D_ARRAY_INDEX : -1; 1148 case GL_TEXTURE_BUFFER_ARB: 1149 return _mesa_is_desktop_gl(ctx) 1150 && ctx->Extensions.ARB_texture_buffer_object 1151 ? TEXTURE_BUFFER_INDEX : -1; 1152 case GL_TEXTURE_EXTERNAL_OES: 1153 return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external 1154 ? TEXTURE_EXTERNAL_INDEX : -1; 1155 default: 1156 return -1; 1157 } 1158} 1159 1160 1161/** 1162 * Bind a named texture to a texturing target. 1163 * 1164 * \param target texture target. 1165 * \param texName texture name. 1166 * 1167 * \sa glBindTexture(). 1168 * 1169 * Determines the old texture object bound and returns immediately if rebinding 1170 * the same texture. Get the current texture which is either a default texture 1171 * if name is null, a named texture from the hash, or a new texture if the 1172 * given texture name is new. Increments its reference count, binds it, and 1173 * calls dd_function_table::BindTexture. Decrements the old texture reference 1174 * count and deletes it if it reaches zero. 1175 */ 1176void GLAPIENTRY 1177_mesa_BindTexture( GLenum target, GLuint texName ) 1178{ 1179 GET_CURRENT_CONTEXT(ctx); 1180 struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); 1181 struct gl_texture_object *newTexObj = NULL; 1182 GLint targetIndex; 1183 ASSERT_OUTSIDE_BEGIN_END(ctx); 1184 1185 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 1186 _mesa_debug(ctx, "glBindTexture %s %d\n", 1187 _mesa_lookup_enum_by_nr(target), (GLint) texName); 1188 1189 targetIndex = target_enum_to_index(ctx, target); 1190 if (targetIndex < 0) { 1191 _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target)"); 1192 return; 1193 } 1194 assert(targetIndex < NUM_TEXTURE_TARGETS); 1195 1196 /* 1197 * Get pointer to new texture object (newTexObj) 1198 */ 1199 if (texName == 0) { 1200 /* Use a default texture object */ 1201 newTexObj = ctx->Shared->DefaultTex[targetIndex]; 1202 } 1203 else { 1204 /* non-default texture object */ 1205 newTexObj = _mesa_lookup_texture(ctx, texName); 1206 if (newTexObj) { 1207 /* error checking */ 1208 if (newTexObj->Target != 0 && newTexObj->Target != target) { 1209 /* the named texture object's target doesn't match the given target */ 1210 _mesa_error( ctx, GL_INVALID_OPERATION, 1211 "glBindTexture(target mismatch)" ); 1212 return; 1213 } 1214 if (newTexObj->Target == 0) { 1215 finish_texture_init(ctx, target, newTexObj); 1216 } 1217 } 1218 else { 1219 /* if this is a new texture id, allocate a texture object now */ 1220 newTexObj = ctx->Driver.NewTextureObject(ctx, texName, target); 1221 if (!newTexObj) { 1222 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture"); 1223 return; 1224 } 1225 1226 /* and insert it into hash table */ 1227 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 1228 _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj); 1229 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 1230 } 1231 newTexObj->Target = target; 1232 } 1233 1234 assert(valid_texture_object(newTexObj)); 1235 1236 /* Check if this texture is only used by this context and is already bound. 1237 * If so, just return. 1238 */ 1239 { 1240 GLboolean early_out; 1241 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 1242 early_out = ((ctx->Shared->RefCount == 1) 1243 && (newTexObj == texUnit->CurrentTex[targetIndex])); 1244 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 1245 if (early_out) { 1246 return; 1247 } 1248 } 1249 1250 /* flush before changing binding */ 1251 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 1252 1253 /* Do the actual binding. The refcount on the previously bound 1254 * texture object will be decremented. It'll be deleted if the 1255 * count hits zero. 1256 */ 1257 _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], newTexObj); 1258 ASSERT(texUnit->CurrentTex[targetIndex]); 1259 1260 /* Pass BindTexture call to device driver */ 1261 if (ctx->Driver.BindTexture) 1262 ctx->Driver.BindTexture(ctx, target, newTexObj); 1263} 1264 1265 1266/** 1267 * Set texture priorities. 1268 * 1269 * \param n number of textures. 1270 * \param texName texture names. 1271 * \param priorities corresponding texture priorities. 1272 * 1273 * \sa glPrioritizeTextures(). 1274 * 1275 * Looks up each texture in the hash, clamps the corresponding priority between 1276 * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture. 1277 */ 1278void GLAPIENTRY 1279_mesa_PrioritizeTextures( GLsizei n, const GLuint *texName, 1280 const GLclampf *priorities ) 1281{ 1282 GET_CURRENT_CONTEXT(ctx); 1283 GLint i; 1284 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1285 1286 if (n < 0) { 1287 _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" ); 1288 return; 1289 } 1290 1291 if (!priorities) 1292 return; 1293 1294 for (i = 0; i < n; i++) { 1295 if (texName[i] > 0) { 1296 struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]); 1297 if (t) { 1298 t->Priority = CLAMP( priorities[i], 0.0F, 1.0F ); 1299 } 1300 } 1301 } 1302 1303 ctx->NewState |= _NEW_TEXTURE; 1304} 1305 1306 1307 1308/** 1309 * See if textures are loaded in texture memory. 1310 * 1311 * \param n number of textures to query. 1312 * \param texName array with the texture names. 1313 * \param residences array which will hold the residence status. 1314 * 1315 * \return GL_TRUE if all textures are resident and \p residences is left unchanged, 1316 * 1317 * Note: we assume all textures are always resident 1318 */ 1319GLboolean GLAPIENTRY 1320_mesa_AreTexturesResident(GLsizei n, const GLuint *texName, 1321 GLboolean *residences) 1322{ 1323 GET_CURRENT_CONTEXT(ctx); 1324 GLboolean allResident = GL_TRUE; 1325 GLint i; 1326 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 1327 1328 if (n < 0) { 1329 _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)"); 1330 return GL_FALSE; 1331 } 1332 1333 if (!texName || !residences) 1334 return GL_FALSE; 1335 1336 /* We only do error checking on the texture names */ 1337 for (i = 0; i < n; i++) { 1338 struct gl_texture_object *t; 1339 if (texName[i] == 0) { 1340 _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident"); 1341 return GL_FALSE; 1342 } 1343 t = _mesa_lookup_texture(ctx, texName[i]); 1344 if (!t) { 1345 _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident"); 1346 return GL_FALSE; 1347 } 1348 } 1349 1350 return allResident; 1351} 1352 1353 1354/** 1355 * See if a name corresponds to a texture. 1356 * 1357 * \param texture texture name. 1358 * 1359 * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE 1360 * otherwise. 1361 * 1362 * \sa glIsTexture(). 1363 * 1364 * Calls _mesa_HashLookup(). 1365 */ 1366GLboolean GLAPIENTRY 1367_mesa_IsTexture( GLuint texture ) 1368{ 1369 struct gl_texture_object *t; 1370 GET_CURRENT_CONTEXT(ctx); 1371 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 1372 1373 if (!texture) 1374 return GL_FALSE; 1375 1376 t = _mesa_lookup_texture(ctx, texture); 1377 1378 /* IsTexture is true only after object has been bound once. */ 1379 return t && t->Target; 1380} 1381 1382 1383/** 1384 * Simplest implementation of texture locking: grab the shared tex 1385 * mutex. Examine the shared context state timestamp and if there has 1386 * been a change, set the appropriate bits in ctx->NewState. 1387 * 1388 * This is used to deal with synchronizing things when a texture object 1389 * is used/modified by different contexts (or threads) which are sharing 1390 * the texture. 1391 * 1392 * See also _mesa_lock/unlock_texture() in teximage.h 1393 */ 1394void 1395_mesa_lock_context_textures( struct gl_context *ctx ) 1396{ 1397 _glthread_LOCK_MUTEX(ctx->Shared->TexMutex); 1398 1399 if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) { 1400 ctx->NewState |= _NEW_TEXTURE; 1401 ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp; 1402 } 1403} 1404 1405 1406void 1407_mesa_unlock_context_textures( struct gl_context *ctx ) 1408{ 1409 assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp); 1410 _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex); 1411} 1412 1413void GLAPIENTRY 1414_mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset, 1415 GLint yoffset, GLint zoffset, GLsizei width, 1416 GLsizei height, GLsizei depth) 1417{ 1418 struct gl_texture_object *t; 1419 struct gl_texture_image *image; 1420 GET_CURRENT_CONTEXT(ctx); 1421 1422 ASSERT_OUTSIDE_BEGIN_END(ctx); 1423 1424 t = invalidate_tex_image_error_check(ctx, texture, level, 1425 "glInvalidateTexSubImage"); 1426 1427 /* The GL_ARB_invalidate_subdata spec says: 1428 * 1429 * "...the specified subregion must be between -<b> and <dim>+<b> where 1430 * <dim> is the size of the dimension of the texture image, and <b> is 1431 * the size of the border of that texture image, otherwise 1432 * INVALID_VALUE is generated (border is not applied to dimensions that 1433 * don't exist in a given texture target)." 1434 */ 1435 image = t->Image[0][level]; 1436 if (image) { 1437 int xBorder; 1438 int yBorder; 1439 int zBorder; 1440 int imageWidth; 1441 int imageHeight; 1442 int imageDepth; 1443 1444 /* The GL_ARB_invalidate_subdata spec says: 1445 * 1446 * "For texture targets that don't have certain dimensions, this 1447 * command treats those dimensions as having a size of 1. For 1448 * example, to invalidate a portion of a two-dimensional texture, 1449 * the application would use <zoffset> equal to zero and <depth> 1450 * equal to one." 1451 */ 1452 switch (t->Target) { 1453 case GL_TEXTURE_BUFFER: 1454 xBorder = 0; 1455 yBorder = 0; 1456 zBorder = 0; 1457 imageWidth = 1; 1458 imageHeight = 1; 1459 imageDepth = 1; 1460 break; 1461 case GL_TEXTURE_1D: 1462 xBorder = image->Border; 1463 yBorder = 0; 1464 zBorder = 0; 1465 imageWidth = image->Width; 1466 imageHeight = 1; 1467 imageDepth = 1; 1468 break; 1469 case GL_TEXTURE_1D_ARRAY: 1470 xBorder = image->Border; 1471 yBorder = 0; 1472 zBorder = 0; 1473 imageWidth = image->Width; 1474 imageHeight = image->Height; 1475 imageDepth = 1; 1476 break; 1477 case GL_TEXTURE_2D: 1478 case GL_TEXTURE_CUBE_MAP: 1479 case GL_TEXTURE_RECTANGLE: 1480 case GL_TEXTURE_2D_MULTISAMPLE: 1481 xBorder = image->Border; 1482 yBorder = image->Border; 1483 zBorder = 0; 1484 imageWidth = image->Width; 1485 imageHeight = image->Height; 1486 imageDepth = 1; 1487 break; 1488 case GL_TEXTURE_2D_ARRAY: 1489 case GL_TEXTURE_CUBE_MAP_ARRAY: 1490 xBorder = image->Border; 1491 yBorder = image->Border; 1492 zBorder = 0; 1493 imageWidth = image->Width; 1494 imageHeight = image->Height; 1495 imageDepth = image->Depth; 1496 break; 1497 case GL_TEXTURE_3D: 1498 xBorder = image->Border; 1499 yBorder = image->Border; 1500 zBorder = image->Border; 1501 imageWidth = image->Width; 1502 imageHeight = image->Height; 1503 imageDepth = image->Depth; 1504 break; 1505 default: 1506 assert(!"Should not get here."); 1507 xBorder = 0; 1508 yBorder = 0; 1509 zBorder = 0; 1510 imageWidth = 0; 1511 imageHeight = 0; 1512 imageDepth = 0; 1513 break; 1514 } 1515 1516 if (xoffset < -xBorder) { 1517 _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(xoffset)"); 1518 return; 1519 } 1520 1521 if (xoffset + width > imageWidth + xBorder) { 1522 _mesa_error(ctx, GL_INVALID_VALUE, 1523 "glInvalidateSubTexImage(xoffset+width)"); 1524 return; 1525 } 1526 1527 if (yoffset < -yBorder) { 1528 _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(yoffset)"); 1529 return; 1530 } 1531 1532 if (yoffset + height > imageHeight + yBorder) { 1533 _mesa_error(ctx, GL_INVALID_VALUE, 1534 "glInvalidateSubTexImage(yoffset+height)"); 1535 return; 1536 } 1537 1538 if (zoffset < -zBorder) { 1539 _mesa_error(ctx, GL_INVALID_VALUE, 1540 "glInvalidateSubTexImage(zoffset)"); 1541 return; 1542 } 1543 1544 if (zoffset + depth > imageDepth + zBorder) { 1545 _mesa_error(ctx, GL_INVALID_VALUE, 1546 "glInvalidateSubTexImage(zoffset+depth)"); 1547 return; 1548 } 1549 } 1550 1551 /* We don't actually do anything for this yet. Just return after 1552 * validating the parameters and generating the required errors. 1553 */ 1554 return; 1555} 1556 1557void GLAPIENTRY 1558_mesa_InvalidateTexImage(GLuint texture, GLint level) 1559{ 1560 GET_CURRENT_CONTEXT(ctx); 1561 1562 ASSERT_OUTSIDE_BEGIN_END(ctx); 1563 1564 invalidate_tex_image_error_check(ctx, texture, level, 1565 "glInvalidateTexImage"); 1566 1567 /* We don't actually do anything for this yet. Just return after 1568 * validating the parameters and generating the required errors. 1569 */ 1570 return; 1571} 1572 1573/*@}*/ 1574