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