• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 2011  VMware, Inc.  All Rights Reserved.
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
17  * OR 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
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 /**
26  * \file texstorage.c
27  * GL_ARB_texture_storage functions
28  */
29 
30 #include "util/glheader.h"
31 #include "context.h"
32 #include "enums.h"
33 
34 #include "macros.h"
35 #include "teximage.h"
36 #include "texobj.h"
37 #include "mipmap.h"
38 #include "texstorage.h"
39 #include "textureview.h"
40 #include "mtypes.h"
41 #include "glformats.h"
42 #include "hash.h"
43 #include "api_exec_decl.h"
44 
45 #include "state_tracker/st_cb_texture.h"
46 
47 /**
48  * Check if the given texture target is a legal texture object target
49  * for a glTexStorage() command.
50  * This is a bit different than legal_teximage_target() when it comes
51  * to cube maps.
52  */
53 bool
_mesa_is_legal_tex_storage_target(const struct gl_context * ctx,GLuint dims,GLenum target)54 _mesa_is_legal_tex_storage_target(const struct gl_context *ctx,
55                                   GLuint dims, GLenum target)
56 {
57    if (dims < 1 || dims > 3) {
58       _mesa_problem(ctx, "invalid dims=%u in _mesa_is_legal_tex_storage_target()", dims);
59       return false;
60    }
61 
62    switch (dims) {
63    case 2:
64       switch (target) {
65       case GL_TEXTURE_2D:
66       case GL_TEXTURE_CUBE_MAP:
67          return true;
68       }
69       break;
70    case 3:
71       switch (target) {
72       case GL_TEXTURE_3D:
73          return true;
74       case GL_TEXTURE_2D_ARRAY:
75          return ctx->Extensions.EXT_texture_array;
76       case GL_TEXTURE_CUBE_MAP_ARRAY:
77          return _mesa_has_texture_cube_map_array(ctx);
78       }
79       break;
80    }
81 
82    if (!_mesa_is_desktop_gl(ctx))
83       return false;
84 
85    switch (dims) {
86    case 1:
87       switch (target) {
88       case GL_TEXTURE_1D:
89       case GL_PROXY_TEXTURE_1D:
90          return true;
91       default:
92          return false;
93       }
94    case 2:
95       switch (target) {
96       case GL_PROXY_TEXTURE_2D:
97       case GL_PROXY_TEXTURE_CUBE_MAP:
98          return true;
99       case GL_TEXTURE_RECTANGLE:
100       case GL_PROXY_TEXTURE_RECTANGLE:
101          return ctx->Extensions.NV_texture_rectangle;
102       case GL_TEXTURE_1D_ARRAY:
103       case GL_PROXY_TEXTURE_1D_ARRAY:
104          return ctx->Extensions.EXT_texture_array;
105       default:
106          return false;
107       }
108    case 3:
109       switch (target) {
110       case GL_PROXY_TEXTURE_3D:
111          return true;
112       case GL_PROXY_TEXTURE_2D_ARRAY:
113          return ctx->Extensions.EXT_texture_array;
114       case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
115          return ctx->Extensions.ARB_texture_cube_map_array;
116       default:
117          return false;
118       }
119    default:
120       unreachable("impossible dimensions");
121    }
122 }
123 
124 
125 /** Helper to get a particular texture image in a texture object */
126 static struct gl_texture_image *
get_tex_image(struct gl_context * ctx,struct gl_texture_object * texObj,GLuint face,GLuint level)127 get_tex_image(struct gl_context *ctx,
128               struct gl_texture_object *texObj,
129               GLuint face, GLuint level)
130 {
131    const GLenum faceTarget =
132       (texObj->Target == GL_TEXTURE_CUBE_MAP ||
133        texObj->Target == GL_PROXY_TEXTURE_CUBE_MAP)
134       ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : texObj->Target;
135    return _mesa_get_tex_image(ctx, texObj, faceTarget, level);
136 }
137 
138 
139 
140 static GLboolean
initialize_texture_fields(struct gl_context * ctx,struct gl_texture_object * texObj,GLint levels,GLsizei width,GLsizei height,GLsizei depth,GLenum internalFormat,mesa_format texFormat)141 initialize_texture_fields(struct gl_context *ctx,
142                           struct gl_texture_object *texObj,
143                           GLint levels,
144                           GLsizei width, GLsizei height, GLsizei depth,
145                           GLenum internalFormat, mesa_format texFormat)
146 {
147    const GLenum target = texObj->Target;
148    const GLuint numFaces = _mesa_num_tex_faces(target);
149    GLint level, levelWidth = width, levelHeight = height, levelDepth = depth;
150    GLuint face;
151 
152    /* Set up all the texture object's gl_texture_images */
153    for (level = 0; level < levels; level++) {
154       for (face = 0; face < numFaces; face++) {
155          struct gl_texture_image *texImage =
156             get_tex_image(ctx, texObj, face, level);
157 
158 	 if (!texImage) {
159 	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
160             return GL_FALSE;
161 	 }
162 
163          _mesa_init_teximage_fields(ctx, texImage,
164                                     levelWidth, levelHeight, levelDepth,
165                                     0, internalFormat, texFormat);
166       }
167 
168       _mesa_next_mipmap_level_size(target, 0,
169                                    levelWidth, levelHeight, levelDepth,
170                                    &levelWidth, &levelHeight, &levelDepth);
171    }
172    _mesa_update_texture_object_swizzle(ctx, texObj);
173    return GL_TRUE;
174 }
175 
176 
177 /**
178  * Clear all fields of texture object to zeros.  Used for proxy texture tests
179  * and to clean up when a texture memory allocation fails.
180  */
181 static void
clear_texture_fields(struct gl_context * ctx,struct gl_texture_object * texObj)182 clear_texture_fields(struct gl_context *ctx,
183                      struct gl_texture_object *texObj)
184 {
185    const GLenum target = texObj->Target;
186    const GLuint numFaces = _mesa_num_tex_faces(target);
187    GLint level;
188    GLuint face;
189 
190    for (level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
191       for (face = 0; face < numFaces; face++) {
192          struct gl_texture_image *texImage =
193             get_tex_image(ctx, texObj, face, level);
194 
195 	 if (!texImage) {
196 	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
197             return;
198 	 }
199 
200          _mesa_clear_texture_image(ctx, texImage);
201       }
202    }
203 }
204 
205 
206 /**
207  * Update/re-validate framebuffer object.
208  */
209 static void
update_fbo_texture(struct gl_context * ctx,struct gl_texture_object * texObj)210 update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
211 {
212    const unsigned numFaces = _mesa_num_tex_faces(texObj->Target);
213    for (int level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
214       for (unsigned face = 0; face < numFaces; face++)
215          _mesa_update_fbo_texture(ctx, texObj, face, level);
216    }
217 }
218 
219 
220 GLboolean
_mesa_is_legal_tex_storage_format(const struct gl_context * ctx,GLenum internalformat)221 _mesa_is_legal_tex_storage_format(const struct gl_context *ctx,
222                                   GLenum internalformat)
223 {
224    if (!_mesa_is_desktop_gl(ctx)) {
225       assert(_mesa_has_EXT_texture_storage(ctx));
226 
227       /* EXT_texture_storage allows us to use some sized internal formats
228        * for TexStorage* that aren't otherwise allowed in OpenGL ES.
229        **/
230       switch (internalformat) {
231       case GL_ALPHA8:
232       case GL_LUMINANCE8:
233       case GL_LUMINANCE8_ALPHA8:
234          return true;
235 
236       case GL_RGBA32F:
237       case GL_RGB32F:
238       case GL_ALPHA32F_EXT:
239       case GL_LUMINANCE32F_EXT:
240       case GL_LUMINANCE_ALPHA32F_EXT:
241          return _mesa_has_OES_texture_float(ctx);
242 
243       case GL_RGBA16F:
244       case GL_RGB16F:
245       case GL_ALPHA16F_EXT:
246       case GL_LUMINANCE16F_EXT:
247       case GL_LUMINANCE_ALPHA16F_EXT:
248          return _mesa_has_OES_texture_half_float(ctx);
249 
250       case GL_RGB10_A2:
251       case GL_RGB10:
252          return _mesa_has_EXT_texture_type_2_10_10_10_REV(ctx);
253 
254       case GL_BGRA8_EXT:
255          assert(_mesa_has_EXT_texture_format_BGRA8888(ctx));
256          return true;
257 
258       case GL_R8:
259       case GL_RG8:
260          return _mesa_has_EXT_texture_rg(ctx);
261 
262       case GL_R32F_EXT:
263       case GL_RG32F_EXT:
264          return _mesa_has_EXT_texture_rg(ctx) &&
265                 _mesa_has_OES_texture_float(ctx);
266 
267       case GL_R16F_EXT:
268       case GL_RG16F_EXT:
269          return _mesa_has_EXT_texture_rg(ctx) &&
270                 _mesa_has_OES_texture_half_float(ctx);
271       }
272    }
273 
274    /* check internal format - note that only sized formats are allowed */
275    switch (internalformat) {
276    case GL_ALPHA:
277    case GL_LUMINANCE:
278    case GL_LUMINANCE_ALPHA:
279    case GL_INTENSITY:
280    case GL_RED:
281    case GL_RG:
282    case GL_RGB:
283    case GL_RGBA:
284    case GL_BGRA:
285    case GL_DEPTH_COMPONENT:
286    case GL_DEPTH_STENCIL:
287    case GL_COMPRESSED_ALPHA:
288    case GL_COMPRESSED_LUMINANCE_ALPHA:
289    case GL_COMPRESSED_LUMINANCE:
290    case GL_COMPRESSED_INTENSITY:
291    case GL_COMPRESSED_RGB:
292    case GL_COMPRESSED_RGBA:
293    case GL_COMPRESSED_SRGB:
294    case GL_COMPRESSED_SRGB_ALPHA:
295    case GL_COMPRESSED_SLUMINANCE:
296    case GL_COMPRESSED_SLUMINANCE_ALPHA:
297    case GL_RED_INTEGER:
298    case GL_GREEN_INTEGER:
299    case GL_BLUE_INTEGER:
300    case GL_ALPHA_INTEGER:
301    case GL_RGB_INTEGER:
302    case GL_RGBA_INTEGER:
303    case GL_BGR_INTEGER:
304    case GL_BGRA_INTEGER:
305    case GL_LUMINANCE_INTEGER_EXT:
306    case GL_LUMINANCE_ALPHA_INTEGER_EXT:
307       /* these unsized formats are illegal */
308       return GL_FALSE;
309    default:
310       return _mesa_base_tex_format(ctx, internalformat) > 0;
311    }
312 }
313 
314 
315 /**
316  * Do error checking for calls to glTexStorage1/2/3D().
317  * If an error is found, record it with _mesa_error(), unless the target
318  * is a proxy texture.
319  * \return GL_TRUE if any error, GL_FALSE otherwise.
320  */
321 static GLboolean
tex_storage_error_check(struct gl_context * ctx,struct gl_texture_object * texObj,struct gl_memory_object * memObj,GLuint dims,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,bool dsa)322 tex_storage_error_check(struct gl_context *ctx,
323                         struct gl_texture_object *texObj,
324                         struct gl_memory_object *memObj,
325                         GLuint dims, GLenum target,
326                         GLsizei levels, GLenum internalformat,
327                         GLsizei width, GLsizei height, GLsizei depth,
328                         bool dsa)
329 {
330    const char* suffix = dsa ? (memObj ? "tureMem" : "ture") :
331                               (memObj ? "Mem" : "");
332 
333    /* Legal format checking has been moved to texstorage and texturestorage in
334     * order to allow meta functions to use legacy formats. */
335 
336    /* size check */
337    if (!_mesa_valid_tex_storage_dim(width, height, depth)) {
338       _mesa_error(ctx, GL_INVALID_VALUE,
339                   "glTex%sStorage%uD(width, height or depth < 1)",
340                   suffix, dims);
341       return GL_TRUE;
342    }
343 
344    if (_mesa_is_compressed_format(ctx, internalformat)) {
345       GLenum err;
346       if (!_mesa_target_can_be_compressed(ctx, target, internalformat, &err)) {
347          _mesa_error(ctx, err,
348                   "glTex%sStorage%dD(internalformat = %s)", suffix, dims,
349                   _mesa_enum_to_string(internalformat));
350          return GL_TRUE;
351       }
352    }
353 
354    /* levels check */
355    if (levels < 1) {
356       _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(levels < 1)",
357                   suffix, dims);
358       return GL_TRUE;
359    }
360 
361    /* check levels against maximum (note different error than above) */
362    if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) {
363       _mesa_error(ctx, GL_INVALID_OPERATION,
364                   "glTex%sStorage%uD(levels too large)",
365                   suffix, dims);
366       return GL_TRUE;
367    }
368 
369    /* check levels against width/height/depth */
370    if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) {
371       _mesa_error(ctx, GL_INVALID_OPERATION,
372                   "glTex%sStorage%uD(too many levels"
373                   " for max texture dimension)",
374                   suffix, dims);
375       return GL_TRUE;
376    }
377 
378    /* non-default texture object check */
379    if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) {
380       _mesa_error(ctx, GL_INVALID_OPERATION,
381                   "glTex%sStorage%uD(texture object 0)",
382                   suffix, dims);
383       return GL_TRUE;
384    }
385 
386    /* Check if texObj->Immutable is set */
387    if (!_mesa_is_proxy_texture(target) && texObj->Immutable) {
388       _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(immutable)",
389                   suffix, dims);
390       return GL_TRUE;
391    }
392 
393    /* additional checks for depth textures */
394    if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat)) {
395       _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(bad target for texture)",
396                   suffix, dims);
397       return GL_TRUE;
398    }
399 
400    return GL_FALSE;
401 }
402 
403 GLboolean
_mesa_sparse_texture_error_check(struct gl_context * ctx,GLuint dims,struct gl_texture_object * texObj,mesa_format format,GLenum target,GLsizei levels,GLsizei width,GLsizei height,GLsizei depth,const char * func)404 _mesa_sparse_texture_error_check(struct gl_context *ctx, GLuint dims,
405                                  struct gl_texture_object *texObj,
406                                  mesa_format format, GLenum target, GLsizei levels,
407                                  GLsizei width, GLsizei height, GLsizei depth,
408                                  const char *func)
409 {
410    int px, py, pz;
411    int index = texObj->VirtualPageSizeIndex;
412    if (!st_GetSparseTextureVirtualPageSize(ctx, target, format, index,
413                                            &px, &py, &pz)) {
414       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(sparse index = %d)",
415                   func, index);
416       return GL_TRUE;
417    }
418 
419    if (target == GL_TEXTURE_3D) {
420       if (width > ctx->Const.MaxSparse3DTextureSize ||
421           height > ctx->Const.MaxSparse3DTextureSize ||
422           depth > ctx->Const.MaxSparse3DTextureSize)
423          goto exceed_max_size;
424    } else {
425       if (width > ctx->Const.MaxSparseTextureSize ||
426           height > ctx->Const.MaxSparseTextureSize)
427          goto exceed_max_size;
428 
429       if (target == GL_TEXTURE_2D_ARRAY ||
430           target == GL_TEXTURE_CUBE_MAP_ARRAY) {
431          if (depth > ctx->Const.MaxSparseArrayTextureLayers)
432             goto exceed_max_size;
433       } else if (target == GL_TEXTURE_1D_ARRAY) {
434          if (height > ctx->Const.MaxSparseArrayTextureLayers)
435             goto exceed_max_size;
436       }
437    }
438 
439    /* ARB_sparse_texture2 allow non-page-aligned base texture size. */
440    if (!_mesa_has_ARB_sparse_texture2(ctx) &&
441        (width % px || height % py || depth % pz)) {
442       _mesa_error(ctx, GL_INVALID_VALUE, "%s(sparse page size)", func);
443       return GL_TRUE;
444    }
445 
446    /* ARB_sparse_texture spec:
447     *
448     *   If the value of SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB is FALSE,
449     *   then TexStorage* will generate an INVALID_OPERATION error if
450     *     * the texture's TEXTURE_SPARSE_ARB parameter is TRUE,
451     *     * <target> is one of TEXTURE_1D_ARRAY, TEXTURE_2D_ARRAY,
452     *       TEXTURE_CUBE_MAP, or TEXTURE_CUBE_MAP_ARRAY, and
453     *     * for the virtual page size corresponding to the
454     *       VIRTUAL_PAGE_SIZE_INDEX_ARB parameter, either of the following is
455     *       true:
456     *         - <width> is not a multiple of VIRTUAL_PAGE_SIZE_X_ARB *
457     *            2^(<levels>-1), or
458     *         - <height> is not a multiple of VIRTUAL_PAGE_SIZE_Y_ARB *
459     *            2^(<levels>-1).
460     *
461     * This make sure all allocated mipmap level size is multiple of virtual
462     * page size when SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB is FALSE.
463     */
464    if (!ctx->Const.SparseTextureFullArrayCubeMipmaps &&
465        (target == GL_TEXTURE_1D_ARRAY ||
466         target == GL_TEXTURE_2D_ARRAY ||
467         target == GL_TEXTURE_CUBE_MAP ||
468         target == GL_TEXTURE_CUBE_MAP_ARRAY) &&
469        (width % (px << (levels - 1)) ||
470         height % (py << (levels - 1)))) {
471       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(sparse array align)", func);
472       return GL_TRUE;
473    }
474 
475    return GL_FALSE;
476 
477 exceed_max_size:
478    _mesa_error(ctx, GL_INVALID_VALUE, "%s(exceed max sparse size)", func);
479    return GL_TRUE;
480 }
481 
482 /**
483  * Helper that does the storage allocation for _mesa_TexStorage1/2/3D()
484  * and _mesa_TextureStorage1/2/3D().
485  */
486 static ALWAYS_INLINE void
texture_storage(struct gl_context * ctx,GLuint dims,struct gl_texture_object * texObj,struct gl_memory_object * memObj,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLuint64 offset,bool dsa,bool no_error,const char * func)487 texture_storage(struct gl_context *ctx, GLuint dims,
488                 struct gl_texture_object *texObj,
489                 struct gl_memory_object *memObj, GLenum target,
490                 GLsizei levels, GLenum internalformat, GLsizei width,
491                 GLsizei height, GLsizei depth, GLuint64 offset, bool dsa,
492                 bool no_error, const char *func)
493 {
494    GLboolean sizeOK = GL_TRUE, dimensionsOK = GL_TRUE;
495    mesa_format texFormat;
496    const char* suffix = dsa ? (memObj ? "tureMem" : "ture") :
497                               (memObj ? "Mem" : "");
498 
499    assert(texObj);
500 
501    if (!no_error) {
502       if (tex_storage_error_check(ctx, texObj, memObj, dims, target, levels,
503                                   internalformat, width, height, depth, dsa)) {
504          return; /* error was recorded */
505       }
506    }
507 
508    texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0,
509                                            internalformat, GL_NONE, GL_NONE);
510 
511    if (!no_error) {
512       /* check that width, height, depth are legal for the mipmap level */
513       dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0,
514                                                      width, height, depth, 0);
515 
516       sizeOK = st_TestProxyTexImage(ctx, target, levels, 0, texFormat,
517                                     1, width, height, depth);
518    }
519 
520    if (_mesa_is_proxy_texture(target)) {
521       if (dimensionsOK && sizeOK) {
522          initialize_texture_fields(ctx, texObj, levels, width, height, depth,
523                                    internalformat, texFormat);
524       }
525       else {
526          /* clear all image fields for [levels] */
527          clear_texture_fields(ctx, texObj);
528       }
529    }
530    else {
531       if (!no_error) {
532          if (!dimensionsOK) {
533             _mesa_error(ctx, GL_INVALID_VALUE,
534                         "glTex%sStorage%uD(invalid width, height or depth)",
535                         suffix, dims);
536             return;
537          }
538 
539          if (!sizeOK) {
540             _mesa_error(ctx, GL_OUT_OF_MEMORY,
541                         "glTex%sStorage%uD(texture too large)",
542                         suffix, dims);
543             return;
544          }
545 
546          if (texObj->IsSparse) {
547             char func[32];
548             snprintf(func, 32, "glTex%sStorage%uD", suffix, dims);
549             if (_mesa_sparse_texture_error_check(ctx, dims, texObj, texFormat, target,
550                                                  levels, width, height, depth, func))
551                return; /* error was recorded */
552          }
553       }
554 
555       assert(levels > 0);
556       assert(width > 0);
557       assert(height > 0);
558       assert(depth > 0);
559 
560       if (!initialize_texture_fields(ctx, texObj, levels, width, height, depth,
561                                      internalformat, texFormat)) {
562          return;
563       }
564 
565       /* Setup the backing memory */
566       if (memObj) {
567          if (!st_SetTextureStorageForMemoryObject(ctx, texObj, memObj,
568                                                   levels,
569                                                   width, height, depth,
570                                                   offset, func)) {
571 
572             clear_texture_fields(ctx, texObj);
573             return;
574          }
575       }
576       else {
577          if (!st_AllocTextureStorage(ctx, texObj, levels,
578                                      width, height, depth, func)) {
579             /* Reset the texture images' info to zeros.
580              * Strictly speaking, we probably don't have to do this since
581              * generating GL_OUT_OF_MEMORY can leave things in an undefined
582              * state but this puts things in a consistent state.
583              */
584             clear_texture_fields(ctx, texObj);
585             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex%sStorage%uD",
586                         suffix, dims);
587             return;
588          }
589       }
590 
591       _mesa_set_texture_view_state(ctx, texObj, target, levels);
592 
593       update_fbo_texture(ctx, texObj);
594    }
595 }
596 
597 
598 static void
texture_storage_error(struct gl_context * ctx,GLuint dims,struct gl_texture_object * texObj,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,bool dsa,const char * func)599 texture_storage_error(struct gl_context *ctx, GLuint dims,
600                       struct gl_texture_object *texObj,
601                       GLenum target, GLsizei levels,
602                       GLenum internalformat, GLsizei width,
603                       GLsizei height, GLsizei depth, bool dsa, const char *func)
604 {
605    texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat,
606                    width, height, depth, dsa, 0, false, func);
607 }
608 
609 
610 static void
texture_storage_no_error(struct gl_context * ctx,GLuint dims,struct gl_texture_object * texObj,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,bool dsa,const char * func)611 texture_storage_no_error(struct gl_context *ctx, GLuint dims,
612                          struct gl_texture_object *texObj,
613                          GLenum target, GLsizei levels,
614                          GLenum internalformat, GLsizei width,
615                          GLsizei height, GLsizei depth, bool dsa, const char *func)
616 {
617    texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat,
618                    width, height, depth, dsa, 0, true, func);
619 }
620 
621 
622 /**
623  * Helper used by _mesa_TexStorage1/2/3D().
624  */
625 static void
texstorage_error(GLuint dims,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,const char * caller)626 texstorage_error(GLuint dims, GLenum target, GLsizei levels,
627                  GLenum internalformat, GLsizei width, GLsizei height,
628                  GLsizei depth, const char *caller)
629 {
630    struct gl_texture_object *texObj;
631    GET_CURRENT_CONTEXT(ctx);
632 
633    /* Check target.  This is done here so that texture_storage
634     * can receive unsized formats.
635     */
636    if (!_mesa_is_legal_tex_storage_target(ctx, dims, target)) {
637       _mesa_error(ctx, GL_INVALID_ENUM,
638                   "%s(illegal target=%s)",
639                   caller, _mesa_enum_to_string(target));
640       return;
641    }
642 
643    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
644       _mesa_debug(ctx, "%s %s %d %s %d %d %d\n", caller,
645                   _mesa_enum_to_string(target), levels,
646                   _mesa_enum_to_string(internalformat),
647                   width, height, depth);
648 
649    /* Check the format to make sure it is sized. */
650    if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
651       _mesa_error(ctx, GL_INVALID_ENUM,
652                   "%s(internalformat = %s)", caller,
653                   _mesa_enum_to_string(internalformat));
654       return;
655    }
656 
657    texObj = _mesa_get_current_tex_object(ctx, target);
658    if (!texObj)
659       return;
660 
661    texture_storage_error(ctx, dims, texObj, target, levels,
662                          internalformat, width, height, depth, false, caller);
663 }
664 
665 
666 static void
texstorage_no_error(GLuint dims,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,const char * caller)667 texstorage_no_error(GLuint dims, GLenum target, GLsizei levels,
668                     GLenum internalformat, GLsizei width, GLsizei height,
669                     GLsizei depth, const char *caller)
670 {
671    GET_CURRENT_CONTEXT(ctx);
672 
673    struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target);
674    texture_storage_no_error(ctx, dims, texObj, target, levels,
675                             internalformat, width, height, depth, false, caller);
676 }
677 
678 
679 /**
680  * Helper used by _mesa_TextureStorage1/2/3D().
681  */
682 static void
texturestorage_error(GLuint dims,GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,const char * caller)683 texturestorage_error(GLuint dims, GLuint texture, GLsizei levels,
684                      GLenum internalformat, GLsizei width, GLsizei height,
685                      GLsizei depth, const char *caller)
686 {
687    struct gl_texture_object *texObj;
688    GET_CURRENT_CONTEXT(ctx);
689 
690    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
691       _mesa_debug(ctx, "%s %d %d %s %d %d %d\n",
692                   caller, texture, levels,
693                   _mesa_enum_to_string(internalformat),
694                   width, height, depth);
695 
696    /* Check the format to make sure it is sized. */
697    if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
698       _mesa_error(ctx, GL_INVALID_ENUM,
699                   "%s(internalformat = %s)", caller,
700                   _mesa_enum_to_string(internalformat));
701       return;
702    }
703 
704    texObj = _mesa_lookup_texture_err(ctx, texture, caller);
705    if (!texObj)
706       return;
707 
708    /* Check target.  This is done here so that texture_storage
709     * can receive unsized formats.
710     */
711    if (!_mesa_is_legal_tex_storage_target(ctx, dims, texObj->Target)) {
712       _mesa_error(ctx, GL_INVALID_OPERATION,
713                   "%s(illegal target=%s)", caller,
714                   _mesa_enum_to_string(texObj->Target));
715       return;
716    }
717 
718    texture_storage_error(ctx, dims, texObj, texObj->Target,
719                          levels, internalformat, width, height, depth, true, caller);
720 }
721 
722 
723 static void
texturestorage_no_error(GLuint dims,GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,const char * caller)724 texturestorage_no_error(GLuint dims, GLuint texture, GLsizei levels,
725                         GLenum internalformat, GLsizei width, GLsizei height,
726                         GLsizei depth, const char *caller)
727 {
728    GET_CURRENT_CONTEXT(ctx);
729 
730    struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture);
731    texture_storage_no_error(ctx, dims, texObj, texObj->Target,
732                             levels, internalformat, width, height, depth, true, caller);
733 }
734 
735 
736 void GLAPIENTRY
_mesa_TexStorage1D_no_error(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)737 _mesa_TexStorage1D_no_error(GLenum target, GLsizei levels,
738                             GLenum internalformat, GLsizei width)
739 {
740    texstorage_no_error(1, target, levels, internalformat, width, 1, 1,
741                        "glTexStorage1D");
742 }
743 
744 
745 void GLAPIENTRY
_mesa_TexStorage1D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)746 _mesa_TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat,
747                    GLsizei width)
748 {
749    texstorage_error(1, target, levels, internalformat, width, 1, 1,
750                     "glTexStorage1D");
751 }
752 
753 
754 void GLAPIENTRY
_mesa_TexStorage2D_no_error(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)755 _mesa_TexStorage2D_no_error(GLenum target, GLsizei levels,
756                             GLenum internalformat, GLsizei width,
757                             GLsizei height)
758 {
759    texstorage_no_error(2, target, levels, internalformat, width, height, 1,
760                        "glTexStorage2D");
761 }
762 
763 
764 void GLAPIENTRY
_mesa_TexStorage2D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)765 _mesa_TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat,
766                    GLsizei width, GLsizei height)
767 {
768    texstorage_error(2, target, levels, internalformat, width, height, 1,
769                     "glTexStorage2D");
770 }
771 
772 
773 void GLAPIENTRY
_mesa_TexStorage3D_no_error(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)774 _mesa_TexStorage3D_no_error(GLenum target, GLsizei levels,
775                             GLenum internalformat, GLsizei width,
776                             GLsizei height, GLsizei depth)
777 {
778    texstorage_no_error(3, target, levels, internalformat, width, height, depth,
779                        "glTexStorage3D");
780 }
781 
782 
783 void GLAPIENTRY
_mesa_TexStorage3D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)784 _mesa_TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
785                    GLsizei width, GLsizei height, GLsizei depth)
786 {
787    texstorage_error(3, target, levels, internalformat, width, height, depth,
788                     "glTexStorage3D");
789 }
790 
791 
792 void GLAPIENTRY
_mesa_TextureStorage1D_no_error(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width)793 _mesa_TextureStorage1D_no_error(GLuint texture, GLsizei levels,
794                                 GLenum internalformat, GLsizei width)
795 {
796    texturestorage_no_error(1, texture, levels, internalformat, width, 1, 1,
797                            "glTextureStorage1D");
798 }
799 
800 
801 void GLAPIENTRY
_mesa_TextureStorage1D(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width)802 _mesa_TextureStorage1D(GLuint texture, GLsizei levels, GLenum internalformat,
803                        GLsizei width)
804 {
805    texturestorage_error(1, texture, levels, internalformat, width, 1, 1,
806                         "glTextureStorage1D");
807 }
808 
809 
810 void GLAPIENTRY
_mesa_TextureStorage2D_no_error(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)811 _mesa_TextureStorage2D_no_error(GLuint texture, GLsizei levels,
812                                 GLenum internalformat,
813                                 GLsizei width, GLsizei height)
814 {
815    texturestorage_no_error(2, texture, levels, internalformat, width, height, 1,
816                            "glTextureStorage2D");
817 }
818 
819 
820 void GLAPIENTRY
_mesa_TextureStorage2D(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)821 _mesa_TextureStorage2D(GLuint texture, GLsizei levels,
822                        GLenum internalformat,
823                        GLsizei width, GLsizei height)
824 {
825    texturestorage_error(2, texture, levels, internalformat, width, height, 1,
826                         "glTextureStorage2D");
827 }
828 
829 
830 void GLAPIENTRY
_mesa_TextureStorage3D_no_error(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)831 _mesa_TextureStorage3D_no_error(GLuint texture, GLsizei levels,
832                                 GLenum internalformat, GLsizei width,
833                                 GLsizei height, GLsizei depth)
834 {
835    texturestorage_no_error(3, texture, levels, internalformat, width, height,
836                            depth, "glTextureStorage3D");
837 }
838 
839 
840 void GLAPIENTRY
_mesa_TextureStorage3D(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)841 _mesa_TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat,
842                        GLsizei width, GLsizei height, GLsizei depth)
843 {
844    texturestorage_error(3, texture, levels, internalformat, width, height, depth,
845                         "glTextureStorage3D");
846 }
847 
848 
849 void GLAPIENTRY
_mesa_TextureStorage1DEXT(GLuint texture,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)850 _mesa_TextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels,
851                           GLenum internalformat,
852                           GLsizei width)
853 {
854    GET_CURRENT_CONTEXT(ctx);
855    /* 'texture' must always be initialized, even if the call to
856     * glTextureStorage1DEXT will generate an error.
857     */
858    if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
859                                        "glTextureStorage1DEXT"))
860       return;
861    texturestorage_error(1, texture, levels, internalformat, width, 1, 1,
862                         "glTextureStorage1DEXT");
863 }
864 
865 
866 void GLAPIENTRY
_mesa_TextureStorage2DEXT(GLuint texture,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)867 _mesa_TextureStorage2DEXT(GLuint texture, GLenum target, GLsizei levels,
868                           GLenum internalformat,
869                           GLsizei width, GLsizei height)
870 {
871    GET_CURRENT_CONTEXT(ctx);
872    /* 'texture' must always be initialized, even if the call to
873     * glTextureStorage2DEXT will generate an error.
874     */
875    if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
876                                        "glTextureStorage2DEXT"))
877       return;
878    texturestorage_error(2, texture, levels, internalformat, width, height, 1,
879                         "glTextureStorage2DEXT");
880 }
881 
882 
883 void GLAPIENTRY
_mesa_TextureStorage3DEXT(GLuint texture,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)884 _mesa_TextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels,
885                           GLenum internalformat,
886                           GLsizei width, GLsizei height, GLsizei depth)
887 {
888    GET_CURRENT_CONTEXT(ctx);
889    /* 'texture' must always be initialized, even if the call to
890     * glTextureStorage3DEXT will generate an error.
891     */
892    if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
893                                        "glTextureStorage3DEXT"))
894       return;
895    texturestorage_error(3, texture, levels, internalformat, width, height, depth,
896                         "glTextureStorage3DEXT");
897 }
898 
899 
900 void
_mesa_texture_storage_memory(struct gl_context * ctx,GLuint dims,struct gl_texture_object * texObj,struct gl_memory_object * memObj,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLuint64 offset,bool dsa)901 _mesa_texture_storage_memory(struct gl_context *ctx, GLuint dims,
902                              struct gl_texture_object *texObj,
903                              struct gl_memory_object *memObj,
904                              GLenum target, GLsizei levels,
905                              GLenum internalformat, GLsizei width,
906                              GLsizei height, GLsizei depth,
907                              GLuint64 offset, bool dsa)
908 {
909    assert(memObj);
910 
911    texture_storage(ctx, dims, texObj, memObj, target, levels, internalformat,
912                    width, height, depth, offset, dsa, false, "");
913 }
914