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