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 (at) 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 118 struct internal_format_class_info { 119 GLenum view_class; 120 GLenum internal_format; 121 }; 122 static 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 187 static 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 198 static 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 211 static 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 233 static 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 251 GLenum 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 */ 301 static GLboolean 302 initialize_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 { 309 const GLuint numFaces = _mesa_num_tex_faces(target); 310 GLint level, levelWidth = width, levelHeight = height, levelDepth = depth; 311 GLuint face; 312 313 /* Pretend we are bound to initialize the gl_texture_image structs */ 314 texObj->Target = target; 315 316 /* Set up all the texture object's gl_texture_images */ 317 for (level = 0; level < levels; level++) { 318 for (face = 0; face < numFaces; face++) { 319 struct gl_texture_image *texImage; 320 const GLenum faceTarget = _mesa_cube_face_target(target, face); 321 322 texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, level); 323 324 if (!texImage) { 325 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage"); 326 return GL_FALSE; 327 } 328 329 _mesa_init_teximage_fields(ctx, texImage, 330 levelWidth, levelHeight, levelDepth, 331 0, internalFormat, texFormat); 332 } 333 334 _mesa_next_mipmap_level_size(target, 0, 335 levelWidth, levelHeight, levelDepth, 336 &levelWidth, &levelHeight, &levelDepth); 337 } 338 339 /* "unbind" */ 340 texObj->Target = 0; 341 342 return GL_TRUE; 343 } 344 345 #define RETURN_IF_SUPPORTED(t) do { \ 346 if (newTarget == GL_ ## t) \ 347 return true; \ 348 } while (0) 349 350 /** 351 * Check for compatible target 352 * If an error is found, record it with _mesa_error() 353 * \return false if any error, true otherwise. 354 */ 355 static bool 356 target_valid(struct gl_context *ctx, GLenum origTarget, GLenum newTarget) 357 { 358 /* 359 * From ARB_texture_view spec: 360 --------------------------------------------------------------------------------------------------------- 361 | Original target | Valid new targets | 362 --------------------------------------------------------------------------------------------------------- 363 | TEXTURE_1D | TEXTURE_1D, TEXTURE_1D_ARRAY | 364 | ------------------------------------------------------------------------------------------------------- | 365 | TEXTURE_2D | TEXTURE_2D, TEXTURE_2D_ARRAY | 366 | ------------------------------------------------------------------------------------------------------- | 367 | TEXTURE_3D | TEXTURE_3D | 368 | ------------------------------------------------------------------------------------------------------- | 369 | TEXTURE_CUBE_MAP | TEXTURE_CUBE_MAP, TEXTURE_2D, TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY | 370 | ------------------------------------------------------------------------------------------------------- | 371 | TEXTURE_RECTANGLE | TEXTURE_RECTANGLE | 372 | ------------------------------------------------------------------------------------------------------- | 373 | TEXTURE_BUFFER | <none> | 374 | ------------------------------------------------------------------------------------------------------- | 375 | TEXTURE_1D_ARRAY | TEXTURE_1D_ARRAY, TEXTURE_1D | 376 | ------------------------------------------------------------------------------------------------------- | 377 | TEXTURE_2D_ARRAY | TEXTURE_2D_ARRAY, TEXTURE_2D, TEXTURE_CUBE_MAP, TEXTURE_CUBE_MAP_ARRAY | 378 | ------------------------------------------------------------------------------------------------------- | 379 | TEXTURE_CUBE_MAP_ARRAY | TEXTURE_CUBE_MAP_ARRAY, TEXTURE_2D_ARRAY, TEXTURE_2D, TEXTURE_CUBE_MAP | 380 | ------------------------------------------------------------------------------------------------------- | 381 | TEXTURE_2D_MULTISAMPLE | TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY | 382 | ------------------------------------------------------------------------------------------------------- | 383 | TEXTURE_2D_MULTISAMPLE_ARRAY | TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY | 384 --------------------------------------------------------------------------------------------------------- 385 */ 386 387 switch (origTarget) { 388 case GL_TEXTURE_1D: 389 case GL_TEXTURE_1D_ARRAY: 390 RETURN_IF_SUPPORTED(TEXTURE_1D); 391 RETURN_IF_SUPPORTED(TEXTURE_1D_ARRAY); 392 break; 393 case GL_TEXTURE_2D: 394 RETURN_IF_SUPPORTED(TEXTURE_2D); 395 RETURN_IF_SUPPORTED(TEXTURE_2D_ARRAY); 396 break; 397 case GL_TEXTURE_3D: 398 RETURN_IF_SUPPORTED(TEXTURE_3D); 399 break; 400 case GL_TEXTURE_RECTANGLE: 401 RETURN_IF_SUPPORTED(TEXTURE_RECTANGLE); 402 break; 403 case GL_TEXTURE_CUBE_MAP: 404 case GL_TEXTURE_2D_ARRAY: 405 case GL_TEXTURE_CUBE_MAP_ARRAY: 406 RETURN_IF_SUPPORTED(TEXTURE_2D); 407 RETURN_IF_SUPPORTED(TEXTURE_2D_ARRAY); 408 RETURN_IF_SUPPORTED(TEXTURE_CUBE_MAP); 409 RETURN_IF_SUPPORTED(TEXTURE_CUBE_MAP_ARRAY); 410 break; 411 case GL_TEXTURE_2D_MULTISAMPLE: 412 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 413 RETURN_IF_SUPPORTED(TEXTURE_2D_MULTISAMPLE); 414 RETURN_IF_SUPPORTED(TEXTURE_2D_MULTISAMPLE_ARRAY); 415 break; 416 } 417 _mesa_error(ctx, GL_INVALID_OPERATION, 418 "glTextureView(illegal target=%s)", 419 _mesa_enum_to_string(newTarget)); 420 return false; 421 } 422 #undef RETURN_IF_SUPPORTED 423 424 /** 425 * Check for compatible format 426 * If an error is found, record it with _mesa_error() 427 * \return false if any error, true otherwise. 428 */ 429 bool 430 _mesa_texture_view_compatible_format(const struct gl_context *ctx, 431 GLenum origInternalFormat, 432 GLenum newInternalFormat) 433 { 434 unsigned int origViewClass, newViewClass; 435 436 /* The two textures' internal formats must be compatible according to 437 * Table 3.X.2 (Compatible internal formats for TextureView) 438 * if the internal format exists in that table the view class must match. 439 * The internal formats must be identical if not in that table, 440 * or an INVALID_OPERATION error is generated. 441 */ 442 if (origInternalFormat == newInternalFormat) 443 return true; 444 445 origViewClass = _mesa_texture_view_lookup_view_class(ctx, origInternalFormat); 446 newViewClass = _mesa_texture_view_lookup_view_class(ctx, newInternalFormat); 447 if ((origViewClass == newViewClass) && origViewClass != false) 448 return true; 449 450 return false; 451 } 452 453 /** 454 * Helper function for TexStorage and teximagemultisample to set immutable 455 * texture state needed by ARB_texture_view. 456 */ 457 void 458 _mesa_set_texture_view_state(struct gl_context *ctx, 459 struct gl_texture_object *texObj, 460 GLenum target, GLuint levels) 461 { 462 struct gl_texture_image *texImage; 463 464 /* Get a reference to what will become this View's base level */ 465 texImage = _mesa_select_tex_image(texObj, target, 0); 466 467 /* When an immutable texture is created via glTexStorage or 468 * glTexImageMultisample, 469 * TEXTURE_IMMUTABLE_FORMAT becomes TRUE. 470 * TEXTURE_IMMUTABLE_LEVELS and TEXTURE_VIEW_NUM_LEVELS become levels. 471 * If the texture target is TEXTURE_1D_ARRAY then 472 * TEXTURE_VIEW_NUM_LAYERS becomes height. 473 * If the texture target is TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY, 474 * or TEXTURE_2D_MULTISAMPLE_ARRAY then TEXTURE_VIEW_NUM_LAYERS becomes 475 * depth. 476 * If the texture target is TEXTURE_CUBE_MAP, then 477 * TEXTURE_VIEW_NUM_LAYERS becomes 6. 478 * For any other texture target, TEXTURE_VIEW_NUM_LAYERS becomes 1. 479 * 480 * ARB_texture_multisample: Multisample textures do 481 * not have multiple image levels. 482 */ 483 484 texObj->Immutable = GL_TRUE; 485 texObj->ImmutableLevels = levels; 486 texObj->MinLevel = 0; 487 texObj->NumLevels = levels; 488 texObj->MinLayer = 0; 489 texObj->NumLayers = 1; 490 switch (target) { 491 case GL_TEXTURE_1D_ARRAY: 492 texObj->NumLayers = texImage->Height; 493 break; 494 495 case GL_TEXTURE_2D_MULTISAMPLE: 496 texObj->NumLevels = 1; 497 texObj->ImmutableLevels = 1; 498 break; 499 500 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 501 texObj->NumLevels = 1; 502 texObj->ImmutableLevels = 1; 503 /* fall through to set NumLayers */ 504 505 case GL_TEXTURE_2D_ARRAY: 506 case GL_TEXTURE_CUBE_MAP_ARRAY: 507 texObj->NumLayers = texImage->Depth; 508 break; 509 510 case GL_TEXTURE_CUBE_MAP: 511 texObj->NumLayers = 6; 512 break; 513 } 514 } 515 516 /** 517 * glTextureView (ARB_texture_view) 518 * If an error is found, record it with _mesa_error() 519 * \return none. 520 */ 521 void GLAPIENTRY 522 _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, 523 GLenum internalformat, 524 GLuint minlevel, GLuint numlevels, 525 GLuint minlayer, GLuint numlayers) 526 { 527 struct gl_texture_object *texObj; 528 struct gl_texture_object *origTexObj; 529 struct gl_texture_image *origTexImage; 530 GLuint newViewMinLevel, newViewMinLayer; 531 GLuint newViewNumLevels, newViewNumLayers; 532 GLsizei width, height, depth; 533 mesa_format texFormat; 534 GLboolean sizeOK, dimensionsOK; 535 GLenum faceTarget; 536 537 GET_CURRENT_CONTEXT(ctx); 538 539 if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) 540 _mesa_debug(ctx, "glTextureView %d %s %d %s %d %d %d %d\n", 541 texture, _mesa_enum_to_string(target), origtexture, 542 _mesa_enum_to_string(internalformat), 543 minlevel, numlevels, minlayer, numlayers); 544 545 if (origtexture == 0) { 546 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", 547 origtexture); 548 return; 549 } 550 551 /* Need original texture information to validate arguments */ 552 origTexObj = _mesa_lookup_texture(ctx, origtexture); 553 554 /* If <origtexture> is not the name of a texture, INVALID_VALUE 555 * is generated. 556 */ 557 if (!origTexObj) { 558 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", 559 origtexture); 560 return; 561 } 562 563 /* If <origtexture>'s TEXTURE_IMMUTABLE_FORMAT value is not TRUE, 564 * INVALID_OPERATION is generated. 565 */ 566 if (!origTexObj->Immutable) { 567 _mesa_error(ctx, GL_INVALID_OPERATION, 568 "glTextureView(origtexture not immutable)"); 569 return; 570 } 571 572 /* If <texture> is 0, INVALID_VALUE is generated. */ 573 if (texture == 0) { 574 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(texture = 0)"); 575 return; 576 } 577 578 /* If <texture> is not a valid name returned by GenTextures, 579 * the error INVALID_OPERATION is generated. 580 */ 581 texObj = _mesa_lookup_texture(ctx, texture); 582 if (texObj == NULL) { 583 _mesa_error(ctx, GL_INVALID_OPERATION, 584 "glTextureView(texture = %u non-gen name)", texture); 585 return; 586 } 587 588 /* If <texture> has already been bound and given a target, then 589 * the error INVALID_OPERATION is generated. 590 */ 591 if (texObj->Target) { 592 _mesa_error(ctx, GL_INVALID_OPERATION, 593 "glTextureView(texture = %u already bound)", texture); 594 return; 595 } 596 597 /* Check for compatible target */ 598 if (!target_valid(ctx, origTexObj->Target, target)) { 599 return; /* error was recorded */ 600 } 601 602 /* minlevel and minlayer are relative to the view of origtexture. 603 * If minlevel or minlayer is greater than level or layer, respectively, 604 * return INVALID_VALUE. 605 */ 606 newViewMinLevel = origTexObj->MinLevel + minlevel; 607 newViewMinLayer = origTexObj->MinLayer + minlayer; 608 if (newViewMinLevel >= (origTexObj->MinLevel + origTexObj->NumLevels)) { 609 _mesa_error(ctx, GL_INVALID_VALUE, 610 "glTextureView(new minlevel (%d) > orig minlevel (%d)" 611 " + orig numlevels (%d))", 612 newViewMinLevel, origTexObj->MinLevel, origTexObj->NumLevels); 613 return; 614 } 615 616 if (newViewMinLayer >= (origTexObj->MinLayer + origTexObj->NumLayers)) { 617 _mesa_error(ctx, GL_INVALID_VALUE, 618 "glTextureView(new minlayer (%d) > orig minlayer (%d)" 619 " + orig numlayers (%d))", 620 newViewMinLayer, origTexObj->MinLayer, origTexObj->NumLayers); 621 return; 622 } 623 624 if (!_mesa_texture_view_compatible_format(ctx, 625 origTexObj->Image[0][0]->InternalFormat, 626 internalformat)) { 627 _mesa_error(ctx, GL_INVALID_OPERATION, 628 "glTextureView(internalformat %s not compatible with origtexture %s)", 629 _mesa_enum_to_string(internalformat), 630 _mesa_enum_to_string(origTexObj->Image[0][0]->InternalFormat)); 631 return; 632 } 633 634 texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, 635 internalformat, GL_NONE, GL_NONE); 636 assert(texFormat != MESA_FORMAT_NONE); 637 if (texFormat == MESA_FORMAT_NONE) return; 638 639 newViewNumLevels = MIN2(numlevels, origTexObj->NumLevels - minlevel); 640 newViewNumLayers = MIN2(numlayers, origTexObj->NumLayers - minlayer); 641 642 faceTarget = _mesa_cube_face_target(origTexObj->Target, minlayer); 643 644 /* Get a reference to what will become this View's base level */ 645 origTexImage = _mesa_select_tex_image(origTexObj, faceTarget, minlevel); 646 width = origTexImage->Width; 647 height = origTexImage->Height; 648 depth = origTexImage->Depth; 649 650 /* Adjust width, height, depth to be appropriate for new target */ 651 switch (target) { 652 case GL_TEXTURE_1D: 653 height = 1; 654 break; 655 656 case GL_TEXTURE_3D: 657 break; 658 659 case GL_TEXTURE_1D_ARRAY: 660 height = (GLsizei) newViewNumLayers; 661 break; 662 663 case GL_TEXTURE_2D: 664 case GL_TEXTURE_2D_MULTISAMPLE: 665 case GL_TEXTURE_RECTANGLE: 666 depth = 1; 667 break; 668 case GL_TEXTURE_CUBE_MAP: 669 /* If the new texture's target is TEXTURE_CUBE_MAP, the clamped 670 * <numlayers> must be equal to 6. 671 */ 672 if (newViewNumLayers != 6) { 673 _mesa_error(ctx, GL_INVALID_VALUE, 674 "glTextureView(clamped numlayers %d != 6)", 675 newViewNumLayers); 676 return; 677 } 678 depth = 1; 679 break; 680 681 case GL_TEXTURE_2D_ARRAY: 682 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 683 depth = newViewNumLayers; 684 break; 685 case GL_TEXTURE_CUBE_MAP_ARRAY: 686 /* If the new texture's target is TEXTURE_CUBE_MAP_ARRAY, 687 * then <numlayers> counts layer-faces rather than layers, 688 * and the clamped <numlayers> must be a multiple of 6. 689 * Otherwise, the error INVALID_VALUE is generated. 690 */ 691 if ((newViewNumLayers % 6) != 0) { 692 _mesa_error(ctx, GL_INVALID_VALUE, 693 "glTextureView(clamped numlayers %d is not" 694 " a multiple of 6)", 695 newViewNumLayers); 696 return; 697 } 698 depth = newViewNumLayers; 699 break; 700 } 701 702 /* If the dimensions of the original texture are larger than the maximum 703 * supported dimensions of the new target, the error INVALID_OPERATION is 704 * generated. For example, if the original texture has a TEXTURE_2D_ARRAY 705 * target and its width is greater than MAX_CUBE_MAP_TEXTURE_SIZE, an error 706 * will be generated if TextureView is called to create a TEXTURE_CUBE_MAP 707 * view. 708 */ 709 dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, 710 width, height, depth, 0); 711 if (!dimensionsOK) { 712 _mesa_error(ctx, GL_INVALID_OPERATION, 713 "glTextureView(invalid width or height or depth)"); 714 return; 715 } 716 717 sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 1, 0, texFormat, 718 origTexImage->NumSamples, 719 width, height, depth); 720 if (!sizeOK) { 721 _mesa_error(ctx, GL_INVALID_OPERATION, 722 "glTextureView(invalid texture size)"); 723 return; 724 } 725 726 /* If <target> is TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_RECTANGLE, 727 * or TEXTURE_2D_MULTISAMPLE and <numlayers> does not equal 1, the error 728 * INVALID_VALUE is generated. 729 */ 730 switch (target) { 731 case GL_TEXTURE_1D: 732 case GL_TEXTURE_2D: 733 case GL_TEXTURE_3D: 734 case GL_TEXTURE_RECTANGLE: 735 case GL_TEXTURE_2D_MULTISAMPLE: 736 if (numlayers != 1) { 737 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(numlayers %d != 1)", 738 numlayers); 739 return; 740 } 741 break; 742 case GL_TEXTURE_CUBE_MAP: 743 break; 744 case GL_TEXTURE_CUBE_MAP_ARRAY: 745 break; 746 } 747 748 /* If the new texture's target is TEXTURE_CUBE_MAP or 749 * TEXTURE_CUBE_MAP_ARRAY, the width and height of the original texture's 750 * levels must be equal otherwise the error INVALID_OPERATION is generated. 751 */ 752 if ((target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY) && 753 (origTexImage->Width != origTexImage->Height)) { 754 _mesa_error(ctx, GL_INVALID_OPERATION, 755 "glTextureView(origtexture width (%d) != height (%d))", 756 origTexImage->Width, origTexImage->Height); 757 return; 758 } 759 760 /* When the original texture's target is TEXTURE_CUBE_MAP, the layer 761 * parameters are interpreted in the same order as if it were a 762 * TEXTURE_CUBE_MAP_ARRAY with 6 layer-faces. 763 */ 764 765 /* If the internal format does not exactly match the internal format of the 766 * original texture, the contents of the memory are reinterpreted in the 767 * same manner as for image bindings described in 768 * section 3.9.20 (Texture Image Loads and Stores). 769 */ 770 771 /* TEXTURE_BASE_LEVEL and TEXTURE_MAX_LEVEL are interpreted 772 * relative to the view and not relative to the original data store. 773 */ 774 775 if (!initialize_texture_fields(ctx, target, texObj, newViewNumLevels, 776 width, height, depth, 777 internalformat, texFormat)) { 778 return; /* Already recorded error */ 779 } 780 781 texObj->MinLevel = newViewMinLevel; 782 texObj->MinLayer = newViewMinLayer; 783 texObj->NumLevels = newViewNumLevels; 784 texObj->NumLayers = newViewNumLayers; 785 texObj->Immutable = GL_TRUE; 786 texObj->ImmutableLevels = origTexObj->ImmutableLevels; 787 texObj->Target = target; 788 texObj->TargetIndex = _mesa_tex_target_to_index(ctx, target); 789 assert(texObj->TargetIndex < NUM_TEXTURE_TARGETS); 790 791 if (ctx->Driver.TextureView != NULL && 792 !ctx->Driver.TextureView(ctx, texObj, origTexObj)) { 793 return; /* driver recorded error */ 794 } 795 } 796