• 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 "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    return GL_TRUE;
173 }
174 
175 
176 /**
177  * Clear all fields of texture object to zeros.  Used for proxy texture tests
178  * and to clean up when a texture memory allocation fails.
179  */
180 static void
clear_texture_fields(struct gl_context * ctx,struct gl_texture_object * texObj)181 clear_texture_fields(struct gl_context *ctx,
182                      struct gl_texture_object *texObj)
183 {
184    const GLenum target = texObj->Target;
185    const GLuint numFaces = _mesa_num_tex_faces(target);
186    GLint level;
187    GLuint face;
188 
189    for (level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
190       for (face = 0; face < numFaces; face++) {
191          struct gl_texture_image *texImage =
192             get_tex_image(ctx, texObj, face, level);
193 
194 	 if (!texImage) {
195 	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
196             return;
197 	 }
198 
199          _mesa_clear_texture_image(ctx, texImage);
200       }
201    }
202 }
203 
204 
205 /**
206  * Update/re-validate framebuffer object.
207  */
208 static void
update_fbo_texture(struct gl_context * ctx,struct gl_texture_object * texObj)209 update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
210 {
211    const unsigned numFaces = _mesa_num_tex_faces(texObj->Target);
212    for (int level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
213       for (unsigned face = 0; face < numFaces; face++)
214          _mesa_update_fbo_texture(ctx, texObj, face, level);
215    }
216 }
217 
218 
219 GLboolean
_mesa_is_legal_tex_storage_format(const struct gl_context * ctx,GLenum internalformat)220 _mesa_is_legal_tex_storage_format(const struct gl_context *ctx,
221                                   GLenum internalformat)
222 {
223    /* check internal format - note that only sized formats are allowed */
224    switch (internalformat) {
225    case GL_ALPHA:
226    case GL_LUMINANCE:
227    case GL_LUMINANCE_ALPHA:
228    case GL_INTENSITY:
229    case GL_RED:
230    case GL_RG:
231    case GL_RGB:
232    case GL_RGBA:
233    case GL_BGRA:
234    case GL_DEPTH_COMPONENT:
235    case GL_DEPTH_STENCIL:
236    case GL_COMPRESSED_ALPHA:
237    case GL_COMPRESSED_LUMINANCE_ALPHA:
238    case GL_COMPRESSED_LUMINANCE:
239    case GL_COMPRESSED_INTENSITY:
240    case GL_COMPRESSED_RGB:
241    case GL_COMPRESSED_RGBA:
242    case GL_COMPRESSED_SRGB:
243    case GL_COMPRESSED_SRGB_ALPHA:
244    case GL_COMPRESSED_SLUMINANCE:
245    case GL_COMPRESSED_SLUMINANCE_ALPHA:
246    case GL_RED_INTEGER:
247    case GL_GREEN_INTEGER:
248    case GL_BLUE_INTEGER:
249    case GL_ALPHA_INTEGER:
250    case GL_RGB_INTEGER:
251    case GL_RGBA_INTEGER:
252    case GL_BGR_INTEGER:
253    case GL_BGRA_INTEGER:
254    case GL_LUMINANCE_INTEGER_EXT:
255    case GL_LUMINANCE_ALPHA_INTEGER_EXT:
256       /* these unsized formats are illegal */
257       return GL_FALSE;
258    default:
259       return _mesa_base_tex_format(ctx, internalformat) > 0;
260    }
261 }
262 
263 
264 /**
265  * Do error checking for calls to glTexStorage1/2/3D().
266  * If an error is found, record it with _mesa_error(), unless the target
267  * is a proxy texture.
268  * \return GL_TRUE if any error, GL_FALSE otherwise.
269  */
270 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)271 tex_storage_error_check(struct gl_context *ctx,
272                         struct gl_texture_object *texObj,
273                         struct gl_memory_object *memObj,
274                         GLuint dims, GLenum target,
275                         GLsizei levels, GLenum internalformat,
276                         GLsizei width, GLsizei height, GLsizei depth,
277                         bool dsa)
278 {
279    const char* suffix = dsa ? (memObj ? "tureMem" : "ture") :
280                               (memObj ? "Mem" : "");
281 
282    /* Legal format checking has been moved to texstorage and texturestorage in
283     * order to allow meta functions to use legacy formats. */
284 
285    /* size check */
286    if (!_mesa_valid_tex_storage_dim(width, height, depth)) {
287       _mesa_error(ctx, GL_INVALID_VALUE,
288                   "glTex%sStorage%uD(width, height or depth < 1)",
289                   suffix, dims);
290       return GL_TRUE;
291    }
292 
293    if (_mesa_is_compressed_format(ctx, internalformat)) {
294       GLenum err;
295       if (!_mesa_target_can_be_compressed(ctx, target, internalformat, &err)) {
296          _mesa_error(ctx, err,
297                   "glTex%sStorage%dD(internalformat = %s)", suffix, dims,
298                   _mesa_enum_to_string(internalformat));
299          return GL_TRUE;
300       }
301    }
302 
303    /* levels check */
304    if (levels < 1) {
305       _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(levels < 1)",
306                   suffix, dims);
307       return GL_TRUE;
308    }
309 
310    /* check levels against maximum (note different error than above) */
311    if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) {
312       _mesa_error(ctx, GL_INVALID_OPERATION,
313                   "glTex%sStorage%uD(levels too large)",
314                   suffix, dims);
315       return GL_TRUE;
316    }
317 
318    /* check levels against width/height/depth */
319    if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) {
320       _mesa_error(ctx, GL_INVALID_OPERATION,
321                   "glTex%sStorage%uD(too many levels"
322                   " for max texture dimension)",
323                   suffix, dims);
324       return GL_TRUE;
325    }
326 
327    /* non-default texture object check */
328    if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) {
329       _mesa_error(ctx, GL_INVALID_OPERATION,
330                   "glTex%sStorage%uD(texture object 0)",
331                   suffix, dims);
332       return GL_TRUE;
333    }
334 
335    /* Check if texObj->Immutable is set */
336    if (!_mesa_is_proxy_texture(target) && texObj->Immutable) {
337       _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(immutable)",
338                   suffix, dims);
339       return GL_TRUE;
340    }
341 
342    /* additional checks for depth textures */
343    if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat)) {
344       _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(bad target for texture)",
345                   suffix, dims);
346       return GL_TRUE;
347    }
348 
349    return GL_FALSE;
350 }
351 
352 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)353 _mesa_sparse_texture_error_check(struct gl_context *ctx, GLuint dims,
354                                  struct gl_texture_object *texObj,
355                                  mesa_format format, GLenum target, GLsizei levels,
356                                  GLsizei width, GLsizei height, GLsizei depth,
357                                  const char *func)
358 {
359    int px, py, pz;
360    int index = texObj->VirtualPageSizeIndex;
361    if (!st_GetSparseTextureVirtualPageSize(ctx, target, format, index,
362                                            &px, &py, &pz)) {
363       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(sparse index = %d)",
364                   func, index);
365       return GL_TRUE;
366    }
367 
368    if (target == GL_TEXTURE_3D) {
369       if (width > ctx->Const.MaxSparse3DTextureSize ||
370           height > ctx->Const.MaxSparse3DTextureSize ||
371           depth > ctx->Const.MaxSparse3DTextureSize)
372          goto exceed_max_size;
373    } else {
374       if (width > ctx->Const.MaxSparseTextureSize ||
375           height > ctx->Const.MaxSparseTextureSize)
376          goto exceed_max_size;
377 
378       if (target == GL_TEXTURE_2D_ARRAY ||
379           target == GL_TEXTURE_CUBE_MAP_ARRAY) {
380          if (depth > ctx->Const.MaxSparseArrayTextureLayers)
381             goto exceed_max_size;
382       } else if (target == GL_TEXTURE_1D_ARRAY) {
383          if (height > ctx->Const.MaxSparseArrayTextureLayers)
384             goto exceed_max_size;
385       }
386    }
387 
388    /* ARB_sparse_texture2 allow non-page-aligned base texture size. */
389    if (!_mesa_has_ARB_sparse_texture2(ctx) &&
390        (width % px || height % py || depth % pz)) {
391       _mesa_error(ctx, GL_INVALID_VALUE, "%s(sparse page size)", func);
392       return GL_TRUE;
393    }
394 
395    /* ARB_sparse_texture spec:
396     *
397     *   If the value of SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB is FALSE,
398     *   then TexStorage* will generate an INVALID_OPERATION error if
399     *     * the texture's TEXTURE_SPARSE_ARB parameter is TRUE,
400     *     * <target> is one of TEXTURE_1D_ARRAY, TEXTURE_2D_ARRAY,
401     *       TEXTURE_CUBE_MAP, or TEXTURE_CUBE_MAP_ARRAY, and
402     *     * for the virtual page size corresponding to the
403     *       VIRTUAL_PAGE_SIZE_INDEX_ARB parameter, either of the following is
404     *       true:
405     *         - <width> is not a multiple of VIRTUAL_PAGE_SIZE_X_ARB *
406     *            2^(<levels>-1), or
407     *         - <height> is not a multiple of VIRTUAL_PAGE_SIZE_Y_ARB *
408     *            2^(<levels>-1).
409     *
410     * This make sure all allocated mipmap level size is multiple of virtual
411     * page size when SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB is FALSE.
412     */
413    if (!ctx->Const.SparseTextureFullArrayCubeMipmaps &&
414        (target == GL_TEXTURE_1D_ARRAY ||
415         target == GL_TEXTURE_2D_ARRAY ||
416         target == GL_TEXTURE_CUBE_MAP ||
417         target == GL_TEXTURE_CUBE_MAP_ARRAY) &&
418        (width % (px << (levels - 1)) ||
419         height % (py << (levels - 1)))) {
420       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(sparse array align)", func);
421       return GL_TRUE;
422    }
423 
424    return GL_FALSE;
425 
426 exceed_max_size:
427    _mesa_error(ctx, GL_INVALID_VALUE, "%s(exceed max sparse size)", func);
428    return GL_TRUE;
429 }
430 
431 /**
432  * Helper that does the storage allocation for _mesa_TexStorage1/2/3D()
433  * and _mesa_TextureStorage1/2/3D().
434  */
435 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)436 texture_storage(struct gl_context *ctx, GLuint dims,
437                 struct gl_texture_object *texObj,
438                 struct gl_memory_object *memObj, GLenum target,
439                 GLsizei levels, GLenum internalformat, GLsizei width,
440                 GLsizei height, GLsizei depth, GLuint64 offset, bool dsa,
441                 bool no_error)
442 {
443    GLboolean sizeOK = GL_TRUE, dimensionsOK = GL_TRUE;
444    mesa_format texFormat;
445    const char* suffix = dsa ? (memObj ? "tureMem" : "ture") :
446                               (memObj ? "Mem" : "");
447 
448    assert(texObj);
449 
450    if (!no_error) {
451       if (tex_storage_error_check(ctx, texObj, memObj, dims, target, levels,
452                                   internalformat, width, height, depth, dsa)) {
453          return; /* error was recorded */
454       }
455    }
456 
457    texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0,
458                                            internalformat, GL_NONE, GL_NONE);
459 
460    if (!no_error) {
461       /* check that width, height, depth are legal for the mipmap level */
462       dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0,
463                                                      width, height, depth, 0);
464 
465       sizeOK = st_TestProxyTexImage(ctx, target, levels, 0, texFormat,
466                                     1, width, height, depth);
467    }
468 
469    if (_mesa_is_proxy_texture(target)) {
470       if (dimensionsOK && sizeOK) {
471          initialize_texture_fields(ctx, texObj, levels, width, height, depth,
472                                    internalformat, texFormat);
473       }
474       else {
475          /* clear all image fields for [levels] */
476          clear_texture_fields(ctx, texObj);
477       }
478    }
479    else {
480       if (!no_error) {
481          if (!dimensionsOK) {
482             _mesa_error(ctx, GL_INVALID_VALUE,
483                         "glTex%sStorage%uD(invalid width, height or depth)",
484                         suffix, dims);
485             return;
486          }
487 
488          if (!sizeOK) {
489             _mesa_error(ctx, GL_OUT_OF_MEMORY,
490                         "glTex%sStorage%uD(texture too large)",
491                         suffix, dims);
492             return;
493          }
494 
495          if (texObj->IsSparse) {
496             char func[32];
497             snprintf(func, 32, "glTex%sStorage%uD", suffix, dims);
498             if (_mesa_sparse_texture_error_check(ctx, dims, texObj, texFormat, target,
499                                                  levels, width, height, depth, func))
500                return; /* error was recorded */
501          }
502       }
503 
504       assert(levels > 0);
505       assert(width > 0);
506       assert(height > 0);
507       assert(depth > 0);
508 
509       if (!initialize_texture_fields(ctx, texObj, levels, width, height, depth,
510                                      internalformat, texFormat)) {
511          return;
512       }
513 
514       /* Setup the backing memory */
515       if (memObj) {
516          if (!st_SetTextureStorageForMemoryObject(ctx, texObj, memObj,
517                                                   levels,
518                                                   width, height, depth,
519                                                   offset)) {
520 
521             clear_texture_fields(ctx, texObj);
522             return;
523          }
524       }
525       else {
526          if (!st_AllocTextureStorage(ctx, texObj, levels,
527                                      width, height, depth)) {
528             /* Reset the texture images' info to zeros.
529              * Strictly speaking, we probably don't have to do this since
530              * generating GL_OUT_OF_MEMORY can leave things in an undefined
531              * state but this puts things in a consistent state.
532              */
533             clear_texture_fields(ctx, texObj);
534             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex%sStorage%uD",
535                         suffix, dims);
536             return;
537          }
538       }
539 
540       _mesa_set_texture_view_state(ctx, texObj, target, levels);
541 
542       update_fbo_texture(ctx, texObj);
543    }
544 }
545 
546 
547 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)548 texture_storage_error(struct gl_context *ctx, GLuint dims,
549                       struct gl_texture_object *texObj,
550                       GLenum target, GLsizei levels,
551                       GLenum internalformat, GLsizei width,
552                       GLsizei height, GLsizei depth, bool dsa)
553 {
554    texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat,
555                    width, height, depth, dsa, 0, false);
556 }
557 
558 
559 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)560 texture_storage_no_error(struct gl_context *ctx, GLuint dims,
561                          struct gl_texture_object *texObj,
562                          GLenum target, GLsizei levels,
563                          GLenum internalformat, GLsizei width,
564                          GLsizei height, GLsizei depth, bool dsa)
565 {
566    texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat,
567                    width, height, depth, dsa, 0, true);
568 }
569 
570 
571 /**
572  * Helper used by _mesa_TexStorage1/2/3D().
573  */
574 static void
texstorage_error(GLuint dims,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,const char * caller)575 texstorage_error(GLuint dims, GLenum target, GLsizei levels,
576                  GLenum internalformat, GLsizei width, GLsizei height,
577                  GLsizei depth, const char *caller)
578 {
579    struct gl_texture_object *texObj;
580    GET_CURRENT_CONTEXT(ctx);
581 
582    /* Check target.  This is done here so that texture_storage
583     * can receive unsized formats.
584     */
585    if (!_mesa_is_legal_tex_storage_target(ctx, dims, target)) {
586       _mesa_error(ctx, GL_INVALID_ENUM,
587                   "%s(illegal target=%s)",
588                   caller, _mesa_enum_to_string(target));
589       return;
590    }
591 
592    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
593       _mesa_debug(ctx, "%s %s %d %s %d %d %d\n", caller,
594                   _mesa_enum_to_string(target), levels,
595                   _mesa_enum_to_string(internalformat),
596                   width, height, depth);
597 
598    /* Check the format to make sure it is sized. */
599    if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
600       _mesa_error(ctx, GL_INVALID_ENUM,
601                   "%s(internalformat = %s)", caller,
602                   _mesa_enum_to_string(internalformat));
603       return;
604    }
605 
606    texObj = _mesa_get_current_tex_object(ctx, target);
607    if (!texObj)
608       return;
609 
610    texture_storage_error(ctx, dims, texObj, target, levels,
611                          internalformat, width, height, depth, false);
612 }
613 
614 
615 static void
texstorage_no_error(GLuint dims,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)616 texstorage_no_error(GLuint dims, GLenum target, GLsizei levels,
617                     GLenum internalformat, GLsizei width, GLsizei height,
618                     GLsizei depth)
619 {
620    GET_CURRENT_CONTEXT(ctx);
621 
622    struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target);
623    texture_storage_no_error(ctx, dims, texObj, target, levels,
624                             internalformat, width, height, depth, false);
625 }
626 
627 
628 /**
629  * Helper used by _mesa_TextureStorage1/2/3D().
630  */
631 static void
texturestorage_error(GLuint dims,GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,const char * caller)632 texturestorage_error(GLuint dims, GLuint texture, GLsizei levels,
633                      GLenum internalformat, GLsizei width, GLsizei height,
634                      GLsizei depth, const char *caller)
635 {
636    struct gl_texture_object *texObj;
637    GET_CURRENT_CONTEXT(ctx);
638 
639    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
640       _mesa_debug(ctx, "%s %d %d %s %d %d %d\n",
641                   caller, texture, levels,
642                   _mesa_enum_to_string(internalformat),
643                   width, height, depth);
644 
645    /* Check the format to make sure it is sized. */
646    if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
647       _mesa_error(ctx, GL_INVALID_ENUM,
648                   "%s(internalformat = %s)", caller,
649                   _mesa_enum_to_string(internalformat));
650       return;
651    }
652 
653    texObj = _mesa_lookup_texture_err(ctx, texture, caller);
654    if (!texObj)
655       return;
656 
657    /* Check target.  This is done here so that texture_storage
658     * can receive unsized formats.
659     */
660    if (!_mesa_is_legal_tex_storage_target(ctx, dims, texObj->Target)) {
661       _mesa_error(ctx, GL_INVALID_OPERATION,
662                   "%s(illegal target=%s)", caller,
663                   _mesa_enum_to_string(texObj->Target));
664       return;
665    }
666 
667    texture_storage_error(ctx, dims, texObj, texObj->Target,
668                          levels, internalformat, width, height, depth, true);
669 }
670 
671 
672 static void
texturestorage_no_error(GLuint dims,GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)673 texturestorage_no_error(GLuint dims, GLuint texture, GLsizei levels,
674                         GLenum internalformat, GLsizei width, GLsizei height,
675                         GLsizei depth)
676 {
677    GET_CURRENT_CONTEXT(ctx);
678 
679    struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture);
680    texture_storage_no_error(ctx, dims, texObj, texObj->Target,
681                             levels, internalformat, width, height, depth, true);
682 }
683 
684 
685 void GLAPIENTRY
_mesa_TexStorage1D_no_error(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)686 _mesa_TexStorage1D_no_error(GLenum target, GLsizei levels,
687                             GLenum internalformat, GLsizei width)
688 {
689    texstorage_no_error(1, target, levels, internalformat, width, 1, 1);
690 }
691 
692 
693 void GLAPIENTRY
_mesa_TexStorage1D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)694 _mesa_TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat,
695                    GLsizei width)
696 {
697    texstorage_error(1, target, levels, internalformat, width, 1, 1,
698                     "glTexStorage1D");
699 }
700 
701 
702 void GLAPIENTRY
_mesa_TexStorage2D_no_error(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)703 _mesa_TexStorage2D_no_error(GLenum target, GLsizei levels,
704                             GLenum internalformat, GLsizei width,
705                             GLsizei height)
706 {
707    texstorage_no_error(2, target, levels, internalformat, width, height, 1);
708 }
709 
710 
711 void GLAPIENTRY
_mesa_TexStorage2D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)712 _mesa_TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat,
713                    GLsizei width, GLsizei height)
714 {
715    texstorage_error(2, target, levels, internalformat, width, height, 1,
716                     "glTexStorage2D");
717 }
718 
719 
720 void GLAPIENTRY
_mesa_TexStorage3D_no_error(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)721 _mesa_TexStorage3D_no_error(GLenum target, GLsizei levels,
722                             GLenum internalformat, GLsizei width,
723                             GLsizei height, GLsizei depth)
724 {
725    texstorage_no_error(3, target, levels, internalformat, width, height, depth);
726 }
727 
728 
729 void GLAPIENTRY
_mesa_TexStorage3D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)730 _mesa_TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
731                    GLsizei width, GLsizei height, GLsizei depth)
732 {
733    texstorage_error(3, target, levels, internalformat, width, height, depth,
734                     "glTexStorage3D");
735 }
736 
737 
738 void GLAPIENTRY
_mesa_TextureStorage1D_no_error(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width)739 _mesa_TextureStorage1D_no_error(GLuint texture, GLsizei levels,
740                                 GLenum internalformat, GLsizei width)
741 {
742    texturestorage_no_error(1, texture, levels, internalformat, width, 1, 1);
743 }
744 
745 
746 void GLAPIENTRY
_mesa_TextureStorage1D(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width)747 _mesa_TextureStorage1D(GLuint texture, GLsizei levels, GLenum internalformat,
748                        GLsizei width)
749 {
750    texturestorage_error(1, texture, levels, internalformat, width, 1, 1,
751                         "glTextureStorage1D");
752 }
753 
754 
755 void GLAPIENTRY
_mesa_TextureStorage2D_no_error(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)756 _mesa_TextureStorage2D_no_error(GLuint texture, GLsizei levels,
757                                 GLenum internalformat,
758                                 GLsizei width, GLsizei height)
759 {
760    texturestorage_no_error(2, texture, levels, internalformat, width, height, 1);
761 }
762 
763 
764 void GLAPIENTRY
_mesa_TextureStorage2D(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)765 _mesa_TextureStorage2D(GLuint texture, GLsizei levels,
766                        GLenum internalformat,
767                        GLsizei width, GLsizei height)
768 {
769    texturestorage_error(2, texture, levels, internalformat, width, height, 1,
770                         "glTextureStorage2D");
771 }
772 
773 
774 void GLAPIENTRY
_mesa_TextureStorage3D_no_error(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)775 _mesa_TextureStorage3D_no_error(GLuint texture, GLsizei levels,
776                                 GLenum internalformat, GLsizei width,
777                                 GLsizei height, GLsizei depth)
778 {
779    texturestorage_no_error(3, texture, levels, internalformat, width, height,
780                            depth);
781 }
782 
783 
784 void GLAPIENTRY
_mesa_TextureStorage3D(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)785 _mesa_TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat,
786                        GLsizei width, GLsizei height, GLsizei depth)
787 {
788    texturestorage_error(3, texture, levels, internalformat, width, height, depth,
789                         "glTextureStorage3D");
790 }
791 
792 
793 void GLAPIENTRY
_mesa_TextureStorage1DEXT(GLuint texture,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)794 _mesa_TextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels,
795                           GLenum internalformat,
796                           GLsizei width)
797 {
798    GET_CURRENT_CONTEXT(ctx);
799    /* 'texture' must always be initialized, even if the call to
800     * glTextureStorage1DEXT will generate an error.
801     */
802    if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
803                                        "glTextureStorage1DEXT"))
804       return;
805    texturestorage_error(1, texture, levels, internalformat, width, 1, 1,
806                         "glTextureStorage1DEXT");
807 }
808 
809 
810 void GLAPIENTRY
_mesa_TextureStorage2DEXT(GLuint texture,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)811 _mesa_TextureStorage2DEXT(GLuint texture, GLenum target, GLsizei levels,
812                           GLenum internalformat,
813                           GLsizei width, GLsizei height)
814 {
815    GET_CURRENT_CONTEXT(ctx);
816    /* 'texture' must always be initialized, even if the call to
817     * glTextureStorage2DEXT will generate an error.
818     */
819    if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
820                                        "glTextureStorage2DEXT"))
821       return;
822    texturestorage_error(2, texture, levels, internalformat, width, height, 1,
823                         "glTextureStorage2DEXT");
824 }
825 
826 
827 void GLAPIENTRY
_mesa_TextureStorage3DEXT(GLuint texture,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)828 _mesa_TextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels,
829                           GLenum internalformat,
830                           GLsizei width, GLsizei height, GLsizei depth)
831 {
832    GET_CURRENT_CONTEXT(ctx);
833    /* 'texture' must always be initialized, even if the call to
834     * glTextureStorage3DEXT will generate an error.
835     */
836    if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
837                                        "glTextureStorage3DEXT"))
838       return;
839    texturestorage_error(3, texture, levels, internalformat, width, height, depth,
840                         "glTextureStorage3DEXT");
841 }
842 
843 
844 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)845 _mesa_texture_storage_memory(struct gl_context *ctx, GLuint dims,
846                              struct gl_texture_object *texObj,
847                              struct gl_memory_object *memObj,
848                              GLenum target, GLsizei levels,
849                              GLenum internalformat, GLsizei width,
850                              GLsizei height, GLsizei depth,
851                              GLuint64 offset, bool dsa)
852 {
853    assert(memObj);
854 
855    texture_storage(ctx, dims, texObj, memObj, target, levels, internalformat,
856                    width, height, depth, offset, dsa, false);
857 }
858