textureview.c revision 7ec681f3
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 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_SRG8_EXT}, 173 {GL_VIEW_CLASS_16_BITS, GL_R16_SNORM}, 174 {GL_VIEW_CLASS_8_BITS, GL_R8UI}, 175 {GL_VIEW_CLASS_8_BITS, GL_R8I}, 176 {GL_VIEW_CLASS_8_BITS, GL_R8}, 177 {GL_VIEW_CLASS_8_BITS, GL_R8_SNORM}, 178 {GL_VIEW_CLASS_8_BITS, GL_SR8_EXT}, 179 {GL_VIEW_CLASS_RGTC1_RED, GL_COMPRESSED_RED_RGTC1}, 180 {GL_VIEW_CLASS_RGTC1_RED, GL_COMPRESSED_SIGNED_RED_RGTC1}, 181 {GL_VIEW_CLASS_RGTC2_RG, GL_COMPRESSED_RG_RGTC2}, 182 {GL_VIEW_CLASS_RGTC2_RG, GL_COMPRESSED_SIGNED_RG_RGTC2}, 183 {GL_VIEW_CLASS_BPTC_UNORM, GL_COMPRESSED_RGBA_BPTC_UNORM_ARB}, 184 {GL_VIEW_CLASS_BPTC_UNORM, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB}, 185 {GL_VIEW_CLASS_BPTC_FLOAT, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB}, 186 {GL_VIEW_CLASS_BPTC_FLOAT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB}, 187}; 188 189static const struct internal_format_class_info s3tc_compatible_internal_formats[] = { 190 {GL_VIEW_CLASS_S3TC_DXT1_RGB, GL_COMPRESSED_RGB_S3TC_DXT1_EXT}, 191 {GL_VIEW_CLASS_S3TC_DXT1_RGB, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT}, 192 {GL_VIEW_CLASS_S3TC_DXT1_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT}, 193 {GL_VIEW_CLASS_S3TC_DXT1_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT}, 194 {GL_VIEW_CLASS_S3TC_DXT3_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT}, 195 {GL_VIEW_CLASS_S3TC_DXT3_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT}, 196 {GL_VIEW_CLASS_S3TC_DXT5_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT}, 197 {GL_VIEW_CLASS_S3TC_DXT5_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}, 198}; 199 200static const struct internal_format_class_info gles_etc2_compatible_internal_formats[] = { 201 {VIEW_CLASS_EAC_R11, GL_COMPRESSED_R11_EAC}, 202 {VIEW_CLASS_EAC_R11, GL_COMPRESSED_SIGNED_R11_EAC}, 203 {VIEW_CLASS_EAC_RG11, GL_COMPRESSED_RG11_EAC}, 204 {VIEW_CLASS_EAC_RG11, GL_COMPRESSED_SIGNED_RG11_EAC}, 205 {VIEW_CLASS_ETC2_RGB, GL_COMPRESSED_RGB8_ETC2}, 206 {VIEW_CLASS_ETC2_RGB, GL_COMPRESSED_SRGB8_ETC2}, 207 {VIEW_CLASS_ETC2_RGBA, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2}, 208 {VIEW_CLASS_ETC2_RGBA, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2}, 209 {VIEW_CLASS_ETC2_EAC_RGBA, GL_COMPRESSED_RGBA8_ETC2_EAC}, 210 {VIEW_CLASS_ETC2_EAC_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC}, 211}; 212 213static const struct internal_format_class_info gles_astc_compatible_internal_formats[] = { 214#define ASTC_FMT(size) \ 215 {VIEW_CLASS_ASTC_##size##_RGBA, GL_COMPRESSED_RGBA_ASTC_##size##_KHR}, \ 216 {VIEW_CLASS_ASTC_##size##_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_##size##_KHR} 217 218 ASTC_FMT(4x4), 219 ASTC_FMT(5x4), 220 ASTC_FMT(5x5), 221 ASTC_FMT(6x5), 222 ASTC_FMT(6x6), 223 ASTC_FMT(8x5), 224 ASTC_FMT(8x6), 225 ASTC_FMT(8x8), 226 ASTC_FMT(10x5), 227 ASTC_FMT(10x6), 228 ASTC_FMT(10x8), 229 ASTC_FMT(10x10), 230 ASTC_FMT(12x10), 231 ASTC_FMT(12x12), 232#undef ASTC_FMT 233}; 234 235static const struct internal_format_class_info gles_astc_3d_compatible_internal_formats[] = { 236#define ASTC_FMT(size) \ 237 {VIEW_CLASS_ASTC_##size##_RGBA, GL_COMPRESSED_RGBA_ASTC_##size##_OES}, \ 238 {VIEW_CLASS_ASTC_##size##_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_##size##_OES} 239 240 ASTC_FMT(3x3x3), 241 ASTC_FMT(4x3x3), 242 ASTC_FMT(4x4x3), 243 ASTC_FMT(4x4x4), 244 ASTC_FMT(5x4x4), 245 ASTC_FMT(5x5x4), 246 ASTC_FMT(5x5x5), 247 ASTC_FMT(6x5x5), 248 ASTC_FMT(6x6x5), 249 ASTC_FMT(6x6x6), 250#undef ASTC_FMT 251}; 252 253GLenum 254_mesa_texture_view_lookup_view_class(const struct gl_context *ctx, GLenum internalformat) 255{ 256 GLuint i; 257 258 for (i = 0; i < ARRAY_SIZE(compatible_internal_formats); i++) { 259 if (compatible_internal_formats[i].internal_format == internalformat) 260 return compatible_internal_formats[i].view_class; 261 } 262 263 if (ctx->Extensions.EXT_texture_compression_s3tc && 264 ctx->Extensions.EXT_texture_sRGB) { 265 for (i = 0; i < ARRAY_SIZE(s3tc_compatible_internal_formats); i++) { 266 if (s3tc_compatible_internal_formats[i].internal_format 267 == internalformat) 268 return s3tc_compatible_internal_formats[i].view_class; 269 } 270 } 271 272 if (_mesa_is_gles3(ctx)) { 273 for (i = 0; i < ARRAY_SIZE(gles_etc2_compatible_internal_formats); i++) { 274 if (gles_etc2_compatible_internal_formats[i].internal_format 275 == internalformat) 276 return gles_etc2_compatible_internal_formats[i].view_class; 277 } 278 279 if (ctx->Extensions.KHR_texture_compression_astc_ldr) { 280 for (i = 0; i < ARRAY_SIZE(gles_astc_compatible_internal_formats); i++) { 281 if (gles_astc_compatible_internal_formats[i].internal_format 282 == internalformat) 283 return gles_astc_compatible_internal_formats[i].view_class; 284 } 285 } 286 287 if (ctx->Extensions.OES_texture_compression_astc) { 288 for (i = 0; i < ARRAY_SIZE(gles_astc_3d_compatible_internal_formats); i++) { 289 if (gles_astc_3d_compatible_internal_formats[i].internal_format 290 == internalformat) 291 return gles_astc_3d_compatible_internal_formats[i].view_class; 292 } 293 } 294 } 295 return GL_FALSE; 296} 297 298/** 299 * Initialize new texture's gl_texture_image structures. Will not call driver 300 * to allocate new space, simply record relevant layer, face, format, etc. 301 * \return GL_FALSE if any error, GL_TRUE otherwise. 302 */ 303static GLboolean 304initialize_texture_fields(struct gl_context *ctx, 305 GLenum target, 306 struct gl_texture_object *texObj, 307 GLint levels, 308 GLsizei width, GLsizei height, GLsizei depth, 309 GLenum internalFormat, mesa_format texFormat, 310 GLuint numSamples, GLboolean fixedSampleLocations) 311{ 312 const GLuint numFaces = _mesa_num_tex_faces(target); 313 GLint level, levelWidth = width, levelHeight = height, levelDepth = depth; 314 GLuint face; 315 316 /* Pretend we are bound to initialize the gl_texture_image structs */ 317 texObj->Target = target; 318 319 /* Set up all the texture object's gl_texture_images */ 320 for (level = 0; level < levels; level++) { 321 for (face = 0; face < numFaces; face++) { 322 struct gl_texture_image *texImage; 323 const GLenum faceTarget = _mesa_cube_face_target(target, face); 324 325 texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, level); 326 327 if (!texImage) { 328 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage"); 329 return GL_FALSE; 330 } 331 332 _mesa_init_teximage_fields_ms(ctx, texImage, 333 levelWidth, levelHeight, levelDepth, 334 0, internalFormat, texFormat, 335 numSamples, fixedSampleLocations); 336 } 337 338 _mesa_next_mipmap_level_size(target, 0, 339 levelWidth, levelHeight, levelDepth, 340 &levelWidth, &levelHeight, &levelDepth); 341 } 342 343 /* "unbind" */ 344 texObj->Target = 0; 345 346 return GL_TRUE; 347} 348 349#define RETURN_IF_SUPPORTED(t) do { \ 350 if (newTarget == GL_ ## t) \ 351 return true; \ 352} while (0) 353 354/** 355 * Check for compatible target 356 * If an error is found, record it with _mesa_error() 357 * \return false if any error, true otherwise. 358 */ 359static bool 360target_valid(struct gl_context *ctx, GLenum origTarget, GLenum newTarget) 361{ 362 /* 363 * From ARB_texture_view spec: 364 --------------------------------------------------------------------------------------------------------- 365 | Original target | Valid new targets | 366 --------------------------------------------------------------------------------------------------------- 367 | TEXTURE_1D | TEXTURE_1D, TEXTURE_1D_ARRAY | 368 | ------------------------------------------------------------------------------------------------------- | 369 | TEXTURE_2D | TEXTURE_2D, TEXTURE_2D_ARRAY | 370 | ------------------------------------------------------------------------------------------------------- | 371 | TEXTURE_3D | TEXTURE_3D | 372 | ------------------------------------------------------------------------------------------------------- | 373 | TEXTURE_CUBE_MAP | TEXTURE_CUBE_MAP, TEXTURE_2D, TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY | 374 | ------------------------------------------------------------------------------------------------------- | 375 | TEXTURE_RECTANGLE | TEXTURE_RECTANGLE | 376 | ------------------------------------------------------------------------------------------------------- | 377 | TEXTURE_BUFFER | <none> | 378 | ------------------------------------------------------------------------------------------------------- | 379 | TEXTURE_1D_ARRAY | TEXTURE_1D_ARRAY, TEXTURE_1D | 380 | ------------------------------------------------------------------------------------------------------- | 381 | TEXTURE_2D_ARRAY | TEXTURE_2D_ARRAY, TEXTURE_2D, TEXTURE_CUBE_MAP, TEXTURE_CUBE_MAP_ARRAY | 382 | ------------------------------------------------------------------------------------------------------- | 383 | TEXTURE_CUBE_MAP_ARRAY | TEXTURE_CUBE_MAP_ARRAY, TEXTURE_2D_ARRAY, TEXTURE_2D, TEXTURE_CUBE_MAP | 384 | ------------------------------------------------------------------------------------------------------- | 385 | TEXTURE_2D_MULTISAMPLE | TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY | 386 | ------------------------------------------------------------------------------------------------------- | 387 | TEXTURE_2D_MULTISAMPLE_ARRAY | TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY | 388 --------------------------------------------------------------------------------------------------------- 389 */ 390 391 switch (origTarget) { 392 case GL_TEXTURE_1D: 393 case GL_TEXTURE_1D_ARRAY: 394 RETURN_IF_SUPPORTED(TEXTURE_1D); 395 RETURN_IF_SUPPORTED(TEXTURE_1D_ARRAY); 396 break; 397 case GL_TEXTURE_2D: 398 RETURN_IF_SUPPORTED(TEXTURE_2D); 399 RETURN_IF_SUPPORTED(TEXTURE_2D_ARRAY); 400 break; 401 case GL_TEXTURE_3D: 402 RETURN_IF_SUPPORTED(TEXTURE_3D); 403 break; 404 case GL_TEXTURE_RECTANGLE: 405 RETURN_IF_SUPPORTED(TEXTURE_RECTANGLE); 406 break; 407 case GL_TEXTURE_CUBE_MAP: 408 case GL_TEXTURE_2D_ARRAY: 409 case GL_TEXTURE_CUBE_MAP_ARRAY: 410 RETURN_IF_SUPPORTED(TEXTURE_2D); 411 RETURN_IF_SUPPORTED(TEXTURE_2D_ARRAY); 412 RETURN_IF_SUPPORTED(TEXTURE_CUBE_MAP); 413 RETURN_IF_SUPPORTED(TEXTURE_CUBE_MAP_ARRAY); 414 break; 415 case GL_TEXTURE_2D_MULTISAMPLE: 416 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 417 RETURN_IF_SUPPORTED(TEXTURE_2D_MULTISAMPLE); 418 RETURN_IF_SUPPORTED(TEXTURE_2D_MULTISAMPLE_ARRAY); 419 break; 420 } 421 _mesa_error(ctx, GL_INVALID_OPERATION, 422 "glTextureView(illegal target=%s)", 423 _mesa_enum_to_string(newTarget)); 424 return false; 425} 426#undef RETURN_IF_SUPPORTED 427 428/** 429 * Check for compatible format 430 * If an error is found, record it with _mesa_error() 431 * \return false if any error, true otherwise. 432 */ 433bool 434_mesa_texture_view_compatible_format(const struct gl_context *ctx, 435 GLenum origInternalFormat, 436 GLenum newInternalFormat) 437{ 438 unsigned int origViewClass, newViewClass; 439 440 /* The two textures' internal formats must be compatible according to 441 * Table 3.X.2 (Compatible internal formats for TextureView) 442 * if the internal format exists in that table the view class must match. 443 * The internal formats must be identical if not in that table, 444 * or an INVALID_OPERATION error is generated. 445 */ 446 if (origInternalFormat == newInternalFormat) 447 return true; 448 449 origViewClass = _mesa_texture_view_lookup_view_class(ctx, origInternalFormat); 450 newViewClass = _mesa_texture_view_lookup_view_class(ctx, newInternalFormat); 451 if ((origViewClass == newViewClass) && origViewClass != false) 452 return true; 453 454 return false; 455} 456 457/** 458 * Helper function for TexStorage and teximagemultisample to set immutable 459 * texture state needed by ARB_texture_view. 460 */ 461void 462_mesa_set_texture_view_state(struct gl_context *ctx, 463 struct gl_texture_object *texObj, 464 GLenum target, GLuint levels) 465{ 466 struct gl_texture_image *texImage; 467 468 /* Get a reference to what will become this View's base level */ 469 texImage = _mesa_select_tex_image(texObj, target, 0); 470 471 /* When an immutable texture is created via glTexStorage or 472 * glTexImageMultisample, 473 * TEXTURE_IMMUTABLE_FORMAT becomes TRUE. 474 * TEXTURE_IMMUTABLE_LEVELS and TEXTURE_VIEW_NUM_LEVELS become levels. 475 * If the texture target is TEXTURE_1D_ARRAY then 476 * TEXTURE_VIEW_NUM_LAYERS becomes height. 477 * If the texture target is TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY, 478 * or TEXTURE_2D_MULTISAMPLE_ARRAY then TEXTURE_VIEW_NUM_LAYERS becomes 479 * depth. 480 * If the texture target is TEXTURE_CUBE_MAP, then 481 * TEXTURE_VIEW_NUM_LAYERS becomes 6. 482 * For any other texture target, TEXTURE_VIEW_NUM_LAYERS becomes 1. 483 * 484 * ARB_texture_multisample: Multisample textures do 485 * not have multiple image levels. 486 */ 487 488 texObj->Immutable = GL_TRUE; 489 texObj->External = GL_FALSE; 490 texObj->Attrib.ImmutableLevels = levels; 491 texObj->Attrib.MinLevel = 0; 492 texObj->Attrib.NumLevels = levels; 493 texObj->Attrib.MinLayer = 0; 494 texObj->Attrib.NumLayers = 1; 495 switch (target) { 496 case GL_TEXTURE_1D_ARRAY: 497 texObj->Attrib.NumLayers = texImage->Height; 498 break; 499 500 case GL_TEXTURE_2D_MULTISAMPLE: 501 texObj->Attrib.NumLevels = 1; 502 texObj->Attrib.ImmutableLevels = 1; 503 break; 504 505 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 506 texObj->Attrib.NumLevels = 1; 507 texObj->Attrib.ImmutableLevels = 1; 508 FALLTHROUGH; 509 /* fallthrough to set NumLayers */ 510 511 case GL_TEXTURE_2D_ARRAY: 512 case GL_TEXTURE_CUBE_MAP_ARRAY: 513 texObj->Attrib.NumLayers = texImage->Depth; 514 break; 515 516 case GL_TEXTURE_CUBE_MAP: 517 texObj->Attrib.NumLayers = 6; 518 break; 519 } 520} 521 522/** 523 * glTextureView (ARB_texture_view) 524 * If an error is found, record it with _mesa_error() 525 * \return none. 526 */ 527static ALWAYS_INLINE void 528texture_view(struct gl_context *ctx, struct gl_texture_object *origTexObj, 529 struct gl_texture_object *texObj, GLenum target, 530 GLenum internalformat, GLuint minlevel, GLuint numlevels, 531 GLuint minlayer, GLuint numlayers, bool no_error) 532{ 533 struct gl_texture_image *origTexImage; 534 GLuint newViewNumLevels, newViewNumLayers; 535 GLsizei width, height, depth; 536 mesa_format texFormat; 537 GLboolean sizeOK, dimensionsOK; 538 GLenum faceTarget; 539 540 texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, 541 internalformat, GL_NONE, GL_NONE); 542 if (texFormat == MESA_FORMAT_NONE) return; 543 544 newViewNumLevels = MIN2(numlevels, origTexObj->Attrib.NumLevels - minlevel); 545 newViewNumLayers = MIN2(numlayers, origTexObj->Attrib.NumLayers - minlayer); 546 547 faceTarget = _mesa_cube_face_target(origTexObj->Target, minlayer); 548 549 /* Get a reference to what will become this View's base level */ 550 origTexImage = _mesa_select_tex_image(origTexObj, faceTarget, minlevel); 551 width = origTexImage->Width; 552 height = origTexImage->Height; 553 depth = origTexImage->Depth; 554 555 /* Adjust width, height, depth to be appropriate for new target */ 556 switch (target) { 557 case GL_TEXTURE_1D: 558 height = 1; 559 break; 560 561 case GL_TEXTURE_3D: 562 break; 563 564 case GL_TEXTURE_1D_ARRAY: 565 height = (GLsizei) newViewNumLayers; 566 break; 567 568 case GL_TEXTURE_2D: 569 case GL_TEXTURE_2D_MULTISAMPLE: 570 case GL_TEXTURE_RECTANGLE: 571 depth = 1; 572 break; 573 case GL_TEXTURE_CUBE_MAP: 574 /* If the new texture's target is TEXTURE_CUBE_MAP, the clamped 575 * <numlayers> must be equal to 6. 576 */ 577 if (!no_error && newViewNumLayers != 6) { 578 _mesa_error(ctx, GL_INVALID_VALUE, 579 "glTextureView(clamped numlayers %d != 6)", 580 newViewNumLayers); 581 return; 582 } 583 depth = 1; 584 break; 585 586 case GL_TEXTURE_2D_ARRAY: 587 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 588 depth = newViewNumLayers; 589 break; 590 case GL_TEXTURE_CUBE_MAP_ARRAY: 591 /* If the new texture's target is TEXTURE_CUBE_MAP_ARRAY, 592 * then <numlayers> counts layer-faces rather than layers, 593 * and the clamped <numlayers> must be a multiple of 6. 594 * Otherwise, the error INVALID_VALUE is generated. 595 */ 596 if (!no_error && (newViewNumLayers % 6) != 0) { 597 _mesa_error(ctx, GL_INVALID_VALUE, 598 "glTextureView(clamped numlayers %d is not" 599 " a multiple of 6)", 600 newViewNumLayers); 601 return; 602 } 603 depth = newViewNumLayers; 604 break; 605 } 606 607 if (!no_error) { 608 /* If the dimensions of the original texture are larger than the maximum 609 * supported dimensions of the new target, the error INVALID_OPERATION is 610 * generated. For example, if the original texture has a TEXTURE_2D_ARRAY 611 * target and its width is greater than MAX_CUBE_MAP_TEXTURE_SIZE, an 612 * error will be generated if TextureView is called to create a 613 * TEXTURE_CUBE_MAP view. 614 */ 615 dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, 616 width, height, depth, 0); 617 if (!dimensionsOK) { 618 _mesa_error(ctx, GL_INVALID_OPERATION, 619 "glTextureView(invalid width or height or depth)"); 620 return; 621 } 622 623 sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 1, 0, texFormat, 624 origTexImage->NumSamples, 625 width, height, depth); 626 if (!sizeOK) { 627 _mesa_error(ctx, GL_INVALID_OPERATION, 628 "glTextureView(invalid texture size)"); 629 return; 630 } 631 632 /* If <target> is TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_RECTANGLE, 633 * or TEXTURE_2D_MULTISAMPLE and <numlayers> does not equal 1, the error 634 * INVALID_VALUE is generated. 635 */ 636 switch (target) { 637 case GL_TEXTURE_1D: 638 case GL_TEXTURE_2D: 639 case GL_TEXTURE_3D: 640 case GL_TEXTURE_RECTANGLE: 641 case GL_TEXTURE_2D_MULTISAMPLE: 642 if (numlayers != 1) { 643 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(numlayers %d != 1)", 644 numlayers); 645 return; 646 } 647 break; 648 case GL_TEXTURE_CUBE_MAP: 649 break; 650 case GL_TEXTURE_CUBE_MAP_ARRAY: 651 break; 652 } 653 654 /* If the new texture's target is TEXTURE_CUBE_MAP or 655 * TEXTURE_CUBE_MAP_ARRAY, the width and height of the original texture's 656 * levels must be equal otherwise the error INVALID_OPERATION is 657 * generated. 658 */ 659 if ((target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY) 660 && (origTexImage->Width != origTexImage->Height)) { 661 _mesa_error(ctx, GL_INVALID_OPERATION, 662 "glTextureView(origtexture width (%d) != height (%d))", 663 origTexImage->Width, origTexImage->Height); 664 return; 665 } 666 } 667 668 /* When the original texture's target is TEXTURE_CUBE_MAP, the layer 669 * parameters are interpreted in the same order as if it were a 670 * TEXTURE_CUBE_MAP_ARRAY with 6 layer-faces. 671 */ 672 673 /* If the internal format does not exactly match the internal format of the 674 * original texture, the contents of the memory are reinterpreted in the 675 * same manner as for image bindings described in 676 * section 3.9.20 (Texture Image Loads and Stores). 677 */ 678 679 /* TEXTURE_BASE_LEVEL and TEXTURE_MAX_LEVEL are interpreted 680 * relative to the view and not relative to the original data store. 681 */ 682 683 if (!initialize_texture_fields(ctx, target, texObj, newViewNumLevels, 684 width, height, depth, 685 internalformat, texFormat, 686 origTexImage->NumSamples, 687 origTexImage->FixedSampleLocations)) { 688 return; /* Already recorded error */ 689 } 690 691 texObj->Attrib.MinLevel = origTexObj->Attrib.MinLevel + minlevel; 692 texObj->Attrib.MinLayer = origTexObj->Attrib.MinLayer + minlayer; 693 texObj->Attrib.NumLevels = newViewNumLevels; 694 texObj->Attrib.NumLayers = newViewNumLayers; 695 texObj->Immutable = GL_TRUE; 696 texObj->External = GL_FALSE; 697 texObj->Attrib.ImmutableLevels = origTexObj->Attrib.ImmutableLevels; 698 texObj->Target = target; 699 texObj->TargetIndex = _mesa_tex_target_to_index(ctx, target); 700 assert(texObj->TargetIndex < NUM_TEXTURE_TARGETS); 701 702 if (ctx->Driver.TextureView != NULL && 703 !ctx->Driver.TextureView(ctx, texObj, origTexObj)) { 704 return; /* driver recorded error */ 705 } 706} 707 708void GLAPIENTRY 709_mesa_TextureView_no_error(GLuint texture, GLenum target, GLuint origtexture, 710 GLenum internalformat, 711 GLuint minlevel, GLuint numlevels, 712 GLuint minlayer, GLuint numlayers) 713{ 714 struct gl_texture_object *texObj; 715 struct gl_texture_object *origTexObj; 716 717 GET_CURRENT_CONTEXT(ctx); 718 719 origTexObj = _mesa_lookup_texture(ctx, origtexture); 720 texObj = _mesa_lookup_texture(ctx, texture); 721 722 texture_view(ctx, origTexObj, texObj, target, internalformat, minlevel, 723 numlevels, minlayer, numlayers, true); 724} 725 726void GLAPIENTRY 727_mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, 728 GLenum internalformat, 729 GLuint minlevel, GLuint numlevels, 730 GLuint minlayer, GLuint numlayers) 731{ 732 struct gl_texture_object *texObj; 733 struct gl_texture_object *origTexObj; 734 GLuint newViewMinLevel, newViewMinLayer; 735 736 GET_CURRENT_CONTEXT(ctx); 737 738 if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) 739 _mesa_debug(ctx, "glTextureView %d %s %d %s %d %d %d %d\n", 740 texture, _mesa_enum_to_string(target), origtexture, 741 _mesa_enum_to_string(internalformat), 742 minlevel, numlevels, minlayer, numlayers); 743 744 if (origtexture == 0) { 745 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", 746 origtexture); 747 return; 748 } 749 750 /* Need original texture information to validate arguments */ 751 origTexObj = _mesa_lookup_texture(ctx, origtexture); 752 753 /* If <origtexture> is not the name of a texture, INVALID_VALUE 754 * is generated. 755 */ 756 if (!origTexObj) { 757 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(origtexture = %u)", 758 origtexture); 759 return; 760 } 761 762 /* If <origtexture>'s TEXTURE_IMMUTABLE_FORMAT value is not TRUE, 763 * INVALID_OPERATION is generated. 764 */ 765 if (!origTexObj->Immutable) { 766 _mesa_error(ctx, GL_INVALID_OPERATION, 767 "glTextureView(origtexture not immutable)"); 768 return; 769 } 770 771 /* If <texture> is 0, INVALID_VALUE is generated. */ 772 if (texture == 0) { 773 _mesa_error(ctx, GL_INVALID_VALUE, "glTextureView(texture = 0)"); 774 return; 775 } 776 777 /* If <texture> is not a valid name returned by GenTextures, 778 * the error INVALID_OPERATION is generated. 779 */ 780 texObj = _mesa_lookup_texture(ctx, texture); 781 if (texObj == NULL) { 782 _mesa_error(ctx, GL_INVALID_OPERATION, 783 "glTextureView(texture = %u non-gen name)", texture); 784 return; 785 } 786 787 /* If <texture> has already been bound and given a target, then 788 * the error INVALID_OPERATION is generated. 789 */ 790 if (texObj->Target) { 791 _mesa_error(ctx, GL_INVALID_OPERATION, 792 "glTextureView(texture = %u already bound)", texture); 793 return; 794 } 795 796 /* Check for compatible target */ 797 if (!target_valid(ctx, origTexObj->Target, target)) { 798 return; /* error was recorded */ 799 } 800 801 /* minlevel and minlayer are relative to the view of origtexture. 802 * If minlevel or minlayer is greater than level or layer, respectively, 803 * return INVALID_VALUE. 804 */ 805 newViewMinLevel = origTexObj->Attrib.MinLevel + minlevel; 806 newViewMinLayer = origTexObj->Attrib.MinLayer + minlayer; 807 if (newViewMinLevel >= (origTexObj->Attrib.MinLevel + 808 origTexObj->Attrib.NumLevels)) { 809 _mesa_error(ctx, GL_INVALID_VALUE, 810 "glTextureView(new minlevel (%d) > orig minlevel (%d)" 811 " + orig numlevels (%d))", 812 newViewMinLevel, origTexObj->Attrib.MinLevel, 813 origTexObj->Attrib.NumLevels); 814 return; 815 } 816 817 if (newViewMinLayer >= (origTexObj->Attrib.MinLayer + 818 origTexObj->Attrib.NumLayers)) { 819 _mesa_error(ctx, GL_INVALID_VALUE, 820 "glTextureView(new minlayer (%d) > orig minlayer (%d)" 821 " + orig numlayers (%d))", 822 newViewMinLayer, origTexObj->Attrib.MinLayer, 823 origTexObj->Attrib.NumLayers); 824 return; 825 } 826 827 if (!_mesa_texture_view_compatible_format(ctx, 828 origTexObj->Image[0][0]->InternalFormat, 829 internalformat)) { 830 _mesa_error(ctx, GL_INVALID_OPERATION, 831 "glTextureView(internalformat %s not compatible with origtexture %s)", 832 _mesa_enum_to_string(internalformat), 833 _mesa_enum_to_string(origTexObj->Image[0][0]->InternalFormat)); 834 return; 835 } 836 837 texture_view(ctx, origTexObj, texObj, target, internalformat, minlevel, 838 numlevels, minlayer, numlayers, false); 839} 840