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