xref: /third_party/mesa3d/src/mesa/main/texstorage.c (revision bf215546)
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 */
53bool
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 */
126static struct gl_texture_image *
127get_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
140static GLboolean
141initialize_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 */
180static void
181clear_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 */
208static void
209update_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
219GLboolean
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 */
270static GLboolean
271tex_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
352GLboolean
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
426exceed_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 */
435static ALWAYS_INLINE void
436texture_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
547static void
548texture_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
559static void
560texture_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 */
574static void
575texstorage_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
615static void
616texstorage_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 */
631static void
632texturestorage_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
672static void
673texturestorage_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
685void GLAPIENTRY
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
693void GLAPIENTRY
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
702void GLAPIENTRY
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
711void GLAPIENTRY
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
720void GLAPIENTRY
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
729void GLAPIENTRY
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
738void GLAPIENTRY
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
746void GLAPIENTRY
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
755void GLAPIENTRY
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
764void GLAPIENTRY
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
774void GLAPIENTRY
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
784void GLAPIENTRY
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
793void GLAPIENTRY
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
810void GLAPIENTRY
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
827void GLAPIENTRY
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
844void
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