1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2011 VMware, Inc. All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file texstorage.c
27 * GL_ARB_texture_storage functions
28 */
29
30 #include "glheader.h"
31 #include "context.h"
32 #include "enums.h"
33
34 #include "macros.h"
35 #include "teximage.h"
36 #include "texobj.h"
37 #include "mipmap.h"
38 #include "texstorage.h"
39 #include "textureview.h"
40 #include "mtypes.h"
41 #include "glformats.h"
42 #include "hash.h"
43 #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 return GL_TRUE;
173 }
174
175
176 /**
177 * Clear all fields of texture object to zeros. Used for proxy texture tests
178 * and to clean up when a texture memory allocation fails.
179 */
180 static void
clear_texture_fields(struct gl_context * ctx,struct gl_texture_object * texObj)181 clear_texture_fields(struct gl_context *ctx,
182 struct gl_texture_object *texObj)
183 {
184 const GLenum target = texObj->Target;
185 const GLuint numFaces = _mesa_num_tex_faces(target);
186 GLint level;
187 GLuint face;
188
189 for (level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
190 for (face = 0; face < numFaces; face++) {
191 struct gl_texture_image *texImage =
192 get_tex_image(ctx, texObj, face, level);
193
194 if (!texImage) {
195 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
196 return;
197 }
198
199 _mesa_clear_texture_image(ctx, texImage);
200 }
201 }
202 }
203
204
205 /**
206 * Update/re-validate framebuffer object.
207 */
208 static void
update_fbo_texture(struct gl_context * ctx,struct gl_texture_object * texObj)209 update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
210 {
211 const unsigned numFaces = _mesa_num_tex_faces(texObj->Target);
212 for (int level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
213 for (unsigned face = 0; face < numFaces; face++)
214 _mesa_update_fbo_texture(ctx, texObj, face, level);
215 }
216 }
217
218
219 GLboolean
_mesa_is_legal_tex_storage_format(const struct gl_context * ctx,GLenum internalformat)220 _mesa_is_legal_tex_storage_format(const struct gl_context *ctx,
221 GLenum internalformat)
222 {
223 /* check internal format - note that only sized formats are allowed */
224 switch (internalformat) {
225 case GL_ALPHA:
226 case GL_LUMINANCE:
227 case GL_LUMINANCE_ALPHA:
228 case GL_INTENSITY:
229 case GL_RED:
230 case GL_RG:
231 case GL_RGB:
232 case GL_RGBA:
233 case GL_BGRA:
234 case GL_DEPTH_COMPONENT:
235 case GL_DEPTH_STENCIL:
236 case GL_COMPRESSED_ALPHA:
237 case GL_COMPRESSED_LUMINANCE_ALPHA:
238 case GL_COMPRESSED_LUMINANCE:
239 case GL_COMPRESSED_INTENSITY:
240 case GL_COMPRESSED_RGB:
241 case GL_COMPRESSED_RGBA:
242 case GL_COMPRESSED_SRGB:
243 case GL_COMPRESSED_SRGB_ALPHA:
244 case GL_COMPRESSED_SLUMINANCE:
245 case GL_COMPRESSED_SLUMINANCE_ALPHA:
246 case GL_RED_INTEGER:
247 case GL_GREEN_INTEGER:
248 case GL_BLUE_INTEGER:
249 case GL_ALPHA_INTEGER:
250 case GL_RGB_INTEGER:
251 case GL_RGBA_INTEGER:
252 case GL_BGR_INTEGER:
253 case GL_BGRA_INTEGER:
254 case GL_LUMINANCE_INTEGER_EXT:
255 case GL_LUMINANCE_ALPHA_INTEGER_EXT:
256 /* these unsized formats are illegal */
257 return GL_FALSE;
258 default:
259 return _mesa_base_tex_format(ctx, internalformat) > 0;
260 }
261 }
262
263
264 /**
265 * Do error checking for calls to glTexStorage1/2/3D().
266 * If an error is found, record it with _mesa_error(), unless the target
267 * is a proxy texture.
268 * \return GL_TRUE if any error, GL_FALSE otherwise.
269 */
270 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)271 tex_storage_error_check(struct gl_context *ctx,
272 struct gl_texture_object *texObj,
273 struct gl_memory_object *memObj,
274 GLuint dims, GLenum target,
275 GLsizei levels, GLenum internalformat,
276 GLsizei width, GLsizei height, GLsizei depth,
277 bool dsa)
278 {
279 const char* suffix = dsa ? (memObj ? "tureMem" : "ture") :
280 (memObj ? "Mem" : "");
281
282 /* Legal format checking has been moved to texstorage and texturestorage in
283 * order to allow meta functions to use legacy formats. */
284
285 /* size check */
286 if (!_mesa_valid_tex_storage_dim(width, height, depth)) {
287 _mesa_error(ctx, GL_INVALID_VALUE,
288 "glTex%sStorage%uD(width, height or depth < 1)",
289 suffix, dims);
290 return GL_TRUE;
291 }
292
293 if (_mesa_is_compressed_format(ctx, internalformat)) {
294 GLenum err;
295 if (!_mesa_target_can_be_compressed(ctx, target, internalformat, &err)) {
296 _mesa_error(ctx, err,
297 "glTex%sStorage%dD(internalformat = %s)", suffix, dims,
298 _mesa_enum_to_string(internalformat));
299 return GL_TRUE;
300 }
301 }
302
303 /* levels check */
304 if (levels < 1) {
305 _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(levels < 1)",
306 suffix, dims);
307 return GL_TRUE;
308 }
309
310 /* check levels against maximum (note different error than above) */
311 if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) {
312 _mesa_error(ctx, GL_INVALID_OPERATION,
313 "glTex%sStorage%uD(levels too large)",
314 suffix, dims);
315 return GL_TRUE;
316 }
317
318 /* check levels against width/height/depth */
319 if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) {
320 _mesa_error(ctx, GL_INVALID_OPERATION,
321 "glTex%sStorage%uD(too many levels"
322 " for max texture dimension)",
323 suffix, dims);
324 return GL_TRUE;
325 }
326
327 /* non-default texture object check */
328 if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) {
329 _mesa_error(ctx, GL_INVALID_OPERATION,
330 "glTex%sStorage%uD(texture object 0)",
331 suffix, dims);
332 return GL_TRUE;
333 }
334
335 /* Check if texObj->Immutable is set */
336 if (!_mesa_is_proxy_texture(target) && texObj->Immutable) {
337 _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(immutable)",
338 suffix, dims);
339 return GL_TRUE;
340 }
341
342 /* additional checks for depth textures */
343 if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat)) {
344 _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(bad target for texture)",
345 suffix, dims);
346 return GL_TRUE;
347 }
348
349 return GL_FALSE;
350 }
351
352 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)353 _mesa_sparse_texture_error_check(struct gl_context *ctx, GLuint dims,
354 struct gl_texture_object *texObj,
355 mesa_format format, GLenum target, GLsizei levels,
356 GLsizei width, GLsizei height, GLsizei depth,
357 const char *func)
358 {
359 int px, py, pz;
360 int index = texObj->VirtualPageSizeIndex;
361 if (!st_GetSparseTextureVirtualPageSize(ctx, target, format, index,
362 &px, &py, &pz)) {
363 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(sparse index = %d)",
364 func, index);
365 return GL_TRUE;
366 }
367
368 if (target == GL_TEXTURE_3D) {
369 if (width > ctx->Const.MaxSparse3DTextureSize ||
370 height > ctx->Const.MaxSparse3DTextureSize ||
371 depth > ctx->Const.MaxSparse3DTextureSize)
372 goto exceed_max_size;
373 } else {
374 if (width > ctx->Const.MaxSparseTextureSize ||
375 height > ctx->Const.MaxSparseTextureSize)
376 goto exceed_max_size;
377
378 if (target == GL_TEXTURE_2D_ARRAY ||
379 target == GL_TEXTURE_CUBE_MAP_ARRAY) {
380 if (depth > ctx->Const.MaxSparseArrayTextureLayers)
381 goto exceed_max_size;
382 } else if (target == GL_TEXTURE_1D_ARRAY) {
383 if (height > ctx->Const.MaxSparseArrayTextureLayers)
384 goto exceed_max_size;
385 }
386 }
387
388 /* ARB_sparse_texture2 allow non-page-aligned base texture size. */
389 if (!_mesa_has_ARB_sparse_texture2(ctx) &&
390 (width % px || height % py || depth % pz)) {
391 _mesa_error(ctx, GL_INVALID_VALUE, "%s(sparse page size)", func);
392 return GL_TRUE;
393 }
394
395 /* ARB_sparse_texture spec:
396 *
397 * If the value of SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB is FALSE,
398 * then TexStorage* will generate an INVALID_OPERATION error if
399 * * the texture's TEXTURE_SPARSE_ARB parameter is TRUE,
400 * * <target> is one of TEXTURE_1D_ARRAY, TEXTURE_2D_ARRAY,
401 * TEXTURE_CUBE_MAP, or TEXTURE_CUBE_MAP_ARRAY, and
402 * * for the virtual page size corresponding to the
403 * VIRTUAL_PAGE_SIZE_INDEX_ARB parameter, either of the following is
404 * true:
405 * - <width> is not a multiple of VIRTUAL_PAGE_SIZE_X_ARB *
406 * 2^(<levels>-1), or
407 * - <height> is not a multiple of VIRTUAL_PAGE_SIZE_Y_ARB *
408 * 2^(<levels>-1).
409 *
410 * This make sure all allocated mipmap level size is multiple of virtual
411 * page size when SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB is FALSE.
412 */
413 if (!ctx->Const.SparseTextureFullArrayCubeMipmaps &&
414 (target == GL_TEXTURE_1D_ARRAY ||
415 target == GL_TEXTURE_2D_ARRAY ||
416 target == GL_TEXTURE_CUBE_MAP ||
417 target == GL_TEXTURE_CUBE_MAP_ARRAY) &&
418 (width % (px << (levels - 1)) ||
419 height % (py << (levels - 1)))) {
420 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(sparse array align)", func);
421 return GL_TRUE;
422 }
423
424 return GL_FALSE;
425
426 exceed_max_size:
427 _mesa_error(ctx, GL_INVALID_VALUE, "%s(exceed max sparse size)", func);
428 return GL_TRUE;
429 }
430
431 /**
432 * Helper that does the storage allocation for _mesa_TexStorage1/2/3D()
433 * and _mesa_TextureStorage1/2/3D().
434 */
435 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)436 texture_storage(struct gl_context *ctx, GLuint dims,
437 struct gl_texture_object *texObj,
438 struct gl_memory_object *memObj, GLenum target,
439 GLsizei levels, GLenum internalformat, GLsizei width,
440 GLsizei height, GLsizei depth, GLuint64 offset, bool dsa,
441 bool no_error)
442 {
443 GLboolean sizeOK = GL_TRUE, dimensionsOK = GL_TRUE;
444 mesa_format texFormat;
445 const char* suffix = dsa ? (memObj ? "tureMem" : "ture") :
446 (memObj ? "Mem" : "");
447
448 assert(texObj);
449
450 if (!no_error) {
451 if (tex_storage_error_check(ctx, texObj, memObj, dims, target, levels,
452 internalformat, width, height, depth, dsa)) {
453 return; /* error was recorded */
454 }
455 }
456
457 texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0,
458 internalformat, GL_NONE, GL_NONE);
459
460 if (!no_error) {
461 /* check that width, height, depth are legal for the mipmap level */
462 dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0,
463 width, height, depth, 0);
464
465 sizeOK = st_TestProxyTexImage(ctx, target, levels, 0, texFormat,
466 1, width, height, depth);
467 }
468
469 if (_mesa_is_proxy_texture(target)) {
470 if (dimensionsOK && sizeOK) {
471 initialize_texture_fields(ctx, texObj, levels, width, height, depth,
472 internalformat, texFormat);
473 }
474 else {
475 /* clear all image fields for [levels] */
476 clear_texture_fields(ctx, texObj);
477 }
478 }
479 else {
480 if (!no_error) {
481 if (!dimensionsOK) {
482 _mesa_error(ctx, GL_INVALID_VALUE,
483 "glTex%sStorage%uD(invalid width, height or depth)",
484 suffix, dims);
485 return;
486 }
487
488 if (!sizeOK) {
489 _mesa_error(ctx, GL_OUT_OF_MEMORY,
490 "glTex%sStorage%uD(texture too large)",
491 suffix, dims);
492 return;
493 }
494
495 if (texObj->IsSparse) {
496 char func[32];
497 snprintf(func, 32, "glTex%sStorage%uD", suffix, dims);
498 if (_mesa_sparse_texture_error_check(ctx, dims, texObj, texFormat, target,
499 levels, width, height, depth, func))
500 return; /* error was recorded */
501 }
502 }
503
504 assert(levels > 0);
505 assert(width > 0);
506 assert(height > 0);
507 assert(depth > 0);
508
509 if (!initialize_texture_fields(ctx, texObj, levels, width, height, depth,
510 internalformat, texFormat)) {
511 return;
512 }
513
514 /* Setup the backing memory */
515 if (memObj) {
516 if (!st_SetTextureStorageForMemoryObject(ctx, texObj, memObj,
517 levels,
518 width, height, depth,
519 offset)) {
520
521 clear_texture_fields(ctx, texObj);
522 return;
523 }
524 }
525 else {
526 if (!st_AllocTextureStorage(ctx, texObj, levels,
527 width, height, depth)) {
528 /* Reset the texture images' info to zeros.
529 * Strictly speaking, we probably don't have to do this since
530 * generating GL_OUT_OF_MEMORY can leave things in an undefined
531 * state but this puts things in a consistent state.
532 */
533 clear_texture_fields(ctx, texObj);
534 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex%sStorage%uD",
535 suffix, dims);
536 return;
537 }
538 }
539
540 _mesa_set_texture_view_state(ctx, texObj, target, levels);
541
542 update_fbo_texture(ctx, texObj);
543 }
544 }
545
546
547 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)548 texture_storage_error(struct gl_context *ctx, GLuint dims,
549 struct gl_texture_object *texObj,
550 GLenum target, GLsizei levels,
551 GLenum internalformat, GLsizei width,
552 GLsizei height, GLsizei depth, bool dsa)
553 {
554 texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat,
555 width, height, depth, dsa, 0, false);
556 }
557
558
559 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)560 texture_storage_no_error(struct gl_context *ctx, GLuint dims,
561 struct gl_texture_object *texObj,
562 GLenum target, GLsizei levels,
563 GLenum internalformat, GLsizei width,
564 GLsizei height, GLsizei depth, bool dsa)
565 {
566 texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat,
567 width, height, depth, dsa, 0, true);
568 }
569
570
571 /**
572 * Helper used by _mesa_TexStorage1/2/3D().
573 */
574 static void
texstorage_error(GLuint dims,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,const char * caller)575 texstorage_error(GLuint dims, GLenum target, GLsizei levels,
576 GLenum internalformat, GLsizei width, GLsizei height,
577 GLsizei depth, const char *caller)
578 {
579 struct gl_texture_object *texObj;
580 GET_CURRENT_CONTEXT(ctx);
581
582 /* Check target. This is done here so that texture_storage
583 * can receive unsized formats.
584 */
585 if (!_mesa_is_legal_tex_storage_target(ctx, dims, target)) {
586 _mesa_error(ctx, GL_INVALID_ENUM,
587 "%s(illegal target=%s)",
588 caller, _mesa_enum_to_string(target));
589 return;
590 }
591
592 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
593 _mesa_debug(ctx, "%s %s %d %s %d %d %d\n", caller,
594 _mesa_enum_to_string(target), levels,
595 _mesa_enum_to_string(internalformat),
596 width, height, depth);
597
598 /* Check the format to make sure it is sized. */
599 if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
600 _mesa_error(ctx, GL_INVALID_ENUM,
601 "%s(internalformat = %s)", caller,
602 _mesa_enum_to_string(internalformat));
603 return;
604 }
605
606 texObj = _mesa_get_current_tex_object(ctx, target);
607 if (!texObj)
608 return;
609
610 texture_storage_error(ctx, dims, texObj, target, levels,
611 internalformat, width, height, depth, false);
612 }
613
614
615 static void
texstorage_no_error(GLuint dims,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)616 texstorage_no_error(GLuint dims, GLenum target, GLsizei levels,
617 GLenum internalformat, GLsizei width, GLsizei height,
618 GLsizei depth)
619 {
620 GET_CURRENT_CONTEXT(ctx);
621
622 struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target);
623 texture_storage_no_error(ctx, dims, texObj, target, levels,
624 internalformat, width, height, depth, false);
625 }
626
627
628 /**
629 * Helper used by _mesa_TextureStorage1/2/3D().
630 */
631 static void
texturestorage_error(GLuint dims,GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,const char * caller)632 texturestorage_error(GLuint dims, GLuint texture, GLsizei levels,
633 GLenum internalformat, GLsizei width, GLsizei height,
634 GLsizei depth, const char *caller)
635 {
636 struct gl_texture_object *texObj;
637 GET_CURRENT_CONTEXT(ctx);
638
639 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
640 _mesa_debug(ctx, "%s %d %d %s %d %d %d\n",
641 caller, texture, levels,
642 _mesa_enum_to_string(internalformat),
643 width, height, depth);
644
645 /* Check the format to make sure it is sized. */
646 if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
647 _mesa_error(ctx, GL_INVALID_ENUM,
648 "%s(internalformat = %s)", caller,
649 _mesa_enum_to_string(internalformat));
650 return;
651 }
652
653 texObj = _mesa_lookup_texture_err(ctx, texture, caller);
654 if (!texObj)
655 return;
656
657 /* Check target. This is done here so that texture_storage
658 * can receive unsized formats.
659 */
660 if (!_mesa_is_legal_tex_storage_target(ctx, dims, texObj->Target)) {
661 _mesa_error(ctx, GL_INVALID_OPERATION,
662 "%s(illegal target=%s)", caller,
663 _mesa_enum_to_string(texObj->Target));
664 return;
665 }
666
667 texture_storage_error(ctx, dims, texObj, texObj->Target,
668 levels, internalformat, width, height, depth, true);
669 }
670
671
672 static void
texturestorage_no_error(GLuint dims,GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)673 texturestorage_no_error(GLuint dims, GLuint texture, GLsizei levels,
674 GLenum internalformat, GLsizei width, GLsizei height,
675 GLsizei depth)
676 {
677 GET_CURRENT_CONTEXT(ctx);
678
679 struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture);
680 texture_storage_no_error(ctx, dims, texObj, texObj->Target,
681 levels, internalformat, width, height, depth, true);
682 }
683
684
685 void GLAPIENTRY
_mesa_TexStorage1D_no_error(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)686 _mesa_TexStorage1D_no_error(GLenum target, GLsizei levels,
687 GLenum internalformat, GLsizei width)
688 {
689 texstorage_no_error(1, target, levels, internalformat, width, 1, 1);
690 }
691
692
693 void GLAPIENTRY
_mesa_TexStorage1D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)694 _mesa_TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat,
695 GLsizei width)
696 {
697 texstorage_error(1, target, levels, internalformat, width, 1, 1,
698 "glTexStorage1D");
699 }
700
701
702 void GLAPIENTRY
_mesa_TexStorage2D_no_error(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)703 _mesa_TexStorage2D_no_error(GLenum target, GLsizei levels,
704 GLenum internalformat, GLsizei width,
705 GLsizei height)
706 {
707 texstorage_no_error(2, target, levels, internalformat, width, height, 1);
708 }
709
710
711 void GLAPIENTRY
_mesa_TexStorage2D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)712 _mesa_TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat,
713 GLsizei width, GLsizei height)
714 {
715 texstorage_error(2, target, levels, internalformat, width, height, 1,
716 "glTexStorage2D");
717 }
718
719
720 void GLAPIENTRY
_mesa_TexStorage3D_no_error(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)721 _mesa_TexStorage3D_no_error(GLenum target, GLsizei levels,
722 GLenum internalformat, GLsizei width,
723 GLsizei height, GLsizei depth)
724 {
725 texstorage_no_error(3, target, levels, internalformat, width, height, depth);
726 }
727
728
729 void GLAPIENTRY
_mesa_TexStorage3D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)730 _mesa_TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
731 GLsizei width, GLsizei height, GLsizei depth)
732 {
733 texstorage_error(3, target, levels, internalformat, width, height, depth,
734 "glTexStorage3D");
735 }
736
737
738 void GLAPIENTRY
_mesa_TextureStorage1D_no_error(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width)739 _mesa_TextureStorage1D_no_error(GLuint texture, GLsizei levels,
740 GLenum internalformat, GLsizei width)
741 {
742 texturestorage_no_error(1, texture, levels, internalformat, width, 1, 1);
743 }
744
745
746 void GLAPIENTRY
_mesa_TextureStorage1D(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width)747 _mesa_TextureStorage1D(GLuint texture, GLsizei levels, GLenum internalformat,
748 GLsizei width)
749 {
750 texturestorage_error(1, texture, levels, internalformat, width, 1, 1,
751 "glTextureStorage1D");
752 }
753
754
755 void GLAPIENTRY
_mesa_TextureStorage2D_no_error(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)756 _mesa_TextureStorage2D_no_error(GLuint texture, GLsizei levels,
757 GLenum internalformat,
758 GLsizei width, GLsizei height)
759 {
760 texturestorage_no_error(2, texture, levels, internalformat, width, height, 1);
761 }
762
763
764 void GLAPIENTRY
_mesa_TextureStorage2D(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)765 _mesa_TextureStorage2D(GLuint texture, GLsizei levels,
766 GLenum internalformat,
767 GLsizei width, GLsizei height)
768 {
769 texturestorage_error(2, texture, levels, internalformat, width, height, 1,
770 "glTextureStorage2D");
771 }
772
773
774 void GLAPIENTRY
_mesa_TextureStorage3D_no_error(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)775 _mesa_TextureStorage3D_no_error(GLuint texture, GLsizei levels,
776 GLenum internalformat, GLsizei width,
777 GLsizei height, GLsizei depth)
778 {
779 texturestorage_no_error(3, texture, levels, internalformat, width, height,
780 depth);
781 }
782
783
784 void GLAPIENTRY
_mesa_TextureStorage3D(GLuint texture,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)785 _mesa_TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat,
786 GLsizei width, GLsizei height, GLsizei depth)
787 {
788 texturestorage_error(3, texture, levels, internalformat, width, height, depth,
789 "glTextureStorage3D");
790 }
791
792
793 void GLAPIENTRY
_mesa_TextureStorage1DEXT(GLuint texture,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)794 _mesa_TextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels,
795 GLenum internalformat,
796 GLsizei width)
797 {
798 GET_CURRENT_CONTEXT(ctx);
799 /* 'texture' must always be initialized, even if the call to
800 * glTextureStorage1DEXT will generate an error.
801 */
802 if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
803 "glTextureStorage1DEXT"))
804 return;
805 texturestorage_error(1, texture, levels, internalformat, width, 1, 1,
806 "glTextureStorage1DEXT");
807 }
808
809
810 void GLAPIENTRY
_mesa_TextureStorage2DEXT(GLuint texture,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)811 _mesa_TextureStorage2DEXT(GLuint texture, GLenum target, GLsizei levels,
812 GLenum internalformat,
813 GLsizei width, GLsizei height)
814 {
815 GET_CURRENT_CONTEXT(ctx);
816 /* 'texture' must always be initialized, even if the call to
817 * glTextureStorage2DEXT will generate an error.
818 */
819 if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
820 "glTextureStorage2DEXT"))
821 return;
822 texturestorage_error(2, texture, levels, internalformat, width, height, 1,
823 "glTextureStorage2DEXT");
824 }
825
826
827 void GLAPIENTRY
_mesa_TextureStorage3DEXT(GLuint texture,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)828 _mesa_TextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels,
829 GLenum internalformat,
830 GLsizei width, GLsizei height, GLsizei depth)
831 {
832 GET_CURRENT_CONTEXT(ctx);
833 /* 'texture' must always be initialized, even if the call to
834 * glTextureStorage3DEXT will generate an error.
835 */
836 if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true,
837 "glTextureStorage3DEXT"))
838 return;
839 texturestorage_error(3, texture, levels, internalformat, width, height, depth,
840 "glTextureStorage3DEXT");
841 }
842
843
844 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)845 _mesa_texture_storage_memory(struct gl_context *ctx, GLuint dims,
846 struct gl_texture_object *texObj,
847 struct gl_memory_object *memObj,
848 GLenum target, GLsizei levels,
849 GLenum internalformat, GLsizei width,
850 GLsizei height, GLsizei depth,
851 GLuint64 offset, bool dsa)
852 {
853 assert(memObj);
854
855 texture_storage(ctx, dims, texObj, memObj, target, levels, internalformat,
856 width, height, depth, offset, dsa, false);
857 }
858