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