textureview.c revision 01e04c3f
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2013 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Courtney Goeltzenleuchter <courtney@lunarg.com> 26 */ 27 28 29/** 30 * \file textureview.c 31 * GL_ARB_texture_view functions 32 */ 33 34#include "glheader.h" 35#include "context.h" 36#include "enums.h" 37#include "imports.h" 38#include "macros.h" 39#include "teximage.h" 40#include "texobj.h" 41#include "mipmap.h" 42#include "texstorage.h" 43#include "textureview.h" 44#include "stdbool.h" 45#include "mtypes.h" 46 47/* Table 3.X.2 (Compatible internal formats for TextureView) 48 --------------------------------------------------------------------------- 49 | Class | Internal formats | 50 --------------------------------------------------------------------------- 51 | VIEW_CLASS_128_BITS | RGBA32F, RGBA32UI, RGBA32I | 52 --------------------------------------------------------------------------- 53 | VIEW_CLASS_96_BITS | RGB32F, RGB32UI, RGB32I | 54 --------------------------------------------------------------------------- 55 | VIEW_CLASS_64_BITS | RGBA16F, RG32F, RGBA16UI, RG32UI, RGBA16I, | 56 | | RG32I, RGBA16, RGBA16_SNORM | 57 --------------------------------------------------------------------------- 58 | VIEW_CLASS_48_BITS | RGB16, RGB16_SNORM, RGB16F, RGB16UI, RGB16I | 59 --------------------------------------------------------------------------- 60 | VIEW_CLASS_32_BITS | RG16F, R11F_G11F_B10F, R32F, | 61 | | RGB10_A2UI, RGBA8UI, RG16UI, R32UI, | 62 | | RGBA8I, RG16I, R32I, RGB10_A2, RGBA8, RG16, | 63 | | RGBA8_SNORM, RG16_SNORM, SRGB8_ALPHA8, RGB9_E5 | 64 --------------------------------------------------------------------------- 65 | VIEW_CLASS_24_BITS | RGB8, RGB8_SNORM, SRGB8, RGB8UI, RGB8I | 66 --------------------------------------------------------------------------- 67 | VIEW_CLASS_16_BITS | R16F, RG8UI, R16UI, RG8I, R16I, RG8, R16, | 68 | | RG8_SNORM, R16_SNORM | 69 --------------------------------------------------------------------------- 70 | VIEW_CLASS_8_BITS | R8UI, R8I, R8, R8_SNORM | 71 --------------------------------------------------------------------------- 72 | VIEW_CLASS_RGTC1_RED | COMPRESSED_RED_RGTC1, | 73 | | COMPRESSED_SIGNED_RED_RGTC1 | 74 --------------------------------------------------------------------------- 75 | VIEW_CLASS_RGTC2_RG | COMPRESSED_RG_RGTC2, | 76 | | COMPRESSED_SIGNED_RG_RGTC2 | 77 --------------------------------------------------------------------------- 78 | VIEW_CLASS_BPTC_UNORM | COMPRESSED_RGBA_BPTC_UNORM, | 79 | | COMPRESSED_SRGB_ALPHA_BPTC_UNORM | 80 --------------------------------------------------------------------------- 81 | VIEW_CLASS_BPTC_FLOAT | COMPRESSED_RGB_BPTC_SIGNED_FLOAT, | 82 | | COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT | 83 --------------------------------------------------------------------------- 84 */ 85 86#define VIEW_CLASS_GLES(x) (GL_VIEW_CLASS_BPTC_FLOAT + 1 + x) 87#define VIEW_CLASS_EAC_R11 VIEW_CLASS_GLES(0) 88#define VIEW_CLASS_EAC_RG11 VIEW_CLASS_GLES(1) 89#define VIEW_CLASS_ETC2_RGB VIEW_CLASS_GLES(2) 90#define VIEW_CLASS_ETC2_RGBA VIEW_CLASS_GLES(3) 91#define VIEW_CLASS_ETC2_EAC_RGBA VIEW_CLASS_GLES(4) 92#define VIEW_CLASS_ASTC_4x4_RGBA VIEW_CLASS_GLES(5) 93#define VIEW_CLASS_ASTC_5x4_RGBA VIEW_CLASS_GLES(6) 94#define VIEW_CLASS_ASTC_5x5_RGBA VIEW_CLASS_GLES(7) 95#define VIEW_CLASS_ASTC_6x5_RGBA VIEW_CLASS_GLES(8) 96#define VIEW_CLASS_ASTC_6x6_RGBA VIEW_CLASS_GLES(9) 97#define VIEW_CLASS_ASTC_8x5_RGBA VIEW_CLASS_GLES(10) 98#define VIEW_CLASS_ASTC_8x6_RGBA VIEW_CLASS_GLES(11) 99#define VIEW_CLASS_ASTC_8x8_RGBA VIEW_CLASS_GLES(12) 100#define VIEW_CLASS_ASTC_10x5_RGBA VIEW_CLASS_GLES(13) 101#define VIEW_CLASS_ASTC_10x6_RGBA VIEW_CLASS_GLES(14) 102#define VIEW_CLASS_ASTC_10x8_RGBA VIEW_CLASS_GLES(15) 103#define VIEW_CLASS_ASTC_10x10_RGBA VIEW_CLASS_GLES(16) 104#define VIEW_CLASS_ASTC_12x10_RGBA VIEW_CLASS_GLES(17) 105#define VIEW_CLASS_ASTC_12x12_RGBA VIEW_CLASS_GLES(18) 106#define VIEW_CLASS_ASTC_3x3x3_RGBA VIEW_CLASS_GLES(19) 107#define VIEW_CLASS_ASTC_4x3x3_RGBA VIEW_CLASS_GLES(20) 108#define VIEW_CLASS_ASTC_4x4x3_RGBA VIEW_CLASS_GLES(21) 109#define VIEW_CLASS_ASTC_4x4x4_RGBA VIEW_CLASS_GLES(22) 110#define VIEW_CLASS_ASTC_5x4x4_RGBA VIEW_CLASS_GLES(23) 111#define VIEW_CLASS_ASTC_5x5x4_RGBA VIEW_CLASS_GLES(24) 112#define VIEW_CLASS_ASTC_5x5x5_RGBA VIEW_CLASS_GLES(25) 113#define VIEW_CLASS_ASTC_6x5x5_RGBA VIEW_CLASS_GLES(26) 114#define VIEW_CLASS_ASTC_6x6x5_RGBA VIEW_CLASS_GLES(27) 115#define VIEW_CLASS_ASTC_6x6x6_RGBA VIEW_CLASS_GLES(28) 116 117 118struct internal_format_class_info { 119 GLenum view_class; 120 GLenum internal_format; 121}; 122static const struct internal_format_class_info compatible_internal_formats[] = { 123 {GL_VIEW_CLASS_128_BITS, GL_RGBA32F}, 124 {GL_VIEW_CLASS_128_BITS, GL_RGBA32UI}, 125 {GL_VIEW_CLASS_128_BITS, GL_RGBA32I}, 126 {GL_VIEW_CLASS_96_BITS, GL_RGB32F}, 127 {GL_VIEW_CLASS_96_BITS, GL_RGB32UI}, 128 {GL_VIEW_CLASS_96_BITS, GL_RGB32I}, 129 {GL_VIEW_CLASS_64_BITS, GL_RGBA16F}, 130 {GL_VIEW_CLASS_64_BITS, GL_RG32F}, 131 {GL_VIEW_CLASS_64_BITS, GL_RGBA16UI}, 132 {GL_VIEW_CLASS_64_BITS, GL_RG32UI}, 133 {GL_VIEW_CLASS_64_BITS, GL_RGBA16I}, 134 {GL_VIEW_CLASS_64_BITS, GL_RG32I}, 135 {GL_VIEW_CLASS_64_BITS, GL_RGBA16}, 136 {GL_VIEW_CLASS_64_BITS, GL_RGBA16_SNORM}, 137 {GL_VIEW_CLASS_48_BITS, GL_RGB16}, 138 {GL_VIEW_CLASS_48_BITS, GL_RGB16_SNORM}, 139 {GL_VIEW_CLASS_48_BITS, GL_RGB16F}, 140 {GL_VIEW_CLASS_48_BITS, GL_RGB16UI}, 141 {GL_VIEW_CLASS_48_BITS, GL_RGB16I}, 142 {GL_VIEW_CLASS_32_BITS, GL_RG16F}, 143 {GL_VIEW_CLASS_32_BITS, GL_R11F_G11F_B10F}, 144 {GL_VIEW_CLASS_32_BITS, GL_R32F}, 145 {GL_VIEW_CLASS_32_BITS, GL_RGB10_A2UI}, 146 {GL_VIEW_CLASS_32_BITS, GL_RGBA8UI}, 147 {GL_VIEW_CLASS_32_BITS, GL_RG16UI}, 148 {GL_VIEW_CLASS_32_BITS, GL_R32UI}, 149 {GL_VIEW_CLASS_32_BITS, GL_RGBA8I}, 150 {GL_VIEW_CLASS_32_BITS, GL_RG16I}, 151 {GL_VIEW_CLASS_32_BITS, GL_R32I}, 152 {GL_VIEW_CLASS_32_BITS, GL_RGB10_A2}, 153 {GL_VIEW_CLASS_32_BITS, GL_RGBA8}, 154 {GL_VIEW_CLASS_32_BITS, GL_RG16}, 155 {GL_VIEW_CLASS_32_BITS, GL_RGBA8_SNORM}, 156 {GL_VIEW_CLASS_32_BITS, GL_RG16_SNORM}, 157 {GL_VIEW_CLASS_32_BITS, GL_SRGB8_ALPHA8}, 158 {GL_VIEW_CLASS_32_BITS, GL_RGB9_E5}, 159 {GL_VIEW_CLASS_24_BITS, GL_RGB8}, 160 {GL_VIEW_CLASS_24_BITS, GL_RGB8_SNORM}, 161 {GL_VIEW_CLASS_24_BITS, GL_SRGB8}, 162 {GL_VIEW_CLASS_24_BITS, GL_RGB8UI}, 163 {GL_VIEW_CLASS_24_BITS, GL_RGB8I}, 164 {GL_VIEW_CLASS_16_BITS, GL_R16F}, 165 {GL_VIEW_CLASS_16_BITS, GL_RG8UI}, 166 {GL_VIEW_CLASS_16_BITS, GL_R16UI}, 167 {GL_VIEW_CLASS_16_BITS, GL_RG8I}, 168 {GL_VIEW_CLASS_16_BITS, GL_R16I}, 169 {GL_VIEW_CLASS_16_BITS, GL_RG8}, 170 {GL_VIEW_CLASS_16_BITS, GL_R16}, 171 {GL_VIEW_CLASS_16_BITS, GL_RG8_SNORM}, 172 {GL_VIEW_CLASS_16_BITS, GL_R16_SNORM}, 173 {GL_VIEW_CLASS_8_BITS, GL_R8UI}, 174 {GL_VIEW_CLASS_8_BITS, GL_R8I}, 175 {GL_VIEW_CLASS_8_BITS, GL_R8}, 176 {GL_VIEW_CLASS_8_BITS, GL_R8_SNORM}, 177 {GL_VIEW_CLASS_RGTC1_RED, GL_COMPRESSED_RED_RGTC1}, 178 {GL_VIEW_CLASS_RGTC1_RED, GL_COMPRESSED_SIGNED_RED_RGTC1}, 179 {GL_VIEW_CLASS_RGTC2_RG, GL_COMPRESSED_RG_RGTC2}, 180 {GL_VIEW_CLASS_RGTC2_RG, GL_COMPRESSED_SIGNED_RG_RGTC2}, 181 {GL_VIEW_CLASS_BPTC_UNORM, GL_COMPRESSED_RGBA_BPTC_UNORM_ARB}, 182 {GL_VIEW_CLASS_BPTC_UNORM, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB}, 183 {GL_VIEW_CLASS_BPTC_FLOAT, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB}, 184 {GL_VIEW_CLASS_BPTC_FLOAT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB}, 185}; 186 187static const struct internal_format_class_info s3tc_compatible_internal_formats[] = { 188 {GL_VIEW_CLASS_S3TC_DXT1_RGB, GL_COMPRESSED_RGB_S3TC_DXT1_EXT}, 189 {GL_VIEW_CLASS_S3TC_DXT1_RGB, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT}, 190 {GL_VIEW_CLASS_S3TC_DXT1_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT}, 191 {GL_VIEW_CLASS_S3TC_DXT1_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT}, 192 {GL_VIEW_CLASS_S3TC_DXT3_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT}, 193 {GL_VIEW_CLASS_S3TC_DXT3_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT}, 194 {GL_VIEW_CLASS_S3TC_DXT5_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT}, 195 {GL_VIEW_CLASS_S3TC_DXT5_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}, 196}; 197 198static const struct internal_format_class_info gles_etc2_compatible_internal_formats[] = { 199 {VIEW_CLASS_EAC_R11, GL_COMPRESSED_R11_EAC}, 200 {VIEW_CLASS_EAC_R11, GL_COMPRESSED_SIGNED_R11_EAC}, 201 {VIEW_CLASS_EAC_RG11, GL_COMPRESSED_RG11_EAC}, 202 {VIEW_CLASS_EAC_RG11, GL_COMPRESSED_SIGNED_RG11_EAC}, 203 {VIEW_CLASS_ETC2_RGB, GL_COMPRESSED_RGB8_ETC2}, 204 {VIEW_CLASS_ETC2_RGB, GL_COMPRESSED_SRGB8_ETC2}, 205 {VIEW_CLASS_ETC2_RGBA, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2}, 206 {VIEW_CLASS_ETC2_RGBA, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2}, 207 {VIEW_CLASS_ETC2_EAC_RGBA, GL_COMPRESSED_RGBA8_ETC2_EAC}, 208 {VIEW_CLASS_ETC2_EAC_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC}, 209}; 210 211static const struct internal_format_class_info gles_astc_compatible_internal_formats[] = { 212#define ASTC_FMT(size) \ 213 {VIEW_CLASS_ASTC_##size##_RGBA, GL_COMPRESSED_RGBA_ASTC_##size##_KHR}, \ 214 {VIEW_CLASS_ASTC_##size##_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_##size##_KHR} 215 216 ASTC_FMT(4x4), 217 ASTC_FMT(5x4), 218 ASTC_FMT(5x5), 219 ASTC_FMT(6x5), 220 ASTC_FMT(6x6), 221 ASTC_FMT(8x5), 222 ASTC_FMT(8x6), 223 ASTC_FMT(8x8), 224 ASTC_FMT(10x5), 225 ASTC_FMT(10x6), 226 ASTC_FMT(10x8), 227 ASTC_FMT(10x10), 228 ASTC_FMT(12x10), 229 ASTC_FMT(12x12), 230#undef ASTC_FMT 231}; 232 233static const struct internal_format_class_info gles_astc_3d_compatible_internal_formats[] = { 234#define ASTC_FMT(size) \ 235 {VIEW_CLASS_ASTC_##size##_RGBA, GL_COMPRESSED_RGBA_ASTC_##size##_OES}, \ 236 {VIEW_CLASS_ASTC_##size##_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_##size##_OES} 237 238 ASTC_FMT(3x3x3), 239 ASTC_FMT(4x3x3), 240 ASTC_FMT(4x4x3), 241 ASTC_FMT(4x4x4), 242 ASTC_FMT(5x4x4), 243 ASTC_FMT(5x5x4), 244 ASTC_FMT(5x5x5), 245 ASTC_FMT(6x5x5), 246 ASTC_FMT(6x6x5), 247 ASTC_FMT(6x6x6), 248#undef ASTC_FMT 249}; 250 251GLenum 252_mesa_texture_view_lookup_view_class(const struct gl_context *ctx, GLenum internalformat) 253{ 254 GLuint i; 255 256 for (i = 0; i < ARRAY_SIZE(compatible_internal_formats); i++) { 257 if (compatible_internal_formats[i].internal_format == internalformat) 258 return compatible_internal_formats[i].view_class; 259 } 260 261 if (ctx->Extensions.EXT_texture_compression_s3tc && 262 ctx->Extensions.EXT_texture_sRGB) { 263 for (i = 0; i < ARRAY_SIZE(s3tc_compatible_internal_formats); i++) { 264 if (s3tc_compatible_internal_formats[i].internal_format 265 == internalformat) 266 return s3tc_compatible_internal_formats[i].view_class; 267 } 268 } 269 270 if (_mesa_is_gles3(ctx)) { 271 for (i = 0; i < ARRAY_SIZE(gles_etc2_compatible_internal_formats); i++) { 272 if (gles_etc2_compatible_internal_formats[i].internal_format 273 == internalformat) 274 return gles_etc2_compatible_internal_formats[i].view_class; 275 } 276 277 if (ctx->Extensions.KHR_texture_compression_astc_ldr) { 278 for (i = 0; i < ARRAY_SIZE(gles_astc_compatible_internal_formats); i++) { 279 if (gles_astc_compatible_internal_formats[i].internal_format 280 == internalformat) 281 return gles_astc_compatible_internal_formats[i].view_class; 282 } 283 } 284 285 if (ctx->Extensions.OES_texture_compression_astc) { 286 for (i = 0; i < ARRAY_SIZE(gles_astc_3d_compatible_internal_formats); i++) { 287 if (gles_astc_3d_compatible_internal_formats[i].internal_format 288 == internalformat) 289 return gles_astc_3d_compatible_internal_formats[i].view_class; 290 } 291 } 292 } 293 return GL_FALSE; 294} 295 296/** 297 * Initialize new texture's gl_texture_image structures. Will not call driver 298 * to allocate new space, simply record relevant layer, face, format, etc. 299 * \return GL_FALSE if any error, GL_TRUE otherwise. 300 */ 301static GLboolean 302initialize_texture_fields(struct gl_context *ctx, 303 GLenum target, 304 struct gl_texture_object *texObj, 305 GLint levels, 306 GLsizei width, GLsizei height, GLsizei depth, 307 GLenum internalFormat, mesa_format texFormat, 308 GLuint numSamples, GLboolean fixedSampleLocations) 309{ 310 const GLuint numFaces = _mesa_num_tex_faces(target); 311 GLint level, levelWidth = width, levelHeight = height, levelDepth = depth; 312 GLuint face; 313 314 /* Pretend we are bound to initialize the gl_texture_image structs */ 315 texObj->Target = target; 316 317 /* Set up all the texture object's gl_texture_images */ 318 for (level = 0; level < levels; level++) { 319 for (face = 0; face < numFaces; face++) { 320 struct gl_texture_image *texImage; 321 const GLenum faceTarget = _mesa_cube_face_target(target, face); 322 323 texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, level); 324 325 if (!texImage) { 326 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage"); 327 return GL_FALSE; 328 } 329 330 _mesa_init_teximage_fields_ms(ctx, texImage, 331 levelWidth, levelHeight, levelDepth, 332 0, internalFormat, texFormat, 333 numSamples, fixedSampleLocations); 334 } 335 336 _mesa_next_mipmap_level_size(target, 0, 337 levelWidth, levelHeight, levelDepth, 338 &levelWidth, &levelHeight, &levelDepth); 339 } 340 341 /* "unbind" */ 342 texObj->Target = 0; 343 344 return GL_TRUE; 345} 346 347#define RETURN_IF_SUPPORTED(t) do { \ 348 if (newTarget == GL_ ## t) \ 349 return true; \ 350} while (0) 351 352/** 353 * Check for compatible target 354 * If an error is found, record it with _mesa_error() 355 * \return false if any error, true otherwise. 356 */ 357static bool 358target_valid(struct gl_context *ctx, GLenum origTarget, GLenum newTarget) 359{ 360 /* 361 * From ARB_texture_view spec: 362 --------------------------------------------------------------------------------------------------------- 363 | Original target | Valid new targets | 364 --------------------------------------------------------------------------------------------------------- 365 | TEXTURE_1D | TEXTURE_1D, TEXTURE_1D_ARRAY | 366 | ------------------------------------------------------------------------------------------------------- | 367 | TEXTURE_2D | TEXTURE_2D, TEXTURE_2D_ARRAY | 368 | ------------------------------------------------------------------------------------------------------- | 369 | TEXTURE_3D | TEXTURE_3D | 370 | ------------------------------------------------------------------------------------------------------- | 371 | TEXTURE_CUBE_MAP | TEXTURE_CUBE_MAP, TEXTURE_2D, TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY | 372 | ------------------------------------------------------------------------------------------------------- | 373 | TEXTURE_RECTANGLE | TEXTURE_RECTANGLE | 374 | ------------------------------------------------------------------------------------------------------- | 375 | TEXTURE_BUFFER | <none> | 376 | ------------------------------------------------------------------------------------------------------- | 377 | TEXTURE_1D_ARRAY | TEXTURE_1D_ARRAY, TEXTURE_1D | 378 | ------------------------------------------------------------------------------------------------------- | 379 | TEXTURE_2D_ARRAY | TEXTURE_2D_ARRAY, TEXTURE_2D, TEXTURE_CUBE_MAP, TEXTURE_CUBE_MAP_ARRAY | 380 | ------------------------------------------------------------------------------------------------------- | 381 | TEXTURE_CUBE_MAP_ARRAY | TEXTURE_CUBE_MAP_ARRAY, TEXTURE_2D_ARRAY, TEXTURE_2D, TEXTURE_CUBE_MAP | 382 | ------------------------------------------------------------------------------------------------------- | 383 | TEXTURE_2D_MULTISAMPLE | TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY | 384 | ------------------------------------------------------------------------------------------------------- | 385 | TEXTURE_2D_MULTISAMPLE_ARRAY | TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY | 386 --------------------------------------------------------------------------------------------------------- 387 */ 388 389 switch (origTarget) { 390 case GL_TEXTURE_1D: 391 case GL_TEXTURE_1D_ARRAY: 392 RETURN_IF_SUPPORTED(TEXTURE_1D); 393 RETURN_IF_SUPPORTED(TEXTURE_1D_ARRAY); 394 break; 395 case GL_TEXTURE_2D: 396 RETURN_IF_SUPPORTED(TEXTURE_2D); 397 RETURN_IF_SUPPORTED(TEXTURE_2D_ARRAY); 398 break; 399 case GL_TEXTURE_3D: 400 RETURN_IF_SUPPORTED(TEXTURE_3D); 401 break; 402 case GL_TEXTURE_RECTANGLE: 403 RETURN_IF_SUPPORTED(TEXTURE_RECTANGLE); 404 break; 405 case GL_TEXTURE_CUBE_MAP: 406 case GL_TEXTURE_2D_ARRAY: 407 case GL_TEXTURE_CUBE_MAP_ARRAY: 408 RETURN_IF_SUPPORTED(TEXTURE_2D); 409 RETURN_IF_SUPPORTED(TEXTURE_2D_ARRAY); 410 RETURN_IF_SUPPORTED(TEXTURE_CUBE_MAP); 411 RETURN_IF_SUPPORTED(TEXTURE_CUBE_MAP_ARRAY); 412 break; 413 case GL_TEXTURE_2D_MULTISAMPLE: 414 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 415 RETURN_IF_SUPPORTED(TEXTURE_2D_MULTISAMPLE); 416 RETURN_IF_SUPPORTED(TEXTURE_2D_MULTISAMPLE_ARRAY); 417 break; 418 } 419 _mesa_error(ctx, GL_INVALID_OPERATION, 420 "glTextureView(illegal target=%s)", 421 _mesa_enum_to_string(newTarget)); 422 return false; 423} 424#undef RETURN_IF_SUPPORTED 425 426/** 427 * Check for compatible format 428 * If an error is found, record it with _mesa_error() 429 * \return false if any error, true otherwise. 430 */ 431bool 432_mesa_texture_view_compatible_format(const struct gl_context *ctx, 433 GLenum origInternalFormat, 434 GLenum newInternalFormat) 435{ 436 unsigned int origViewClass, newViewClass; 437 438 /* The two textures' internal formats must be compatible according to 439 * Table 3.X.2 (Compatible internal formats for TextureView) 440 * if the internal format exists in that table the view class must match. 441 * The internal formats must be identical if not in that table, 442 * or an INVALID_OPERATION error is generated. 443 */ 444 if (origInternalFormat == newInternalFormat) 445 return true; 446 447 origViewClass = _mesa_texture_view_lookup_view_class(ctx, origInternalFormat); 448 newViewClass = _mesa_texture_view_lookup_view_class(ctx, newInternalFormat); 449 if ((origViewClass == newViewClass) && origViewClass != false) 450 return true; 451 452 return false; 453} 454 455/** 456 * Helper function for TexStorage and teximagemultisample to set immutable 457 * texture state needed by ARB_texture_view. 458 */ 459void 460_mesa_set_texture_view_state(struct gl_context *ctx, 461 struct gl_texture_object *texObj, 462 GLenum target, GLuint levels) 463{ 464 struct gl_texture_image *texImage; 465 466 /* Get a reference to what will become this View's base level */ 467 texImage = _mesa_select_tex_image(texObj, target, 0); 468 469 /* When an immutable texture is created via glTexStorage or 470 * glTexImageMultisample, 471 * TEXTURE_IMMUTABLE_FORMAT becomes TRUE. 472 * TEXTURE_IMMUTABLE_LEVELS and TEXTURE_VIEW_NUM_LEVELS become levels. 473 * If the texture target is TEXTURE_1D_ARRAY then 474 * TEXTURE_VIEW_NUM_LAYERS becomes height. 475 * If the texture target is TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY, 476 * or TEXTURE_2D_MULTISAMPLE_ARRAY then TEXTURE_VIEW_NUM_LAYERS becomes 477 * depth. 478 * If the texture target is TEXTURE_CUBE_MAP, then 479 * TEXTURE_VIEW_NUM_LAYERS becomes 6. 480 * For any other texture target, TEXTURE_VIEW_NUM_LAYERS becomes 1. 481 * 482 * ARB_texture_multisample: Multisample textures do 483 * not have multiple image levels. 484 */ 485 486 texObj->Immutable = GL_TRUE; 487 texObj->ImmutableLevels = levels; 488 texObj->MinLevel = 0; 489 texObj->NumLevels = levels; 490 texObj->MinLayer = 0; 491 texObj->NumLayers = 1; 492 switch (target) { 493 case GL_TEXTURE_1D_ARRAY: 494 texObj->NumLayers = texImage->Height; 495 break; 496 497 case GL_TEXTURE_2D_MULTISAMPLE: 498 texObj->NumLevels = 1; 499 texObj->ImmutableLevels = 1; 500 break; 501 502 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 503 texObj->NumLevels = 1; 504 texObj->ImmutableLevels = 1; 505 /* fall through to set NumLayers */ 506 507 case GL_TEXTURE_2D_ARRAY: 508 case GL_TEXTURE_CUBE_MAP_ARRAY: 509 texObj->NumLayers = texImage->Depth; 510 break; 511 512 case GL_TEXTURE_CUBE_MAP: 513 texObj->NumLayers = 6; 514 break; 515 } 516} 517 518/** 519 * glTextureView (ARB_texture_view) 520 * If an error is found, record it with _mesa_error() 521 * \return none. 522 */ 523static ALWAYS_INLINE void 524texture_view(struct gl_context *ctx, struct gl_texture_object *origTexObj, 525 struct gl_texture_object *texObj, GLenum target, 526 GLenum internalformat, GLuint minlevel, GLuint numlevels, 527 GLuint minlayer, GLuint numlayers, bool no_error) 528{ 529 struct gl_texture_image *origTexImage; 530 GLuint newViewNumLevels, newViewNumLayers; 531 GLsizei width, height, depth; 532 mesa_format texFormat; 533 GLboolean sizeOK, dimensionsOK; 534 GLenum faceTarget; 535 536 texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, 537 internalformat, GL_NONE, GL_NONE); 538 if (texFormat == MESA_FORMAT_NONE) return; 539 540 newViewNumLevels = MIN2(numlevels, origTexObj->NumLevels - minlevel); 541 newViewNumLayers = MIN2(numlayers, origTexObj->NumLayers - minlayer); 542 543 faceTarget = _mesa_cube_face_target(origTexObj->Target, minlayer); 544 545 /* Get a reference to what will become this View's base level */ 546 origTexImage = _mesa_select_tex_image(origTexObj, faceTarget, minlevel); 547 width = origTexImage->Width; 548 height = origTexImage->Height; 549 depth = origTexImage->Depth; 550 551 /* Adjust width, height, depth to be appropriate for new target */ 552 switch (target) { 553 case GL_TEXTURE_1D: 554 height = 1; 555 break; 556 557 case GL_TEXTURE_3D: 558 break; 559 560 case GL_TEXTURE_1D_ARRAY: 561 height = (GLsizei) newViewNumLayers; 562 break; 563 564 case GL_TEXTURE_2D: 565 case GL_TEXTURE_2D_MULTISAMPLE: 566 case GL_TEXTURE_RECTANGLE: 567 depth = 1; 568 break; 569 case GL_TEXTURE_CUBE_MAP: 570 /* If the new texture's target is TEXTURE_CUBE_MAP, the clamped 571 * <numlayers> must be equal to 6. 572 */ 573 if (!no_error && newViewNumLayers != 6) { 574 _mesa_error(ctx, GL_INVALID_VALUE, 575 "glTextureView(clamped numlayers %d != 6)", 576 newViewNumLayers); 577 return; 578 } 579 depth = 1; 580 break; 581 582 case GL_TEXTURE_2D_ARRAY: 583 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 584 depth = newViewNumLayers; 585 break; 586 case GL_TEXTURE_CUBE_MAP_ARRAY: 587 /* If the new texture's target is TEXTURE_CUBE_MAP_ARRAY, 588 * then <numlayers> counts layer-faces rather than layers, 589 * and the clamped <numlayers> must be a multiple of 6. 590 * Otherwise, the error INVALID_VALUE is generated. 591 */ 592 if (!no_error && (newViewNumLayers % 6) != 0) { 593 _mesa_error(ctx, GL_INVALID_VALUE, 594 "glTextureView(clamped numlayers %d is not" 595 " a multiple of 6)", 596 newViewNumLayers); 597 return; 598 } 599 depth = newViewNumLayers; 600 break; 601 } 602 603 if (!no_error) { 604 /* If the dimensions of the original texture are larger than the maximum 605 * supported dimensions of the new target, the error INVALID_OPERATION is 606 * generated. For example, if the original texture has a TEXTURE_2D_ARRAY 607 * target and its width is greater than MAX_CUBE_MAP_TEXTURE_SIZE, an 608 * error will be generated if TextureView is called to create a 609 * TEXTURE_CUBE_MAP view. 610 */ 611 dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, 612 width, height, depth, 0); 613 if (!dimensionsOK) { 614 _mesa_error(ctx, GL_INVALID_OPERATION, 615 "glTextureView(invalid width or height or depth)"); 616 return; 617 } 618 619 sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 1, 0, texFormat, 620 origTexImage->NumSamples, 621 width, height, depth); 622 if (!sizeOK) { 623 _mesa_error(ctx, GL_INVALID_OPERATION, 624 "glTextureView(invalid texture size)"); 625 return; 626 } 627 628 /* If <target> is TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_RECTANGLE, 629 * or TEXTURE_2D_MULTISAMPLE and <numlayers> does not equal 1, the error 630 * INVALID_VALUE is generated. 631 */ 632 switch (target) { 633 case GL_TEXTURE_1D: 634 case GL_TEXTURE_2D: 635 case GL_TEXTURE_3D: 636 case GL_TEXTURE_RECTANGLE: 637 case GL_TEXTURE_2D_MULTISAMPLE: 638 if (numlayers != 1) { 639 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(numlayers %d != 1)", 640 numlayers); 641 return; 642 } 643 break; 644 case GL_TEXTURE_CUBE_MAP: 645 break; 646 case GL_TEXTURE_CUBE_MAP_ARRAY: 647 break; 648 } 649 650 /* If the new texture's target is TEXTURE_CUBE_MAP or 651 * TEXTURE_CUBE_MAP_ARRAY, the width and height of the original texture's 652 * levels must be equal otherwise the error INVALID_OPERATION is 653 * generated. 654 */ 655 if ((target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY) 656 && (origTexImage->Width != origTexImage->Height)) { 657 _mesa_error(ctx, GL_INVALID_OPERATION, 658 "glTextureView(origtexture width (%d) != height (%d))", 659 origTexImage->Width, origTexImage->Height); 660 return; 661 } 662 } 663 664 /* When the original texture's target is TEXTURE_CUBE_MAP, the layer 665 * parameters are interpreted in the same order as if it were a 666 * TEXTURE_CUBE_MAP_ARRAY with 6 layer-faces. 667 */ 668 669 /* If the internal format does not exactly match the internal format of the 670 * original texture, the contents of the memory are reinterpreted in the 671 * same manner as for image bindings described in 672 * section 3.9.20 (Texture Image Loads and Stores). 673 */ 674 675 /* TEXTURE_BASE_LEVEL and TEXTURE_MAX_LEVEL are interpreted 676 * relative to the view and not relative to the original data store. 677 */ 678 679 if (!initialize_texture_fields(ctx, target, texObj, newViewNumLevels, 680 width, height, depth, 681 internalformat, texFormat, 682 origTexImage->NumSamples, 683 origTexImage->FixedSampleLocations)) { 684 return; /* Already recorded error */ 685 } 686 687 texObj->MinLevel = origTexObj->MinLevel + minlevel; 688 texObj->MinLayer = origTexObj->MinLayer + minlayer; 689 texObj->NumLevels = newViewNumLevels; 690 texObj->NumLayers = newViewNumLayers; 691 texObj->Immutable = GL_TRUE; 692 texObj->ImmutableLevels = origTexObj->ImmutableLevels; 693 texObj->Target = target; 694 texObj->TargetIndex = _mesa_tex_target_to_index(ctx, target); 695 assert(texObj->TargetIndex < NUM_TEXTURE_TARGETS); 696 697 if (ctx->Driver.TextureView != NULL && 698 !ctx->Driver.TextureView(ctx, texObj, origTexObj)) { 699 return; /* driver recorded error */ 700 } 701} 702 703void GLAPIENTRY 704_mesa_TextureView_no_error(GLuint texture, GLenum target, GLuint origtexture, 705 GLenum internalformat, 706 GLuint minlevel, GLuint numlevels, 707 GLuint minlayer, GLuint numlayers) 708{ 709 struct gl_texture_object *texObj; 710 struct gl_texture_object *origTexObj; 711 712 GET_CURRENT_CONTEXT(ctx); 713 714 origTexObj = _mesa_lookup_texture(ctx, origtexture); 715 texObj = _mesa_lookup_texture(ctx, texture); 716 717 texture_view(ctx, origTexObj, texObj, target, internalformat, minlevel, 718 numlevels, minlayer, numlayers, true); 719} 720 721void GLAPIENTRY 722_mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, 723 GLenum internalformat, 724 GLuint minlevel, GLuint numlevels, 725 GLuint minlayer, GLuint numlayers) 726{ 727 struct gl_texture_object *texObj; 728 struct gl_texture_object *origTexObj; 729 GLuint newViewMinLevel, newViewMinLayer; 730 731 GET_CURRENT_CONTEXT(ctx); 732 733 if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) 734 _mesa_debug(ctx, "glTextureView %d %s %d %s %d %d %d %d\n", 735 texture, _mesa_enum_to_string(target), origtexture, 736 _mesa_enum_to_string(internalformat), 737 minlevel, numlevels, minlayer, numlayers); 738 739 if (origtexture == 0) { 740 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", 741 origtexture); 742 return; 743 } 744 745 /* Need original texture information to validate arguments */ 746 origTexObj = _mesa_lookup_texture(ctx, origtexture); 747 748 /* If <origtexture> is not the name of a texture, INVALID_VALUE 749 * is generated. 750 */ 751 if (!origTexObj) { 752 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", 753 origtexture); 754 return; 755 } 756 757 /* If <origtexture>'s TEXTURE_IMMUTABLE_FORMAT value is not TRUE, 758 * INVALID_OPERATION is generated. 759 */ 760 if (!origTexObj->Immutable) { 761 _mesa_error(ctx, GL_INVALID_OPERATION, 762 "glTextureView(origtexture not immutable)"); 763 return; 764 } 765 766 /* If <texture> is 0, INVALID_VALUE is generated. */ 767 if (texture == 0) { 768 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(texture = 0)"); 769 return; 770 } 771 772 /* If <texture> is not a valid name returned by GenTextures, 773 * the error INVALID_OPERATION is generated. 774 */ 775 texObj = _mesa_lookup_texture(ctx, texture); 776 if (texObj == NULL) { 777 _mesa_error(ctx, GL_INVALID_OPERATION, 778 "glTextureView(texture = %u non-gen name)", texture); 779 return; 780 } 781 782 /* If <texture> has already been bound and given a target, then 783 * the error INVALID_OPERATION is generated. 784 */ 785 if (texObj->Target) { 786 _mesa_error(ctx, GL_INVALID_OPERATION, 787 "glTextureView(texture = %u already bound)", texture); 788 return; 789 } 790 791 /* Check for compatible target */ 792 if (!target_valid(ctx, origTexObj->Target, target)) { 793 return; /* error was recorded */ 794 } 795 796 /* minlevel and minlayer are relative to the view of origtexture. 797 * If minlevel or minlayer is greater than level or layer, respectively, 798 * return INVALID_VALUE. 799 */ 800 newViewMinLevel = origTexObj->MinLevel + minlevel; 801 newViewMinLayer = origTexObj->MinLayer + minlayer; 802 if (newViewMinLevel >= (origTexObj->MinLevel + origTexObj->NumLevels)) { 803 _mesa_error(ctx, GL_INVALID_VALUE, 804 "glTextureView(new minlevel (%d) > orig minlevel (%d)" 805 " + orig numlevels (%d))", 806 newViewMinLevel, origTexObj->MinLevel, origTexObj->NumLevels); 807 return; 808 } 809 810 if (newViewMinLayer >= (origTexObj->MinLayer + origTexObj->NumLayers)) { 811 _mesa_error(ctx, GL_INVALID_VALUE, 812 "glTextureView(new minlayer (%d) > orig minlayer (%d)" 813 " + orig numlayers (%d))", 814 newViewMinLayer, origTexObj->MinLayer, origTexObj->NumLayers); 815 return; 816 } 817 818 if (!_mesa_texture_view_compatible_format(ctx, 819 origTexObj->Image[0][0]->InternalFormat, 820 internalformat)) { 821 _mesa_error(ctx, GL_INVALID_OPERATION, 822 "glTextureView(internalformat %s not compatible with origtexture %s)", 823 _mesa_enum_to_string(internalformat), 824 _mesa_enum_to_string(origTexObj->Image[0][0]->InternalFormat)); 825 return; 826 } 827 828 texture_view(ctx, origTexObj, texObj, target, internalformat, minlevel, 829 numlevels, minlayer, numlayers, false); 830} 831