1af69d88dSmrg/*
2af69d88dSmrg * Mesa 3-D graphics library
3af69d88dSmrg *
4af69d88dSmrg * Copyright (C) 2011  VMware, Inc.  All Rights Reserved.
5af69d88dSmrg *
6af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
7af69d88dSmrg * copy of this software and associated documentation files (the "Software"),
8af69d88dSmrg * to deal in the Software without restriction, including without limitation
9af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the
11af69d88dSmrg * Software is furnished to do so, subject to the following conditions:
12af69d88dSmrg *
13af69d88dSmrg * The above copyright notice and this permission notice shall be included
14af69d88dSmrg * in all copies or substantial portions of the Software.
15af69d88dSmrg *
16af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17af69d88dSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE.
23af69d88dSmrg */
24af69d88dSmrg
25af69d88dSmrg/**
26af69d88dSmrg * \file texstorage.c
27af69d88dSmrg * GL_ARB_texture_storage functions
28af69d88dSmrg */
29af69d88dSmrg
30af69d88dSmrg#include "glheader.h"
31af69d88dSmrg#include "context.h"
32af69d88dSmrg#include "enums.h"
337ec681f3Smrg
34af69d88dSmrg#include "macros.h"
35af69d88dSmrg#include "teximage.h"
36af69d88dSmrg#include "texobj.h"
37af69d88dSmrg#include "mipmap.h"
38af69d88dSmrg#include "texstorage.h"
39af69d88dSmrg#include "textureview.h"
40af69d88dSmrg#include "mtypes.h"
41af69d88dSmrg#include "glformats.h"
4201e04c3fSmrg#include "hash.h"
43af69d88dSmrg
44af69d88dSmrg
45af69d88dSmrg/**
46af69d88dSmrg * Check if the given texture target is a legal texture object target
47af69d88dSmrg * for a glTexStorage() command.
48af69d88dSmrg * This is a bit different than legal_teximage_target() when it comes
49af69d88dSmrg * to cube maps.
50af69d88dSmrg */
5101e04c3fSmrgstatic bool
5201e04c3fSmrglegal_texobj_target(const struct gl_context *ctx, GLuint dims, GLenum target)
53af69d88dSmrg{
5401e04c3fSmrg   if (dims < 1 || dims > 3) {
5501e04c3fSmrg      _mesa_problem(ctx, "invalid dims=%u in legal_texobj_target()", dims);
5601e04c3fSmrg      return false;
5701e04c3fSmrg   }
5801e04c3fSmrg
5901e04c3fSmrg   switch (dims) {
6001e04c3fSmrg   case 2:
6101e04c3fSmrg      switch (target) {
6201e04c3fSmrg      case GL_TEXTURE_2D:
6301e04c3fSmrg         return true;
6401e04c3fSmrg      case GL_TEXTURE_CUBE_MAP:
6501e04c3fSmrg         return ctx->Extensions.ARB_texture_cube_map;
6601e04c3fSmrg      }
6701e04c3fSmrg      break;
6801e04c3fSmrg   case 3:
6901e04c3fSmrg      switch (target) {
7001e04c3fSmrg      case GL_TEXTURE_3D:
7101e04c3fSmrg         return true;
7201e04c3fSmrg      case GL_TEXTURE_2D_ARRAY:
7301e04c3fSmrg         return ctx->Extensions.EXT_texture_array;
7401e04c3fSmrg      case GL_TEXTURE_CUBE_MAP_ARRAY:
7501e04c3fSmrg         return _mesa_has_texture_cube_map_array(ctx);
7601e04c3fSmrg      }
7701e04c3fSmrg      break;
7801e04c3fSmrg   }
7901e04c3fSmrg
8001e04c3fSmrg   if (!_mesa_is_desktop_gl(ctx))
8101e04c3fSmrg      return false;
82af69d88dSmrg
83af69d88dSmrg   switch (dims) {
84af69d88dSmrg   case 1:
85af69d88dSmrg      switch (target) {
86af69d88dSmrg      case GL_TEXTURE_1D:
87af69d88dSmrg      case GL_PROXY_TEXTURE_1D:
8801e04c3fSmrg         return true;
89af69d88dSmrg      default:
9001e04c3fSmrg         return false;
91af69d88dSmrg      }
92af69d88dSmrg   case 2:
93af69d88dSmrg      switch (target) {
94af69d88dSmrg      case GL_PROXY_TEXTURE_2D:
9501e04c3fSmrg         return true;
96af69d88dSmrg      case GL_PROXY_TEXTURE_CUBE_MAP:
97af69d88dSmrg         return ctx->Extensions.ARB_texture_cube_map;
98af69d88dSmrg      case GL_TEXTURE_RECTANGLE:
99af69d88dSmrg      case GL_PROXY_TEXTURE_RECTANGLE:
100af69d88dSmrg         return ctx->Extensions.NV_texture_rectangle;
101af69d88dSmrg      case GL_TEXTURE_1D_ARRAY:
102af69d88dSmrg      case GL_PROXY_TEXTURE_1D_ARRAY:
103af69d88dSmrg         return ctx->Extensions.EXT_texture_array;
104af69d88dSmrg      default:
10501e04c3fSmrg         return false;
106af69d88dSmrg      }
107af69d88dSmrg   case 3:
108af69d88dSmrg      switch (target) {
109af69d88dSmrg      case GL_PROXY_TEXTURE_3D:
11001e04c3fSmrg         return true;
111af69d88dSmrg      case GL_PROXY_TEXTURE_2D_ARRAY:
112af69d88dSmrg         return ctx->Extensions.EXT_texture_array;
113af69d88dSmrg      case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
114af69d88dSmrg         return ctx->Extensions.ARB_texture_cube_map_array;
115af69d88dSmrg      default:
11601e04c3fSmrg         return false;
117af69d88dSmrg      }
118af69d88dSmrg   default:
11901e04c3fSmrg      unreachable("impossible dimensions");
120af69d88dSmrg   }
121af69d88dSmrg}
122af69d88dSmrg
123af69d88dSmrg
124af69d88dSmrg/** Helper to get a particular texture image in a texture object */
125af69d88dSmrgstatic struct gl_texture_image *
12601e04c3fSmrgget_tex_image(struct gl_context *ctx,
127af69d88dSmrg              struct gl_texture_object *texObj,
128af69d88dSmrg              GLuint face, GLuint level)
129af69d88dSmrg{
130af69d88dSmrg   const GLenum faceTarget =
131af69d88dSmrg      (texObj->Target == GL_TEXTURE_CUBE_MAP ||
132af69d88dSmrg       texObj->Target == GL_PROXY_TEXTURE_CUBE_MAP)
133af69d88dSmrg      ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : texObj->Target;
134af69d88dSmrg   return _mesa_get_tex_image(ctx, texObj, faceTarget, level);
135af69d88dSmrg}
136af69d88dSmrg
137af69d88dSmrg
138af69d88dSmrg
139af69d88dSmrgstatic GLboolean
140af69d88dSmrginitialize_texture_fields(struct gl_context *ctx,
141af69d88dSmrg                          struct gl_texture_object *texObj,
142af69d88dSmrg                          GLint levels,
143af69d88dSmrg                          GLsizei width, GLsizei height, GLsizei depth,
144af69d88dSmrg                          GLenum internalFormat, mesa_format texFormat)
145af69d88dSmrg{
146af69d88dSmrg   const GLenum target = texObj->Target;
147af69d88dSmrg   const GLuint numFaces = _mesa_num_tex_faces(target);
148af69d88dSmrg   GLint level, levelWidth = width, levelHeight = height, levelDepth = depth;
149af69d88dSmrg   GLuint face;
150af69d88dSmrg
151af69d88dSmrg   /* Set up all the texture object's gl_texture_images */
152af69d88dSmrg   for (level = 0; level < levels; level++) {
153af69d88dSmrg      for (face = 0; face < numFaces; face++) {
154af69d88dSmrg         struct gl_texture_image *texImage =
155af69d88dSmrg            get_tex_image(ctx, texObj, face, level);
156af69d88dSmrg
157af69d88dSmrg	 if (!texImage) {
158af69d88dSmrg	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
159af69d88dSmrg            return GL_FALSE;
160af69d88dSmrg	 }
161af69d88dSmrg
162af69d88dSmrg         _mesa_init_teximage_fields(ctx, texImage,
163af69d88dSmrg                                    levelWidth, levelHeight, levelDepth,
164af69d88dSmrg                                    0, internalFormat, texFormat);
165af69d88dSmrg      }
166af69d88dSmrg
16701e04c3fSmrg      _mesa_next_mipmap_level_size(target, 0,
16801e04c3fSmrg                                   levelWidth, levelHeight, levelDepth,
169af69d88dSmrg                                   &levelWidth, &levelHeight, &levelDepth);
170af69d88dSmrg   }
171af69d88dSmrg   return GL_TRUE;
172af69d88dSmrg}
173af69d88dSmrg
174af69d88dSmrg
175af69d88dSmrg/**
176af69d88dSmrg * Clear all fields of texture object to zeros.  Used for proxy texture tests
177af69d88dSmrg * and to clean up when a texture memory allocation fails.
178af69d88dSmrg */
179af69d88dSmrgstatic void
180af69d88dSmrgclear_texture_fields(struct gl_context *ctx,
181af69d88dSmrg                     struct gl_texture_object *texObj)
182af69d88dSmrg{
183af69d88dSmrg   const GLenum target = texObj->Target;
184af69d88dSmrg   const GLuint numFaces = _mesa_num_tex_faces(target);
185af69d88dSmrg   GLint level;
186af69d88dSmrg   GLuint face;
187af69d88dSmrg
18801e04c3fSmrg   for (level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
189af69d88dSmrg      for (face = 0; face < numFaces; face++) {
190af69d88dSmrg         struct gl_texture_image *texImage =
191af69d88dSmrg            get_tex_image(ctx, texObj, face, level);
192af69d88dSmrg
193af69d88dSmrg	 if (!texImage) {
194af69d88dSmrg	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
195af69d88dSmrg            return;
196af69d88dSmrg	 }
197af69d88dSmrg
19801e04c3fSmrg         _mesa_clear_texture_image(ctx, texImage);
199af69d88dSmrg      }
200af69d88dSmrg   }
201af69d88dSmrg}
202af69d88dSmrg
203af69d88dSmrg
20401e04c3fSmrg/**
20501e04c3fSmrg * Update/re-validate framebuffer object.
20601e04c3fSmrg */
20701e04c3fSmrgstatic void
20801e04c3fSmrgupdate_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
20901e04c3fSmrg{
21001e04c3fSmrg   const unsigned numFaces = _mesa_num_tex_faces(texObj->Target);
21101e04c3fSmrg   for (int level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
21201e04c3fSmrg      for (unsigned face = 0; face < numFaces; face++)
21301e04c3fSmrg         _mesa_update_fbo_texture(ctx, texObj, face, level);
21401e04c3fSmrg   }
21501e04c3fSmrg}
21601e04c3fSmrg
21701e04c3fSmrg
218af69d88dSmrgGLboolean
21901e04c3fSmrg_mesa_is_legal_tex_storage_format(const struct gl_context *ctx,
22001e04c3fSmrg                                  GLenum internalformat)
221af69d88dSmrg{
222af69d88dSmrg   /* check internal format - note that only sized formats are allowed */
223af69d88dSmrg   switch (internalformat) {
224af69d88dSmrg   case GL_ALPHA:
225af69d88dSmrg   case GL_LUMINANCE:
226af69d88dSmrg   case GL_LUMINANCE_ALPHA:
227af69d88dSmrg   case GL_INTENSITY:
228af69d88dSmrg   case GL_RED:
229af69d88dSmrg   case GL_RG:
230af69d88dSmrg   case GL_RGB:
231af69d88dSmrg   case GL_RGBA:
232af69d88dSmrg   case GL_BGRA:
233af69d88dSmrg   case GL_DEPTH_COMPONENT:
234af69d88dSmrg   case GL_DEPTH_STENCIL:
235af69d88dSmrg   case GL_COMPRESSED_ALPHA:
236af69d88dSmrg   case GL_COMPRESSED_LUMINANCE_ALPHA:
237af69d88dSmrg   case GL_COMPRESSED_LUMINANCE:
238af69d88dSmrg   case GL_COMPRESSED_INTENSITY:
239af69d88dSmrg   case GL_COMPRESSED_RGB:
240af69d88dSmrg   case GL_COMPRESSED_RGBA:
241af69d88dSmrg   case GL_COMPRESSED_SRGB:
242af69d88dSmrg   case GL_COMPRESSED_SRGB_ALPHA:
243af69d88dSmrg   case GL_COMPRESSED_SLUMINANCE:
244af69d88dSmrg   case GL_COMPRESSED_SLUMINANCE_ALPHA:
245af69d88dSmrg   case GL_RED_INTEGER:
246af69d88dSmrg   case GL_GREEN_INTEGER:
247af69d88dSmrg   case GL_BLUE_INTEGER:
248af69d88dSmrg   case GL_ALPHA_INTEGER:
249af69d88dSmrg   case GL_RGB_INTEGER:
250af69d88dSmrg   case GL_RGBA_INTEGER:
251af69d88dSmrg   case GL_BGR_INTEGER:
252af69d88dSmrg   case GL_BGRA_INTEGER:
253af69d88dSmrg   case GL_LUMINANCE_INTEGER_EXT:
254af69d88dSmrg   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
255af69d88dSmrg      /* these unsized formats are illegal */
256af69d88dSmrg      return GL_FALSE;
257af69d88dSmrg   default:
258af69d88dSmrg      return _mesa_base_tex_format(ctx, internalformat) > 0;
259af69d88dSmrg   }
260af69d88dSmrg}
261af69d88dSmrg
26201e04c3fSmrg
263af69d88dSmrg/**
264af69d88dSmrg * Default ctx->Driver.AllocTextureStorage() handler.
265af69d88dSmrg *
266af69d88dSmrg * The driver can override this with a more specific implementation if it
267af69d88dSmrg * desires, but this can be used to get the texture images allocated using the
268af69d88dSmrg * usual texture image handling code.  The immutability of
269af69d88dSmrg * GL_ARB_texture_storage texture layouts is handled by texObj->Immutable
270af69d88dSmrg * checks at glTexImage* time.
271af69d88dSmrg */
272af69d88dSmrgGLboolean
27301e04c3fSmrg_mesa_AllocTextureStorage_sw(struct gl_context *ctx,
27401e04c3fSmrg                             struct gl_texture_object *texObj,
27501e04c3fSmrg                             GLsizei levels, GLsizei width,
27601e04c3fSmrg                             GLsizei height, GLsizei depth)
277af69d88dSmrg{
278af69d88dSmrg   const int numFaces = _mesa_num_tex_faces(texObj->Target);
279af69d88dSmrg   int face;
280af69d88dSmrg   int level;
281af69d88dSmrg
282af69d88dSmrg   (void) width;
283af69d88dSmrg   (void) height;
284af69d88dSmrg   (void) depth;
285af69d88dSmrg
286af69d88dSmrg   for (face = 0; face < numFaces; face++) {
287af69d88dSmrg      for (level = 0; level < levels; level++) {
288af69d88dSmrg         struct gl_texture_image *const texImage = texObj->Image[face][level];
289af69d88dSmrg         if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage))
290af69d88dSmrg            return GL_FALSE;
291af69d88dSmrg      }
292af69d88dSmrg   }
293af69d88dSmrg
294af69d88dSmrg   return GL_TRUE;
295af69d88dSmrg}
296af69d88dSmrg
297af69d88dSmrg
298af69d88dSmrg/**
299af69d88dSmrg * Do error checking for calls to glTexStorage1/2/3D().
300af69d88dSmrg * If an error is found, record it with _mesa_error(), unless the target
301af69d88dSmrg * is a proxy texture.
302af69d88dSmrg * \return GL_TRUE if any error, GL_FALSE otherwise.
303af69d88dSmrg */
304af69d88dSmrgstatic GLboolean
30501e04c3fSmrgtex_storage_error_check(struct gl_context *ctx,
30601e04c3fSmrg                        struct gl_texture_object *texObj,
30701e04c3fSmrg                        struct gl_memory_object *memObj,
30801e04c3fSmrg                        GLuint dims, GLenum target,
309af69d88dSmrg                        GLsizei levels, GLenum internalformat,
31001e04c3fSmrg                        GLsizei width, GLsizei height, GLsizei depth,
31101e04c3fSmrg                        bool dsa)
312af69d88dSmrg{
31301e04c3fSmrg   const char* suffix = dsa ? (memObj ? "tureMem" : "ture") :
31401e04c3fSmrg                              (memObj ? "Mem" : "");
315af69d88dSmrg
31601e04c3fSmrg   /* Legal format checking has been moved to texstorage and texturestorage in
31701e04c3fSmrg    * order to allow meta functions to use legacy formats. */
318af69d88dSmrg
319af69d88dSmrg   /* size check */
32001e04c3fSmrg   if (!_mesa_valid_tex_storage_dim(width, height, depth)) {
321af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
32201e04c3fSmrg                  "glTex%sStorage%uD(width, height or depth < 1)",
32301e04c3fSmrg                  suffix, dims);
324af69d88dSmrg      return GL_TRUE;
325af69d88dSmrg   }
326af69d88dSmrg
32701e04c3fSmrg   if (_mesa_is_compressed_format(ctx, internalformat)) {
32801e04c3fSmrg      GLenum err;
32901e04c3fSmrg      if (!_mesa_target_can_be_compressed(ctx, target, internalformat, &err)) {
33001e04c3fSmrg         _mesa_error(ctx, err,
33101e04c3fSmrg                  "glTex%sStorage%dD(internalformat = %s)", suffix, dims,
33201e04c3fSmrg                  _mesa_enum_to_string(internalformat));
33301e04c3fSmrg         return GL_TRUE;
33401e04c3fSmrg      }
335af69d88dSmrg   }
336af69d88dSmrg
337af69d88dSmrg   /* levels check */
338af69d88dSmrg   if (levels < 1) {
33901e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(levels < 1)",
34001e04c3fSmrg                  suffix, dims);
341af69d88dSmrg      return GL_TRUE;
34201e04c3fSmrg   }
343af69d88dSmrg
344af69d88dSmrg   /* check levels against maximum (note different error than above) */
345af69d88dSmrg   if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) {
346af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
34701e04c3fSmrg                  "glTex%sStorage%uD(levels too large)",
34801e04c3fSmrg                  suffix, dims);
349af69d88dSmrg      return GL_TRUE;
350af69d88dSmrg   }
351af69d88dSmrg
352af69d88dSmrg   /* check levels against width/height/depth */
353af69d88dSmrg   if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) {
354af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
35501e04c3fSmrg                  "glTex%sStorage%uD(too many levels"
35601e04c3fSmrg                  " for max texture dimension)",
35701e04c3fSmrg                  suffix, dims);
358af69d88dSmrg      return GL_TRUE;
359af69d88dSmrg   }
360af69d88dSmrg
361af69d88dSmrg   /* non-default texture object check */
362af69d88dSmrg   if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) {
363af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
36401e04c3fSmrg                  "glTex%sStorage%uD(texture object 0)",
36501e04c3fSmrg                  suffix, dims);
366af69d88dSmrg      return GL_TRUE;
367af69d88dSmrg   }
368af69d88dSmrg
369af69d88dSmrg   /* Check if texObj->Immutable is set */
370af69d88dSmrg   if (!_mesa_is_proxy_texture(target) && texObj->Immutable) {
37101e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(immutable)",
37201e04c3fSmrg                  suffix, dims);
373af69d88dSmrg      return GL_TRUE;
374af69d88dSmrg   }
375af69d88dSmrg
376af69d88dSmrg   /* additional checks for depth textures */
37701e04c3fSmrg   if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat)) {
37801e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(bad target for texture)",
37901e04c3fSmrg                  suffix, dims);
380af69d88dSmrg      return GL_TRUE;
38101e04c3fSmrg   }
382af69d88dSmrg
383af69d88dSmrg   return GL_FALSE;
384af69d88dSmrg}
385af69d88dSmrg
386af69d88dSmrg
387af69d88dSmrg/**
38801e04c3fSmrg * Helper that does the storage allocation for _mesa_TexStorage1/2/3D()
38901e04c3fSmrg * and _mesa_TextureStorage1/2/3D().
390af69d88dSmrg */
39101e04c3fSmrgstatic ALWAYS_INLINE void
39201e04c3fSmrgtexture_storage(struct gl_context *ctx, GLuint dims,
39301e04c3fSmrg                struct gl_texture_object *texObj,
39401e04c3fSmrg                struct gl_memory_object *memObj, GLenum target,
39501e04c3fSmrg                GLsizei levels, GLenum internalformat, GLsizei width,
39601e04c3fSmrg                GLsizei height, GLsizei depth, GLuint64 offset, bool dsa,
39701e04c3fSmrg                bool no_error)
398af69d88dSmrg{
39901e04c3fSmrg   GLboolean sizeOK = GL_TRUE, dimensionsOK = GL_TRUE;
400af69d88dSmrg   mesa_format texFormat;
40101e04c3fSmrg   const char* suffix = dsa ? (memObj ? "tureMem" : "ture") :
40201e04c3fSmrg                              (memObj ? "Mem" : "");
403af69d88dSmrg
40401e04c3fSmrg   assert(texObj);
405af69d88dSmrg
40601e04c3fSmrg   if (!no_error) {
40701e04c3fSmrg      if (tex_storage_error_check(ctx, texObj, memObj, dims, target, levels,
40801e04c3fSmrg                                  internalformat, width, height, depth, dsa)) {
40901e04c3fSmrg         return; /* error was recorded */
41001e04c3fSmrg      }
411af69d88dSmrg   }
412af69d88dSmrg
413af69d88dSmrg   texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0,
414af69d88dSmrg                                           internalformat, GL_NONE, GL_NONE);
415af69d88dSmrg
41601e04c3fSmrg   if (!no_error) {
41701e04c3fSmrg      /* check that width, height, depth are legal for the mipmap level */
41801e04c3fSmrg      dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0,
41901e04c3fSmrg                                                     width, height, depth, 0);
420af69d88dSmrg
42101e04c3fSmrg      sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, levels, 0, texFormat,
42201e04c3fSmrg                                             1, width, height, depth);
42301e04c3fSmrg   }
424af69d88dSmrg
42501e04c3fSmrg   if (_mesa_is_proxy_texture(target)) {
426af69d88dSmrg      if (dimensionsOK && sizeOK) {
427af69d88dSmrg         initialize_texture_fields(ctx, texObj, levels, width, height, depth,
428af69d88dSmrg                                   internalformat, texFormat);
429af69d88dSmrg      }
430af69d88dSmrg      else {
431af69d88dSmrg         /* clear all image fields for [levels] */
432af69d88dSmrg         clear_texture_fields(ctx, texObj);
433af69d88dSmrg      }
434af69d88dSmrg   }
435af69d88dSmrg   else {
43601e04c3fSmrg      if (!no_error) {
43701e04c3fSmrg         if (!dimensionsOK) {
43801e04c3fSmrg            _mesa_error(ctx, GL_INVALID_VALUE,
43901e04c3fSmrg                        "glTex%sStorage%uD(invalid width, height or depth)",
44001e04c3fSmrg                        suffix, dims);
44101e04c3fSmrg            return;
44201e04c3fSmrg         }
443af69d88dSmrg
44401e04c3fSmrg         if (!sizeOK) {
44501e04c3fSmrg            _mesa_error(ctx, GL_OUT_OF_MEMORY,
44601e04c3fSmrg                        "glTex%sStorage%uD(texture too large)",
44701e04c3fSmrg                        suffix, dims);
44801e04c3fSmrg            return;
44901e04c3fSmrg         }
450af69d88dSmrg      }
451af69d88dSmrg
452af69d88dSmrg      assert(levels > 0);
453af69d88dSmrg      assert(width > 0);
454af69d88dSmrg      assert(height > 0);
455af69d88dSmrg      assert(depth > 0);
456af69d88dSmrg
457af69d88dSmrg      if (!initialize_texture_fields(ctx, texObj, levels, width, height, depth,
458af69d88dSmrg                                     internalformat, texFormat)) {
459af69d88dSmrg         return;
460af69d88dSmrg      }
461af69d88dSmrg
46201e04c3fSmrg      /* Setup the backing memory */
46301e04c3fSmrg      if (memObj) {
46401e04c3fSmrg         if (!ctx->Driver.SetTextureStorageForMemoryObject(ctx, texObj, memObj,
46501e04c3fSmrg                                                           levels,
46601e04c3fSmrg                                                           width, height, depth,
46701e04c3fSmrg                                                           offset)) {
46801e04c3fSmrg
46901e04c3fSmrg            clear_texture_fields(ctx, texObj);
47001e04c3fSmrg            return;
47101e04c3fSmrg         }
47201e04c3fSmrg      }
47301e04c3fSmrg      else {
47401e04c3fSmrg         if (!ctx->Driver.AllocTextureStorage(ctx, texObj, levels,
47501e04c3fSmrg                                              width, height, depth)) {
47601e04c3fSmrg            /* Reset the texture images' info to zeros.
47701e04c3fSmrg             * Strictly speaking, we probably don't have to do this since
47801e04c3fSmrg             * generating GL_OUT_OF_MEMORY can leave things in an undefined
47901e04c3fSmrg             * state but this puts things in a consistent state.
48001e04c3fSmrg             */
48101e04c3fSmrg            clear_texture_fields(ctx, texObj);
48201e04c3fSmrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex%sStorage%uD",
48301e04c3fSmrg                        suffix, dims);
48401e04c3fSmrg            return;
48501e04c3fSmrg         }
486af69d88dSmrg      }
487af69d88dSmrg
488af69d88dSmrg      _mesa_set_texture_view_state(ctx, texObj, target, levels);
489af69d88dSmrg
49001e04c3fSmrg      update_fbo_texture(ctx, texObj);
491af69d88dSmrg   }
492af69d88dSmrg}
493af69d88dSmrg
494af69d88dSmrg
49501e04c3fSmrgstatic void
49601e04c3fSmrgtexture_storage_error(struct gl_context *ctx, GLuint dims,
49701e04c3fSmrg                      struct gl_texture_object *texObj,
49801e04c3fSmrg                      GLenum target, GLsizei levels,
49901e04c3fSmrg                      GLenum internalformat, GLsizei width,
50001e04c3fSmrg                      GLsizei height, GLsizei depth, bool dsa)
50101e04c3fSmrg{
50201e04c3fSmrg   texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat,
50301e04c3fSmrg                   width, height, depth, dsa, 0, false);
50401e04c3fSmrg}
50501e04c3fSmrg
50601e04c3fSmrg
50701e04c3fSmrgstatic void
50801e04c3fSmrgtexture_storage_no_error(struct gl_context *ctx, GLuint dims,
50901e04c3fSmrg                         struct gl_texture_object *texObj,
51001e04c3fSmrg                         GLenum target, GLsizei levels,
51101e04c3fSmrg                         GLenum internalformat, GLsizei width,
51201e04c3fSmrg                         GLsizei height, GLsizei depth, bool dsa)
51301e04c3fSmrg{
51401e04c3fSmrg   texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat,
51501e04c3fSmrg                   width, height, depth, dsa, 0, true);
51601e04c3fSmrg}
51701e04c3fSmrg
51801e04c3fSmrg
51901e04c3fSmrg/**
52001e04c3fSmrg * Helper used by _mesa_TexStorage1/2/3D().
52101e04c3fSmrg */
52201e04c3fSmrgstatic void
52301e04c3fSmrgtexstorage_error(GLuint dims, GLenum target, GLsizei levels,
52401e04c3fSmrg                 GLenum internalformat, GLsizei width, GLsizei height,
52501e04c3fSmrg                 GLsizei depth, const char *caller)
52601e04c3fSmrg{
52701e04c3fSmrg   struct gl_texture_object *texObj;
52801e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
52901e04c3fSmrg
53001e04c3fSmrg   /* Check target.  This is done here so that texture_storage
53101e04c3fSmrg    * can receive unsized formats.
53201e04c3fSmrg    */
53301e04c3fSmrg   if (!legal_texobj_target(ctx, dims, target)) {
53401e04c3fSmrg      _mesa_error(ctx, GL_INVALID_ENUM,
53501e04c3fSmrg                  "%s(illegal target=%s)",
53601e04c3fSmrg                  caller, _mesa_enum_to_string(target));
53701e04c3fSmrg      return;
53801e04c3fSmrg   }
53901e04c3fSmrg
54001e04c3fSmrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
54101e04c3fSmrg      _mesa_debug(ctx, "%s %s %d %s %d %d %d\n", caller,
54201e04c3fSmrg                  _mesa_enum_to_string(target), levels,
54301e04c3fSmrg                  _mesa_enum_to_string(internalformat),
54401e04c3fSmrg                  width, height, depth);
54501e04c3fSmrg
54601e04c3fSmrg   /* Check the format to make sure it is sized. */
54701e04c3fSmrg   if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
54801e04c3fSmrg      _mesa_error(ctx, GL_INVALID_ENUM,
54901e04c3fSmrg                  "%s(internalformat = %s)", caller,
55001e04c3fSmrg                  _mesa_enum_to_string(internalformat));
55101e04c3fSmrg      return;
55201e04c3fSmrg   }
55301e04c3fSmrg
55401e04c3fSmrg   texObj = _mesa_get_current_tex_object(ctx, target);
55501e04c3fSmrg   if (!texObj)
55601e04c3fSmrg      return;
55701e04c3fSmrg
55801e04c3fSmrg   texture_storage_error(ctx, dims, texObj, target, levels,
55901e04c3fSmrg                         internalformat, width, height, depth, false);
56001e04c3fSmrg}
56101e04c3fSmrg
56201e04c3fSmrg
56301e04c3fSmrgstatic void
56401e04c3fSmrgtexstorage_no_error(GLuint dims, GLenum target, GLsizei levels,
56501e04c3fSmrg                    GLenum internalformat, GLsizei width, GLsizei height,
56601e04c3fSmrg                    GLsizei depth)
56701e04c3fSmrg{
56801e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
56901e04c3fSmrg
57001e04c3fSmrg   struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target);
57101e04c3fSmrg   texture_storage_no_error(ctx, dims, texObj, target, levels,
57201e04c3fSmrg                            internalformat, width, height, depth, false);
57301e04c3fSmrg}
57401e04c3fSmrg
57501e04c3fSmrg
57601e04c3fSmrg/**
57701e04c3fSmrg * Helper used by _mesa_TextureStorage1/2/3D().
57801e04c3fSmrg */
57901e04c3fSmrgstatic void
58001e04c3fSmrgtexturestorage_error(GLuint dims, GLuint texture, GLsizei levels,
58101e04c3fSmrg                     GLenum internalformat, GLsizei width, GLsizei height,
58201e04c3fSmrg                     GLsizei depth, const char *caller)
58301e04c3fSmrg{
58401e04c3fSmrg   struct gl_texture_object *texObj;
58501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
58601e04c3fSmrg
58701e04c3fSmrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
58801e04c3fSmrg      _mesa_debug(ctx, "%s %d %d %s %d %d %d\n",
58901e04c3fSmrg                  caller, texture, levels,
59001e04c3fSmrg                  _mesa_enum_to_string(internalformat),
59101e04c3fSmrg                  width, height, depth);
59201e04c3fSmrg
59301e04c3fSmrg   /* Check the format to make sure it is sized. */
59401e04c3fSmrg   if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
59501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_ENUM,
59601e04c3fSmrg                  "%s(internalformat = %s)", caller,
59701e04c3fSmrg                  _mesa_enum_to_string(internalformat));
59801e04c3fSmrg      return;
59901e04c3fSmrg   }
60001e04c3fSmrg
60101e04c3fSmrg   texObj = _mesa_lookup_texture_err(ctx, texture, caller);
60201e04c3fSmrg   if (!texObj)
60301e04c3fSmrg      return;
60401e04c3fSmrg
60501e04c3fSmrg   /* Check target.  This is done here so that texture_storage
60601e04c3fSmrg    * can receive unsized formats.
60701e04c3fSmrg    */
60801e04c3fSmrg   if (!legal_texobj_target(ctx, dims, texObj->Target)) {
60901e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
61001e04c3fSmrg                  "%s(illegal target=%s)", caller,
61101e04c3fSmrg                  _mesa_enum_to_string(texObj->Target));
61201e04c3fSmrg      return;
61301e04c3fSmrg   }
61401e04c3fSmrg
61501e04c3fSmrg   texture_storage_error(ctx, dims, texObj, texObj->Target,
61601e04c3fSmrg                         levels, internalformat, width, height, depth, true);
61701e04c3fSmrg}
61801e04c3fSmrg
61901e04c3fSmrg
62001e04c3fSmrgstatic void
62101e04c3fSmrgtexturestorage_no_error(GLuint dims, GLuint texture, GLsizei levels,
62201e04c3fSmrg                        GLenum internalformat, GLsizei width, GLsizei height,
62301e04c3fSmrg                        GLsizei depth)
62401e04c3fSmrg{
62501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
62601e04c3fSmrg
62701e04c3fSmrg   struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture);
62801e04c3fSmrg   texture_storage_no_error(ctx, dims, texObj, texObj->Target,
62901e04c3fSmrg                            levels, internalformat, width, height, depth, true);
63001e04c3fSmrg}
63101e04c3fSmrg
63201e04c3fSmrg
63301e04c3fSmrgvoid GLAPIENTRY
63401e04c3fSmrg_mesa_TexStorage1D_no_error(GLenum target, GLsizei levels,
63501e04c3fSmrg                            GLenum internalformat, GLsizei width)
63601e04c3fSmrg{
63701e04c3fSmrg   texstorage_no_error(1, target, levels, internalformat, width, 1, 1);
63801e04c3fSmrg}
63901e04c3fSmrg
64001e04c3fSmrg
641af69d88dSmrgvoid GLAPIENTRY
642af69d88dSmrg_mesa_TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat,
643af69d88dSmrg                   GLsizei width)
644af69d88dSmrg{
64501e04c3fSmrg   texstorage_error(1, target, levels, internalformat, width, 1, 1,
64601e04c3fSmrg                    "glTexStorage1D");
64701e04c3fSmrg}
64801e04c3fSmrg
64901e04c3fSmrg
65001e04c3fSmrgvoid GLAPIENTRY
65101e04c3fSmrg_mesa_TexStorage2D_no_error(GLenum target, GLsizei levels,
65201e04c3fSmrg                            GLenum internalformat, GLsizei width,
65301e04c3fSmrg                            GLsizei height)
65401e04c3fSmrg{
65501e04c3fSmrg   texstorage_no_error(2, target, levels, internalformat, width, height, 1);
656af69d88dSmrg}
657af69d88dSmrg
658af69d88dSmrg
659af69d88dSmrgvoid GLAPIENTRY
660af69d88dSmrg_mesa_TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat,
661af69d88dSmrg                   GLsizei width, GLsizei height)
662af69d88dSmrg{
66301e04c3fSmrg   texstorage_error(2, target, levels, internalformat, width, height, 1,
66401e04c3fSmrg                    "glTexStorage2D");
66501e04c3fSmrg}
66601e04c3fSmrg
66701e04c3fSmrg
66801e04c3fSmrgvoid GLAPIENTRY
66901e04c3fSmrg_mesa_TexStorage3D_no_error(GLenum target, GLsizei levels,
67001e04c3fSmrg                            GLenum internalformat, GLsizei width,
67101e04c3fSmrg                            GLsizei height, GLsizei depth)
67201e04c3fSmrg{
67301e04c3fSmrg   texstorage_no_error(3, target, levels, internalformat, width, height, depth);
674af69d88dSmrg}
675af69d88dSmrg
676af69d88dSmrg
677af69d88dSmrgvoid GLAPIENTRY
678af69d88dSmrg_mesa_TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
679af69d88dSmrg                   GLsizei width, GLsizei height, GLsizei depth)
680af69d88dSmrg{
68101e04c3fSmrg   texstorage_error(3, target, levels, internalformat, width, height, depth,
68201e04c3fSmrg                    "glTexStorage3D");
683af69d88dSmrg}
684af69d88dSmrg
685af69d88dSmrg
68601e04c3fSmrgvoid GLAPIENTRY
68701e04c3fSmrg_mesa_TextureStorage1D_no_error(GLuint texture, GLsizei levels,
68801e04c3fSmrg                                GLenum internalformat, GLsizei width)
68901e04c3fSmrg{
69001e04c3fSmrg   texturestorage_no_error(1, texture, levels, internalformat, width, 1, 1);
69101e04c3fSmrg}
69201e04c3fSmrg
69301e04c3fSmrg
69401e04c3fSmrgvoid GLAPIENTRY
69501e04c3fSmrg_mesa_TextureStorage1D(GLuint texture, GLsizei levels, GLenum internalformat,
69601e04c3fSmrg                       GLsizei width)
69701e04c3fSmrg{
69801e04c3fSmrg   texturestorage_error(1, texture, levels, internalformat, width, 1, 1,
69901e04c3fSmrg                        "glTextureStorage1D");
70001e04c3fSmrg}
70101e04c3fSmrg
70201e04c3fSmrg
70301e04c3fSmrgvoid GLAPIENTRY
70401e04c3fSmrg_mesa_TextureStorage2D_no_error(GLuint texture, GLsizei levels,
70501e04c3fSmrg                                GLenum internalformat,
70601e04c3fSmrg                                GLsizei width, GLsizei height)
70701e04c3fSmrg{
70801e04c3fSmrg   texturestorage_no_error(2, texture, levels, internalformat, width, height, 1);
70901e04c3fSmrg}
71001e04c3fSmrg
71101e04c3fSmrg
71201e04c3fSmrgvoid GLAPIENTRY
71301e04c3fSmrg_mesa_TextureStorage2D(GLuint texture, GLsizei levels,
71401e04c3fSmrg                       GLenum internalformat,
71501e04c3fSmrg                       GLsizei width, GLsizei height)
71601e04c3fSmrg{
71701e04c3fSmrg   texturestorage_error(2, texture, levels, internalformat, width, height, 1,
71801e04c3fSmrg                        "glTextureStorage2D");
71901e04c3fSmrg}
72001e04c3fSmrg
72101e04c3fSmrg
72201e04c3fSmrgvoid GLAPIENTRY
72301e04c3fSmrg_mesa_TextureStorage3D_no_error(GLuint texture, GLsizei levels,
72401e04c3fSmrg                                GLenum internalformat, GLsizei width,
72501e04c3fSmrg                                GLsizei height, GLsizei depth)
72601e04c3fSmrg{
72701e04c3fSmrg   texturestorage_no_error(3, texture, levels, internalformat, width, height,
72801e04c3fSmrg                           depth);
72901e04c3fSmrg}
73001e04c3fSmrg
73101e04c3fSmrg
73201e04c3fSmrgvoid GLAPIENTRY
73301e04c3fSmrg_mesa_TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat,
73401e04c3fSmrg                       GLsizei width, GLsizei height, GLsizei depth)
73501e04c3fSmrg{
73601e04c3fSmrg   texturestorage_error(3, texture, levels, internalformat, width, height, depth,
73701e04c3fSmrg                        "glTextureStorage3D");
73801e04c3fSmrg}
73901e04c3fSmrg
740af69d88dSmrg
741af69d88dSmrgvoid GLAPIENTRY
742af69d88dSmrg_mesa_TextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels,
743af69d88dSmrg                          GLenum internalformat,
744af69d88dSmrg                          GLsizei width)
745af69d88dSmrg{
746af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
7477ec681f3Smrg   /* 'texture' must always be initialized, even if the call to
7487ec681f3Smrg    * glTextureStorage1DEXT will generate an error.
7497ec681f3Smrg    */
7507ec681f3Smrg   if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
7517ec681f3Smrg                                       "glTextureStorage1DEXT"))
7527ec681f3Smrg      return;
7537ec681f3Smrg   texturestorage_error(1, texture, levels, internalformat, width, 1, 1,
7547ec681f3Smrg                        "glTextureStorage1DEXT");
755af69d88dSmrg}
756af69d88dSmrg
757af69d88dSmrg
758af69d88dSmrgvoid GLAPIENTRY
759af69d88dSmrg_mesa_TextureStorage2DEXT(GLuint texture, GLenum target, GLsizei levels,
760af69d88dSmrg                          GLenum internalformat,
761af69d88dSmrg                          GLsizei width, GLsizei height)
762af69d88dSmrg{
763af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
7647ec681f3Smrg   /* 'texture' must always be initialized, even if the call to
7657ec681f3Smrg    * glTextureStorage2DEXT will generate an error.
7667ec681f3Smrg    */
7677ec681f3Smrg   if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
7687ec681f3Smrg                                       "glTextureStorage2DEXT"))
7697ec681f3Smrg      return;
7707ec681f3Smrg   texturestorage_error(2, texture, levels, internalformat, width, height, 1,
7717ec681f3Smrg                        "glTextureStorage2DEXT");
772af69d88dSmrg}
773af69d88dSmrg
774af69d88dSmrg
775af69d88dSmrgvoid GLAPIENTRY
776af69d88dSmrg_mesa_TextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels,
777af69d88dSmrg                          GLenum internalformat,
778af69d88dSmrg                          GLsizei width, GLsizei height, GLsizei depth)
779af69d88dSmrg{
780af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
7817ec681f3Smrg   /* 'texture' must always be initialized, even if the call to
7827ec681f3Smrg    * glTextureStorage3DEXT will generate an error.
7837ec681f3Smrg    */
7847ec681f3Smrg   if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
7857ec681f3Smrg                                       "glTextureStorage3DEXT"))
7867ec681f3Smrg      return;
7877ec681f3Smrg   texturestorage_error(3, texture, levels, internalformat, width, height, depth,
7887ec681f3Smrg                        "glTextureStorage3DEXT");
789af69d88dSmrg}
79001e04c3fSmrg
79101e04c3fSmrg
79201e04c3fSmrgvoid
79301e04c3fSmrg_mesa_texture_storage_memory(struct gl_context *ctx, GLuint dims,
79401e04c3fSmrg                             struct gl_texture_object *texObj,
79501e04c3fSmrg                             struct gl_memory_object *memObj,
79601e04c3fSmrg                             GLenum target, GLsizei levels,
79701e04c3fSmrg                             GLenum internalformat, GLsizei width,
79801e04c3fSmrg                             GLsizei height, GLsizei depth,
79901e04c3fSmrg                             GLuint64 offset, bool dsa)
80001e04c3fSmrg{
80101e04c3fSmrg   assert(memObj);
80201e04c3fSmrg
80301e04c3fSmrg   texture_storage(ctx, dims, texObj, memObj, target, levels, internalformat,
80401e04c3fSmrg                   width, height, depth, offset, dsa, false);
80501e04c3fSmrg}
806