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
44
45/**
46 * Check if the given texture target is a legal texture object target
47 * for a glTexStorage() command.
48 * This is a bit different than legal_teximage_target() when it comes
49 * to cube maps.
50 */
51static bool
52legal_texobj_target(const struct gl_context *ctx, GLuint dims, GLenum target)
53{
54   if (dims < 1 || dims > 3) {
55      _mesa_problem(ctx, "invalid dims=%u in legal_texobj_target()", dims);
56      return false;
57   }
58
59   switch (dims) {
60   case 2:
61      switch (target) {
62      case GL_TEXTURE_2D:
63         return true;
64      case GL_TEXTURE_CUBE_MAP:
65         return ctx->Extensions.ARB_texture_cube_map;
66      }
67      break;
68   case 3:
69      switch (target) {
70      case GL_TEXTURE_3D:
71         return true;
72      case GL_TEXTURE_2D_ARRAY:
73         return ctx->Extensions.EXT_texture_array;
74      case GL_TEXTURE_CUBE_MAP_ARRAY:
75         return _mesa_has_texture_cube_map_array(ctx);
76      }
77      break;
78   }
79
80   if (!_mesa_is_desktop_gl(ctx))
81      return false;
82
83   switch (dims) {
84   case 1:
85      switch (target) {
86      case GL_TEXTURE_1D:
87      case GL_PROXY_TEXTURE_1D:
88         return true;
89      default:
90         return false;
91      }
92   case 2:
93      switch (target) {
94      case GL_PROXY_TEXTURE_2D:
95         return true;
96      case GL_PROXY_TEXTURE_CUBE_MAP:
97         return ctx->Extensions.ARB_texture_cube_map;
98      case GL_TEXTURE_RECTANGLE:
99      case GL_PROXY_TEXTURE_RECTANGLE:
100         return ctx->Extensions.NV_texture_rectangle;
101      case GL_TEXTURE_1D_ARRAY:
102      case GL_PROXY_TEXTURE_1D_ARRAY:
103         return ctx->Extensions.EXT_texture_array;
104      default:
105         return false;
106      }
107   case 3:
108      switch (target) {
109      case GL_PROXY_TEXTURE_3D:
110         return true;
111      case GL_PROXY_TEXTURE_2D_ARRAY:
112         return ctx->Extensions.EXT_texture_array;
113      case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
114         return ctx->Extensions.ARB_texture_cube_map_array;
115      default:
116         return false;
117      }
118   default:
119      unreachable("impossible dimensions");
120   }
121}
122
123
124/** Helper to get a particular texture image in a texture object */
125static struct gl_texture_image *
126get_tex_image(struct gl_context *ctx,
127              struct gl_texture_object *texObj,
128              GLuint face, GLuint level)
129{
130   const GLenum faceTarget =
131      (texObj->Target == GL_TEXTURE_CUBE_MAP ||
132       texObj->Target == GL_PROXY_TEXTURE_CUBE_MAP)
133      ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : texObj->Target;
134   return _mesa_get_tex_image(ctx, texObj, faceTarget, level);
135}
136
137
138
139static GLboolean
140initialize_texture_fields(struct gl_context *ctx,
141                          struct gl_texture_object *texObj,
142                          GLint levels,
143                          GLsizei width, GLsizei height, GLsizei depth,
144                          GLenum internalFormat, mesa_format texFormat)
145{
146   const GLenum target = texObj->Target;
147   const GLuint numFaces = _mesa_num_tex_faces(target);
148   GLint level, levelWidth = width, levelHeight = height, levelDepth = depth;
149   GLuint face;
150
151   /* Set up all the texture object's gl_texture_images */
152   for (level = 0; level < levels; level++) {
153      for (face = 0; face < numFaces; face++) {
154         struct gl_texture_image *texImage =
155            get_tex_image(ctx, texObj, face, level);
156
157	 if (!texImage) {
158	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
159            return GL_FALSE;
160	 }
161
162         _mesa_init_teximage_fields(ctx, texImage,
163                                    levelWidth, levelHeight, levelDepth,
164                                    0, internalFormat, texFormat);
165      }
166
167      _mesa_next_mipmap_level_size(target, 0,
168                                   levelWidth, levelHeight, levelDepth,
169                                   &levelWidth, &levelHeight, &levelDepth);
170   }
171   return GL_TRUE;
172}
173
174
175/**
176 * Clear all fields of texture object to zeros.  Used for proxy texture tests
177 * and to clean up when a texture memory allocation fails.
178 */
179static void
180clear_texture_fields(struct gl_context *ctx,
181                     struct gl_texture_object *texObj)
182{
183   const GLenum target = texObj->Target;
184   const GLuint numFaces = _mesa_num_tex_faces(target);
185   GLint level;
186   GLuint face;
187
188   for (level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
189      for (face = 0; face < numFaces; face++) {
190         struct gl_texture_image *texImage =
191            get_tex_image(ctx, texObj, face, level);
192
193	 if (!texImage) {
194	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
195            return;
196	 }
197
198         _mesa_clear_texture_image(ctx, texImage);
199      }
200   }
201}
202
203
204/**
205 * Update/re-validate framebuffer object.
206 */
207static void
208update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
209{
210   const unsigned numFaces = _mesa_num_tex_faces(texObj->Target);
211   for (int level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
212      for (unsigned face = 0; face < numFaces; face++)
213         _mesa_update_fbo_texture(ctx, texObj, face, level);
214   }
215}
216
217
218GLboolean
219_mesa_is_legal_tex_storage_format(const struct gl_context *ctx,
220                                  GLenum internalformat)
221{
222   /* check internal format - note that only sized formats are allowed */
223   switch (internalformat) {
224   case GL_ALPHA:
225   case GL_LUMINANCE:
226   case GL_LUMINANCE_ALPHA:
227   case GL_INTENSITY:
228   case GL_RED:
229   case GL_RG:
230   case GL_RGB:
231   case GL_RGBA:
232   case GL_BGRA:
233   case GL_DEPTH_COMPONENT:
234   case GL_DEPTH_STENCIL:
235   case GL_COMPRESSED_ALPHA:
236   case GL_COMPRESSED_LUMINANCE_ALPHA:
237   case GL_COMPRESSED_LUMINANCE:
238   case GL_COMPRESSED_INTENSITY:
239   case GL_COMPRESSED_RGB:
240   case GL_COMPRESSED_RGBA:
241   case GL_COMPRESSED_SRGB:
242   case GL_COMPRESSED_SRGB_ALPHA:
243   case GL_COMPRESSED_SLUMINANCE:
244   case GL_COMPRESSED_SLUMINANCE_ALPHA:
245   case GL_RED_INTEGER:
246   case GL_GREEN_INTEGER:
247   case GL_BLUE_INTEGER:
248   case GL_ALPHA_INTEGER:
249   case GL_RGB_INTEGER:
250   case GL_RGBA_INTEGER:
251   case GL_BGR_INTEGER:
252   case GL_BGRA_INTEGER:
253   case GL_LUMINANCE_INTEGER_EXT:
254   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
255      /* these unsized formats are illegal */
256      return GL_FALSE;
257   default:
258      return _mesa_base_tex_format(ctx, internalformat) > 0;
259   }
260}
261
262
263/**
264 * Default ctx->Driver.AllocTextureStorage() handler.
265 *
266 * The driver can override this with a more specific implementation if it
267 * desires, but this can be used to get the texture images allocated using the
268 * usual texture image handling code.  The immutability of
269 * GL_ARB_texture_storage texture layouts is handled by texObj->Immutable
270 * checks at glTexImage* time.
271 */
272GLboolean
273_mesa_AllocTextureStorage_sw(struct gl_context *ctx,
274                             struct gl_texture_object *texObj,
275                             GLsizei levels, GLsizei width,
276                             GLsizei height, GLsizei depth)
277{
278   const int numFaces = _mesa_num_tex_faces(texObj->Target);
279   int face;
280   int level;
281
282   (void) width;
283   (void) height;
284   (void) depth;
285
286   for (face = 0; face < numFaces; face++) {
287      for (level = 0; level < levels; level++) {
288         struct gl_texture_image *const texImage = texObj->Image[face][level];
289         if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage))
290            return GL_FALSE;
291      }
292   }
293
294   return GL_TRUE;
295}
296
297
298/**
299 * Do error checking for calls to glTexStorage1/2/3D().
300 * If an error is found, record it with _mesa_error(), unless the target
301 * is a proxy texture.
302 * \return GL_TRUE if any error, GL_FALSE otherwise.
303 */
304static GLboolean
305tex_storage_error_check(struct gl_context *ctx,
306                        struct gl_texture_object *texObj,
307                        struct gl_memory_object *memObj,
308                        GLuint dims, GLenum target,
309                        GLsizei levels, GLenum internalformat,
310                        GLsizei width, GLsizei height, GLsizei depth,
311                        bool dsa)
312{
313   const char* suffix = dsa ? (memObj ? "tureMem" : "ture") :
314                              (memObj ? "Mem" : "");
315
316   /* Legal format checking has been moved to texstorage and texturestorage in
317    * order to allow meta functions to use legacy formats. */
318
319   /* size check */
320   if (!_mesa_valid_tex_storage_dim(width, height, depth)) {
321      _mesa_error(ctx, GL_INVALID_VALUE,
322                  "glTex%sStorage%uD(width, height or depth < 1)",
323                  suffix, dims);
324      return GL_TRUE;
325   }
326
327   if (_mesa_is_compressed_format(ctx, internalformat)) {
328      GLenum err;
329      if (!_mesa_target_can_be_compressed(ctx, target, internalformat, &err)) {
330         _mesa_error(ctx, err,
331                  "glTex%sStorage%dD(internalformat = %s)", suffix, dims,
332                  _mesa_enum_to_string(internalformat));
333         return GL_TRUE;
334      }
335   }
336
337   /* levels check */
338   if (levels < 1) {
339      _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(levels < 1)",
340                  suffix, dims);
341      return GL_TRUE;
342   }
343
344   /* check levels against maximum (note different error than above) */
345   if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) {
346      _mesa_error(ctx, GL_INVALID_OPERATION,
347                  "glTex%sStorage%uD(levels too large)",
348                  suffix, dims);
349      return GL_TRUE;
350   }
351
352   /* check levels against width/height/depth */
353   if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) {
354      _mesa_error(ctx, GL_INVALID_OPERATION,
355                  "glTex%sStorage%uD(too many levels"
356                  " for max texture dimension)",
357                  suffix, dims);
358      return GL_TRUE;
359   }
360
361   /* non-default texture object check */
362   if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) {
363      _mesa_error(ctx, GL_INVALID_OPERATION,
364                  "glTex%sStorage%uD(texture object 0)",
365                  suffix, dims);
366      return GL_TRUE;
367   }
368
369   /* Check if texObj->Immutable is set */
370   if (!_mesa_is_proxy_texture(target) && texObj->Immutable) {
371      _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(immutable)",
372                  suffix, dims);
373      return GL_TRUE;
374   }
375
376   /* additional checks for depth textures */
377   if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat)) {
378      _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(bad target for texture)",
379                  suffix, dims);
380      return GL_TRUE;
381   }
382
383   return GL_FALSE;
384}
385
386
387/**
388 * Helper that does the storage allocation for _mesa_TexStorage1/2/3D()
389 * and _mesa_TextureStorage1/2/3D().
390 */
391static ALWAYS_INLINE void
392texture_storage(struct gl_context *ctx, GLuint dims,
393                struct gl_texture_object *texObj,
394                struct gl_memory_object *memObj, GLenum target,
395                GLsizei levels, GLenum internalformat, GLsizei width,
396                GLsizei height, GLsizei depth, GLuint64 offset, bool dsa,
397                bool no_error)
398{
399   GLboolean sizeOK = GL_TRUE, dimensionsOK = GL_TRUE;
400   mesa_format texFormat;
401   const char* suffix = dsa ? (memObj ? "tureMem" : "ture") :
402                              (memObj ? "Mem" : "");
403
404   assert(texObj);
405
406   if (!no_error) {
407      if (tex_storage_error_check(ctx, texObj, memObj, dims, target, levels,
408                                  internalformat, width, height, depth, dsa)) {
409         return; /* error was recorded */
410      }
411   }
412
413   texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0,
414                                           internalformat, GL_NONE, GL_NONE);
415
416   if (!no_error) {
417      /* check that width, height, depth are legal for the mipmap level */
418      dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0,
419                                                     width, height, depth, 0);
420
421      sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, levels, 0, texFormat,
422                                             1, width, height, depth);
423   }
424
425   if (_mesa_is_proxy_texture(target)) {
426      if (dimensionsOK && sizeOK) {
427         initialize_texture_fields(ctx, texObj, levels, width, height, depth,
428                                   internalformat, texFormat);
429      }
430      else {
431         /* clear all image fields for [levels] */
432         clear_texture_fields(ctx, texObj);
433      }
434   }
435   else {
436      if (!no_error) {
437         if (!dimensionsOK) {
438            _mesa_error(ctx, GL_INVALID_VALUE,
439                        "glTex%sStorage%uD(invalid width, height or depth)",
440                        suffix, dims);
441            return;
442         }
443
444         if (!sizeOK) {
445            _mesa_error(ctx, GL_OUT_OF_MEMORY,
446                        "glTex%sStorage%uD(texture too large)",
447                        suffix, dims);
448            return;
449         }
450      }
451
452      assert(levels > 0);
453      assert(width > 0);
454      assert(height > 0);
455      assert(depth > 0);
456
457      if (!initialize_texture_fields(ctx, texObj, levels, width, height, depth,
458                                     internalformat, texFormat)) {
459         return;
460      }
461
462      /* Setup the backing memory */
463      if (memObj) {
464         if (!ctx->Driver.SetTextureStorageForMemoryObject(ctx, texObj, memObj,
465                                                           levels,
466                                                           width, height, depth,
467                                                           offset)) {
468
469            clear_texture_fields(ctx, texObj);
470            return;
471         }
472      }
473      else {
474         if (!ctx->Driver.AllocTextureStorage(ctx, texObj, levels,
475                                              width, height, depth)) {
476            /* Reset the texture images' info to zeros.
477             * Strictly speaking, we probably don't have to do this since
478             * generating GL_OUT_OF_MEMORY can leave things in an undefined
479             * state but this puts things in a consistent state.
480             */
481            clear_texture_fields(ctx, texObj);
482            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex%sStorage%uD",
483                        suffix, dims);
484            return;
485         }
486      }
487
488      _mesa_set_texture_view_state(ctx, texObj, target, levels);
489
490      update_fbo_texture(ctx, texObj);
491   }
492}
493
494
495static void
496texture_storage_error(struct gl_context *ctx, GLuint dims,
497                      struct gl_texture_object *texObj,
498                      GLenum target, GLsizei levels,
499                      GLenum internalformat, GLsizei width,
500                      GLsizei height, GLsizei depth, bool dsa)
501{
502   texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat,
503                   width, height, depth, dsa, 0, false);
504}
505
506
507static void
508texture_storage_no_error(struct gl_context *ctx, GLuint dims,
509                         struct gl_texture_object *texObj,
510                         GLenum target, GLsizei levels,
511                         GLenum internalformat, GLsizei width,
512                         GLsizei height, GLsizei depth, bool dsa)
513{
514   texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat,
515                   width, height, depth, dsa, 0, true);
516}
517
518
519/**
520 * Helper used by _mesa_TexStorage1/2/3D().
521 */
522static void
523texstorage_error(GLuint dims, GLenum target, GLsizei levels,
524                 GLenum internalformat, GLsizei width, GLsizei height,
525                 GLsizei depth, const char *caller)
526{
527   struct gl_texture_object *texObj;
528   GET_CURRENT_CONTEXT(ctx);
529
530   /* Check target.  This is done here so that texture_storage
531    * can receive unsized formats.
532    */
533   if (!legal_texobj_target(ctx, dims, target)) {
534      _mesa_error(ctx, GL_INVALID_ENUM,
535                  "%s(illegal target=%s)",
536                  caller, _mesa_enum_to_string(target));
537      return;
538   }
539
540   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
541      _mesa_debug(ctx, "%s %s %d %s %d %d %d\n", caller,
542                  _mesa_enum_to_string(target), levels,
543                  _mesa_enum_to_string(internalformat),
544                  width, height, depth);
545
546   /* Check the format to make sure it is sized. */
547   if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
548      _mesa_error(ctx, GL_INVALID_ENUM,
549                  "%s(internalformat = %s)", caller,
550                  _mesa_enum_to_string(internalformat));
551      return;
552   }
553
554   texObj = _mesa_get_current_tex_object(ctx, target);
555   if (!texObj)
556      return;
557
558   texture_storage_error(ctx, dims, texObj, target, levels,
559                         internalformat, width, height, depth, false);
560}
561
562
563static void
564texstorage_no_error(GLuint dims, GLenum target, GLsizei levels,
565                    GLenum internalformat, GLsizei width, GLsizei height,
566                    GLsizei depth)
567{
568   GET_CURRENT_CONTEXT(ctx);
569
570   struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target);
571   texture_storage_no_error(ctx, dims, texObj, target, levels,
572                            internalformat, width, height, depth, false);
573}
574
575
576/**
577 * Helper used by _mesa_TextureStorage1/2/3D().
578 */
579static void
580texturestorage_error(GLuint dims, GLuint texture, GLsizei levels,
581                     GLenum internalformat, GLsizei width, GLsizei height,
582                     GLsizei depth, const char *caller)
583{
584   struct gl_texture_object *texObj;
585   GET_CURRENT_CONTEXT(ctx);
586
587   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
588      _mesa_debug(ctx, "%s %d %d %s %d %d %d\n",
589                  caller, texture, levels,
590                  _mesa_enum_to_string(internalformat),
591                  width, height, depth);
592
593   /* Check the format to make sure it is sized. */
594   if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
595      _mesa_error(ctx, GL_INVALID_ENUM,
596                  "%s(internalformat = %s)", caller,
597                  _mesa_enum_to_string(internalformat));
598      return;
599   }
600
601   texObj = _mesa_lookup_texture_err(ctx, texture, caller);
602   if (!texObj)
603      return;
604
605   /* Check target.  This is done here so that texture_storage
606    * can receive unsized formats.
607    */
608   if (!legal_texobj_target(ctx, dims, texObj->Target)) {
609      _mesa_error(ctx, GL_INVALID_OPERATION,
610                  "%s(illegal target=%s)", caller,
611                  _mesa_enum_to_string(texObj->Target));
612      return;
613   }
614
615   texture_storage_error(ctx, dims, texObj, texObj->Target,
616                         levels, internalformat, width, height, depth, true);
617}
618
619
620static void
621texturestorage_no_error(GLuint dims, GLuint texture, GLsizei levels,
622                        GLenum internalformat, GLsizei width, GLsizei height,
623                        GLsizei depth)
624{
625   GET_CURRENT_CONTEXT(ctx);
626
627   struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture);
628   texture_storage_no_error(ctx, dims, texObj, texObj->Target,
629                            levels, internalformat, width, height, depth, true);
630}
631
632
633void GLAPIENTRY
634_mesa_TexStorage1D_no_error(GLenum target, GLsizei levels,
635                            GLenum internalformat, GLsizei width)
636{
637   texstorage_no_error(1, target, levels, internalformat, width, 1, 1);
638}
639
640
641void GLAPIENTRY
642_mesa_TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat,
643                   GLsizei width)
644{
645   texstorage_error(1, target, levels, internalformat, width, 1, 1,
646                    "glTexStorage1D");
647}
648
649
650void GLAPIENTRY
651_mesa_TexStorage2D_no_error(GLenum target, GLsizei levels,
652                            GLenum internalformat, GLsizei width,
653                            GLsizei height)
654{
655   texstorage_no_error(2, target, levels, internalformat, width, height, 1);
656}
657
658
659void GLAPIENTRY
660_mesa_TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat,
661                   GLsizei width, GLsizei height)
662{
663   texstorage_error(2, target, levels, internalformat, width, height, 1,
664                    "glTexStorage2D");
665}
666
667
668void GLAPIENTRY
669_mesa_TexStorage3D_no_error(GLenum target, GLsizei levels,
670                            GLenum internalformat, GLsizei width,
671                            GLsizei height, GLsizei depth)
672{
673   texstorage_no_error(3, target, levels, internalformat, width, height, depth);
674}
675
676
677void GLAPIENTRY
678_mesa_TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
679                   GLsizei width, GLsizei height, GLsizei depth)
680{
681   texstorage_error(3, target, levels, internalformat, width, height, depth,
682                    "glTexStorage3D");
683}
684
685
686void GLAPIENTRY
687_mesa_TextureStorage1D_no_error(GLuint texture, GLsizei levels,
688                                GLenum internalformat, GLsizei width)
689{
690   texturestorage_no_error(1, texture, levels, internalformat, width, 1, 1);
691}
692
693
694void GLAPIENTRY
695_mesa_TextureStorage1D(GLuint texture, GLsizei levels, GLenum internalformat,
696                       GLsizei width)
697{
698   texturestorage_error(1, texture, levels, internalformat, width, 1, 1,
699                        "glTextureStorage1D");
700}
701
702
703void GLAPIENTRY
704_mesa_TextureStorage2D_no_error(GLuint texture, GLsizei levels,
705                                GLenum internalformat,
706                                GLsizei width, GLsizei height)
707{
708   texturestorage_no_error(2, texture, levels, internalformat, width, height, 1);
709}
710
711
712void GLAPIENTRY
713_mesa_TextureStorage2D(GLuint texture, GLsizei levels,
714                       GLenum internalformat,
715                       GLsizei width, GLsizei height)
716{
717   texturestorage_error(2, texture, levels, internalformat, width, height, 1,
718                        "glTextureStorage2D");
719}
720
721
722void GLAPIENTRY
723_mesa_TextureStorage3D_no_error(GLuint texture, GLsizei levels,
724                                GLenum internalformat, GLsizei width,
725                                GLsizei height, GLsizei depth)
726{
727   texturestorage_no_error(3, texture, levels, internalformat, width, height,
728                           depth);
729}
730
731
732void GLAPIENTRY
733_mesa_TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat,
734                       GLsizei width, GLsizei height, GLsizei depth)
735{
736   texturestorage_error(3, texture, levels, internalformat, width, height, depth,
737                        "glTextureStorage3D");
738}
739
740
741void GLAPIENTRY
742_mesa_TextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels,
743                          GLenum internalformat,
744                          GLsizei width)
745{
746   GET_CURRENT_CONTEXT(ctx);
747   /* 'texture' must always be initialized, even if the call to
748    * glTextureStorage1DEXT will generate an error.
749    */
750   if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
751                                       "glTextureStorage1DEXT"))
752      return;
753   texturestorage_error(1, texture, levels, internalformat, width, 1, 1,
754                        "glTextureStorage1DEXT");
755}
756
757
758void GLAPIENTRY
759_mesa_TextureStorage2DEXT(GLuint texture, GLenum target, GLsizei levels,
760                          GLenum internalformat,
761                          GLsizei width, GLsizei height)
762{
763   GET_CURRENT_CONTEXT(ctx);
764   /* 'texture' must always be initialized, even if the call to
765    * glTextureStorage2DEXT will generate an error.
766    */
767   if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
768                                       "glTextureStorage2DEXT"))
769      return;
770   texturestorage_error(2, texture, levels, internalformat, width, height, 1,
771                        "glTextureStorage2DEXT");
772}
773
774
775void GLAPIENTRY
776_mesa_TextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels,
777                          GLenum internalformat,
778                          GLsizei width, GLsizei height, GLsizei depth)
779{
780   GET_CURRENT_CONTEXT(ctx);
781   /* 'texture' must always be initialized, even if the call to
782    * glTextureStorage3DEXT will generate an error.
783    */
784   if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
785                                       "glTextureStorage3DEXT"))
786      return;
787   texturestorage_error(3, texture, levels, internalformat, width, height, depth,
788                        "glTextureStorage3DEXT");
789}
790
791
792void
793_mesa_texture_storage_memory(struct gl_context *ctx, GLuint dims,
794                             struct gl_texture_object *texObj,
795                             struct gl_memory_object *memObj,
796                             GLenum target, GLsizei levels,
797                             GLenum internalformat, GLsizei width,
798                             GLsizei height, GLsizei depth,
799                             GLuint64 offset, bool dsa)
800{
801   assert(memObj);
802
803   texture_storage(ctx, dims, texObj, memObj, target, levels, internalformat,
804                   width, height, depth, offset, dsa, false);
805}
806