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