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