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)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 {
147 const GLenum target = texObj->Target;
148 const GLuint numFaces = _mesa_num_tex_faces(target);
149 GLint level, levelWidth = width, levelHeight = height, levelDepth = depth;
150 GLuint face;
151
152 /* Set up all the texture object's gl_texture_images */
153 for (level = 0; level < levels; level++) {
154 for (face = 0; face < numFaces; face++) {
155 struct gl_texture_image *texImage =
156 get_tex_image(ctx, texObj, face, level);
157
158 if (!texImage) {
159 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
160 return GL_FALSE;
161 }
162
163 _mesa_init_teximage_fields(ctx, texImage,
164 levelWidth, levelHeight, levelDepth,
165 0, internalFormat, texFormat);
166 }
167
168 _mesa_next_mipmap_level_size(target, 0,
169 levelWidth, levelHeight, levelDepth,
170 &levelWidth, &levelHeight, &levelDepth);
171 }
172 _mesa_update_texture_object_swizzle(ctx, texObj);
173 return GL_TRUE;
174 }
175
176
177 /**
178 * Clear all fields of texture object to zeros. Used for proxy texture tests
179 * and to clean up when a texture memory allocation fails.
180 */
181 static void
clear_texture_fields(struct gl_context * ctx,struct gl_texture_object * texObj)182 clear_texture_fields(struct gl_context *ctx,
183 struct gl_texture_object *texObj)
184 {
185 const GLenum target = texObj->Target;
186 const GLuint numFaces = _mesa_num_tex_faces(target);
187 GLint level;
188 GLuint face;
189
190 for (level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
191 for (face = 0; face < numFaces; face++) {
192 struct gl_texture_image *texImage =
193 get_tex_image(ctx, texObj, face, level);
194
195 if (!texImage) {
196 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
197 return;
198 }
199
200 _mesa_clear_texture_image(ctx, texImage);
201 }
202 }
203 }
204
205
206 /**
207 * Update/re-validate framebuffer object.
208 */
209 static void
update_fbo_texture(struct gl_context * ctx,struct gl_texture_object * texObj)210 update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
211 {
212 const unsigned numFaces = _mesa_num_tex_faces(texObj->Target);
213 for (int level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
214 for (unsigned face = 0; face < numFaces; face++)
215 _mesa_update_fbo_texture(ctx, texObj, face, level);
216 }
217 }
218
219
220 GLboolean
_mesa_is_legal_tex_storage_format(const struct gl_context * ctx,GLenum internalformat)221 _mesa_is_legal_tex_storage_format(const struct gl_context *ctx,
222 GLenum internalformat)
223 {
224 if (!_mesa_is_desktop_gl(ctx)) {
225 assert(_mesa_has_EXT_texture_storage(ctx));
226
227 /* EXT_texture_storage allows us to use some sized internal formats
228 * for TexStorage* that aren't otherwise allowed in OpenGL ES.
229 **/
230 switch (internalformat) {
231 case GL_ALPHA8:
232 case GL_LUMINANCE8:
233 case GL_LUMINANCE8_ALPHA8:
234 return true;
235
236 case GL_RGBA32F:
237 case GL_RGB32F:
238 case GL_ALPHA32F_EXT:
239 case GL_LUMINANCE32F_EXT:
240 case GL_LUMINANCE_ALPHA32F_EXT:
241 return _mesa_has_OES_texture_float(ctx);
242
243 case GL_RGBA16F:
244 case GL_RGB16F:
245 case GL_ALPHA16F_EXT:
246 case GL_LUMINANCE16F_EXT:
247 case GL_LUMINANCE_ALPHA16F_EXT:
248 return _mesa_has_OES_texture_half_float(ctx);
249
250 case GL_RGB10_A2:
251 case GL_RGB10:
252 return _mesa_has_EXT_texture_type_2_10_10_10_REV(ctx);
253
254 case GL_BGRA8_EXT:
255 assert(_mesa_has_EXT_texture_format_BGRA8888(ctx));
256 return true;
257
258 case GL_R8:
259 case GL_RG8:
260 return _mesa_has_EXT_texture_rg(ctx);
261
262 case GL_R32F_EXT:
263 case GL_RG32F_EXT:
264 return _mesa_has_EXT_texture_rg(ctx) &&
265 _mesa_has_OES_texture_float(ctx);
266
267 case GL_R16F_EXT:
268 case GL_RG16F_EXT:
269 return _mesa_has_EXT_texture_rg(ctx) &&
270 _mesa_has_OES_texture_half_float(ctx);
271 }
272 }
273
274 /* check internal format - note that only sized formats are allowed */
275 switch (internalformat) {
276 case GL_ALPHA:
277 case GL_LUMINANCE:
278 case GL_LUMINANCE_ALPHA:
279 case GL_INTENSITY:
280 case GL_RED:
281 case GL_RG:
282 case GL_RGB:
283 case GL_RGBA:
284 case GL_BGRA:
285 case GL_DEPTH_COMPONENT:
286 case GL_DEPTH_STENCIL:
287 case GL_COMPRESSED_ALPHA:
288 case GL_COMPRESSED_LUMINANCE_ALPHA:
289 case GL_COMPRESSED_LUMINANCE:
290 case GL_COMPRESSED_INTENSITY:
291 case GL_COMPRESSED_RGB:
292 case GL_COMPRESSED_RGBA:
293 case GL_COMPRESSED_SRGB:
294 case GL_COMPRESSED_SRGB_ALPHA:
295 case GL_COMPRESSED_SLUMINANCE:
296 case GL_COMPRESSED_SLUMINANCE_ALPHA:
297 case GL_RED_INTEGER:
298 case GL_GREEN_INTEGER:
299 case GL_BLUE_INTEGER:
300 case GL_ALPHA_INTEGER:
301 case GL_RGB_INTEGER:
302 case GL_RGBA_INTEGER:
303 case GL_BGR_INTEGER:
304 case GL_BGRA_INTEGER:
305 case GL_LUMINANCE_INTEGER_EXT:
306 case GL_LUMINANCE_ALPHA_INTEGER_EXT:
307 /* these unsized formats are illegal */
308 return GL_FALSE;
309 default:
310 return _mesa_base_tex_format(ctx, internalformat) > 0;
311 }
312 }
313
314
315 /**
316 * Do error checking for calls to glTexStorage1/2/3D().
317 * If an error is found, record it with _mesa_error(), unless the target
318 * is a proxy texture.
319 * \return GL_TRUE if any error, GL_FALSE otherwise.
320 */
321 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)322 tex_storage_error_check(struct gl_context *ctx,
323 struct gl_texture_object *texObj,
324 struct gl_memory_object *memObj,
325 GLuint dims, GLenum target,
326 GLsizei levels, GLenum internalformat,
327 GLsizei width, GLsizei height, GLsizei depth,
328 bool dsa)
329 {
330 const char* suffix = dsa ? (memObj ? "tureMem" : "ture") :
331 (memObj ? "Mem" : "");
332
333 /* Legal format checking has been moved to texstorage and texturestorage in
334 * order to allow meta functions to use legacy formats. */
335
336 /* size check */
337 if (!_mesa_valid_tex_storage_dim(width, height, depth)) {
338 _mesa_error(ctx, GL_INVALID_VALUE,
339 "glTex%sStorage%uD(width, height or depth < 1)",
340 suffix, dims);
341 return GL_TRUE;
342 }
343
344 if (_mesa_is_compressed_format(ctx, internalformat)) {
345 GLenum err;
346 if (!_mesa_target_can_be_compressed(ctx, target, internalformat, &err)) {
347 _mesa_error(ctx, err,
348 "glTex%sStorage%dD(internalformat = %s)", suffix, dims,
349 _mesa_enum_to_string(internalformat));
350 return GL_TRUE;
351 }
352 }
353
354 /* levels check */
355 if (levels < 1) {
356 _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(levels < 1)",
357 suffix, dims);
358 return GL_TRUE;
359 }
360
361 /* check levels against maximum (note different error than above) */
362 if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) {
363 _mesa_error(ctx, GL_INVALID_OPERATION,
364 "glTex%sStorage%uD(levels too large)",
365 suffix, dims);
366 return GL_TRUE;
367 }
368
369 /* check levels against width/height/depth */
370 if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) {
371 _mesa_error(ctx, GL_INVALID_OPERATION,
372 "glTex%sStorage%uD(too many levels"
373 " for max texture dimension)",
374 suffix, dims);
375 return GL_TRUE;
376 }
377
378 /* non-default texture object check */
379 if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) {
380 _mesa_error(ctx, GL_INVALID_OPERATION,
381 "glTex%sStorage%uD(texture object 0)",
382 suffix, dims);
383 return GL_TRUE;
384 }
385
386 /* Check if texObj->Immutable is set */
387 if (!_mesa_is_proxy_texture(target) && texObj->Immutable) {
388 _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(immutable)",
389 suffix, dims);
390 return GL_TRUE;
391 }
392
393 /* additional checks for depth textures */
394 if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat)) {
395 _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(bad target for texture)",
396 suffix, dims);
397 return GL_TRUE;
398 }
399
400 return GL_FALSE;
401 }
402
403 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)404 _mesa_sparse_texture_error_check(struct gl_context *ctx, GLuint dims,
405 struct gl_texture_object *texObj,
406 mesa_format format, GLenum target, GLsizei levels,
407 GLsizei width, GLsizei height, GLsizei depth,
408 const char *func)
409 {
410 int px, py, pz;
411 int index = texObj->VirtualPageSizeIndex;
412 if (!st_GetSparseTextureVirtualPageSize(ctx, target, format, index,
413 &px, &py, &pz)) {
414 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(sparse index = %d)",
415 func, index);
416 return GL_TRUE;
417 }
418
419 if (target == GL_TEXTURE_3D) {
420 if (width > ctx->Const.MaxSparse3DTextureSize ||
421 height > ctx->Const.MaxSparse3DTextureSize ||
422 depth > ctx->Const.MaxSparse3DTextureSize)
423 goto exceed_max_size;
424 } else {
425 if (width > ctx->Const.MaxSparseTextureSize ||
426 height > ctx->Const.MaxSparseTextureSize)
427 goto exceed_max_size;
428
429 if (target == GL_TEXTURE_2D_ARRAY ||
430 target == GL_TEXTURE_CUBE_MAP_ARRAY) {
431 if (depth > ctx->Const.MaxSparseArrayTextureLayers)
432 goto exceed_max_size;
433 } else if (target == GL_TEXTURE_1D_ARRAY) {
434 if (height > ctx->Const.MaxSparseArrayTextureLayers)
435 goto exceed_max_size;
436 }
437 }
438
439 /* ARB_sparse_texture2 allow non-page-aligned base texture size. */
440 if (!_mesa_has_ARB_sparse_texture2(ctx) &&
441 (width % px || height % py || depth % pz)) {
442 _mesa_error(ctx, GL_INVALID_VALUE, "%s(sparse page size)", func);
443 return GL_TRUE;
444 }
445
446 /* ARB_sparse_texture spec:
447 *
448 * If the value of SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB is FALSE,
449 * then TexStorage* will generate an INVALID_OPERATION error if
450 * * the texture's TEXTURE_SPARSE_ARB parameter is TRUE,
451 * * <target> is one of TEXTURE_1D_ARRAY, TEXTURE_2D_ARRAY,
452 * TEXTURE_CUBE_MAP, or TEXTURE_CUBE_MAP_ARRAY, and
453 * * for the virtual page size corresponding to the
454 * VIRTUAL_PAGE_SIZE_INDEX_ARB parameter, either of the following is
455 * true:
456 * - <width> is not a multiple of VIRTUAL_PAGE_SIZE_X_ARB *
457 * 2^(<levels>-1), or
458 * - <height> is not a multiple of VIRTUAL_PAGE_SIZE_Y_ARB *
459 * 2^(<levels>-1).
460 *
461 * This make sure all allocated mipmap level size is multiple of virtual
462 * page size when SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB is FALSE.
463 */
464 if (!ctx->Const.SparseTextureFullArrayCubeMipmaps &&
465 (target == GL_TEXTURE_1D_ARRAY ||
466 target == GL_TEXTURE_2D_ARRAY ||
467 target == GL_TEXTURE_CUBE_MAP ||
468 target == GL_TEXTURE_CUBE_MAP_ARRAY) &&
469 (width % (px << (levels - 1)) ||
470 height % (py << (levels - 1)))) {
471 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(sparse array align)", func);
472 return GL_TRUE;
473 }
474
475 return GL_FALSE;
476
477 exceed_max_size:
478 _mesa_error(ctx, GL_INVALID_VALUE, "%s(exceed max sparse size)", func);
479 return GL_TRUE;
480 }
481
482 /**
483 * Helper that does the storage allocation for _mesa_TexStorage1/2/3D()
484 * and _mesa_TextureStorage1/2/3D().
485 */
486 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,bool no_error,const char * func)487 texture_storage(struct gl_context *ctx, GLuint dims,
488 struct gl_texture_object *texObj,
489 struct gl_memory_object *memObj, GLenum target,
490 GLsizei levels, GLenum internalformat, GLsizei width,
491 GLsizei height, GLsizei depth, GLuint64 offset, bool dsa,
492 bool no_error, const char *func)
493 {
494 GLboolean sizeOK = GL_TRUE, dimensionsOK = GL_TRUE;
495 mesa_format texFormat;
496 const char* suffix = dsa ? (memObj ? "tureMem" : "ture") :
497 (memObj ? "Mem" : "");
498
499 assert(texObj);
500
501 if (!no_error) {
502 if (tex_storage_error_check(ctx, texObj, memObj, dims, target, levels,
503 internalformat, width, height, depth, dsa)) {
504 return; /* error was recorded */
505 }
506 }
507
508 texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0,
509 internalformat, GL_NONE, GL_NONE);
510
511 if (!no_error) {
512 /* check that width, height, depth are legal for the mipmap level */
513 dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0,
514 width, height, depth, 0);
515
516 sizeOK = st_TestProxyTexImage(ctx, target, levels, 0, texFormat,
517 1, width, height, depth);
518 }
519
520 if (_mesa_is_proxy_texture(target)) {
521 if (dimensionsOK && sizeOK) {
522 initialize_texture_fields(ctx, texObj, levels, width, height, depth,
523 internalformat, texFormat);
524 }
525 else {
526 /* clear all image fields for [levels] */
527 clear_texture_fields(ctx, texObj);
528 }
529 }
530 else {
531 if (!no_error) {
532 if (!dimensionsOK) {
533 _mesa_error(ctx, GL_INVALID_VALUE,
534 "glTex%sStorage%uD(invalid width, height or depth)",
535 suffix, dims);
536 return;
537 }
538
539 if (!sizeOK) {
540 _mesa_error(ctx, GL_OUT_OF_MEMORY,
541 "glTex%sStorage%uD(texture too large)",
542 suffix, dims);
543 return;
544 }
545
546 if (texObj->IsSparse) {
547 char func[32];
548 snprintf(func, 32, "glTex%sStorage%uD", suffix, dims);
549 if (_mesa_sparse_texture_error_check(ctx, dims, texObj, texFormat, target,
550 levels, width, height, depth, func))
551 return; /* error was recorded */
552 }
553 }
554
555 assert(levels > 0);
556 assert(width > 0);
557 assert(height > 0);
558 assert(depth > 0);
559
560 if (!initialize_texture_fields(ctx, texObj, levels, width, height, depth,
561 internalformat, texFormat)) {
562 return;
563 }
564
565 /* Setup the backing memory */
566 if (memObj) {
567 if (!st_SetTextureStorageForMemoryObject(ctx, texObj, memObj,
568 levels,
569 width, height, depth,
570 offset, func)) {
571
572 clear_texture_fields(ctx, texObj);
573 return;
574 }
575 }
576 else {
577 if (!st_AllocTextureStorage(ctx, texObj, levels,
578 width, height, depth, func)) {
579 /* Reset the texture images' info to zeros.
580 * Strictly speaking, we probably don't have to do this since
581 * generating GL_OUT_OF_MEMORY can leave things in an undefined
582 * state but this puts things in a consistent state.
583 */
584 clear_texture_fields(ctx, texObj);
585 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex%sStorage%uD",
586 suffix, dims);
587 return;
588 }
589 }
590
591 _mesa_set_texture_view_state(ctx, texObj, target, levels);
592
593 update_fbo_texture(ctx, texObj);
594 }
595 }
596
597
598 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)599 texture_storage_error(struct gl_context *ctx, GLuint dims,
600 struct gl_texture_object *texObj,
601 GLenum target, GLsizei levels,
602 GLenum internalformat, GLsizei width,
603 GLsizei height, GLsizei depth, bool dsa, const char *func)
604 {
605 texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat,
606 width, height, depth, dsa, 0, false, func);
607 }
608
609
610 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)611 texture_storage_no_error(struct gl_context *ctx, GLuint dims,
612 struct gl_texture_object *texObj,
613 GLenum target, GLsizei levels,
614 GLenum internalformat, GLsizei width,
615 GLsizei height, GLsizei depth, bool dsa, const char *func)
616 {
617 texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat,
618 width, height, depth, dsa, 0, true, func);
619 }
620
621
622 /**
623 * Helper used by _mesa_TexStorage1/2/3D().
624 */
625 static void
texstorage_error(GLuint dims,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,const char * caller)626 texstorage_error(GLuint dims, GLenum target, GLsizei levels,
627 GLenum internalformat, GLsizei width, GLsizei height,
628 GLsizei depth, const char *caller)
629 {
630 struct gl_texture_object *texObj;
631 GET_CURRENT_CONTEXT(ctx);
632
633 /* Check target. This is done here so that texture_storage
634 * can receive unsized formats.
635 */
636 if (!_mesa_is_legal_tex_storage_target(ctx, dims, target)) {
637 _mesa_error(ctx, GL_INVALID_ENUM,
638 "%s(illegal target=%s)",
639 caller, _mesa_enum_to_string(target));
640 return;
641 }
642
643 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
644 _mesa_debug(ctx, "%s %s %d %s %d %d %d\n", caller,
645 _mesa_enum_to_string(target), levels,
646 _mesa_enum_to_string(internalformat),
647 width, height, depth);
648
649 /* Check the format to make sure it is sized. */
650 if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
651 _mesa_error(ctx, GL_INVALID_ENUM,
652 "%s(internalformat = %s)", caller,
653 _mesa_enum_to_string(internalformat));
654 return;
655 }
656
657 texObj = _mesa_get_current_tex_object(ctx, target);
658 if (!texObj)
659 return;
660
661 texture_storage_error(ctx, dims, texObj, target, levels,
662 internalformat, width, height, depth, false, caller);
663 }
664
665
666 static void
texstorage_no_error(GLuint dims,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,const char * caller)667 texstorage_no_error(GLuint dims, GLenum target, GLsizei levels,
668 GLenum internalformat, GLsizei width, GLsizei height,
669 GLsizei depth, const char *caller)
670 {
671 GET_CURRENT_CONTEXT(ctx);
672
673 struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target);
674 texture_storage_no_error(ctx, dims, texObj, target, levels,
675 internalformat, width, height, depth, false, caller);
676 }
677
678
679 /**
680 * Helper used by _mesa_TextureStorage1/2/3D().
681 */
682 static void
texturestorage_error(GLuint dims,GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,const char * caller)683 texturestorage_error(GLuint dims, GLuint texture, GLsizei levels,
684 GLenum internalformat, GLsizei width, GLsizei height,
685 GLsizei depth, const char *caller)
686 {
687 struct gl_texture_object *texObj;
688 GET_CURRENT_CONTEXT(ctx);
689
690 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
691 _mesa_debug(ctx, "%s %d %d %s %d %d %d\n",
692 caller, texture, levels,
693 _mesa_enum_to_string(internalformat),
694 width, height, depth);
695
696 /* Check the format to make sure it is sized. */
697 if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
698 _mesa_error(ctx, GL_INVALID_ENUM,
699 "%s(internalformat = %s)", caller,
700 _mesa_enum_to_string(internalformat));
701 return;
702 }
703
704 texObj = _mesa_lookup_texture_err(ctx, texture, caller);
705 if (!texObj)
706 return;
707
708 /* Check target. This is done here so that texture_storage
709 * can receive unsized formats.
710 */
711 if (!_mesa_is_legal_tex_storage_target(ctx, dims, texObj->Target)) {
712 _mesa_error(ctx, GL_INVALID_OPERATION,
713 "%s(illegal target=%s)", caller,
714 _mesa_enum_to_string(texObj->Target));
715 return;
716 }
717
718 texture_storage_error(ctx, dims, texObj, texObj->Target,
719 levels, internalformat, width, height, depth, true, caller);
720 }
721
722
723 static void
texturestorage_no_error(GLuint dims,GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,const char * caller)724 texturestorage_no_error(GLuint dims, GLuint texture, GLsizei levels,
725 GLenum internalformat, GLsizei width, GLsizei height,
726 GLsizei depth, const char *caller)
727 {
728 GET_CURRENT_CONTEXT(ctx);
729
730 struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture);
731 texture_storage_no_error(ctx, dims, texObj, texObj->Target,
732 levels, internalformat, width, height, depth, true, caller);
733 }
734
735
736 void GLAPIENTRY
_mesa_TexStorage1D_no_error(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)737 _mesa_TexStorage1D_no_error(GLenum target, GLsizei levels,
738 GLenum internalformat, GLsizei width)
739 {
740 texstorage_no_error(1, target, levels, internalformat, width, 1, 1,
741 "glTexStorage1D");
742 }
743
744
745 void GLAPIENTRY
_mesa_TexStorage1D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)746 _mesa_TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat,
747 GLsizei width)
748 {
749 texstorage_error(1, target, levels, internalformat, width, 1, 1,
750 "glTexStorage1D");
751 }
752
753
754 void GLAPIENTRY
_mesa_TexStorage2D_no_error(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)755 _mesa_TexStorage2D_no_error(GLenum target, GLsizei levels,
756 GLenum internalformat, GLsizei width,
757 GLsizei height)
758 {
759 texstorage_no_error(2, target, levels, internalformat, width, height, 1,
760 "glTexStorage2D");
761 }
762
763
764 void GLAPIENTRY
_mesa_TexStorage2D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)765 _mesa_TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat,
766 GLsizei width, GLsizei height)
767 {
768 texstorage_error(2, target, levels, internalformat, width, height, 1,
769 "glTexStorage2D");
770 }
771
772
773 void GLAPIENTRY
_mesa_TexStorage3D_no_error(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)774 _mesa_TexStorage3D_no_error(GLenum target, GLsizei levels,
775 GLenum internalformat, GLsizei width,
776 GLsizei height, GLsizei depth)
777 {
778 texstorage_no_error(3, target, levels, internalformat, width, height, depth,
779 "glTexStorage3D");
780 }
781
782
783 void GLAPIENTRY
_mesa_TexStorage3D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)784 _mesa_TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
785 GLsizei width, GLsizei height, GLsizei depth)
786 {
787 texstorage_error(3, target, levels, internalformat, width, height, depth,
788 "glTexStorage3D");
789 }
790
791
792 void GLAPIENTRY
_mesa_TextureStorage1D_no_error(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width)793 _mesa_TextureStorage1D_no_error(GLuint texture, GLsizei levels,
794 GLenum internalformat, GLsizei width)
795 {
796 texturestorage_no_error(1, texture, levels, internalformat, width, 1, 1,
797 "glTextureStorage1D");
798 }
799
800
801 void GLAPIENTRY
_mesa_TextureStorage1D(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width)802 _mesa_TextureStorage1D(GLuint texture, GLsizei levels, GLenum internalformat,
803 GLsizei width)
804 {
805 texturestorage_error(1, texture, levels, internalformat, width, 1, 1,
806 "glTextureStorage1D");
807 }
808
809
810 void GLAPIENTRY
_mesa_TextureStorage2D_no_error(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)811 _mesa_TextureStorage2D_no_error(GLuint texture, GLsizei levels,
812 GLenum internalformat,
813 GLsizei width, GLsizei height)
814 {
815 texturestorage_no_error(2, texture, levels, internalformat, width, height, 1,
816 "glTextureStorage2D");
817 }
818
819
820 void GLAPIENTRY
_mesa_TextureStorage2D(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)821 _mesa_TextureStorage2D(GLuint texture, GLsizei levels,
822 GLenum internalformat,
823 GLsizei width, GLsizei height)
824 {
825 texturestorage_error(2, texture, levels, internalformat, width, height, 1,
826 "glTextureStorage2D");
827 }
828
829
830 void GLAPIENTRY
_mesa_TextureStorage3D_no_error(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)831 _mesa_TextureStorage3D_no_error(GLuint texture, GLsizei levels,
832 GLenum internalformat, GLsizei width,
833 GLsizei height, GLsizei depth)
834 {
835 texturestorage_no_error(3, texture, levels, internalformat, width, height,
836 depth, "glTextureStorage3D");
837 }
838
839
840 void GLAPIENTRY
_mesa_TextureStorage3D(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)841 _mesa_TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat,
842 GLsizei width, GLsizei height, GLsizei depth)
843 {
844 texturestorage_error(3, texture, levels, internalformat, width, height, depth,
845 "glTextureStorage3D");
846 }
847
848
849 void GLAPIENTRY
_mesa_TextureStorage1DEXT(GLuint texture,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)850 _mesa_TextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels,
851 GLenum internalformat,
852 GLsizei width)
853 {
854 GET_CURRENT_CONTEXT(ctx);
855 /* 'texture' must always be initialized, even if the call to
856 * glTextureStorage1DEXT will generate an error.
857 */
858 if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
859 "glTextureStorage1DEXT"))
860 return;
861 texturestorage_error(1, texture, levels, internalformat, width, 1, 1,
862 "glTextureStorage1DEXT");
863 }
864
865
866 void GLAPIENTRY
_mesa_TextureStorage2DEXT(GLuint texture,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)867 _mesa_TextureStorage2DEXT(GLuint texture, GLenum target, GLsizei levels,
868 GLenum internalformat,
869 GLsizei width, GLsizei height)
870 {
871 GET_CURRENT_CONTEXT(ctx);
872 /* 'texture' must always be initialized, even if the call to
873 * glTextureStorage2DEXT will generate an error.
874 */
875 if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
876 "glTextureStorage2DEXT"))
877 return;
878 texturestorage_error(2, texture, levels, internalformat, width, height, 1,
879 "glTextureStorage2DEXT");
880 }
881
882
883 void GLAPIENTRY
_mesa_TextureStorage3DEXT(GLuint texture,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)884 _mesa_TextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels,
885 GLenum internalformat,
886 GLsizei width, GLsizei height, GLsizei depth)
887 {
888 GET_CURRENT_CONTEXT(ctx);
889 /* 'texture' must always be initialized, even if the call to
890 * glTextureStorage3DEXT will generate an error.
891 */
892 if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
893 "glTextureStorage3DEXT"))
894 return;
895 texturestorage_error(3, texture, levels, internalformat, width, height, depth,
896 "glTextureStorage3DEXT");
897 }
898
899
900 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)901 _mesa_texture_storage_memory(struct gl_context *ctx, GLuint dims,
902 struct gl_texture_object *texObj,
903 struct gl_memory_object *memObj,
904 GLenum target, GLsizei levels,
905 GLenum internalformat, GLsizei width,
906 GLsizei height, GLsizei depth,
907 GLuint64 offset, bool dsa)
908 {
909 assert(memObj);
910
911 texture_storage(ctx, dims, texObj, memObj, target, levels, internalformat,
912 width, height, depth, offset, dsa, false, "");
913 }
914