textureview.c revision af69d88d
11.1Smsaitoh/* 21.1Smsaitoh * Mesa 3-D graphics library 31.1Smsaitoh * 41.1Smsaitoh * Copyright (C) 2013 LunarG, Inc. 51.1Smsaitoh * 61.1Smsaitoh * Permission is hereby granted, free of charge, to any person obtaining a 71.1Smsaitoh * copy of this software and associated documentation files (the "Software"), 81.1Smsaitoh * to deal in the Software without restriction, including without limitation 91.1Smsaitoh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 101.1Smsaitoh * and/or sell copies of the Software, and to permit persons to whom the 111.1Smsaitoh * Software is furnished to do so, subject to the following conditions: 121.1Smsaitoh * 131.1Smsaitoh * The above copyright notice and this permission notice shall be included 141.1Smsaitoh * in all copies or substantial portions of the Software. 151.1Smsaitoh * 161.1Smsaitoh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 171.1Smsaitoh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 181.1Smsaitoh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 191.1Smsaitoh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 201.1Smsaitoh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 211.1Smsaitoh * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 221.1Smsaitoh * DEALINGS IN THE SOFTWARE. 231.1Smsaitoh * 241.1Smsaitoh * Authors: 251.1Smsaitoh * Courtney Goeltzenleuchter <courtney@lunarg.com> 261.1Smsaitoh */ 271.1Smsaitoh 281.1Smsaitoh 291.1Smsaitoh/** 301.1Smsaitoh * \file textureview.c 311.1Smsaitoh * GL_ARB_texture_view functions 321.1Smsaitoh */ 331.1Smsaitoh 341.1Smsaitoh#include "glheader.h" 351.1Smsaitoh#include "context.h" 361.1Smsaitoh#include "enums.h" 371.1Smsaitoh#include "imports.h" 381.1Smsaitoh#include "macros.h" 391.1Smsaitoh#include "teximage.h" 401.1Smsaitoh#include "texobj.h" 411.1Smsaitoh#include "mipmap.h" 421.1Smsaitoh#include "texstorage.h" 431.1Smsaitoh#include "textureview.h" 441.1Smsaitoh#include "stdbool.h" 451.1Smsaitoh#include "mtypes.h" 461.1Smsaitoh 471.1Smsaitoh/* Table 3.X.2 (Compatible internal formats for TextureView) 481.1Smsaitoh --------------------------------------------------------------------------- 491.1Smsaitoh | Class | Internal formats | 501.1Smsaitoh --------------------------------------------------------------------------- 511.1Smsaitoh | VIEW_CLASS_128_BITS | RGBA32F, RGBA32UI, RGBA32I | 521.1Smsaitoh --------------------------------------------------------------------------- 531.1Smsaitoh | VIEW_CLASS_96_BITS | RGB32F, RGB32UI, RGB32I | 541.1Smsaitoh --------------------------------------------------------------------------- 551.1Smsaitoh | VIEW_CLASS_64_BITS | RGBA16F, RG32F, RGBA16UI, RG32UI, RGBA16I, | 561.1Smsaitoh | | RG32I, RGBA16, RGBA16_SNORM | 571.1Smsaitoh --------------------------------------------------------------------------- 581.1Smsaitoh | VIEW_CLASS_48_BITS | RGB16, RGB16_SNORM, RGB16F, RGB16UI, RGB16I | 591.1Smsaitoh --------------------------------------------------------------------------- 601.1Smsaitoh | VIEW_CLASS_32_BITS | RG16F, R11F_G11F_B10F, R32F, | 611.1Smsaitoh | | RGB10_A2UI, RGBA8UI, RG16UI, R32UI, | 621.1Smsaitoh | | RGBA8I, RG16I, R32I, RGB10_A2, RGBA8, RG16, | 631.1Smsaitoh | | RGBA8_SNORM, RG16_SNORM, SRGB8_ALPHA8, RGB9_E5 | 641.1Smsaitoh --------------------------------------------------------------------------- 651.1Smsaitoh | VIEW_CLASS_24_BITS | RGB8, RGB8_SNORM, SRGB8, RGB8UI, RGB8I | 661.1Smsaitoh --------------------------------------------------------------------------- 671.1Smsaitoh | VIEW_CLASS_16_BITS | R16F, RG8UI, R16UI, RG8I, R16I, RG8, R16, | 681.1Smsaitoh | | RG8_SNORM, R16_SNORM | 691.1Smsaitoh --------------------------------------------------------------------------- 701.1Smsaitoh | VIEW_CLASS_8_BITS | R8UI, R8I, R8, R8_SNORM | 711.1Smsaitoh --------------------------------------------------------------------------- 721.1Smsaitoh | VIEW_CLASS_RGTC1_RED | COMPRESSED_RED_RGTC1, | 731.1Smsaitoh | | COMPRESSED_SIGNED_RED_RGTC1 | 741.1Smsaitoh --------------------------------------------------------------------------- 751.1Smsaitoh | VIEW_CLASS_RGTC2_RG | COMPRESSED_RG_RGTC2, | 761.1Smsaitoh | | COMPRESSED_SIGNED_RG_RGTC2 | 771.1Smsaitoh --------------------------------------------------------------------------- 781.1Smsaitoh | VIEW_CLASS_BPTC_UNORM | COMPRESSED_RGBA_BPTC_UNORM, | 791.1Smsaitoh | | COMPRESSED_SRGB_ALPHA_BPTC_UNORM | 801.1Smsaitoh --------------------------------------------------------------------------- 811.1Smsaitoh | VIEW_CLASS_BPTC_FLOAT | COMPRESSED_RGB_BPTC_SIGNED_FLOAT, | 821.1Smsaitoh | | COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT | 831.1Smsaitoh --------------------------------------------------------------------------- 841.1Smsaitoh */ 851.1Smsaitohstruct internal_format_class_info { 861.1Smsaitoh GLenum view_class; 871.1Smsaitoh GLenum internal_format; 881.1Smsaitoh}; 891.1Smsaitohstatic const struct internal_format_class_info compatible_internal_formats[] = { 901.1Smsaitoh {GL_VIEW_CLASS_128_BITS, GL_RGBA32F}, 911.1Smsaitoh {GL_VIEW_CLASS_128_BITS, GL_RGBA32UI}, 92 {GL_VIEW_CLASS_128_BITS, GL_RGBA32I}, 93 {GL_VIEW_CLASS_96_BITS, GL_RGB32F}, 94 {GL_VIEW_CLASS_96_BITS, GL_RGB32UI}, 95 {GL_VIEW_CLASS_96_BITS, GL_RGB32I}, 96 {GL_VIEW_CLASS_64_BITS, GL_RGBA16F}, 97 {GL_VIEW_CLASS_64_BITS, GL_RG32F}, 98 {GL_VIEW_CLASS_64_BITS, GL_RGBA16UI}, 99 {GL_VIEW_CLASS_64_BITS, GL_RG32UI}, 100 {GL_VIEW_CLASS_64_BITS, GL_RGBA16I}, 101 {GL_VIEW_CLASS_64_BITS, GL_RG32I}, 102 {GL_VIEW_CLASS_64_BITS, GL_RGBA16}, 103 {GL_VIEW_CLASS_64_BITS, GL_RGBA16_SNORM}, 104 {GL_VIEW_CLASS_48_BITS, GL_RGB16}, 105 {GL_VIEW_CLASS_48_BITS, GL_RGB16_SNORM}, 106 {GL_VIEW_CLASS_48_BITS, GL_RGB16F}, 107 {GL_VIEW_CLASS_48_BITS, GL_RGB16UI}, 108 {GL_VIEW_CLASS_48_BITS, GL_RGB16I}, 109 {GL_VIEW_CLASS_32_BITS, GL_RG16F}, 110 {GL_VIEW_CLASS_32_BITS, GL_R11F_G11F_B10F}, 111 {GL_VIEW_CLASS_32_BITS, GL_R32F}, 112 {GL_VIEW_CLASS_32_BITS, GL_RGB10_A2UI}, 113 {GL_VIEW_CLASS_32_BITS, GL_RGBA8UI}, 114 {GL_VIEW_CLASS_32_BITS, GL_RG16UI}, 115 {GL_VIEW_CLASS_32_BITS, GL_R32UI}, 116 {GL_VIEW_CLASS_32_BITS, GL_RGBA8I}, 117 {GL_VIEW_CLASS_32_BITS, GL_RG16I}, 118 {GL_VIEW_CLASS_32_BITS, GL_R32I}, 119 {GL_VIEW_CLASS_32_BITS, GL_RGB10_A2}, 120 {GL_VIEW_CLASS_32_BITS, GL_RGBA8}, 121 {GL_VIEW_CLASS_32_BITS, GL_RG16}, 122 {GL_VIEW_CLASS_32_BITS, GL_RGBA8_SNORM}, 123 {GL_VIEW_CLASS_32_BITS, GL_RG16_SNORM}, 124 {GL_VIEW_CLASS_32_BITS, GL_SRGB8_ALPHA8}, 125 {GL_VIEW_CLASS_32_BITS, GL_RGB9_E5}, 126 {GL_VIEW_CLASS_24_BITS, GL_RGB8}, 127 {GL_VIEW_CLASS_24_BITS, GL_RGB8_SNORM}, 128 {GL_VIEW_CLASS_24_BITS, GL_SRGB8}, 129 {GL_VIEW_CLASS_24_BITS, GL_RGB8UI}, 130 {GL_VIEW_CLASS_24_BITS, GL_RGB8I}, 131 {GL_VIEW_CLASS_16_BITS, GL_R16F}, 132 {GL_VIEW_CLASS_16_BITS, GL_RG8UI}, 133 {GL_VIEW_CLASS_16_BITS, GL_R16UI}, 134 {GL_VIEW_CLASS_16_BITS, GL_RG8I}, 135 {GL_VIEW_CLASS_16_BITS, GL_R16I}, 136 {GL_VIEW_CLASS_16_BITS, GL_RG8}, 137 {GL_VIEW_CLASS_16_BITS, GL_R16}, 138 {GL_VIEW_CLASS_16_BITS, GL_RG8_SNORM}, 139 {GL_VIEW_CLASS_16_BITS, GL_R16_SNORM}, 140 {GL_VIEW_CLASS_8_BITS, GL_R8UI}, 141 {GL_VIEW_CLASS_8_BITS, GL_R8I}, 142 {GL_VIEW_CLASS_8_BITS, GL_R8}, 143 {GL_VIEW_CLASS_8_BITS, GL_R8_SNORM}, 144 {GL_VIEW_CLASS_RGTC1_RED, GL_COMPRESSED_RED_RGTC1}, 145 {GL_VIEW_CLASS_RGTC1_RED, GL_COMPRESSED_SIGNED_RED_RGTC1}, 146 {GL_VIEW_CLASS_RGTC2_RG, GL_COMPRESSED_RG_RGTC2}, 147 {GL_VIEW_CLASS_RGTC2_RG, GL_COMPRESSED_SIGNED_RG_RGTC2}, 148 {GL_VIEW_CLASS_BPTC_UNORM, GL_COMPRESSED_RGBA_BPTC_UNORM_ARB}, 149 {GL_VIEW_CLASS_BPTC_UNORM, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB}, 150 {GL_VIEW_CLASS_BPTC_FLOAT, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB}, 151 {GL_VIEW_CLASS_BPTC_FLOAT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB}, 152}; 153 154static const struct internal_format_class_info s3tc_compatible_internal_formats[] = { 155 {GL_VIEW_CLASS_S3TC_DXT1_RGB, GL_COMPRESSED_RGB_S3TC_DXT1_EXT}, 156 {GL_VIEW_CLASS_S3TC_DXT1_RGB, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT}, 157 {GL_VIEW_CLASS_S3TC_DXT1_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT}, 158 {GL_VIEW_CLASS_S3TC_DXT1_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT}, 159 {GL_VIEW_CLASS_S3TC_DXT3_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT}, 160 {GL_VIEW_CLASS_S3TC_DXT3_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT}, 161 {GL_VIEW_CLASS_S3TC_DXT5_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT}, 162 {GL_VIEW_CLASS_S3TC_DXT5_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}, 163}; 164 165/** 166 * Lookup format view class based on internalformat 167 * \return VIEW_CLASS if internalformat found in table, false otherwise. 168 */ 169static GLenum 170lookup_view_class(struct gl_context *ctx, GLenum internalformat) 171{ 172 GLuint i; 173 174 for (i = 0; i < ARRAY_SIZE(compatible_internal_formats); i++) { 175 if (compatible_internal_formats[i].internal_format == internalformat) 176 return compatible_internal_formats[i].view_class; 177 } 178 179 if (ctx->Extensions.EXT_texture_compression_s3tc && ctx->Extensions.EXT_texture_sRGB) { 180 for (i = 0; i < ARRAY_SIZE(s3tc_compatible_internal_formats); i++) { 181 if (s3tc_compatible_internal_formats[i].internal_format == internalformat) 182 return s3tc_compatible_internal_formats[i].view_class; 183 } 184 } 185 return GL_FALSE; 186} 187 188/** 189 * Initialize new texture's gl_texture_image structures. Will not call driver 190 * to allocate new space, simply record relevant layer, face, format, etc. 191 * \return GL_FALSE if any error, GL_TRUE otherwise. 192 */ 193static GLboolean 194initialize_texture_fields(struct gl_context *ctx, 195 GLenum target, 196 struct gl_texture_object *texObj, 197 GLint levels, 198 GLsizei width, GLsizei height, GLsizei depth, 199 GLenum internalFormat, mesa_format texFormat) 200{ 201 const GLuint numFaces = _mesa_num_tex_faces(target); 202 GLint level, levelWidth = width, levelHeight = height, levelDepth = depth; 203 GLuint face; 204 205 /* Pretend we are bound to initialize the gl_texture_image structs */ 206 texObj->Target = target; 207 208 /* Set up all the texture object's gl_texture_images */ 209 for (level = 0; level < levels; level++) { 210 for (face = 0; face < numFaces; face++) { 211 struct gl_texture_image *texImage; 212 GLenum faceTarget = target; 213 214 if (target == GL_TEXTURE_CUBE_MAP) 215 faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; 216 217 texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, level); 218 219 if (!texImage) { 220 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage"); 221 return GL_FALSE; 222 } 223 224 _mesa_init_teximage_fields(ctx, texImage, 225 levelWidth, levelHeight, levelDepth, 226 0, internalFormat, texFormat); 227 } 228 229 _mesa_next_mipmap_level_size(target, 0, levelWidth, levelHeight, levelDepth, 230 &levelWidth, &levelHeight, &levelDepth); 231 } 232 233 /* "unbind" */ 234 texObj->Target = 0; 235 236 return GL_TRUE; 237} 238 239#define RETURN_IF_SUPPORTED(t) do { \ 240 if (newTarget == GL_ ## t) \ 241 return true; \ 242} while (0) 243 244/** 245 * Check for compatible target 246 * If an error is found, record it with _mesa_error() 247 * \return false if any error, true otherwise. 248 */ 249static bool 250target_valid(struct gl_context *ctx, GLenum origTarget, GLenum newTarget) 251{ 252 /* 253 * From ARB_texture_view spec: 254 --------------------------------------------------------------------------------------------------------- 255 | Original target | Valid new targets | 256 --------------------------------------------------------------------------------------------------------- 257 | TEXTURE_1D | TEXTURE_1D, TEXTURE_1D_ARRAY | 258 | ------------------------------------------------------------------------------------------------------- | 259 | TEXTURE_2D | TEXTURE_2D, TEXTURE_2D_ARRAY | 260 | ------------------------------------------------------------------------------------------------------- | 261 | TEXTURE_3D | TEXTURE_3D | 262 | ------------------------------------------------------------------------------------------------------- | 263 | TEXTURE_CUBE_MAP | TEXTURE_CUBE_MAP, TEXTURE_2D, TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY | 264 | ------------------------------------------------------------------------------------------------------- | 265 | TEXTURE_RECTANGLE | TEXTURE_RECTANGLE | 266 | ------------------------------------------------------------------------------------------------------- | 267 | TEXTURE_BUFFER | <none> | 268 | ------------------------------------------------------------------------------------------------------- | 269 | TEXTURE_1D_ARRAY | TEXTURE_1D_ARRAY, TEXTURE_1D | 270 | ------------------------------------------------------------------------------------------------------- | 271 | TEXTURE_2D_ARRAY | TEXTURE_2D_ARRAY, TEXTURE_2D, TEXTURE_CUBE_MAP, TEXTURE_CUBE_MAP_ARRAY | 272 | ------------------------------------------------------------------------------------------------------- | 273 | TEXTURE_CUBE_MAP_ARRAY | TEXTURE_CUBE_MAP_ARRAY, TEXTURE_2D_ARRAY, TEXTURE_2D, TEXTURE_CUBE_MAP | 274 | ------------------------------------------------------------------------------------------------------- | 275 | TEXTURE_2D_MULTISAMPLE | TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY | 276 | ------------------------------------------------------------------------------------------------------- | 277 | TEXTURE_2D_MULTISAMPLE_ARRAY | TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY | 278 --------------------------------------------------------------------------------------------------------- 279 */ 280 281 switch (origTarget) { 282 case GL_TEXTURE_1D: 283 case GL_TEXTURE_1D_ARRAY: 284 RETURN_IF_SUPPORTED(TEXTURE_1D); 285 RETURN_IF_SUPPORTED(TEXTURE_1D_ARRAY); 286 break; 287 case GL_TEXTURE_2D: 288 RETURN_IF_SUPPORTED(TEXTURE_2D); 289 RETURN_IF_SUPPORTED(TEXTURE_2D_ARRAY); 290 break; 291 case GL_TEXTURE_3D: 292 RETURN_IF_SUPPORTED(TEXTURE_3D); 293 break; 294 case GL_TEXTURE_RECTANGLE: 295 RETURN_IF_SUPPORTED(TEXTURE_RECTANGLE); 296 break; 297 case GL_TEXTURE_CUBE_MAP: 298 case GL_TEXTURE_2D_ARRAY: 299 case GL_TEXTURE_CUBE_MAP_ARRAY: 300 RETURN_IF_SUPPORTED(TEXTURE_2D); 301 RETURN_IF_SUPPORTED(TEXTURE_2D_ARRAY); 302 RETURN_IF_SUPPORTED(TEXTURE_CUBE_MAP); 303 RETURN_IF_SUPPORTED(TEXTURE_CUBE_MAP_ARRAY); 304 break; 305 case GL_TEXTURE_2D_MULTISAMPLE: 306 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 307 RETURN_IF_SUPPORTED(TEXTURE_2D_MULTISAMPLE); 308 RETURN_IF_SUPPORTED(TEXTURE_2D_MULTISAMPLE_ARRAY); 309 break; 310 } 311 _mesa_error(ctx, GL_INVALID_OPERATION, 312 "glTextureView(illegal target=%s)", 313 _mesa_lookup_enum_by_nr(newTarget)); 314 return false; 315} 316#undef RETURN_IF_SUPPORTED 317 318/** 319 * Check for compatible format 320 * If an error is found, record it with _mesa_error() 321 * \return false if any error, true otherwise. 322 */ 323GLboolean 324_mesa_texture_view_compatible_format(struct gl_context *ctx, 325 GLenum origInternalFormat, 326 GLenum newInternalFormat) 327{ 328 unsigned int origViewClass, newViewClass; 329 330 /* The two textures' internal formats must be compatible according to 331 * Table 3.X.2 (Compatible internal formats for TextureView) 332 * if the internal format exists in that table the view class must match. 333 * The internal formats must be identical if not in that table, 334 * or an INVALID_OPERATION error is generated. 335 */ 336 if (origInternalFormat == newInternalFormat) 337 return GL_TRUE; 338 339 origViewClass = lookup_view_class(ctx, origInternalFormat); 340 newViewClass = lookup_view_class(ctx, newInternalFormat); 341 if ((origViewClass == newViewClass) && origViewClass != false) 342 return GL_TRUE; 343 344 return GL_FALSE; 345} 346/** 347 * Helper function for TexStorage and teximagemultisample to set immutable 348 * texture state needed by ARB_texture_view. 349 */ 350void 351_mesa_set_texture_view_state(struct gl_context *ctx, 352 struct gl_texture_object *texObj, 353 GLenum target, GLuint levels) 354{ 355 struct gl_texture_image *texImage; 356 357 /* Get a reference to what will become this View's base level */ 358 texImage = _mesa_select_tex_image(ctx, texObj, target, 0); 359 360 /* When an immutable texture is created via glTexStorage or glTexImageMultisample, 361 * TEXTURE_IMMUTABLE_FORMAT becomes TRUE. 362 * TEXTURE_IMMUTABLE_LEVELS and TEXTURE_VIEW_NUM_LEVELS become levels. 363 * If the texture target is TEXTURE_1D_ARRAY then 364 * TEXTURE_VIEW_NUM_LAYERS becomes height. 365 * If the texture target is TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY, 366 * or TEXTURE_2D_MULTISAMPLE_ARRAY then TEXTURE_VIEW_NUM_LAYERS becomes depth. 367 * If the texture target is TEXTURE_CUBE_MAP, then 368 * TEXTURE_VIEW_NUM_LAYERS becomes 6. 369 * For any other texture target, TEXTURE_VIEW_NUM_LAYERS becomes 1. 370 * 371 * ARB_texture_multisample: Multisample textures do 372 * not have multiple image levels. 373 */ 374 375 texObj->Immutable = GL_TRUE; 376 texObj->ImmutableLevels = levels; 377 texObj->MinLevel = 0; 378 texObj->NumLevels = levels; 379 texObj->MinLayer = 0; 380 texObj->NumLayers = 1; 381 switch (target) { 382 case GL_TEXTURE_1D_ARRAY: 383 texObj->NumLayers = texImage->Height; 384 break; 385 386 case GL_TEXTURE_2D_MULTISAMPLE: 387 texObj->NumLevels = 1; 388 texObj->ImmutableLevels = 1; 389 break; 390 391 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 392 texObj->NumLevels = 1; 393 texObj->ImmutableLevels = 1; 394 /* fall through to set NumLayers */ 395 396 case GL_TEXTURE_2D_ARRAY: 397 case GL_TEXTURE_CUBE_MAP_ARRAY: 398 texObj->NumLayers = texImage->Depth; 399 break; 400 401 case GL_TEXTURE_CUBE_MAP: 402 texObj->NumLayers = 6; 403 break; 404 405 } 406} 407 408/** 409 * glTextureView (ARB_texture_view) 410 * If an error is found, record it with _mesa_error() 411 * \return none. 412 */ 413void GLAPIENTRY 414_mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, 415 GLenum internalformat, 416 GLuint minlevel, GLuint numlevels, 417 GLuint minlayer, GLuint numlayers) 418{ 419 struct gl_texture_object *texObj; 420 struct gl_texture_object *origTexObj; 421 struct gl_texture_image *origTexImage; 422 GLuint newViewMinLevel, newViewMinLayer; 423 GLuint newViewNumLevels, newViewNumLayers; 424 GLsizei width, height, depth; 425 mesa_format texFormat; 426 GLboolean sizeOK, dimensionsOK; 427 GLenum faceTarget; 428 429 GET_CURRENT_CONTEXT(ctx); 430 431 if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) 432 _mesa_debug(ctx, "glTextureView %d %s %d %s %d %d %d %d\n", 433 texture, _mesa_lookup_enum_by_nr(target), origtexture, 434 _mesa_lookup_enum_by_nr(internalformat), 435 minlevel, numlevels, minlayer, numlayers); 436 437 if (origtexture == 0) { 438 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", origtexture); 439 return; 440 } 441 442 /* Need original texture information to validate arguments */ 443 origTexObj = _mesa_lookup_texture(ctx, origtexture); 444 445 /* If <origtexture> is not the name of a texture, INVALID_VALUE is generated. */ 446 if (!origTexObj) { 447 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", origtexture); 448 return; 449 } 450 451 /* If <origtexture>'s TEXTURE_IMMUTABLE_FORMAT value is not TRUE, 452 * INVALID_OPERATION is generated. 453 */ 454 if (!origTexObj->Immutable) { 455 _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(origtexture not immutable)"); 456 return; 457 } 458 459 /* If <texture> is 0, INVALID_VALUE is generated. */ 460 if (texture == 0) { 461 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(texture = 0)"); 462 return; 463 } 464 465 /* If <texture> is not a valid name returned by GenTextures, 466 * the error INVALID_OPERATION is generated. 467 */ 468 texObj = _mesa_lookup_texture(ctx, texture); 469 if (texObj == NULL) { 470 _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(texture = %u non-gen name)", texture); 471 return; 472 } 473 474 /* If <texture> has already been bound and given a target, then 475 * the error INVALID_OPERATION is generated. 476 */ 477 if (texObj->Target) { 478 _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(texture = %u already bound)", texture); 479 return; 480 } 481 482 /* Check for compatible target */ 483 if (!target_valid(ctx, origTexObj->Target, target)) { 484 return; /* error was recorded */ 485 } 486 487 /* minlevel and minlayer are relative to the view of origtexture 488 * If minlevel or minlayer is greater than level or layer, respectively, 489 * of origtexture return INVALID_VALUE. 490 */ 491 newViewMinLevel = origTexObj->MinLevel + minlevel; 492 newViewMinLayer = origTexObj->MinLayer + minlayer; 493 if (newViewMinLevel >= (origTexObj->MinLevel + origTexObj->NumLevels)) { 494 _mesa_error(ctx, GL_INVALID_VALUE, 495 "glTextureView(new minlevel (%d) > orig minlevel (%d) + orig numlevels (%d))", 496 newViewMinLevel, origTexObj->MinLevel, origTexObj->NumLevels); 497 return; 498 } 499 500 if (newViewMinLayer >= (origTexObj->MinLayer + origTexObj->NumLayers)) { 501 _mesa_error(ctx, GL_INVALID_VALUE, 502 "glTextureView(new minlayer (%d) > orig minlayer (%d) + orig numlayers (%d))", 503 newViewMinLayer, origTexObj->MinLayer, origTexObj->NumLayers); 504 return; 505 } 506 507 if (!_mesa_texture_view_compatible_format(ctx, 508 origTexObj->Image[0][0]->InternalFormat, 509 internalformat)) { 510 _mesa_error(ctx, GL_INVALID_OPERATION, 511 "glTextureView(internalformat %s not compatible with origtexture %s)", 512 _mesa_lookup_enum_by_nr(internalformat), 513 _mesa_lookup_enum_by_nr(origTexObj->Image[0][0]->InternalFormat)); 514 return; 515 } 516 517 texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, 518 internalformat, GL_NONE, GL_NONE); 519 assert(texFormat != MESA_FORMAT_NONE); 520 if (texFormat == MESA_FORMAT_NONE) return; 521 522 newViewNumLevels = MIN2(numlevels, origTexObj->NumLevels - minlevel); 523 newViewNumLayers = MIN2(numlayers, origTexObj->NumLayers - minlayer); 524 525 faceTarget = origTexObj->Target; 526 if (faceTarget == GL_TEXTURE_CUBE_MAP) 527 faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + minlayer; 528 529 /* Get a reference to what will become this View's base level */ 530 origTexImage = _mesa_select_tex_image(ctx, origTexObj, 531 faceTarget, minlevel); 532 width = origTexImage->Width; 533 height = origTexImage->Height; 534 depth = origTexImage->Depth; 535 536 /* Adjust width, height, depth to be appropriate for new target */ 537 switch (target) { 538 case GL_TEXTURE_1D: 539 case GL_TEXTURE_3D: 540 break; 541 542 case GL_TEXTURE_1D_ARRAY: 543 height = (GLsizei) newViewNumLayers; 544 break; 545 546 case GL_TEXTURE_2D: 547 case GL_TEXTURE_2D_MULTISAMPLE: 548 case GL_TEXTURE_RECTANGLE: 549 case GL_TEXTURE_CUBE_MAP: 550 depth = 1; 551 break; 552 553 case GL_TEXTURE_2D_ARRAY: 554 case GL_TEXTURE_CUBE_MAP_ARRAY: 555 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 556 depth = newViewNumLayers; 557 break; 558 } 559 560 /* If the dimensions of the original texture are larger than the maximum 561 * supported dimensions of the new target, the error INVALID_OPERATION is 562 * generated. For example, if the original texture has a TEXTURE_2D_ARRAY 563 * target and its width is greater than MAX_CUBE_MAP_TEXTURE_SIZE, an error 564 * will be generated if TextureView is called to create a TEXTURE_CUBE_MAP 565 * view. 566 */ 567 dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, 568 width, height, depth, 0); 569 if (!dimensionsOK) { 570 _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(invalid width or height or depth)"); 571 return; 572 } 573 574 sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 0, texFormat, 575 width, height, depth, 0); 576 if (!sizeOK) { 577 _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(invalid texture size)"); 578 return; 579 } 580 581 /* If <target> is TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_RECTANGLE, 582 * or TEXTURE_2D_MULTISAMPLE and <numlayers> does not equal 1, the error 583 * INVALID_VALUE is generated. 584 */ 585 switch (target) { 586 case GL_TEXTURE_1D: 587 case GL_TEXTURE_2D: 588 case GL_TEXTURE_3D: 589 case GL_TEXTURE_RECTANGLE: 590 case GL_TEXTURE_2D_MULTISAMPLE: 591 if (numlayers != 1) { 592 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(numlayers %d != 1)", numlayers); 593 return; 594 } 595 break; 596 597 case GL_TEXTURE_CUBE_MAP: 598 /* If the new texture's target is TEXTURE_CUBE_MAP, the clamped <numlayers> 599 * must be equal to 6. 600 */ 601 if (newViewNumLayers != 6) { 602 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(clamped numlayers %d != 6)", 603 newViewNumLayers); 604 return; 605 } 606 break; 607 608 case GL_TEXTURE_CUBE_MAP_ARRAY: 609 /* If the new texture's target is TEXTURE_CUBE_MAP_ARRAY, 610 * then <numlayers> counts layer-faces rather than layers, 611 * and the clamped <numlayers> must be a multiple of 6. 612 * Otherwise, the error INVALID_VALUE is generated. 613 */ 614 if ((newViewNumLayers % 6) != 0) { 615 _mesa_error(ctx, GL_INVALID_VALUE, 616 "glTextureView(clamped numlayers %d is not a multiple of 6)", 617 newViewNumLayers); 618 return; 619 } 620 break; 621 } 622 623 /* If the new texture's target is TEXTURE_CUBE_MAP or 624 * TEXTURE_CUBE_MAP_ARRAY, the width and height of the original texture's 625 * levels must be equal otherwise the error INVALID_OPERATION is generated. 626 */ 627 if ((target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY) && 628 (origTexImage->Width != origTexImage->Height)) { 629 _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureView(origtexture width (%d) != height (%d))", 630 origTexImage->Width, origTexImage->Height); 631 return; 632 } 633 634 /* When the original texture's target is TEXTURE_CUBE_MAP, the layer 635 * parameters are interpreted in the same order as if it were a 636 * TEXTURE_CUBE_MAP_ARRAY with 6 layer-faces. 637 */ 638 639 /* If the internal format does not exactly match the internal format of the 640 * original texture, the contents of the memory are reinterpreted in the 641 * same manner as for image bindings described in 642 * section 3.9.20 (Texture Image Loads and Stores). 643 */ 644 645 /* TEXTURE_BASE_LEVEL and TEXTURE_MAX_LEVEL are interpreted 646 * relative to the view and not relative to the original data store. 647 */ 648 649 if (!initialize_texture_fields(ctx, target, texObj, newViewNumLevels, 650 width, height, depth, 651 internalformat, texFormat)) { 652 return; /* Already recorded error */ 653 } 654 655 texObj->MinLevel = newViewMinLevel; 656 texObj->MinLayer = newViewMinLayer; 657 texObj->NumLevels = newViewNumLevels; 658 texObj->NumLayers = newViewNumLayers; 659 texObj->Immutable = GL_TRUE; 660 texObj->ImmutableLevels = origTexObj->ImmutableLevels; 661 texObj->Target = target; 662 663 if (ctx->Driver.TextureView != NULL && !ctx->Driver.TextureView(ctx, texObj, origTexObj)) { 664 return; /* driver recorded error */ 665 } 666} 667