2 * Mesa 3-D graphics library
4 * Copyright (C) 2011 VMware, Inc. All Rights Reserved.
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:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * GL_ARB_texture_storage functions
37 #include "mfeatures.h"
39 #include "texstorage.h"
45 * Check if the given texture target is a legal texture object target
46 * for a glTexStorage() command.
47 * This is a bit different than legal_teximage_target() when it comes
51 legal_texobj_target(struct gl_context
*ctx
, GLuint dims
, GLenum target
)
57 case GL_PROXY_TEXTURE_1D
:
65 case GL_PROXY_TEXTURE_2D
:
67 case GL_TEXTURE_CUBE_MAP
:
68 case GL_PROXY_TEXTURE_CUBE_MAP
:
69 return ctx
->Extensions
.ARB_texture_cube_map
;
70 case GL_TEXTURE_RECTANGLE
:
71 case GL_PROXY_TEXTURE_RECTANGLE
:
72 return ctx
->Extensions
.NV_texture_rectangle
;
73 case GL_TEXTURE_1D_ARRAY
:
74 case GL_PROXY_TEXTURE_1D_ARRAY
:
75 return (ctx
->Extensions
.MESA_texture_array
||
76 ctx
->Extensions
.EXT_texture_array
);
83 case GL_PROXY_TEXTURE_3D
:
85 case GL_TEXTURE_2D_ARRAY
:
86 case GL_PROXY_TEXTURE_2D_ARRAY
:
87 return (ctx
->Extensions
.MESA_texture_array
||
88 ctx
->Extensions
.EXT_texture_array
);
93 _mesa_problem(ctx
, "invalid dims=%u in legal_texobj_target()", dims
);
100 * Compute the size of the next mipmap level.
103 next_mipmap_level_size(GLenum target
,
104 GLint
*width
, GLint
*height
, GLint
*depth
)
110 if ((*height
> 1) && (target
!= GL_TEXTURE_1D_ARRAY
)) {
114 if ((*depth
> 1) && (target
!= GL_TEXTURE_2D_ARRAY
)) {
121 * Do actual memory allocation for glTexStorage1/2/3D().
124 setup_texstorage(struct gl_context
*ctx
,
125 struct gl_texture_object
*texObj
,
127 GLsizei levels
, GLenum internalFormat
,
128 GLsizei width
, GLsizei height
, GLsizei depth
)
130 const GLenum target
= texObj
->Target
;
131 const GLuint numFaces
= (target
== GL_TEXTURE_CUBE_MAP
) ? 6 : 1;
133 GLint level
, levelWidth
= width
, levelHeight
= height
, levelDepth
= depth
;
141 texFormat
= _mesa_choose_texture_format(ctx
, texObj
, target
, 0,
142 internalFormat
, GL_NONE
, GL_NONE
);
144 /* Set up all the texture object's gl_texture_images */
145 for (level
= 0; level
< levels
; level
++) {
146 for (face
= 0; face
< numFaces
; face
++) {
147 const GLenum faceTarget
=
148 (target
== GL_TEXTURE_CUBE_MAP
)
149 ? GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ face
: target
;
150 struct gl_texture_image
*texImage
=
151 _mesa_get_tex_image(ctx
, texObj
, faceTarget
, level
);
154 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage%uD", dims
);
158 _mesa_init_teximage_fields(ctx
, texImage
,
159 levelWidth
, levelHeight
, levelDepth
,
160 0, internalFormat
, texFormat
);
163 next_mipmap_level_size(target
, &levelWidth
, &levelHeight
, &levelDepth
);
166 assert(levelWidth
> 0);
167 assert(levelHeight
> 0);
168 assert(levelDepth
> 0);
170 if (!_mesa_is_proxy_texture(texObj
->Target
)) {
171 /* Do actual texture memory allocation */
172 if (!ctx
->Driver
.AllocTextureStorage(ctx
, texObj
, levels
,
173 width
, height
, depth
)) {
174 /* Reset the texture images' info to zeros.
175 * Strictly speaking, we probably don't have to do this since
176 * generating GL_OUT_OF_MEMORY can leave things in an undefined
177 * state but this puts things in a consistent state.
179 for (level
= 0; level
< levels
; level
++) {
180 for (face
= 0; face
< numFaces
; face
++) {
181 struct gl_texture_image
*texImage
= texObj
->Image
[face
][level
];
183 _mesa_init_teximage_fields(ctx
, texImage
,
185 GL_NONE
, MESA_FORMAT_NONE
);
190 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexStorage%uD", dims
);
196 texObj
->Immutable
= GL_TRUE
;
201 * Clear all fields of texture object to zeros. Used for proxy texture tests.
204 clear_image_fields(struct gl_context
*ctx
,
206 struct gl_texture_object
*texObj
)
208 const GLenum target
= texObj
->Target
;
209 const GLuint numFaces
= (target
== GL_TEXTURE_CUBE_MAP
) ? 6 : 1;
213 for (level
= 0; level
< Elements(texObj
->Image
[0]); level
++) {
214 for (face
= 0; face
< numFaces
; face
++) {
215 const GLenum faceTarget
=
216 (target
== GL_TEXTURE_CUBE_MAP
)
217 ? GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ face
: target
;
218 struct gl_texture_image
*texImage
=
219 _mesa_get_tex_image(ctx
, texObj
, faceTarget
, level
);
222 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexStorage%uD", dims
);
226 _mesa_init_teximage_fields(ctx
, texImage
,
227 0, 0, 0, 0, GL_NONE
, MESA_FORMAT_NONE
);
234 * Do error checking for calls to glTexStorage1/2/3D().
235 * If an error is found, record it with _mesa_error(), unless the target
236 * is a proxy texture.
237 * \return GL_TRUE if any error, GL_FALSE otherwise.
240 tex_storage_error_check(struct gl_context
*ctx
, GLuint dims
, GLenum target
,
241 GLsizei levels
, GLenum internalformat
,
242 GLsizei width
, GLsizei height
, GLsizei depth
)
244 const GLboolean isProxy
= _mesa_is_proxy_texture(target
);
245 struct gl_texture_object
*texObj
;
249 if (width
< 1 || height
< 1 || depth
< 1) {
251 _mesa_error(ctx
, GL_INVALID_VALUE
,
252 "glTexStorage%uD(width, height or depth < 1)", dims
);
258 if (levels
< 1 || height
< 1 || depth
< 1) {
260 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexStorage%uD(levels < 1)",
267 if (!legal_texobj_target(ctx
, dims
, target
)) {
268 _mesa_error(ctx
, GL_INVALID_ENUM
,
269 "glTexStorage%uD(illegal target=%s)",
270 dims
, _mesa_lookup_enum_by_nr(target
));
274 /* check levels against maximum */
275 if (levels
> _mesa_max_texture_levels(ctx
, target
)) {
277 _mesa_error(ctx
, GL_INVALID_OPERATION
,
278 "glTexStorage%uD(levels too large)", dims
);
283 /* check levels against width/height/depth */
284 maxDim
= MAX3(width
, height
, depth
);
285 if (levels
> _mesa_logbase2(maxDim
) + 1) {
287 _mesa_error(ctx
, GL_INVALID_OPERATION
,
288 "glTexStorage%uD(too many levels for max texture dimension)",
294 /* non-default texture object check */
295 texObj
= _mesa_get_current_tex_object(ctx
, target
);
296 if (!texObj
|| (texObj
->Name
== 0 && !isProxy
)) {
298 _mesa_error(ctx
, GL_INVALID_OPERATION
,
299 "glTexStorage%uD(texture object 0)", dims
);
304 /* Check if texObj->Immutable is set */
305 if (texObj
->Immutable
) {
307 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glTexStorage%uD(immutable)",
318 * Helper used by _mesa_TexStorage1/2/3D().
321 texstorage(GLuint dims
, GLenum target
, GLsizei levels
, GLenum internalformat
,
322 GLsizei width
, GLsizei height
, GLsizei depth
)
324 struct gl_texture_object
*texObj
;
327 GET_CURRENT_CONTEXT(ctx
);
329 texObj
= _mesa_get_current_tex_object(ctx
, target
);
331 error
= tex_storage_error_check(ctx
, dims
, target
, levels
,
332 internalformat
, width
, height
, depth
);
334 setup_texstorage(ctx
, texObj
, dims
, levels
, internalformat
,
335 width
, height
, depth
);
337 else if (_mesa_is_proxy_texture(target
)) {
338 /* clear all image fields for [levels] */
339 clear_image_fields(ctx
, dims
, texObj
);
345 _mesa_TexStorage1D(GLenum target
, GLsizei levels
, GLenum internalformat
,
348 texstorage(1, target
, levels
, internalformat
, width
, 1, 1);
353 _mesa_TexStorage2D(GLenum target
, GLsizei levels
, GLenum internalformat
,
354 GLsizei width
, GLsizei height
)
356 texstorage(2, target
, levels
, internalformat
, width
, height
, 1);
361 _mesa_TexStorage3D(GLenum target
, GLsizei levels
, GLenum internalformat
,
362 GLsizei width
, GLsizei height
, GLsizei depth
)
364 texstorage(3, target
, levels
, internalformat
, width
, height
, depth
);
370 * Note: we don't support GL_EXT_direct_state_access and the spec says
371 * we don't need the following functions. However, glew checks for the
372 * presence of all six functions and will say that GL_ARB_texture_storage
373 * is not supported if these functions are missing.
378 _mesa_TextureStorage1DEXT(GLuint texture
, GLenum target
, GLsizei levels
,
379 GLenum internalformat
,
387 _mesa_TextureStorage2DEXT(GLuint texture
, GLenum target
, GLsizei levels
,
388 GLenum internalformat
,
389 GLsizei width
, GLsizei height
)
397 _mesa_TextureStorage3DEXT(GLuint texture
, GLenum target
, GLsizei levels
,
398 GLenum internalformat
,
399 GLsizei width
, GLsizei height
, GLsizei depth
)