Merge branch 'mesa_7_6_branch'
[mesa.git] / src / mesa / main / teximage.c
1 /*
2 * mesa 3-D graphics library
3 * Version: 7.6
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 /**
28 * \file teximage.c
29 * Texture image-related functions.
30 */
31
32
33 #include "glheader.h"
34 #include "bufferobj.h"
35 #include "context.h"
36 #include "convolve.h"
37 #include "enums.h"
38 #include "fbobject.h"
39 #include "framebuffer.h"
40 #include "hash.h"
41 #include "image.h"
42 #include "imports.h"
43 #include "macros.h"
44 #include "state.h"
45 #include "texcompress.h"
46 #include "texformat.h"
47 #include "teximage.h"
48 #include "texstate.h"
49 #include "texstore.h"
50 #include "mtypes.h"
51
52
53 /**
54 * State changes which we care about for glCopyTex[Sub]Image() calls.
55 * In particular, we care about pixel transfer state and buffer state
56 * (such as glReadBuffer to make sure we read from the right renderbuffer).
57 */
58 #define NEW_COPY_TEX_STATE (_MESA_NEW_TRANSFER_STATE | \
59 _NEW_BUFFERS | \
60 _NEW_PIXEL)
61
62
63
64 /**
65 * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
66 * elsewhere.
67 */
68 void *
69 _mesa_alloc_texmemory(GLsizei bytes)
70 {
71 return _mesa_align_malloc(bytes, 512);
72 }
73
74
75 /**
76 * Free texture memory allocated with _mesa_alloc_texmemory()
77 */
78 void
79 _mesa_free_texmemory(void *m)
80 {
81 _mesa_align_free(m);
82 }
83
84
85
86
87 #if 0
88 static void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img)
89 {
90 #if CHAN_TYPE != GL_UNSIGNED_BYTE
91 _mesa_problem(NULL, "PrintTexture not supported");
92 #else
93 GLuint i, j, c;
94 const GLubyte *data = (const GLubyte *) img->Data;
95
96 if (!data) {
97 _mesa_printf("No texture data\n");
98 return;
99 }
100
101 switch (img->Format) {
102 case GL_ALPHA:
103 case GL_LUMINANCE:
104 case GL_INTENSITY:
105 case GL_COLOR_INDEX:
106 c = 1;
107 break;
108 case GL_LUMINANCE_ALPHA:
109 c = 2;
110 break;
111 case GL_RGB:
112 c = 3;
113 break;
114 case GL_RGBA:
115 c = 4;
116 break;
117 default:
118 _mesa_problem(NULL, "error in PrintTexture\n");
119 return;
120 }
121
122 for (i = 0; i < img->Height; i++) {
123 for (j = 0; j < img->Width; j++) {
124 if (c==1)
125 _mesa_printf("%02x ", data[0]);
126 else if (c==2)
127 _mesa_printf("%02x%02x ", data[0], data[1]);
128 else if (c==3)
129 _mesa_printf("%02x%02x%02x ", data[0], data[1], data[2]);
130 else if (c==4)
131 _mesa_printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]);
132 data += (img->RowStride - img->Width) * c;
133 }
134 /* XXX use img->ImageStride here */
135 _mesa_printf("\n");
136 }
137 #endif
138 }
139 #endif
140
141
142 /*
143 * Compute floor(log_base_2(n)).
144 * If n < 0 return -1.
145 */
146 static int
147 logbase2( int n )
148 {
149 GLint i = 1;
150 GLint log2 = 0;
151
152 if (n < 0)
153 return -1;
154
155 if (n == 0)
156 return 0;
157
158 while ( n > i ) {
159 i *= 2;
160 log2++;
161 }
162 if (i != n) {
163 return log2 - 1;
164 }
165 else {
166 return log2;
167 }
168 }
169
170
171
172 /**
173 * Return the simple base format for a given internal texture format.
174 * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
175 *
176 * \param ctx GL context.
177 * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
178 *
179 * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
180 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
181 *
182 * This is the format which is used during texture application (i.e. the
183 * texture format and env mode determine the arithmetic used.
184 *
185 * XXX this could be static
186 */
187 GLint
188 _mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
189 {
190 switch (internalFormat) {
191 case GL_ALPHA:
192 case GL_ALPHA4:
193 case GL_ALPHA8:
194 case GL_ALPHA12:
195 case GL_ALPHA16:
196 return GL_ALPHA;
197 case 1:
198 case GL_LUMINANCE:
199 case GL_LUMINANCE4:
200 case GL_LUMINANCE8:
201 case GL_LUMINANCE12:
202 case GL_LUMINANCE16:
203 return GL_LUMINANCE;
204 case 2:
205 case GL_LUMINANCE_ALPHA:
206 case GL_LUMINANCE4_ALPHA4:
207 case GL_LUMINANCE6_ALPHA2:
208 case GL_LUMINANCE8_ALPHA8:
209 case GL_LUMINANCE12_ALPHA4:
210 case GL_LUMINANCE12_ALPHA12:
211 case GL_LUMINANCE16_ALPHA16:
212 return GL_LUMINANCE_ALPHA;
213 case GL_INTENSITY:
214 case GL_INTENSITY4:
215 case GL_INTENSITY8:
216 case GL_INTENSITY12:
217 case GL_INTENSITY16:
218 return GL_INTENSITY;
219 case 3:
220 case GL_RGB:
221 case GL_R3_G3_B2:
222 case GL_RGB4:
223 case GL_RGB5:
224 case GL_RGB8:
225 case GL_RGB10:
226 case GL_RGB12:
227 case GL_RGB16:
228 return GL_RGB;
229 case 4:
230 case GL_RGBA:
231 case GL_RGBA2:
232 case GL_RGBA4:
233 case GL_RGB5_A1:
234 case GL_RGBA8:
235 case GL_RGB10_A2:
236 case GL_RGBA12:
237 case GL_RGBA16:
238 return GL_RGBA;
239 default:
240 ; /* fallthrough */
241 }
242
243 if (ctx->Extensions.EXT_paletted_texture) {
244 switch (internalFormat) {
245 case GL_COLOR_INDEX:
246 case GL_COLOR_INDEX1_EXT:
247 case GL_COLOR_INDEX2_EXT:
248 case GL_COLOR_INDEX4_EXT:
249 case GL_COLOR_INDEX8_EXT:
250 case GL_COLOR_INDEX12_EXT:
251 case GL_COLOR_INDEX16_EXT:
252 return GL_COLOR_INDEX;
253 default:
254 ; /* fallthrough */
255 }
256 }
257
258 if (ctx->Extensions.ARB_depth_texture) {
259 switch (internalFormat) {
260 case GL_DEPTH_COMPONENT:
261 case GL_DEPTH_COMPONENT16:
262 case GL_DEPTH_COMPONENT24:
263 case GL_DEPTH_COMPONENT32:
264 return GL_DEPTH_COMPONENT;
265 default:
266 ; /* fallthrough */
267 }
268 }
269
270 switch (internalFormat) {
271 case GL_COMPRESSED_ALPHA:
272 return GL_ALPHA;
273 case GL_COMPRESSED_LUMINANCE:
274 return GL_LUMINANCE;
275 case GL_COMPRESSED_LUMINANCE_ALPHA:
276 return GL_LUMINANCE_ALPHA;
277 case GL_COMPRESSED_INTENSITY:
278 return GL_INTENSITY;
279 case GL_COMPRESSED_RGB:
280 return GL_RGB;
281 case GL_COMPRESSED_RGBA:
282 return GL_RGBA;
283 default:
284 ; /* fallthrough */
285 }
286
287 if (ctx->Extensions.TDFX_texture_compression_FXT1) {
288 switch (internalFormat) {
289 case GL_COMPRESSED_RGB_FXT1_3DFX:
290 return GL_RGB;
291 case GL_COMPRESSED_RGBA_FXT1_3DFX:
292 return GL_RGBA;
293 default:
294 ; /* fallthrough */
295 }
296 }
297
298 if (ctx->Extensions.EXT_texture_compression_s3tc) {
299 switch (internalFormat) {
300 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
301 return GL_RGB;
302 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
303 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
304 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
305 return GL_RGBA;
306 default:
307 ; /* fallthrough */
308 }
309 }
310
311 if (ctx->Extensions.S3_s3tc) {
312 switch (internalFormat) {
313 case GL_RGB_S3TC:
314 case GL_RGB4_S3TC:
315 return GL_RGB;
316 case GL_RGBA_S3TC:
317 case GL_RGBA4_S3TC:
318 return GL_RGBA;
319 default:
320 ; /* fallthrough */
321 }
322 }
323
324 if (ctx->Extensions.MESA_ycbcr_texture) {
325 if (internalFormat == GL_YCBCR_MESA)
326 return GL_YCBCR_MESA;
327 }
328
329 if (ctx->Extensions.ARB_texture_float) {
330 switch (internalFormat) {
331 case GL_ALPHA16F_ARB:
332 case GL_ALPHA32F_ARB:
333 return GL_ALPHA;
334 case GL_RGBA16F_ARB:
335 case GL_RGBA32F_ARB:
336 return GL_RGBA;
337 case GL_RGB16F_ARB:
338 case GL_RGB32F_ARB:
339 return GL_RGB;
340 case GL_INTENSITY16F_ARB:
341 case GL_INTENSITY32F_ARB:
342 return GL_INTENSITY;
343 case GL_LUMINANCE16F_ARB:
344 case GL_LUMINANCE32F_ARB:
345 return GL_LUMINANCE;
346 case GL_LUMINANCE_ALPHA16F_ARB:
347 case GL_LUMINANCE_ALPHA32F_ARB:
348 return GL_LUMINANCE_ALPHA;
349 default:
350 ; /* fallthrough */
351 }
352 }
353
354 if (ctx->Extensions.ATI_envmap_bumpmap) {
355 switch (internalFormat) {
356 case GL_DUDV_ATI:
357 case GL_DU8DV8_ATI:
358 return GL_DUDV_ATI;
359 default:
360 ; /* fallthrough */
361 }
362 }
363
364 if (ctx->Extensions.MESA_texture_signed_rgba) {
365 switch (internalFormat) {
366 case GL_RGBA_SNORM:
367 case GL_RGBA8_SNORM:
368 return GL_RGBA;
369 default:
370 ; /* fallthrough */
371 }
372 }
373
374 if (ctx->Extensions.EXT_packed_depth_stencil) {
375 switch (internalFormat) {
376 case GL_DEPTH_STENCIL_EXT:
377 case GL_DEPTH24_STENCIL8_EXT:
378 return GL_DEPTH_STENCIL_EXT;
379 default:
380 ; /* fallthrough */
381 }
382 }
383
384 #if FEATURE_EXT_texture_sRGB
385 if (ctx->Extensions.EXT_texture_sRGB) {
386 switch (internalFormat) {
387 case GL_SRGB_EXT:
388 case GL_SRGB8_EXT:
389 case GL_COMPRESSED_SRGB_EXT:
390 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
391 return GL_RGB;
392 case GL_SRGB_ALPHA_EXT:
393 case GL_SRGB8_ALPHA8_EXT:
394 case GL_COMPRESSED_SRGB_ALPHA_EXT:
395 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
396 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
397 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
398 return GL_RGBA;
399 case GL_SLUMINANCE_ALPHA_EXT:
400 case GL_SLUMINANCE8_ALPHA8_EXT:
401 case GL_COMPRESSED_SLUMINANCE_EXT:
402 case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
403 return GL_LUMINANCE_ALPHA;
404 case GL_SLUMINANCE_EXT:
405 case GL_SLUMINANCE8_EXT:
406 return GL_LUMINANCE;
407 default:
408 ; /* fallthrough */
409 }
410 }
411
412 #endif /* FEATURE_EXT_texture_sRGB */
413
414 return -1; /* error */
415 }
416
417
418 /**
419 * Test if it is a supported compressed format.
420 *
421 * \param internalFormat the internal format token provided by the user.
422 *
423 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
424 * GL_FALSE otherwise.
425 *
426 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
427 * are supported.
428 */
429 static GLboolean
430 is_compressed_format(GLcontext *ctx, GLenum internalFormat)
431 {
432 GLint supported[100]; /* 100 should be plenty */
433 GLuint i, n;
434
435 n = _mesa_get_compressed_formats(ctx, supported, GL_TRUE);
436 ASSERT(n < 100);
437 for (i = 0; i < n; i++) {
438 if ((GLint) internalFormat == supported[i]) {
439 return GL_TRUE;
440 }
441 }
442 return GL_FALSE;
443 }
444
445
446 /**
447 * For cube map faces, return a face index in [0,5].
448 * For other targets return 0;
449 */
450 GLuint
451 _mesa_tex_target_to_face(GLenum target)
452 {
453 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
454 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)
455 return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
456 else
457 return 0;
458 }
459
460
461
462 /**
463 * Store a gl_texture_image pointer in a gl_texture_object structure
464 * according to the target and level parameters.
465 *
466 * \param tObj texture object.
467 * \param target texture target.
468 * \param level image level.
469 * \param texImage texture image.
470 *
471 * This was basically prompted by the introduction of cube maps.
472 */
473 void
474 _mesa_set_tex_image(struct gl_texture_object *tObj,
475 GLenum target, GLint level,
476 struct gl_texture_image *texImage)
477 {
478 const GLuint face = _mesa_tex_target_to_face(target);
479
480 ASSERT(tObj);
481 ASSERT(texImage);
482 ASSERT(target != GL_TEXTURE_RECTANGLE_NV || level == 0);
483
484 tObj->Image[face][level] = texImage;
485
486 /* Set the 'back' pointer */
487 texImage->TexObject = tObj;
488 }
489
490
491 /**
492 * Allocate a texture image structure.
493 *
494 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
495 * driver.
496 *
497 * \return a pointer to gl_texture_image struct with all fields initialized to
498 * zero.
499 */
500 struct gl_texture_image *
501 _mesa_new_texture_image( GLcontext *ctx )
502 {
503 (void) ctx;
504 return CALLOC_STRUCT(gl_texture_image);
505 }
506
507
508 /**
509 * Free texture image data.
510 * This function is a fallback called via ctx->Driver.FreeTexImageData().
511 *
512 * \param texImage texture image.
513 *
514 * Free the texture image data if it's not marked as client data.
515 */
516 void
517 _mesa_free_texture_image_data(GLcontext *ctx,
518 struct gl_texture_image *texImage)
519 {
520 (void) ctx;
521
522 if (texImage->Data && !texImage->IsClientData) {
523 /* free the old texture data */
524 _mesa_free_texmemory(texImage->Data);
525 }
526
527 texImage->Data = NULL;
528 }
529
530
531 /**
532 * Free texture image.
533 *
534 * \param texImage texture image.
535 *
536 * Free the texture image structure and the associated image data.
537 */
538 void
539 _mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage )
540 {
541 /* Free texImage->Data and/or any other driver-specific texture
542 * image storage.
543 */
544 ASSERT(ctx->Driver.FreeTexImageData);
545 ctx->Driver.FreeTexImageData( ctx, texImage );
546
547 ASSERT(texImage->Data == NULL);
548 if (texImage->ImageOffsets)
549 _mesa_free(texImage->ImageOffsets);
550 _mesa_free(texImage);
551 }
552
553
554 /**
555 * Test if a target is a proxy target.
556 *
557 * \param target texture target.
558 *
559 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
560 */
561 GLboolean
562 _mesa_is_proxy_texture(GLenum target)
563 {
564 /* NUM_TEXTURE_TARGETS should match number of terms below */
565 assert(NUM_TEXTURE_TARGETS == 7);
566
567 return (target == GL_PROXY_TEXTURE_1D ||
568 target == GL_PROXY_TEXTURE_2D ||
569 target == GL_PROXY_TEXTURE_3D ||
570 target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
571 target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
572 target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
573 target == GL_PROXY_TEXTURE_2D_ARRAY_EXT);
574 }
575
576
577 /**
578 * Get the texture object that corresponds to the target of the given texture unit.
579 *
580 * \param ctx GL context.
581 * \param texUnit texture unit.
582 * \param target texture target.
583 *
584 * \return pointer to the texture object on success, or NULL on failure.
585 *
586 * \sa gl_texture_unit.
587 */
588 struct gl_texture_object *
589 _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
590 GLenum target)
591 {
592 switch (target) {
593 case GL_TEXTURE_1D:
594 return texUnit->CurrentTex[TEXTURE_1D_INDEX];
595 case GL_PROXY_TEXTURE_1D:
596 return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
597 case GL_TEXTURE_2D:
598 return texUnit->CurrentTex[TEXTURE_2D_INDEX];
599 case GL_PROXY_TEXTURE_2D:
600 return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
601 case GL_TEXTURE_3D:
602 return texUnit->CurrentTex[TEXTURE_3D_INDEX];
603 case GL_PROXY_TEXTURE_3D:
604 return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
605 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
606 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
607 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
608 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
609 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
610 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
611 case GL_TEXTURE_CUBE_MAP_ARB:
612 return ctx->Extensions.ARB_texture_cube_map
613 ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL;
614 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
615 return ctx->Extensions.ARB_texture_cube_map
616 ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL;
617 case GL_TEXTURE_RECTANGLE_NV:
618 return ctx->Extensions.NV_texture_rectangle
619 ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL;
620 case GL_PROXY_TEXTURE_RECTANGLE_NV:
621 return ctx->Extensions.NV_texture_rectangle
622 ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL;
623 case GL_TEXTURE_1D_ARRAY_EXT:
624 return ctx->Extensions.MESA_texture_array
625 ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
626 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
627 return ctx->Extensions.MESA_texture_array
628 ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
629 case GL_TEXTURE_2D_ARRAY_EXT:
630 return ctx->Extensions.MESA_texture_array
631 ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
632 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
633 return ctx->Extensions.MESA_texture_array
634 ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
635 default:
636 _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
637 return NULL;
638 }
639 }
640
641
642 /**
643 * Get a texture image pointer from a texture object, given a texture
644 * target and mipmap level. The target and level parameters should
645 * have already been error-checked.
646 *
647 * \param ctx GL context.
648 * \param texObj texture unit.
649 * \param target texture target.
650 * \param level image level.
651 *
652 * \return pointer to the texture image structure, or NULL on failure.
653 */
654 struct gl_texture_image *
655 _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj,
656 GLenum target, GLint level)
657 {
658 const GLuint face = _mesa_tex_target_to_face(target);
659
660 ASSERT(texObj);
661 ASSERT(level >= 0);
662 ASSERT(level < MAX_TEXTURE_LEVELS);
663
664 return texObj->Image[face][level];
665 }
666
667
668 /**
669 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
670 * it and install it. Only return NULL if passed a bad parameter or run
671 * out of memory.
672 */
673 struct gl_texture_image *
674 _mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj,
675 GLenum target, GLint level)
676 {
677 struct gl_texture_image *texImage;
678
679 if (!texObj)
680 return NULL;
681
682 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
683 if (!texImage) {
684 texImage = ctx->Driver.NewTextureImage(ctx);
685 if (!texImage) {
686 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
687 return NULL;
688 }
689
690 _mesa_set_tex_image(texObj, target, level, texImage);
691 }
692
693 return texImage;
694 }
695
696
697 /**
698 * Return pointer to the specified proxy texture image.
699 * Note that proxy textures are per-context, not per-texture unit.
700 * \return pointer to texture image or NULL if invalid target, invalid
701 * level, or out of memory.
702 */
703 struct gl_texture_image *
704 _mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level)
705 {
706 struct gl_texture_image *texImage;
707 GLuint texIndex;
708
709 if (level < 0 )
710 return NULL;
711
712 switch (target) {
713 case GL_PROXY_TEXTURE_1D:
714 if (level >= ctx->Const.MaxTextureLevels)
715 return NULL;
716 texIndex = TEXTURE_1D_INDEX;
717 break;
718 case GL_PROXY_TEXTURE_2D:
719 if (level >= ctx->Const.MaxTextureLevels)
720 return NULL;
721 texIndex = TEXTURE_2D_INDEX;
722 break;
723 case GL_PROXY_TEXTURE_3D:
724 if (level >= ctx->Const.Max3DTextureLevels)
725 return NULL;
726 texIndex = TEXTURE_3D_INDEX;
727 break;
728 case GL_PROXY_TEXTURE_CUBE_MAP:
729 if (level >= ctx->Const.MaxCubeTextureLevels)
730 return NULL;
731 texIndex = TEXTURE_CUBE_INDEX;
732 break;
733 case GL_PROXY_TEXTURE_RECTANGLE_NV:
734 if (level > 0)
735 return NULL;
736 texIndex = TEXTURE_RECT_INDEX;
737 break;
738 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
739 if (level >= ctx->Const.MaxTextureLevels)
740 return NULL;
741 texIndex = TEXTURE_1D_ARRAY_INDEX;
742 break;
743 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
744 if (level >= ctx->Const.MaxTextureLevels)
745 return NULL;
746 texIndex = TEXTURE_2D_ARRAY_INDEX;
747 break;
748 default:
749 return NULL;
750 }
751
752 texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level];
753 if (!texImage) {
754 texImage = ctx->Driver.NewTextureImage(ctx);
755 if (!texImage) {
756 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
757 return NULL;
758 }
759 ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage;
760 /* Set the 'back' pointer */
761 texImage->TexObject = ctx->Texture.ProxyTex[texIndex];
762 }
763 return texImage;
764 }
765
766
767 /**
768 * Get the maximum number of allowed mipmap levels.
769 *
770 * \param ctx GL context.
771 * \param target texture target.
772 *
773 * \return the maximum number of allowed mipmap levels for the given
774 * texture target, or zero if passed a bad target.
775 *
776 * \sa gl_constants.
777 */
778 GLint
779 _mesa_max_texture_levels(GLcontext *ctx, GLenum target)
780 {
781 switch (target) {
782 case GL_TEXTURE_1D:
783 case GL_PROXY_TEXTURE_1D:
784 case GL_TEXTURE_2D:
785 case GL_PROXY_TEXTURE_2D:
786 return ctx->Const.MaxTextureLevels;
787 case GL_TEXTURE_3D:
788 case GL_PROXY_TEXTURE_3D:
789 return ctx->Const.Max3DTextureLevels;
790 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
791 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
792 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
793 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
794 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
795 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
796 case GL_TEXTURE_CUBE_MAP_ARB:
797 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
798 return ctx->Extensions.ARB_texture_cube_map
799 ? ctx->Const.MaxCubeTextureLevels : 0;
800 case GL_TEXTURE_RECTANGLE_NV:
801 case GL_PROXY_TEXTURE_RECTANGLE_NV:
802 return ctx->Extensions.NV_texture_rectangle ? 1 : 0;
803 case GL_TEXTURE_1D_ARRAY_EXT:
804 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
805 case GL_TEXTURE_2D_ARRAY_EXT:
806 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
807 return ctx->Extensions.MESA_texture_array
808 ? ctx->Const.MaxTextureLevels : 0;
809 default:
810 return 0; /* bad target */
811 }
812 }
813
814
815
816 #if 000 /* not used anymore */
817 /*
818 * glTexImage[123]D can accept a NULL image pointer. In this case we
819 * create a texture image with unspecified image contents per the OpenGL
820 * spec.
821 */
822 static GLubyte *
823 make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
824 {
825 const GLint components = _mesa_components_in_format(format);
826 const GLint numPixels = width * height * depth;
827 GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
828
829 #ifdef DEBUG
830 /*
831 * Let's see if anyone finds this. If glTexImage2D() is called with
832 * a NULL image pointer then load the texture image with something
833 * interesting instead of leaving it indeterminate.
834 */
835 if (data) {
836 static const char message[8][32] = {
837 " X X XXXXX XXX X ",
838 " XX XX X X X X X ",
839 " X X X X X X X ",
840 " X X XXXX XXX XXXXX ",
841 " X X X X X X ",
842 " X X X X X X X ",
843 " X X XXXXX XXX X X ",
844 " "
845 };
846
847 GLubyte *imgPtr = data;
848 GLint h, i, j, k;
849 for (h = 0; h < depth; h++) {
850 for (i = 0; i < height; i++) {
851 GLint srcRow = 7 - (i % 8);
852 for (j = 0; j < width; j++) {
853 GLint srcCol = j % 32;
854 GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
855 for (k = 0; k < components; k++) {
856 *imgPtr++ = texel;
857 }
858 }
859 }
860 }
861 }
862 #endif
863
864 return data;
865 }
866 #endif
867
868
869
870 /**
871 * Reset the fields of a gl_texture_image struct to zero.
872 *
873 * \param img texture image structure.
874 *
875 * This is called when a proxy texture test fails, we set all the
876 * image members (except DriverData) to zero.
877 * It's also used in glTexImage[123]D as a safeguard to be sure all
878 * required fields get initialized properly by the Driver.TexImage[123]D
879 * functions.
880 */
881 static void
882 clear_teximage_fields(struct gl_texture_image *img)
883 {
884 ASSERT(img);
885 img->_BaseFormat = 0;
886 img->InternalFormat = 0;
887 img->Border = 0;
888 img->Width = 0;
889 img->Height = 0;
890 img->Depth = 0;
891 img->RowStride = 0;
892 if (img->ImageOffsets) {
893 _mesa_free(img->ImageOffsets);
894 img->ImageOffsets = NULL;
895 }
896 img->Width2 = 0;
897 img->Height2 = 0;
898 img->Depth2 = 0;
899 img->WidthLog2 = 0;
900 img->HeightLog2 = 0;
901 img->DepthLog2 = 0;
902 img->Data = NULL;
903 img->TexFormat = &_mesa_null_texformat;
904 img->FetchTexelc = NULL;
905 img->FetchTexelf = NULL;
906 img->IsCompressed = 0;
907 img->CompressedSize = 0;
908 }
909
910
911 /**
912 * Initialize basic fields of the gl_texture_image struct.
913 *
914 * \param ctx GL context.
915 * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
916 * \param img texture image structure to be initialized.
917 * \param width image width.
918 * \param height image height.
919 * \param depth image depth.
920 * \param border image border.
921 * \param internalFormat internal format.
922 *
923 * Fills in the fields of \p img with the given information.
924 * Note: width, height and depth include the border.
925 */
926 void
927 _mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
928 struct gl_texture_image *img,
929 GLsizei width, GLsizei height, GLsizei depth,
930 GLint border, GLenum internalFormat)
931 {
932 GLint i;
933
934 ASSERT(img);
935 ASSERT(width >= 0);
936 ASSERT(height >= 0);
937 ASSERT(depth >= 0);
938
939 img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
940 ASSERT(img->_BaseFormat > 0);
941 img->InternalFormat = internalFormat;
942 img->Border = border;
943 img->Width = width;
944 img->Height = height;
945 img->Depth = depth;
946
947 img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */
948 img->WidthLog2 = logbase2(img->Width2);
949
950 if (height == 1) { /* 1-D texture */
951 img->Height2 = 1;
952 img->HeightLog2 = 0;
953 }
954 else {
955 img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
956 img->HeightLog2 = logbase2(img->Height2);
957 }
958
959 if (depth == 1) { /* 2-D texture */
960 img->Depth2 = 1;
961 img->DepthLog2 = 0;
962 }
963 else {
964 img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */
965 img->DepthLog2 = logbase2(img->Depth2);
966 }
967
968 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
969
970 img->IsCompressed = GL_FALSE;
971 img->CompressedSize = 0;
972
973 if ((width == 1 || _mesa_is_pow_two(img->Width2)) &&
974 (height == 1 || _mesa_is_pow_two(img->Height2)) &&
975 (depth == 1 || _mesa_is_pow_two(img->Depth2)))
976 img->_IsPowerOfTwo = GL_TRUE;
977 else
978 img->_IsPowerOfTwo = GL_FALSE;
979
980 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
981 img->RowStride = width;
982 /* Allocate the ImageOffsets array and initialize to typical values.
983 * We allocate the array for 1D/2D textures too in order to avoid special-
984 * case code in the texstore routines.
985 */
986 if (img->ImageOffsets)
987 _mesa_free(img->ImageOffsets);
988 img->ImageOffsets = (GLuint *) _mesa_malloc(depth * sizeof(GLuint));
989 for (i = 0; i < depth; i++) {
990 img->ImageOffsets[i] = i * width * height;
991 }
992
993 /* Compute Width/Height/DepthScale for mipmap lod computation */
994 if (target == GL_TEXTURE_RECTANGLE_NV) {
995 /* scale = 1.0 since texture coords directly map to texels */
996 img->WidthScale = 1.0;
997 img->HeightScale = 1.0;
998 img->DepthScale = 1.0;
999 }
1000 else {
1001 img->WidthScale = (GLfloat) img->Width;
1002 img->HeightScale = (GLfloat) img->Height;
1003 img->DepthScale = (GLfloat) img->Depth;
1004 }
1005 }
1006
1007
1008 /**
1009 * Free and clear fields of the gl_texture_image struct.
1010 *
1011 * \param ctx GL context.
1012 * \param texImage texture image structure to be cleared.
1013 *
1014 * After the call, \p texImage will have no data associated with it. Its
1015 * fields are cleared so that its parent object will test incomplete.
1016 */
1017 void
1018 _mesa_clear_texture_image(GLcontext *ctx, struct gl_texture_image *texImage)
1019 {
1020 ctx->Driver.FreeTexImageData(ctx, texImage);
1021 clear_teximage_fields(texImage);
1022 }
1023
1024
1025 /**
1026 * This is the fallback for Driver.TestProxyTexImage(). Test the texture
1027 * level, width, height and depth against the ctx->Const limits for textures.
1028 *
1029 * A hardware driver might override this function if, for example, the
1030 * max 3D texture size is 512x512x64 (i.e. not a cube).
1031 *
1032 * Note that width, height, depth == 0 is not an error. However, a
1033 * texture with zero width/height/depth will be considered "incomplete"
1034 * and texturing will effectively be disabled.
1035 *
1036 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
1037 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
1038 * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
1039 * \param level as passed to glTexImage
1040 * \param internalFormat as passed to glTexImage
1041 * \param format as passed to glTexImage
1042 * \param type as passed to glTexImage
1043 * \param width as passed to glTexImage
1044 * \param height as passed to glTexImage
1045 * \param depth as passed to glTexImage
1046 * \param border as passed to glTexImage
1047 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1048 */
1049 GLboolean
1050 _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
1051 GLint internalFormat, GLenum format, GLenum type,
1052 GLint width, GLint height, GLint depth, GLint border)
1053 {
1054 GLint maxSize;
1055
1056 (void) internalFormat;
1057 (void) format;
1058 (void) type;
1059
1060 switch (target) {
1061 case GL_PROXY_TEXTURE_1D:
1062 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1063 if (width < 2 * border || width > 2 + maxSize ||
1064 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1065 width >0 && !_mesa_is_pow_two(width - 2 * border)) ||
1066 level >= ctx->Const.MaxTextureLevels) {
1067 /* bad width or level */
1068 return GL_FALSE;
1069 }
1070 return GL_TRUE;
1071 case GL_PROXY_TEXTURE_2D:
1072 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1073 if (width < 2 * border || width > 2 + maxSize ||
1074 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1075 width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1076 height < 2 * border || height > 2 + maxSize ||
1077 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1078 height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1079 level >= ctx->Const.MaxTextureLevels) {
1080 /* bad width or height or level */
1081 return GL_FALSE;
1082 }
1083 return GL_TRUE;
1084 case GL_PROXY_TEXTURE_3D:
1085 maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
1086 if (width < 2 * border || width > 2 + maxSize ||
1087 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1088 width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1089 height < 2 * border || height > 2 + maxSize ||
1090 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1091 height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1092 depth < 2 * border || depth > 2 + maxSize ||
1093 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1094 depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) ||
1095 level >= ctx->Const.Max3DTextureLevels) {
1096 /* bad width or height or depth or level */
1097 return GL_FALSE;
1098 }
1099 return GL_TRUE;
1100 case GL_PROXY_TEXTURE_RECTANGLE_NV:
1101 if (width < 0 || width > ctx->Const.MaxTextureRectSize ||
1102 height < 0 || height > ctx->Const.MaxTextureRectSize ||
1103 level != 0) {
1104 /* bad width or height or level */
1105 return GL_FALSE;
1106 }
1107 return GL_TRUE;
1108 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
1109 maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
1110 if (width < 2 * border || width > 2 + maxSize ||
1111 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1112 width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1113 height < 2 * border || height > 2 + maxSize ||
1114 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1115 height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1116 level >= ctx->Const.MaxCubeTextureLevels) {
1117 /* bad width or height */
1118 return GL_FALSE;
1119 }
1120 return GL_TRUE;
1121 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
1122 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1123 if (width < 2 * border || width > 2 + maxSize ||
1124 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1125 width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1126 level >= ctx->Const.MaxTextureLevels) {
1127 /* bad width or level */
1128 return GL_FALSE;
1129 }
1130
1131 if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) {
1132 return GL_FALSE;
1133 }
1134 return GL_TRUE;
1135 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
1136 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1137 if (width < 2 * border || width > 2 + maxSize ||
1138 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1139 width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1140 height < 2 * border || height > 2 + maxSize ||
1141 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1142 height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1143 level >= ctx->Const.MaxTextureLevels) {
1144 /* bad width or height or level */
1145 return GL_FALSE;
1146 }
1147 if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) {
1148 return GL_FALSE;
1149 }
1150 return GL_TRUE;
1151 default:
1152 _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
1153 return GL_FALSE;
1154 }
1155 }
1156
1157
1158 /**
1159 * Helper function to determine whether a target supports compressed textures
1160 */
1161 static GLboolean
1162 target_can_be_compressed(GLcontext *ctx, GLenum target)
1163 {
1164 return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D))
1165 || ((ctx->Extensions.ARB_texture_cube_map &&
1166 (target == GL_PROXY_TEXTURE_CUBE_MAP ||
1167 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1168 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))))
1169 || ((ctx->Extensions.MESA_texture_array &&
1170 ((target == GL_PROXY_TEXTURE_2D_ARRAY_EXT) ||
1171 (target == GL_TEXTURE_2D_ARRAY_EXT)))));
1172 }
1173
1174
1175 /**
1176 * Test the glTexImage[123]D() parameters for errors.
1177 *
1178 * \param ctx GL context.
1179 * \param target texture target given by the user.
1180 * \param level image level given by the user.
1181 * \param internalFormat internal format given by the user.
1182 * \param format pixel data format given by the user.
1183 * \param type pixel data type given by the user.
1184 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1185 * \param width image width given by the user.
1186 * \param height image height given by the user.
1187 * \param depth image depth given by the user.
1188 * \param border image border given by the user.
1189 *
1190 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1191 *
1192 * Verifies each of the parameters against the constants specified in
1193 * __GLcontextRec::Const and the supported extensions, and according to the
1194 * OpenGL specification.
1195 */
1196 static GLboolean
1197 texture_error_check( GLcontext *ctx, GLenum target,
1198 GLint level, GLint internalFormat,
1199 GLenum format, GLenum type,
1200 GLuint dimensions,
1201 GLint width, GLint height,
1202 GLint depth, GLint border )
1203 {
1204 const GLboolean isProxy = _mesa_is_proxy_texture(target);
1205 GLboolean sizeOK = GL_TRUE;
1206 GLboolean colorFormat, indexFormat;
1207 GLenum proxy_target;
1208
1209 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1210 if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1211 if (!isProxy) {
1212 _mesa_error(ctx, GL_INVALID_VALUE,
1213 "glTexImage%dD(level=%d)", dimensions, level);
1214 }
1215 return GL_TRUE;
1216 }
1217
1218 /* Check border */
1219 if (border < 0 || border > 1 ||
1220 ((target == GL_TEXTURE_RECTANGLE_NV ||
1221 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1222 if (!isProxy) {
1223 _mesa_error(ctx, GL_INVALID_VALUE,
1224 "glTexImage%dD(border=%d)", dimensions, border);
1225 }
1226 return GL_TRUE;
1227 }
1228
1229 if (width < 0 || height < 0 || depth < 0) {
1230 if (!isProxy) {
1231 _mesa_error(ctx, GL_INVALID_VALUE,
1232 "glTexImage%dD(width, height or depth < 0)", dimensions);
1233 }
1234 return GL_TRUE;
1235 }
1236
1237 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1238 * level, width, height and depth.
1239 */
1240 if (dimensions == 1) {
1241 if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
1242 proxy_target = GL_PROXY_TEXTURE_1D;
1243 height = 1;
1244 depth = 1;
1245 }
1246 else {
1247 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1248 return GL_TRUE;
1249 }
1250 }
1251 else if (dimensions == 2) {
1252 depth = 1;
1253 if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
1254 proxy_target = GL_PROXY_TEXTURE_2D;
1255 }
1256 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
1257 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1258 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1259 if (!ctx->Extensions.ARB_texture_cube_map) {
1260 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1261 return GL_TRUE;
1262 }
1263 proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB;
1264 sizeOK = (width == height);
1265 }
1266 else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
1267 target == GL_TEXTURE_RECTANGLE_NV) {
1268 if (!ctx->Extensions.NV_texture_rectangle) {
1269 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1270 return GL_TRUE;
1271 }
1272 proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV;
1273 }
1274 else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
1275 target == GL_TEXTURE_1D_ARRAY_EXT) {
1276 proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT;
1277 }
1278 else {
1279 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1280 return GL_TRUE;
1281 }
1282 }
1283 else if (dimensions == 3) {
1284 if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
1285 proxy_target = GL_PROXY_TEXTURE_3D;
1286 }
1287 else if (target == GL_PROXY_TEXTURE_2D_ARRAY_EXT ||
1288 target == GL_TEXTURE_2D_ARRAY_EXT) {
1289 proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT;
1290 }
1291 else {
1292 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1293 return GL_TRUE;
1294 }
1295 }
1296 else {
1297 _mesa_problem( ctx, "bad dims in texture_error_check" );
1298 return GL_TRUE;
1299 }
1300
1301 sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level,
1302 internalFormat, format,
1303 type, width, height,
1304 depth, border);
1305 if (!sizeOK) {
1306 if (!isProxy) {
1307 _mesa_error(ctx, GL_INVALID_VALUE,
1308 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1309 dimensions, level, width, height, depth);
1310 }
1311 return GL_TRUE;
1312 }
1313
1314 /* Check internalFormat */
1315 if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
1316 if (!isProxy) {
1317 _mesa_error(ctx, GL_INVALID_VALUE,
1318 "glTexImage%dD(internalFormat=0x%x)",
1319 dimensions, internalFormat);
1320 }
1321 return GL_TRUE;
1322 }
1323
1324 /* Check incoming image format and type */
1325 if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
1326 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1327 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1328 */
1329 if (!isProxy) {
1330 _mesa_error(ctx, GL_INVALID_OPERATION,
1331 "glTexImage%dD(incompatible format 0x%x, type 0x%x)",
1332 dimensions, format, type);
1333 }
1334 return GL_TRUE;
1335 }
1336
1337 /* make sure internal format and format basically agree */
1338 colorFormat = _mesa_is_color_format(format);
1339 indexFormat = _mesa_is_index_format(format);
1340 if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
1341 (_mesa_is_index_format(internalFormat) && !indexFormat) ||
1342 (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) ||
1343 (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) ||
1344 (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) ||
1345 (_mesa_is_dudv_format(internalFormat) != _mesa_is_dudv_format(format))) {
1346 if (!isProxy)
1347 _mesa_error(ctx, GL_INVALID_OPERATION,
1348 "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)",
1349 dimensions, internalFormat, format);
1350 return GL_TRUE;
1351 }
1352
1353 /* additional checks for ycbcr textures */
1354 if (internalFormat == GL_YCBCR_MESA) {
1355 ASSERT(ctx->Extensions.MESA_ycbcr_texture);
1356 if (type != GL_UNSIGNED_SHORT_8_8_MESA &&
1357 type != GL_UNSIGNED_SHORT_8_8_REV_MESA) {
1358 char message[100];
1359 _mesa_sprintf(message,
1360 "glTexImage%d(format/type YCBCR mismatch", dimensions);
1361 _mesa_error(ctx, GL_INVALID_ENUM, message);
1362 return GL_TRUE; /* error */
1363 }
1364 if (target != GL_TEXTURE_2D &&
1365 target != GL_PROXY_TEXTURE_2D &&
1366 target != GL_TEXTURE_RECTANGLE_NV &&
1367 target != GL_PROXY_TEXTURE_RECTANGLE_NV) {
1368 if (!isProxy)
1369 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)");
1370 return GL_TRUE;
1371 }
1372 if (border != 0) {
1373 if (!isProxy) {
1374 char message[100];
1375 _mesa_sprintf(message,
1376 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1377 dimensions, border);
1378 _mesa_error(ctx, GL_INVALID_VALUE, message);
1379 }
1380 return GL_TRUE;
1381 }
1382 }
1383
1384 /* additional checks for depth textures */
1385 if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) {
1386 /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
1387 if (target != GL_TEXTURE_1D &&
1388 target != GL_PROXY_TEXTURE_1D &&
1389 target != GL_TEXTURE_2D &&
1390 target != GL_PROXY_TEXTURE_2D &&
1391 target != GL_TEXTURE_RECTANGLE_ARB &&
1392 target != GL_PROXY_TEXTURE_RECTANGLE_ARB) {
1393 if (!isProxy)
1394 _mesa_error(ctx, GL_INVALID_ENUM,
1395 "glTexImage(target/internalFormat)");
1396 return GL_TRUE;
1397 }
1398 }
1399
1400 /* additional checks for compressed textures */
1401 if (is_compressed_format(ctx, internalFormat)) {
1402 if (!target_can_be_compressed(ctx, target) && !isProxy) {
1403 _mesa_error(ctx, GL_INVALID_ENUM,
1404 "glTexImage%d(target)", dimensions);
1405 return GL_TRUE;
1406 }
1407 if (border != 0) {
1408 if (!isProxy) {
1409 _mesa_error(ctx, GL_INVALID_OPERATION,
1410 "glTexImage%D(border!=0)", dimensions);
1411 }
1412 return GL_TRUE;
1413 }
1414 }
1415
1416 /* if we get here, the parameters are OK */
1417 return GL_FALSE;
1418 }
1419
1420
1421 /**
1422 * Test glTexSubImage[123]D() parameters for errors.
1423 *
1424 * \param ctx GL context.
1425 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1426 * \param target texture target given by the user.
1427 * \param level image level given by the user.
1428 * \param xoffset sub-image x offset given by the user.
1429 * \param yoffset sub-image y offset given by the user.
1430 * \param zoffset sub-image z offset given by the user.
1431 * \param format pixel data format given by the user.
1432 * \param type pixel data type given by the user.
1433 * \param width image width given by the user.
1434 * \param height image height given by the user.
1435 * \param depth image depth given by the user.
1436 *
1437 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1438 *
1439 * Verifies each of the parameters against the constants specified in
1440 * __GLcontextRec::Const and the supported extensions, and according to the
1441 * OpenGL specification.
1442 */
1443 static GLboolean
1444 subtexture_error_check( GLcontext *ctx, GLuint dimensions,
1445 GLenum target, GLint level,
1446 GLint xoffset, GLint yoffset, GLint zoffset,
1447 GLint width, GLint height, GLint depth,
1448 GLenum format, GLenum type )
1449 {
1450 /* Check target */
1451 if (dimensions == 1) {
1452 if (target != GL_TEXTURE_1D) {
1453 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1454 return GL_TRUE;
1455 }
1456 }
1457 else if (dimensions == 2) {
1458 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1459 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1460 if (!ctx->Extensions.ARB_texture_cube_map) {
1461 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1462 return GL_TRUE;
1463 }
1464 }
1465 else if (target == GL_TEXTURE_RECTANGLE_NV) {
1466 if (!ctx->Extensions.NV_texture_rectangle) {
1467 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1468 return GL_TRUE;
1469 }
1470 }
1471 else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
1472 if (!ctx->Extensions.MESA_texture_array) {
1473 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1474 return GL_TRUE;
1475 }
1476 }
1477 else if (target != GL_TEXTURE_2D) {
1478 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1479 return GL_TRUE;
1480 }
1481 }
1482 else if (dimensions == 3) {
1483 if (target == GL_TEXTURE_2D_ARRAY_EXT) {
1484 if (!ctx->Extensions.MESA_texture_array) {
1485 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1486 return GL_TRUE;
1487 }
1488 }
1489 else if (target != GL_TEXTURE_3D) {
1490 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1491 return GL_TRUE;
1492 }
1493 }
1494 else {
1495 _mesa_problem( ctx, "invalid dims in texture_error_check" );
1496 return GL_TRUE;
1497 }
1498
1499 /* Basic level check */
1500 if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1501 _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
1502 return GL_TRUE;
1503 }
1504
1505 if (width < 0) {
1506 _mesa_error(ctx, GL_INVALID_VALUE,
1507 "glTexSubImage%dD(width=%d)", dimensions, width);
1508 return GL_TRUE;
1509 }
1510 if (height < 0 && dimensions > 1) {
1511 _mesa_error(ctx, GL_INVALID_VALUE,
1512 "glTexSubImage%dD(height=%d)", dimensions, height);
1513 return GL_TRUE;
1514 }
1515 if (depth < 0 && dimensions > 2) {
1516 _mesa_error(ctx, GL_INVALID_VALUE,
1517 "glTexSubImage%dD(depth=%d)", dimensions, depth);
1518 return GL_TRUE;
1519 }
1520
1521 if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
1522 _mesa_error(ctx, GL_INVALID_ENUM,
1523 "glTexSubImage%dD(incompatible format 0x%x, type 0x%x)",
1524 dimensions, format, type);
1525 return GL_TRUE;
1526 }
1527
1528 return GL_FALSE;
1529 }
1530
1531 static GLboolean
1532 subtexture_error_check2( GLcontext *ctx, GLuint dimensions,
1533 GLenum target, GLint level,
1534 GLint xoffset, GLint yoffset, GLint zoffset,
1535 GLint width, GLint height, GLint depth,
1536 GLenum format, GLenum type,
1537 const struct gl_texture_image *destTex )
1538 {
1539 if (!destTex) {
1540 /* undefined image level */
1541 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions);
1542 return GL_TRUE;
1543 }
1544
1545 if (xoffset < -((GLint)destTex->Border)) {
1546 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)",
1547 dimensions);
1548 return GL_TRUE;
1549 }
1550 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1551 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)",
1552 dimensions);
1553 return GL_TRUE;
1554 }
1555 if (dimensions > 1) {
1556 if (yoffset < -((GLint)destTex->Border)) {
1557 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)",
1558 dimensions);
1559 return GL_TRUE;
1560 }
1561 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1562 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)",
1563 dimensions);
1564 return GL_TRUE;
1565 }
1566 }
1567 if (dimensions > 2) {
1568 if (zoffset < -((GLint)destTex->Border)) {
1569 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1570 return GL_TRUE;
1571 }
1572 if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) {
1573 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1574 return GL_TRUE;
1575 }
1576 }
1577
1578 #if FEATURE_EXT_texture_sRGB
1579 if (destTex->InternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
1580 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
1581 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
1582 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) {
1583 if ((width & 0x3) || (height & 0x3) ||
1584 (xoffset & 0x3) || (yoffset & 0x3))
1585 _mesa_error(ctx, GL_INVALID_OPERATION,
1586 "glTexSubImage%dD(size or offset not multiple of 4)",
1587 dimensions);
1588 return GL_TRUE;
1589 }
1590 #endif
1591
1592 if (destTex->IsCompressed) {
1593 if (!target_can_be_compressed(ctx, target)) {
1594 _mesa_error(ctx, GL_INVALID_ENUM,
1595 "glTexSubImage%D(target)", dimensions);
1596 return GL_TRUE;
1597 }
1598 /* offset must be multiple of 4 */
1599 if ((xoffset & 3) || (yoffset & 3)) {
1600 _mesa_error(ctx, GL_INVALID_OPERATION,
1601 "glTexSubImage%D(xoffset or yoffset)", dimensions);
1602 return GL_TRUE;
1603 }
1604 /* size must be multiple of 4 or equal to whole texture size */
1605 if ((width & 3) && (GLuint) width != destTex->Width) {
1606 _mesa_error(ctx, GL_INVALID_OPERATION,
1607 "glTexSubImage%D(width)", dimensions);
1608 return GL_TRUE;
1609 }
1610 if ((height & 3) && (GLuint) height != destTex->Height) {
1611 _mesa_error(ctx, GL_INVALID_OPERATION,
1612 "glTexSubImage%D(width)", dimensions);
1613 return GL_TRUE;
1614 }
1615 }
1616
1617 return GL_FALSE;
1618 }
1619
1620
1621 /**
1622 * Test glCopyTexImage[12]D() parameters for errors.
1623 *
1624 * \param ctx GL context.
1625 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1626 * \param target texture target given by the user.
1627 * \param level image level given by the user.
1628 * \param internalFormat internal format given by the user.
1629 * \param width image width given by the user.
1630 * \param height image height given by the user.
1631 * \param border texture border.
1632 *
1633 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1634 *
1635 * Verifies each of the parameters against the constants specified in
1636 * __GLcontextRec::Const and the supported extensions, and according to the
1637 * OpenGL specification.
1638 */
1639 static GLboolean
1640 copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1641 GLenum target, GLint level, GLint internalFormat,
1642 GLint width, GLint height, GLint border )
1643 {
1644 GLenum type;
1645 GLboolean sizeOK;
1646 GLint format;
1647
1648 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1649 if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1650 _mesa_error(ctx, GL_INVALID_VALUE,
1651 "glCopyTexImage%dD(level=%d)", dimensions, level);
1652 return GL_TRUE;
1653 }
1654
1655 /* Check that the source buffer is complete */
1656 if (ctx->ReadBuffer->Name) {
1657 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
1658 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1659 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1660 "glCopyTexImage%dD(invalid readbuffer)", dimensions);
1661 return GL_TRUE;
1662 }
1663 }
1664
1665 /* Check border */
1666 if (border < 0 || border > 1 ||
1667 ((target == GL_TEXTURE_RECTANGLE_NV ||
1668 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1669 return GL_TRUE;
1670 }
1671
1672 format = _mesa_base_tex_format(ctx, internalFormat);
1673 if (format < 0) {
1674 _mesa_error(ctx, GL_INVALID_VALUE,
1675 "glCopyTexImage%dD(internalFormat)", dimensions);
1676 return GL_TRUE;
1677 }
1678
1679 if (!_mesa_source_buffer_exists(ctx, format)) {
1680 _mesa_error(ctx, GL_INVALID_OPERATION,
1681 "glCopyTexImage%dD(missing readbuffer)", dimensions);
1682 return GL_TRUE;
1683 }
1684
1685 /* NOTE: the format and type aren't really significant for
1686 * TestProxyTexImage(). Only the internalformat really matters.
1687 */
1688 type = GL_FLOAT;
1689
1690 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1691 * level, width, height and depth.
1692 */
1693 if (dimensions == 1) {
1694 if (target == GL_TEXTURE_1D) {
1695 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
1696 level, internalFormat,
1697 format, type,
1698 width, 1, 1, border);
1699 }
1700 else {
1701 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1702 return GL_TRUE;
1703 }
1704 }
1705 else if (dimensions == 2) {
1706 if (target == GL_TEXTURE_2D) {
1707 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
1708 level, internalFormat,
1709 format, type,
1710 width, height, 1, border);
1711 }
1712 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1713 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1714 if (!ctx->Extensions.ARB_texture_cube_map) {
1715 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1716 return GL_TRUE;
1717 }
1718 sizeOK = (width == height) &&
1719 ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
1720 level, internalFormat, format, type,
1721 width, height, 1, border);
1722 }
1723 else if (target == GL_TEXTURE_RECTANGLE_NV) {
1724 if (!ctx->Extensions.NV_texture_rectangle) {
1725 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1726 return GL_TRUE;
1727 }
1728 sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1729 GL_PROXY_TEXTURE_RECTANGLE_NV,
1730 level, internalFormat,
1731 format, type,
1732 width, height, 1, border);
1733 }
1734 else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
1735 if (!ctx->Extensions.MESA_texture_array) {
1736 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)");
1737 return GL_TRUE;
1738 }
1739 sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1740 GL_PROXY_TEXTURE_1D_ARRAY_EXT,
1741 level, internalFormat,
1742 format, type,
1743 width, height, 1, border);
1744 }
1745 else {
1746 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1747 return GL_TRUE;
1748 }
1749 }
1750 else {
1751 _mesa_problem(ctx, "invalid dimensions in copytexture_error_check");
1752 return GL_TRUE;
1753 }
1754
1755 if (!sizeOK) {
1756 if (dimensions == 1) {
1757 _mesa_error(ctx, GL_INVALID_VALUE,
1758 "glCopyTexImage1D(width=%d)", width);
1759 }
1760 else {
1761 ASSERT(dimensions == 2);
1762 _mesa_error(ctx, GL_INVALID_VALUE,
1763 "glCopyTexImage2D(width=%d, height=%d)", width, height);
1764 }
1765 return GL_TRUE;
1766 }
1767
1768 if (is_compressed_format(ctx, internalFormat)) {
1769 if (!target_can_be_compressed(ctx, target)) {
1770 _mesa_error(ctx, GL_INVALID_ENUM,
1771 "glCopyTexImage%d(target)", dimensions);
1772 return GL_TRUE;
1773 }
1774 if (border != 0) {
1775 _mesa_error(ctx, GL_INVALID_OPERATION,
1776 "glCopyTexImage%D(border!=0)", dimensions);
1777 return GL_TRUE;
1778 }
1779 }
1780 else if (_mesa_is_depth_format(internalFormat)) {
1781 /* make sure we have depth/stencil buffers */
1782 if (!ctx->ReadBuffer->_DepthBuffer) {
1783 _mesa_error(ctx, GL_INVALID_OPERATION,
1784 "glCopyTexImage%D(no depth)", dimensions);
1785 return GL_TRUE;
1786 }
1787 }
1788 else if (_mesa_is_depthstencil_format(internalFormat)) {
1789 /* make sure we have depth/stencil buffers */
1790 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
1791 _mesa_error(ctx, GL_INVALID_OPERATION,
1792 "glCopyTexImage%D(no depth/stencil buffer)", dimensions);
1793 return GL_TRUE;
1794 }
1795 }
1796
1797 /* if we get here, the parameters are OK */
1798 return GL_FALSE;
1799 }
1800
1801
1802 /**
1803 * Test glCopyTexSubImage[12]D() parameters for errors.
1804 * Note that this is the first part of error checking.
1805 * See also copytexsubimage_error_check2() below for the second part.
1806 *
1807 * \param ctx GL context.
1808 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1809 * \param target texture target given by the user.
1810 * \param level image level given by the user.
1811 *
1812 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1813 */
1814 static GLboolean
1815 copytexsubimage_error_check1( GLcontext *ctx, GLuint dimensions,
1816 GLenum target, GLint level)
1817 {
1818 /* Check that the source buffer is complete */
1819 if (ctx->ReadBuffer->Name) {
1820 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
1821 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1822 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1823 "glCopyTexImage%dD(invalid readbuffer)", dimensions);
1824 return GL_TRUE;
1825 }
1826 }
1827
1828 /* Check target */
1829 if (dimensions == 1) {
1830 if (target != GL_TEXTURE_1D) {
1831 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1832 return GL_TRUE;
1833 }
1834 }
1835 else if (dimensions == 2) {
1836 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1837 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1838 if (!ctx->Extensions.ARB_texture_cube_map) {
1839 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1840 return GL_TRUE;
1841 }
1842 }
1843 else if (target == GL_TEXTURE_RECTANGLE_NV) {
1844 if (!ctx->Extensions.NV_texture_rectangle) {
1845 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1846 return GL_TRUE;
1847 }
1848 }
1849 else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
1850 if (!ctx->Extensions.MESA_texture_array) {
1851 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1852 return GL_TRUE;
1853 }
1854 }
1855 else if (target != GL_TEXTURE_2D) {
1856 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1857 return GL_TRUE;
1858 }
1859 }
1860 else if (dimensions == 3) {
1861 if (((target != GL_TEXTURE_2D_ARRAY_EXT) ||
1862 (!ctx->Extensions.MESA_texture_array))
1863 && (target != GL_TEXTURE_3D)) {
1864 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1865 return GL_TRUE;
1866 }
1867 }
1868
1869 /* Check level */
1870 if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1871 _mesa_error(ctx, GL_INVALID_VALUE,
1872 "glCopyTexSubImage%dD(level=%d)", dimensions, level);
1873 return GL_TRUE;
1874 }
1875
1876 return GL_FALSE;
1877 }
1878
1879
1880 /**
1881 * Second part of error checking for glCopyTexSubImage[12]D().
1882 * \param xoffset sub-image x offset given by the user.
1883 * \param yoffset sub-image y offset given by the user.
1884 * \param zoffset sub-image z offset given by the user.
1885 * \param width image width given by the user.
1886 * \param height image height given by the user.
1887 */
1888 static GLboolean
1889 copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
1890 GLenum target, GLint level,
1891 GLint xoffset, GLint yoffset, GLint zoffset,
1892 GLsizei width, GLsizei height,
1893 const struct gl_texture_image *teximage )
1894 {
1895 /* check that dest tex image exists */
1896 if (!teximage) {
1897 _mesa_error(ctx, GL_INVALID_OPERATION,
1898 "glCopyTexSubImage%dD(undefined texture level: %d)",
1899 dimensions, level);
1900 return GL_TRUE;
1901 }
1902
1903 /* Check size */
1904 if (width < 0) {
1905 _mesa_error(ctx, GL_INVALID_VALUE,
1906 "glCopyTexSubImage%dD(width=%d)", dimensions, width);
1907 return GL_TRUE;
1908 }
1909 if (dimensions > 1 && height < 0) {
1910 _mesa_error(ctx, GL_INVALID_VALUE,
1911 "glCopyTexSubImage%dD(height=%d)", dimensions, height);
1912 return GL_TRUE;
1913 }
1914
1915 /* check x/y offsets */
1916 if (xoffset < -((GLint)teximage->Border)) {
1917 _mesa_error(ctx, GL_INVALID_VALUE,
1918 "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
1919 return GL_TRUE;
1920 }
1921 if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
1922 _mesa_error(ctx, GL_INVALID_VALUE,
1923 "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1924 return GL_TRUE;
1925 }
1926 if (dimensions > 1) {
1927 if (yoffset < -((GLint)teximage->Border)) {
1928 _mesa_error(ctx, GL_INVALID_VALUE,
1929 "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
1930 return GL_TRUE;
1931 }
1932 /* NOTE: we're adding the border here, not subtracting! */
1933 if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
1934 _mesa_error(ctx, GL_INVALID_VALUE,
1935 "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1936 return GL_TRUE;
1937 }
1938 }
1939
1940 /* check z offset */
1941 if (dimensions > 2) {
1942 if (zoffset < -((GLint)teximage->Border)) {
1943 _mesa_error(ctx, GL_INVALID_VALUE,
1944 "glCopyTexSubImage%dD(zoffset)", dimensions);
1945 return GL_TRUE;
1946 }
1947 if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
1948 _mesa_error(ctx, GL_INVALID_VALUE,
1949 "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1950 return GL_TRUE;
1951 }
1952 }
1953
1954 if (teximage->IsCompressed) {
1955 if (!target_can_be_compressed(ctx, target)) {
1956 _mesa_error(ctx, GL_INVALID_ENUM,
1957 "glCopyTexSubImage%d(target)", dimensions);
1958 return GL_TRUE;
1959 }
1960 /* offset must be multiple of 4 */
1961 if ((xoffset & 3) || (yoffset & 3)) {
1962 _mesa_error(ctx, GL_INVALID_VALUE,
1963 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions);
1964 return GL_TRUE;
1965 }
1966 /* size must be multiple of 4 */
1967 if ((width & 3) != 0 && (GLuint) width != teximage->Width) {
1968 _mesa_error(ctx, GL_INVALID_VALUE,
1969 "glCopyTexSubImage%D(width)", dimensions);
1970 return GL_TRUE;
1971 }
1972 if ((height & 3) != 0 && (GLuint) height != teximage->Height) {
1973 _mesa_error(ctx, GL_INVALID_VALUE,
1974 "glCopyTexSubImage%D(height)", dimensions);
1975 return GL_TRUE;
1976 }
1977 }
1978
1979 if (teximage->InternalFormat == GL_YCBCR_MESA) {
1980 _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D");
1981 return GL_TRUE;
1982 }
1983
1984 if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) {
1985 _mesa_error(ctx, GL_INVALID_OPERATION,
1986 "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)",
1987 dimensions, teximage->_BaseFormat);
1988 return GL_TRUE;
1989 }
1990
1991 if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) {
1992 if (!ctx->ReadBuffer->_DepthBuffer) {
1993 _mesa_error(ctx, GL_INVALID_OPERATION,
1994 "glCopyTexSubImage%D(no depth buffer)",
1995 dimensions);
1996 return GL_TRUE;
1997 }
1998 }
1999 else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
2000 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
2001 _mesa_error(ctx, GL_INVALID_OPERATION,
2002 "glCopyTexSubImage%D(no depth/stencil buffer)",
2003 dimensions);
2004 return GL_TRUE;
2005 }
2006 }
2007
2008 /* if we get here, the parameters are OK */
2009 return GL_FALSE;
2010 }
2011
2012
2013 /** Callback info for walking over FBO hash table */
2014 struct cb_info
2015 {
2016 GLcontext *ctx;
2017 struct gl_texture_object *texObj;
2018 GLuint level, face;
2019 };
2020
2021
2022 /**
2023 * Check render to texture callback. Called from _mesa_HashWalk().
2024 */
2025 static void
2026 check_rtt_cb(GLuint key, void *data, void *userData)
2027 {
2028 struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
2029 const struct cb_info *info = (struct cb_info *) userData;
2030 GLcontext *ctx = info->ctx;
2031 const struct gl_texture_object *texObj = info->texObj;
2032 const GLuint level = info->level, face = info->face;
2033
2034 /* If this is a user-created FBO */
2035 if (fb->Name) {
2036 GLuint i;
2037 /* check if any of the FBO's attachments point to 'texObj' */
2038 for (i = 0; i < BUFFER_COUNT; i++) {
2039 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2040 if (att->Type == GL_TEXTURE &&
2041 att->Texture == texObj &&
2042 att->TextureLevel == level &&
2043 att->CubeMapFace == face) {
2044 ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
2045 /* Tell driver about the new renderbuffer texture */
2046 ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
2047 /* Mark fb status as indeterminate to force re-validation */
2048 fb->_Status = 0;
2049 }
2050 }
2051 }
2052 }
2053
2054
2055 /**
2056 * When a texture image is specified we have to check if it's bound to
2057 * any framebuffer objects (render to texture) in order to detect changes
2058 * in size or format since that effects FBO completeness.
2059 * Any FBOs rendering into the texture must be re-validated.
2060 */
2061 static void
2062 update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj,
2063 GLuint face, GLuint level)
2064 {
2065 /* Only check this texture if it's been marked as RenderToTexture */
2066 if (texObj->_RenderToTexture) {
2067 struct cb_info info;
2068 info.ctx = ctx;
2069 info.texObj = texObj;
2070 info.level = level;
2071 info.face = face;
2072 _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info);
2073 }
2074 }
2075
2076
2077 /**
2078 * If the texture object's GenerateMipmap flag is set and we've
2079 * changed the texture base level image, regenerate the rest of the
2080 * mipmap levels now.
2081 */
2082 static INLINE void
2083 check_gen_mipmap(GLcontext *ctx, GLenum target,
2084 struct gl_texture_object *texObj, GLint level)
2085 {
2086 ASSERT(target != GL_TEXTURE_CUBE_MAP);
2087 if (texObj->GenerateMipmap && level == texObj->BaseLevel) {
2088 ASSERT(ctx->Driver.GenerateMipmap);
2089 ctx->Driver.GenerateMipmap(ctx, target, texObj);
2090 }
2091 }
2092
2093
2094 /** Debug helper: override the user-requested internal format */
2095 static GLenum
2096 override_internal_format(GLenum internalFormat, GLint width, GLint height)
2097 {
2098 #if 0
2099 if (internalFormat == GL_RGBA16F_ARB ||
2100 internalFormat == GL_RGBA32F_ARB) {
2101 printf("Convert rgba float tex to int %d x %d\n", width, height);
2102 return GL_RGBA;
2103 }
2104 else if (internalFormat == GL_RGB16F_ARB ||
2105 internalFormat == GL_RGB32F_ARB) {
2106 printf("Convert rgb float tex to int %d x %d\n", width, height);
2107 return GL_RGB;
2108 }
2109 else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB ||
2110 internalFormat == GL_LUMINANCE_ALPHA32F_ARB) {
2111 printf("Convert luminance float tex to int %d x %d\n", width, height);
2112 return GL_LUMINANCE_ALPHA;
2113 }
2114 else if (internalFormat == GL_LUMINANCE16F_ARB ||
2115 internalFormat == GL_LUMINANCE32F_ARB) {
2116 printf("Convert luminance float tex to int %d x %d\n", width, height);
2117 return GL_LUMINANCE;
2118 }
2119 else if (internalFormat == GL_ALPHA16F_ARB ||
2120 internalFormat == GL_ALPHA32F_ARB) {
2121 printf("Convert luminance float tex to int %d x %d\n", width, height);
2122 return GL_ALPHA;
2123 }
2124 /*
2125 else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
2126 internalFormat = GL_RGBA;
2127 }
2128 */
2129 else {
2130 return internalFormat;
2131 }
2132 #else
2133 return internalFormat;
2134 #endif
2135 }
2136
2137
2138 /*
2139 * Called from the API. Note that width includes the border.
2140 */
2141 void GLAPIENTRY
2142 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
2143 GLsizei width, GLint border, GLenum format,
2144 GLenum type, const GLvoid *pixels )
2145 {
2146 GLsizei postConvWidth = width;
2147 GET_CURRENT_CONTEXT(ctx);
2148 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2149
2150 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2151 _mesa_debug(ctx, "glTexImage1D %s %d %s %d %d %s %s %p\n",
2152 _mesa_lookup_enum_by_nr(target), level,
2153 _mesa_lookup_enum_by_nr(internalFormat), width, border,
2154 _mesa_lookup_enum_by_nr(format),
2155 _mesa_lookup_enum_by_nr(type), pixels);
2156
2157 internalFormat = override_internal_format(internalFormat, width, 1);
2158
2159 #if FEATURE_convolve
2160 if (_mesa_is_color_format(internalFormat)) {
2161 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2162 }
2163 #endif
2164
2165 if (target == GL_TEXTURE_1D) {
2166 /* non-proxy target */
2167 struct gl_texture_unit *texUnit;
2168 struct gl_texture_object *texObj;
2169 struct gl_texture_image *texImage;
2170 const GLuint face = _mesa_tex_target_to_face(target);
2171
2172 if (texture_error_check(ctx, target, level, internalFormat,
2173 format, type, 1, postConvWidth, 1, 1, border)) {
2174 return; /* error was recorded */
2175 }
2176
2177 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2178 _mesa_update_state(ctx);
2179
2180 texUnit = _mesa_get_current_tex_unit(ctx);
2181 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2182 _mesa_lock_texture(ctx, texObj);
2183 {
2184 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2185 if (!texImage) {
2186 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2187 }
2188 else {
2189 if (texImage->Data) {
2190 ctx->Driver.FreeTexImageData( ctx, texImage );
2191 }
2192
2193 ASSERT(texImage->Data == NULL);
2194
2195 clear_teximage_fields(texImage); /* not really needed, but helpful */
2196 _mesa_init_teximage_fields(ctx, target, texImage,
2197 postConvWidth, 1, 1,
2198 border, internalFormat);
2199
2200 /* Give the texture to the driver. <pixels> may be null. */
2201 ASSERT(ctx->Driver.TexImage1D);
2202 ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
2203 width, border, format, type, pixels,
2204 &ctx->Unpack, texObj, texImage);
2205
2206 ASSERT(texImage->TexFormat);
2207
2208 check_gen_mipmap(ctx, target, texObj, level);
2209
2210 update_fbo_texture(ctx, texObj, face, level);
2211
2212 /* state update */
2213 texObj->_Complete = GL_FALSE;
2214 ctx->NewState |= _NEW_TEXTURE;
2215 }
2216 }
2217 _mesa_unlock_texture(ctx, texObj);
2218 }
2219 else if (target == GL_PROXY_TEXTURE_1D) {
2220 /* Proxy texture: check for errors and update proxy state */
2221 struct gl_texture_image *texImage;
2222 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2223 if (texture_error_check(ctx, target, level, internalFormat,
2224 format, type, 1, postConvWidth, 1, 1, border)) {
2225 /* when error, clear all proxy texture image parameters */
2226 if (texImage)
2227 clear_teximage_fields(texImage);
2228 }
2229 else {
2230 /* no error, set the tex image parameters */
2231 ASSERT(texImage);
2232 _mesa_init_teximage_fields(ctx, target, texImage,
2233 postConvWidth, 1, 1,
2234 border, internalFormat);
2235 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2236 internalFormat, format, type);
2237 }
2238 }
2239 else {
2240 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
2241 return;
2242 }
2243 }
2244
2245
2246 void GLAPIENTRY
2247 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
2248 GLsizei width, GLsizei height, GLint border,
2249 GLenum format, GLenum type,
2250 const GLvoid *pixels )
2251 {
2252 GLsizei postConvWidth = width, postConvHeight = height;
2253 GET_CURRENT_CONTEXT(ctx);
2254 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2255
2256 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2257 _mesa_debug(ctx, "glTexImage2D %s %d %s %d %d %d %s %s %p\n",
2258 _mesa_lookup_enum_by_nr(target), level,
2259 _mesa_lookup_enum_by_nr(internalFormat), width, height,
2260 border, _mesa_lookup_enum_by_nr(format),
2261 _mesa_lookup_enum_by_nr(type), pixels);
2262
2263 internalFormat = override_internal_format(internalFormat, width, height);
2264
2265 #if FEATURE_convolve
2266 if (_mesa_is_color_format(internalFormat)) {
2267 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2268 &postConvHeight);
2269 }
2270 #endif
2271
2272 if (target == GL_TEXTURE_2D ||
2273 (ctx->Extensions.ARB_texture_cube_map &&
2274 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2275 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ||
2276 (ctx->Extensions.NV_texture_rectangle &&
2277 target == GL_TEXTURE_RECTANGLE_NV) ||
2278 (ctx->Extensions.MESA_texture_array &&
2279 target == GL_TEXTURE_1D_ARRAY_EXT)) {
2280 /* non-proxy target */
2281 struct gl_texture_unit *texUnit;
2282 struct gl_texture_object *texObj;
2283 struct gl_texture_image *texImage;
2284 const GLuint face = _mesa_tex_target_to_face(target);
2285
2286 if (texture_error_check(ctx, target, level, internalFormat,
2287 format, type, 2, postConvWidth, postConvHeight,
2288 1, border)) {
2289 return; /* error was recorded */
2290 }
2291
2292 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2293 _mesa_update_state(ctx);
2294
2295 texUnit = _mesa_get_current_tex_unit(ctx);
2296 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2297 _mesa_lock_texture(ctx, texObj);
2298 {
2299 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2300 if (!texImage) {
2301 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2302 }
2303 else {
2304 if (texImage->Data) {
2305 ctx->Driver.FreeTexImageData( ctx, texImage );
2306 }
2307
2308 ASSERT(texImage->Data == NULL);
2309 clear_teximage_fields(texImage); /* not really needed, but helpful */
2310 _mesa_init_teximage_fields(ctx, target, texImage,
2311 postConvWidth, postConvHeight, 1,
2312 border, internalFormat);
2313
2314 /* Give the texture to the driver. <pixels> may be null. */
2315 ASSERT(ctx->Driver.TexImage2D);
2316 ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
2317 width, height, border, format, type,
2318 pixels, &ctx->Unpack, texObj, texImage);
2319
2320 ASSERT(texImage->TexFormat);
2321
2322 check_gen_mipmap(ctx, target, texObj, level);
2323
2324 update_fbo_texture(ctx, texObj, face, level);
2325
2326 /* state update */
2327 texObj->_Complete = GL_FALSE;
2328 ctx->NewState |= _NEW_TEXTURE;
2329 }
2330 }
2331 _mesa_unlock_texture(ctx, texObj);
2332 }
2333 else if (target == GL_PROXY_TEXTURE_2D ||
2334 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
2335 ctx->Extensions.ARB_texture_cube_map) ||
2336 (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
2337 ctx->Extensions.NV_texture_rectangle) ||
2338 (ctx->Extensions.MESA_texture_array &&
2339 target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) {
2340 /* Proxy texture: check for errors and update proxy state */
2341 struct gl_texture_image *texImage;
2342 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2343 if (texture_error_check(ctx, target, level, internalFormat,
2344 format, type, 2, postConvWidth, postConvHeight,
2345 1, border)) {
2346 /* when error, clear all proxy texture image parameters */
2347 if (texImage)
2348 clear_teximage_fields(texImage);
2349 }
2350 else {
2351 /* no error, set the tex image parameters */
2352 _mesa_init_teximage_fields(ctx, target, texImage,
2353 postConvWidth, postConvHeight, 1,
2354 border, internalFormat);
2355 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2356 internalFormat, format, type);
2357 }
2358 }
2359 else {
2360 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
2361 return;
2362 }
2363 }
2364
2365
2366 /*
2367 * Called by the API or display list executor.
2368 * Note that width and height include the border.
2369 */
2370 void GLAPIENTRY
2371 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
2372 GLsizei width, GLsizei height, GLsizei depth,
2373 GLint border, GLenum format, GLenum type,
2374 const GLvoid *pixels )
2375 {
2376 GET_CURRENT_CONTEXT(ctx);
2377 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2378
2379 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2380 _mesa_debug(ctx, "glTexImage3D %s %d %s %d %d %d %d %s %s %p\n",
2381 _mesa_lookup_enum_by_nr(target), level,
2382 _mesa_lookup_enum_by_nr(internalFormat), width, height,
2383 depth, border, _mesa_lookup_enum_by_nr(format),
2384 _mesa_lookup_enum_by_nr(type), pixels);
2385
2386 internalFormat = override_internal_format(internalFormat, width, height);
2387
2388 if (target == GL_TEXTURE_3D ||
2389 (ctx->Extensions.MESA_texture_array &&
2390 target == GL_TEXTURE_2D_ARRAY_EXT)) {
2391 /* non-proxy target */
2392 struct gl_texture_unit *texUnit;
2393 struct gl_texture_object *texObj;
2394 struct gl_texture_image *texImage;
2395 const GLuint face = _mesa_tex_target_to_face(target);
2396
2397 if (texture_error_check(ctx, target, level, (GLint) internalFormat,
2398 format, type, 3, width, height, depth, border)) {
2399 return; /* error was recorded */
2400 }
2401
2402 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2403 _mesa_update_state(ctx);
2404
2405 texUnit = _mesa_get_current_tex_unit(ctx);
2406 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2407 _mesa_lock_texture(ctx, texObj);
2408 {
2409 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2410 if (!texImage) {
2411 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2412 }
2413 else {
2414 if (texImage->Data) {
2415 ctx->Driver.FreeTexImageData( ctx, texImage );
2416 }
2417
2418 ASSERT(texImage->Data == NULL);
2419 clear_teximage_fields(texImage); /* not really needed, but helpful */
2420 _mesa_init_teximage_fields(ctx, target, texImage,
2421 width, height, depth,
2422 border, internalFormat);
2423
2424 /* Give the texture to the driver. <pixels> may be null. */
2425 ASSERT(ctx->Driver.TexImage3D);
2426 ctx->Driver.TexImage3D(ctx, target, level, internalFormat,
2427 width, height, depth, border, format, type,
2428 pixels, &ctx->Unpack, texObj, texImage);
2429
2430 ASSERT(texImage->TexFormat);
2431
2432 check_gen_mipmap(ctx, target, texObj, level);
2433
2434 update_fbo_texture(ctx, texObj, face, level);
2435
2436 /* state update */
2437 texObj->_Complete = GL_FALSE;
2438 ctx->NewState |= _NEW_TEXTURE;
2439 }
2440 }
2441 _mesa_unlock_texture(ctx, texObj);
2442 }
2443 else if (target == GL_PROXY_TEXTURE_3D ||
2444 (ctx->Extensions.MESA_texture_array &&
2445 target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) {
2446 /* Proxy texture: check for errors and update proxy state */
2447 struct gl_texture_image *texImage;
2448 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2449 if (texture_error_check(ctx, target, level, internalFormat,
2450 format, type, 3, width, height, depth, border)) {
2451 /* when error, clear all proxy texture image parameters */
2452 if (texImage)
2453 clear_teximage_fields(texImage);
2454 }
2455 else {
2456 /* no error, set the tex image parameters */
2457 _mesa_init_teximage_fields(ctx, target, texImage, width, height,
2458 depth, border, internalFormat);
2459 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2460 internalFormat, format, type);
2461 }
2462 }
2463 else {
2464 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
2465 return;
2466 }
2467 }
2468
2469
2470 void GLAPIENTRY
2471 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2472 GLsizei width, GLsizei height, GLsizei depth,
2473 GLint border, GLenum format, GLenum type,
2474 const GLvoid *pixels )
2475 {
2476 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2477 depth, border, format, type, pixels);
2478 }
2479
2480
2481
2482 void GLAPIENTRY
2483 _mesa_TexSubImage1D( GLenum target, GLint level,
2484 GLint xoffset, GLsizei width,
2485 GLenum format, GLenum type,
2486 const GLvoid *pixels )
2487 {
2488 GLsizei postConvWidth = width;
2489 struct gl_texture_unit *texUnit;
2490 struct gl_texture_object *texObj;
2491 struct gl_texture_image *texImage = NULL;
2492 GET_CURRENT_CONTEXT(ctx);
2493 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2494
2495 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2496 _mesa_debug(ctx, "glTexSubImage1D %s %d %d %d %s %s %p\n",
2497 _mesa_lookup_enum_by_nr(target), level,
2498 xoffset, width, _mesa_lookup_enum_by_nr(format),
2499 _mesa_lookup_enum_by_nr(type), pixels);
2500
2501 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2502 _mesa_update_state(ctx);
2503
2504 #if FEATURE_convolve
2505 /* XXX should test internal format */
2506 if (_mesa_is_color_format(format)) {
2507 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2508 }
2509 #endif
2510
2511 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2512 postConvWidth, 1, 1, format, type)) {
2513 return; /* error was detected */
2514 }
2515
2516
2517 texUnit = _mesa_get_current_tex_unit(ctx);
2518 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2519 assert(texObj);
2520
2521 _mesa_lock_texture(ctx, texObj);
2522 {
2523 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2524
2525 if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0,
2526 postConvWidth, 1, 1,
2527 format, type, texImage)) {
2528 /* error was recorded */
2529 }
2530 else if (width > 0) {
2531 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2532 xoffset += texImage->Border;
2533
2534 ASSERT(ctx->Driver.TexSubImage1D);
2535 ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width,
2536 format, type, pixels, &ctx->Unpack,
2537 texObj, texImage);
2538
2539 check_gen_mipmap(ctx, target, texObj, level);
2540
2541 ctx->NewState |= _NEW_TEXTURE;
2542 }
2543 }
2544 _mesa_unlock_texture(ctx, texObj);
2545 }
2546
2547
2548 void GLAPIENTRY
2549 _mesa_TexSubImage2D( GLenum target, GLint level,
2550 GLint xoffset, GLint yoffset,
2551 GLsizei width, GLsizei height,
2552 GLenum format, GLenum type,
2553 const GLvoid *pixels )
2554 {
2555 GLsizei postConvWidth = width, postConvHeight = height;
2556 struct gl_texture_unit *texUnit;
2557 struct gl_texture_object *texObj;
2558 struct gl_texture_image *texImage;
2559 GET_CURRENT_CONTEXT(ctx);
2560 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2561
2562 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2563 _mesa_debug(ctx, "glTexSubImage2D %s %d %d %d %d %d %s %s %p\n",
2564 _mesa_lookup_enum_by_nr(target), level,
2565 xoffset, yoffset, width, height,
2566 _mesa_lookup_enum_by_nr(format),
2567 _mesa_lookup_enum_by_nr(type), pixels);
2568
2569 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2570 _mesa_update_state(ctx);
2571
2572 #if FEATURE_convolve
2573 /* XXX should test internal format */
2574 if (_mesa_is_color_format(format)) {
2575 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2576 &postConvHeight);
2577 }
2578 #endif
2579
2580 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2581 postConvWidth, postConvHeight, 1, format, type)) {
2582 return; /* error was detected */
2583 }
2584
2585 texUnit = _mesa_get_current_tex_unit(ctx);
2586 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2587
2588 _mesa_lock_texture(ctx, texObj);
2589 {
2590 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2591
2592 if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
2593 postConvWidth, postConvHeight, 1,
2594 format, type, texImage)) {
2595 /* error was recorded */
2596 }
2597 else if (width > 0 && height >= 0) {
2598 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2599 xoffset += texImage->Border;
2600 yoffset += texImage->Border;
2601
2602 ASSERT(ctx->Driver.TexSubImage2D);
2603 ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset,
2604 width, height, format, type, pixels,
2605 &ctx->Unpack, texObj, texImage);
2606
2607 check_gen_mipmap(ctx, target, texObj, level);
2608
2609 ctx->NewState |= _NEW_TEXTURE;
2610 }
2611 }
2612 _mesa_unlock_texture(ctx, texObj);
2613 }
2614
2615
2616
2617 void GLAPIENTRY
2618 _mesa_TexSubImage3D( GLenum target, GLint level,
2619 GLint xoffset, GLint yoffset, GLint zoffset,
2620 GLsizei width, GLsizei height, GLsizei depth,
2621 GLenum format, GLenum type,
2622 const GLvoid *pixels )
2623 {
2624 struct gl_texture_unit *texUnit;
2625 struct gl_texture_object *texObj;
2626 struct gl_texture_image *texImage;
2627 GET_CURRENT_CONTEXT(ctx);
2628 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2629
2630 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2631 _mesa_debug(ctx, "glTexSubImage3D %s %d %d %d %d %d %d %d %s %s %p\n",
2632 _mesa_lookup_enum_by_nr(target), level,
2633 xoffset, yoffset, zoffset, width, height, depth,
2634 _mesa_lookup_enum_by_nr(format),
2635 _mesa_lookup_enum_by_nr(type), pixels);
2636
2637 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2638 _mesa_update_state(ctx);
2639
2640 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2641 width, height, depth, format, type)) {
2642 return; /* error was detected */
2643 }
2644
2645 texUnit = _mesa_get_current_tex_unit(ctx);
2646 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2647
2648 _mesa_lock_texture(ctx, texObj);
2649 {
2650 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2651
2652 if (subtexture_error_check2(ctx, 3, target, level,
2653 xoffset, yoffset, zoffset,
2654 width, height, depth,
2655 format, type, texImage)) {
2656 /* error was recorded */
2657 }
2658 else if (width > 0 && height > 0 && height > 0) {
2659 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2660 xoffset += texImage->Border;
2661 yoffset += texImage->Border;
2662 zoffset += texImage->Border;
2663
2664 ASSERT(ctx->Driver.TexSubImage3D);
2665 ctx->Driver.TexSubImage3D(ctx, target, level,
2666 xoffset, yoffset, zoffset,
2667 width, height, depth,
2668 format, type, pixels,
2669 &ctx->Unpack, texObj, texImage );
2670
2671 check_gen_mipmap(ctx, target, texObj, level);
2672
2673 ctx->NewState |= _NEW_TEXTURE;
2674 }
2675 }
2676 _mesa_unlock_texture(ctx, texObj);
2677 }
2678
2679
2680
2681 void GLAPIENTRY
2682 _mesa_CopyTexImage1D( GLenum target, GLint level,
2683 GLenum internalFormat,
2684 GLint x, GLint y,
2685 GLsizei width, GLint border )
2686 {
2687 struct gl_texture_unit *texUnit;
2688 struct gl_texture_object *texObj;
2689 struct gl_texture_image *texImage;
2690 GLsizei postConvWidth = width;
2691 const GLuint face = _mesa_tex_target_to_face(target);
2692 GET_CURRENT_CONTEXT(ctx);
2693 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2694
2695 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2696 _mesa_debug(ctx, "glCopyTexImage1D %s %d %s %d %d %d %d\n",
2697 _mesa_lookup_enum_by_nr(target), level,
2698 _mesa_lookup_enum_by_nr(internalFormat),
2699 x, y, width, border);
2700
2701 if (ctx->NewState & NEW_COPY_TEX_STATE)
2702 _mesa_update_state(ctx);
2703
2704 #if FEATURE_convolve
2705 if (_mesa_is_color_format(internalFormat)) {
2706 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2707 }
2708 #endif
2709
2710 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2711 postConvWidth, 1, border))
2712 return;
2713
2714 texUnit = _mesa_get_current_tex_unit(ctx);
2715 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2716
2717 _mesa_lock_texture(ctx, texObj);
2718 {
2719 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2720 if (!texImage) {
2721 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
2722 }
2723 else {
2724 if (texImage->Data) {
2725 ctx->Driver.FreeTexImageData( ctx, texImage );
2726 }
2727
2728 ASSERT(texImage->Data == NULL);
2729
2730 clear_teximage_fields(texImage); /* not really needed, but helpful */
2731 _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
2732 border, internalFormat);
2733
2734 ASSERT(ctx->Driver.CopyTexImage1D);
2735 ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat,
2736 x, y, width, border);
2737
2738 ASSERT(texImage->TexFormat);
2739
2740 check_gen_mipmap(ctx, target, texObj, level);
2741
2742 update_fbo_texture(ctx, texObj, face, level);
2743
2744 /* state update */
2745 texObj->_Complete = GL_FALSE;
2746 ctx->NewState |= _NEW_TEXTURE;
2747 }
2748 }
2749 _mesa_unlock_texture(ctx, texObj);
2750 }
2751
2752
2753
2754 void GLAPIENTRY
2755 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2756 GLint x, GLint y, GLsizei width, GLsizei height,
2757 GLint border )
2758 {
2759 struct gl_texture_unit *texUnit;
2760 struct gl_texture_object *texObj;
2761 struct gl_texture_image *texImage;
2762 GLsizei postConvWidth = width, postConvHeight = height;
2763 const GLuint face = _mesa_tex_target_to_face(target);
2764 GET_CURRENT_CONTEXT(ctx);
2765 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2766
2767 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2768 _mesa_debug(ctx, "glCopyTexImage2D %s %d %s %d %d %d %d %d\n",
2769 _mesa_lookup_enum_by_nr(target), level,
2770 _mesa_lookup_enum_by_nr(internalFormat),
2771 x, y, width, height, border);
2772
2773 if (ctx->NewState & NEW_COPY_TEX_STATE)
2774 _mesa_update_state(ctx);
2775
2776 #if FEATURE_convolve
2777 if (_mesa_is_color_format(internalFormat)) {
2778 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2779 &postConvHeight);
2780 }
2781 #endif
2782
2783 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2784 postConvWidth, postConvHeight, border))
2785 return;
2786
2787 texUnit = _mesa_get_current_tex_unit(ctx);
2788 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2789
2790 _mesa_lock_texture(ctx, texObj);
2791 {
2792 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2793
2794 if (!texImage) {
2795 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
2796 }
2797 else {
2798 if (texImage->Data) {
2799 ctx->Driver.FreeTexImageData( ctx, texImage );
2800 }
2801
2802 ASSERT(texImage->Data == NULL);
2803
2804 clear_teximage_fields(texImage); /* not really needed, but helpful */
2805 _mesa_init_teximage_fields(ctx, target, texImage,
2806 postConvWidth, postConvHeight, 1,
2807 border, internalFormat);
2808
2809 ASSERT(ctx->Driver.CopyTexImage2D);
2810 ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat,
2811 x, y, width, height, border);
2812
2813 ASSERT(texImage->TexFormat);
2814
2815 check_gen_mipmap(ctx, target, texObj, level);
2816
2817 update_fbo_texture(ctx, texObj, face, level);
2818
2819 /* state update */
2820 texObj->_Complete = GL_FALSE;
2821 ctx->NewState |= _NEW_TEXTURE;
2822 }
2823 }
2824 _mesa_unlock_texture(ctx, texObj);
2825 }
2826
2827
2828 void GLAPIENTRY
2829 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
2830 GLint xoffset, GLint x, GLint y, GLsizei width )
2831 {
2832 struct gl_texture_unit *texUnit;
2833 struct gl_texture_object *texObj;
2834 struct gl_texture_image *texImage;
2835 GLsizei postConvWidth = width;
2836 GLint yoffset = 0;
2837 GLsizei height = 1;
2838
2839 GET_CURRENT_CONTEXT(ctx);
2840 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2841
2842 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2843 _mesa_debug(ctx, "glCopyTexSubImage1D %s %d %d %d %d %d\n",
2844 _mesa_lookup_enum_by_nr(target),
2845 level, xoffset, x, y, width);
2846
2847 if (ctx->NewState & NEW_COPY_TEX_STATE)
2848 _mesa_update_state(ctx);
2849
2850 if (copytexsubimage_error_check1(ctx, 1, target, level))
2851 return;
2852
2853 texUnit = _mesa_get_current_tex_unit(ctx);
2854 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2855
2856 _mesa_lock_texture(ctx, texObj);
2857 {
2858 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2859
2860 #if FEATURE_convolve
2861 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
2862 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2863 }
2864 #endif
2865
2866 if (copytexsubimage_error_check2(ctx, 1, target, level,
2867 xoffset, 0, 0, postConvWidth, 1,
2868 texImage)) {
2869 /* error was recorded */
2870 }
2871 else {
2872 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2873 xoffset += texImage->Border;
2874
2875 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
2876 &width, &height)) {
2877 ASSERT(ctx->Driver.CopyTexSubImage1D);
2878 ctx->Driver.CopyTexSubImage1D(ctx, target, level,
2879 xoffset, x, y, width);
2880
2881 check_gen_mipmap(ctx, target, texObj, level);
2882
2883 ctx->NewState |= _NEW_TEXTURE;
2884 }
2885 }
2886 }
2887 _mesa_unlock_texture(ctx, texObj);
2888 }
2889
2890
2891
2892 void GLAPIENTRY
2893 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
2894 GLint xoffset, GLint yoffset,
2895 GLint x, GLint y, GLsizei width, GLsizei height )
2896 {
2897 struct gl_texture_unit *texUnit;
2898 struct gl_texture_object *texObj;
2899 struct gl_texture_image *texImage;
2900 GLsizei postConvWidth = width, postConvHeight = height;
2901 GET_CURRENT_CONTEXT(ctx);
2902 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2903
2904 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2905 _mesa_debug(ctx, "glCopyTexSubImage2D %s %d %d %d %d %d %d %d\n",
2906 _mesa_lookup_enum_by_nr(target),
2907 level, xoffset, yoffset, x, y, width, height);
2908
2909 if (ctx->NewState & NEW_COPY_TEX_STATE)
2910 _mesa_update_state(ctx);
2911
2912 if (copytexsubimage_error_check1(ctx, 2, target, level))
2913 return;
2914
2915 texUnit = _mesa_get_current_tex_unit(ctx);
2916 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2917
2918 _mesa_lock_texture(ctx, texObj);
2919 {
2920 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2921
2922 #if FEATURE_convolve
2923 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
2924 _mesa_adjust_image_for_convolution(ctx, 2,
2925 &postConvWidth, &postConvHeight);
2926 }
2927 #endif
2928
2929 if (copytexsubimage_error_check2(ctx, 2, target, level,
2930 xoffset, yoffset, 0,
2931 postConvWidth, postConvHeight,
2932 texImage)) {
2933 /* error was recorded */
2934 }
2935 else {
2936 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2937 xoffset += texImage->Border;
2938 yoffset += texImage->Border;
2939
2940 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
2941 &width, &height)) {
2942 ASSERT(ctx->Driver.CopyTexSubImage2D);
2943 ctx->Driver.CopyTexSubImage2D(ctx, target, level, xoffset, yoffset,
2944 x, y, width, height);
2945
2946 check_gen_mipmap(ctx, target, texObj, level);
2947
2948 ctx->NewState |= _NEW_TEXTURE;
2949 }
2950 }
2951 }
2952 _mesa_unlock_texture(ctx, texObj);
2953 }
2954
2955
2956
2957 void GLAPIENTRY
2958 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2959 GLint xoffset, GLint yoffset, GLint zoffset,
2960 GLint x, GLint y, GLsizei width, GLsizei height )
2961 {
2962 struct gl_texture_unit *texUnit;
2963 struct gl_texture_object *texObj;
2964 struct gl_texture_image *texImage;
2965 GLsizei postConvWidth = width, postConvHeight = height;
2966 GET_CURRENT_CONTEXT(ctx);
2967 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2968
2969 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2970 _mesa_debug(ctx, "glCopyTexSubImage3D %s %d %d %d %d %d %d %d %d\n",
2971 _mesa_lookup_enum_by_nr(target),
2972 level, xoffset, yoffset, zoffset, x, y, width, height);
2973
2974 if (ctx->NewState & NEW_COPY_TEX_STATE)
2975 _mesa_update_state(ctx);
2976
2977 if (copytexsubimage_error_check1(ctx, 3, target, level))
2978 return;
2979
2980 texUnit = _mesa_get_current_tex_unit(ctx);
2981 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2982
2983 _mesa_lock_texture(ctx, texObj);
2984 {
2985 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2986
2987 #if FEATURE_convolve
2988 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
2989 _mesa_adjust_image_for_convolution(ctx, 2,
2990 &postConvWidth, &postConvHeight);
2991 }
2992 #endif
2993
2994 if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
2995 zoffset, postConvWidth, postConvHeight,
2996 texImage)) {
2997 /* error was recored */
2998 }
2999 else {
3000 /* If we have a border, xoffset=-1 is legal. Bias by border width */
3001 xoffset += texImage->Border;
3002 yoffset += texImage->Border;
3003 zoffset += texImage->Border;
3004
3005 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
3006 &width, &height)) {
3007 ASSERT(ctx->Driver.CopyTexSubImage3D);
3008 ctx->Driver.CopyTexSubImage3D(ctx, target, level,
3009 xoffset, yoffset, zoffset,
3010 x, y, width, height);
3011
3012 check_gen_mipmap(ctx, target, texObj, level);
3013
3014 ctx->NewState |= _NEW_TEXTURE;
3015 }
3016 }
3017 }
3018 _mesa_unlock_texture(ctx, texObj);
3019 }
3020
3021
3022
3023
3024 /**********************************************************************/
3025 /****** Compressed Textures ******/
3026 /**********************************************************************/
3027
3028
3029 /**
3030 * Error checking for glCompressedTexImage[123]D().
3031 * \return error code or GL_NO_ERROR.
3032 */
3033 static GLenum
3034 compressed_texture_error_check(GLcontext *ctx, GLint dimensions,
3035 GLenum target, GLint level,
3036 GLenum internalFormat, GLsizei width,
3037 GLsizei height, GLsizei depth, GLint border,
3038 GLsizei imageSize)
3039 {
3040 GLint expectedSize, maxLevels = 0, maxTextureSize;
3041
3042 if (dimensions == 1) {
3043 /* 1D compressed textures not allowed */
3044 return GL_INVALID_ENUM;
3045 }
3046 else if (dimensions == 2) {
3047 if (target == GL_PROXY_TEXTURE_2D) {
3048 maxLevels = ctx->Const.MaxTextureLevels;
3049 }
3050 else if (target == GL_TEXTURE_2D) {
3051 maxLevels = ctx->Const.MaxTextureLevels;
3052 }
3053 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3054 if (!ctx->Extensions.ARB_texture_cube_map)
3055 return GL_INVALID_ENUM; /*target*/
3056 maxLevels = ctx->Const.MaxCubeTextureLevels;
3057 }
3058 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3059 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3060 if (!ctx->Extensions.ARB_texture_cube_map)
3061 return GL_INVALID_ENUM; /*target*/
3062 maxLevels = ctx->Const.MaxCubeTextureLevels;
3063 }
3064 else {
3065 return GL_INVALID_ENUM; /*target*/
3066 }
3067 }
3068 else if (dimensions == 3) {
3069 /* 3D compressed textures not allowed */
3070 return GL_INVALID_ENUM;
3071 }
3072
3073 maxTextureSize = 1 << (maxLevels - 1);
3074
3075 /* This will detect any invalid internalFormat value */
3076 if (!is_compressed_format(ctx, internalFormat))
3077 return GL_INVALID_ENUM;
3078
3079 /* This should really never fail */
3080 if (_mesa_base_tex_format(ctx, internalFormat) < 0)
3081 return GL_INVALID_ENUM;
3082
3083 if (border != 0)
3084 return GL_INVALID_VALUE;
3085
3086 /*
3087 * XXX We should probably use the proxy texture error check function here.
3088 */
3089 if (width < 1 || width > maxTextureSize ||
3090 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width)))
3091 return GL_INVALID_VALUE;
3092
3093 if ((height < 1 || height > maxTextureSize ||
3094 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height)))
3095 && dimensions > 1)
3096 return GL_INVALID_VALUE;
3097
3098 if ((depth < 1 || depth > maxTextureSize ||
3099 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth)))
3100 && dimensions > 2)
3101 return GL_INVALID_VALUE;
3102
3103 /* For cube map, width must equal height */
3104 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3105 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
3106 return GL_INVALID_VALUE;
3107
3108 if (level < 0 || level >= maxLevels)
3109 return GL_INVALID_VALUE;
3110
3111 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
3112 depth, internalFormat);
3113 if (expectedSize != imageSize)
3114 return GL_INVALID_VALUE;
3115
3116 #if FEATURE_EXT_texture_sRGB
3117 if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
3118 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
3119 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
3120 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
3121 && border != 0) {
3122 return GL_INVALID_OPERATION;
3123 }
3124 #endif
3125
3126 return GL_NO_ERROR;
3127 }
3128
3129
3130 /**
3131 * Error checking for glCompressedTexSubImage[123]D().
3132 * \warning There are some bad assumptions here about the size of compressed
3133 * texture tiles (multiple of 4) used to test the validity of the
3134 * offset and size parameters.
3135 * \return error code or GL_NO_ERROR.
3136 */
3137 static GLenum
3138 compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions,
3139 GLenum target, GLint level,
3140 GLint xoffset, GLint yoffset, GLint zoffset,
3141 GLsizei width, GLsizei height, GLsizei depth,
3142 GLenum format, GLsizei imageSize)
3143 {
3144 GLint expectedSize, maxLevels = 0, maxTextureSize;
3145 (void) zoffset;
3146
3147 if (dimensions == 1) {
3148 /* 1D compressed textures not allowed */
3149 return GL_INVALID_ENUM;
3150 }
3151 else if (dimensions == 2) {
3152 if (target == GL_PROXY_TEXTURE_2D) {
3153 maxLevels = ctx->Const.MaxTextureLevels;
3154 }
3155 else if (target == GL_TEXTURE_2D) {
3156 maxLevels = ctx->Const.MaxTextureLevels;
3157 }
3158 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3159 if (!ctx->Extensions.ARB_texture_cube_map)
3160 return GL_INVALID_ENUM; /*target*/
3161 maxLevels = ctx->Const.MaxCubeTextureLevels;
3162 }
3163 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3164 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3165 if (!ctx->Extensions.ARB_texture_cube_map)
3166 return GL_INVALID_ENUM; /*target*/
3167 maxLevels = ctx->Const.MaxCubeTextureLevels;
3168 }
3169 else {
3170 return GL_INVALID_ENUM; /*target*/
3171 }
3172 }
3173 else if (dimensions == 3) {
3174 /* 3D compressed textures not allowed */
3175 return GL_INVALID_ENUM;
3176 }
3177
3178 maxTextureSize = 1 << (maxLevels - 1);
3179
3180 /* this will catch any invalid compressed format token */
3181 if (!is_compressed_format(ctx, format))
3182 return GL_INVALID_ENUM;
3183
3184 if (width < 1 || width > maxTextureSize)
3185 return GL_INVALID_VALUE;
3186
3187 if ((height < 1 || height > maxTextureSize)
3188 && dimensions > 1)
3189 return GL_INVALID_VALUE;
3190
3191 if (level < 0 || level >= maxLevels)
3192 return GL_INVALID_VALUE;
3193
3194 /* XXX these tests are specific to the compressed format.
3195 * this code should be generalized in some way.
3196 */
3197 if ((xoffset & 3) != 0 || (yoffset & 3) != 0)
3198 return GL_INVALID_VALUE;
3199
3200 if ((width & 3) != 0 && width != 2 && width != 1)
3201 return GL_INVALID_VALUE;
3202
3203 if ((height & 3) != 0 && height != 2 && height != 1)
3204 return GL_INVALID_VALUE;
3205
3206 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
3207 depth, format);
3208 if (expectedSize != imageSize)
3209 return GL_INVALID_VALUE;
3210
3211 return GL_NO_ERROR;
3212 }
3213
3214
3215
3216 void GLAPIENTRY
3217 _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
3218 GLenum internalFormat, GLsizei width,
3219 GLint border, GLsizei imageSize,
3220 const GLvoid *data)
3221 {
3222 GET_CURRENT_CONTEXT(ctx);
3223 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3224
3225 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3226 _mesa_debug(ctx, "glCompressedTexImage1DARB %s %d %s %d %d %d %p\n",
3227 _mesa_lookup_enum_by_nr(target), level,
3228 _mesa_lookup_enum_by_nr(internalFormat),
3229 width, border, imageSize, data);
3230
3231 if (target == GL_TEXTURE_1D) {
3232 /* non-proxy target */
3233 struct gl_texture_unit *texUnit;
3234 struct gl_texture_object *texObj;
3235 struct gl_texture_image *texImage;
3236 GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3237 internalFormat, width, 1, 1, border, imageSize);
3238 if (error) {
3239 _mesa_error(ctx, error, "glCompressedTexImage1D");
3240 return;
3241 }
3242
3243 texUnit = _mesa_get_current_tex_unit(ctx);
3244 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3245
3246 _mesa_lock_texture(ctx, texObj);
3247 {
3248 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3249 if (!texImage) {
3250 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
3251 }
3252 else {
3253 if (texImage->Data) {
3254 ctx->Driver.FreeTexImageData( ctx, texImage );
3255 }
3256 ASSERT(texImage->Data == NULL);
3257
3258 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3259 border, internalFormat);
3260
3261 ASSERT(ctx->Driver.CompressedTexImage1D);
3262 ctx->Driver.CompressedTexImage1D(ctx, target, level,
3263 internalFormat, width, border,
3264 imageSize, data,
3265 texObj, texImage);
3266
3267 check_gen_mipmap(ctx, target, texObj, level);
3268
3269 /* state update */
3270 texObj->_Complete = GL_FALSE;
3271 ctx->NewState |= _NEW_TEXTURE;
3272 }
3273 }
3274 _mesa_unlock_texture(ctx, texObj);
3275 }
3276 else if (target == GL_PROXY_TEXTURE_1D) {
3277 /* Proxy texture: check for errors and update proxy state */
3278 GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3279 internalFormat, width, 1, 1, border, imageSize);
3280 if (!error) {
3281 ASSERT(ctx->Driver.TestProxyTexImage);
3282 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3283 internalFormat, GL_NONE, GL_NONE,
3284 width, 1, 1, border);
3285 }
3286 if (error) {
3287 /* if error, clear all proxy texture image parameters */
3288 struct gl_texture_image *texImage;
3289 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3290 if (texImage)
3291 clear_teximage_fields(texImage);
3292 }
3293 else {
3294 /* store the teximage parameters */
3295 struct gl_texture_unit *texUnit;
3296 struct gl_texture_object *texObj;
3297 struct gl_texture_image *texImage;
3298 texUnit = _mesa_get_current_tex_unit(ctx);
3299 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3300
3301 _mesa_lock_texture(ctx, texObj);
3302 {
3303 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3304 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3305 border, internalFormat);
3306 }
3307 _mesa_unlock_texture(ctx, texObj);
3308 }
3309 }
3310 else {
3311 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
3312 return;
3313 }
3314 }
3315
3316
3317 void GLAPIENTRY
3318 _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3319 GLenum internalFormat, GLsizei width,
3320 GLsizei height, GLint border, GLsizei imageSize,
3321 const GLvoid *data)
3322 {
3323 GET_CURRENT_CONTEXT(ctx);
3324 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3325
3326 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3327 _mesa_debug(ctx, "glCompressedTexImage2DARB %s %d %s %d %d %d %d %p\n",
3328 _mesa_lookup_enum_by_nr(target), level,
3329 _mesa_lookup_enum_by_nr(internalFormat),
3330 width, height, border, imageSize, data);
3331
3332 if (target == GL_TEXTURE_2D ||
3333 (ctx->Extensions.ARB_texture_cube_map &&
3334 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3335 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3336 /* non-proxy target */
3337 struct gl_texture_unit *texUnit;
3338 struct gl_texture_object *texObj;
3339 struct gl_texture_image *texImage;
3340 GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3341 internalFormat, width, height, 1, border, imageSize);
3342 if (error) {
3343 _mesa_error(ctx, error, "glCompressedTexImage2D");
3344 return;
3345 }
3346
3347 texUnit = _mesa_get_current_tex_unit(ctx);
3348 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3349
3350 _mesa_lock_texture(ctx, texObj);
3351 {
3352 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3353 if (!texImage) {
3354 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
3355 }
3356 else {
3357 if (texImage->Data) {
3358 ctx->Driver.FreeTexImageData( ctx, texImage );
3359 }
3360 ASSERT(texImage->Data == NULL);
3361
3362 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3363 border, internalFormat);
3364
3365 ASSERT(ctx->Driver.CompressedTexImage2D);
3366 ctx->Driver.CompressedTexImage2D(ctx, target, level,
3367 internalFormat, width, height,
3368 border, imageSize, data,
3369 texObj, texImage);
3370
3371 check_gen_mipmap(ctx, target, texObj, level);
3372
3373 /* state update */
3374 texObj->_Complete = GL_FALSE;
3375 ctx->NewState |= _NEW_TEXTURE;
3376 }
3377 }
3378 _mesa_unlock_texture(ctx, texObj);
3379 }
3380 else if (target == GL_PROXY_TEXTURE_2D ||
3381 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
3382 ctx->Extensions.ARB_texture_cube_map)) {
3383 /* Proxy texture: check for errors and update proxy state */
3384 GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3385 internalFormat, width, height, 1, border, imageSize);
3386 if (!error) {
3387 ASSERT(ctx->Driver.TestProxyTexImage);
3388 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3389 internalFormat, GL_NONE, GL_NONE,
3390 width, height, 1, border);
3391 }
3392 if (error) {
3393 /* if error, clear all proxy texture image parameters */
3394 struct gl_texture_image *texImage;
3395 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3396 if (texImage)
3397 clear_teximage_fields(texImage);
3398 }
3399 else {
3400 /* store the teximage parameters */
3401 struct gl_texture_unit *texUnit;
3402 struct gl_texture_object *texObj;
3403 struct gl_texture_image *texImage;
3404 texUnit = _mesa_get_current_tex_unit(ctx);
3405 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3406
3407 _mesa_lock_texture(ctx, texObj);
3408 {
3409 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3410 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3411 border, internalFormat);
3412 }
3413 _mesa_unlock_texture(ctx, texObj);
3414 }
3415 }
3416 else {
3417 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
3418 return;
3419 }
3420 }
3421
3422
3423 void GLAPIENTRY
3424 _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3425 GLenum internalFormat, GLsizei width,
3426 GLsizei height, GLsizei depth, GLint border,
3427 GLsizei imageSize, const GLvoid *data)
3428 {
3429 GET_CURRENT_CONTEXT(ctx);
3430 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3431
3432 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3433 _mesa_debug(ctx, "glCompressedTexImage3DARB %s %d %s %d %d %d %d %d %p\n",
3434 _mesa_lookup_enum_by_nr(target), level,
3435 _mesa_lookup_enum_by_nr(internalFormat),
3436 width, height, depth, border, imageSize, data);
3437
3438 if (target == GL_TEXTURE_3D) {
3439 /* non-proxy target */
3440 struct gl_texture_unit *texUnit;
3441 struct gl_texture_object *texObj;
3442 struct gl_texture_image *texImage;
3443 GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3444 internalFormat, width, height, depth, border, imageSize);
3445 if (error) {
3446 _mesa_error(ctx, error, "glCompressedTexImage3D");
3447 return;
3448 }
3449
3450 texUnit = _mesa_get_current_tex_unit(ctx);
3451 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3452 _mesa_lock_texture(ctx, texObj);
3453 {
3454 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3455 if (!texImage) {
3456 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
3457 }
3458 else {
3459 if (texImage->Data) {
3460 ctx->Driver.FreeTexImageData( ctx, texImage );
3461 }
3462 ASSERT(texImage->Data == NULL);
3463
3464 _mesa_init_teximage_fields(ctx, target, texImage,
3465 width, height, depth,
3466 border, internalFormat);
3467
3468 ASSERT(ctx->Driver.CompressedTexImage3D);
3469 ctx->Driver.CompressedTexImage3D(ctx, target, level,
3470 internalFormat,
3471 width, height, depth,
3472 border, imageSize, data,
3473 texObj, texImage);
3474
3475 check_gen_mipmap(ctx, target, texObj, level);
3476
3477 /* state update */
3478 texObj->_Complete = GL_FALSE;
3479 ctx->NewState |= _NEW_TEXTURE;
3480 }
3481 }
3482 _mesa_unlock_texture(ctx, texObj);
3483 }
3484 else if (target == GL_PROXY_TEXTURE_3D) {
3485 /* Proxy texture: check for errors and update proxy state */
3486 GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3487 internalFormat, width, height, depth, border, imageSize);
3488 if (!error) {
3489 ASSERT(ctx->Driver.TestProxyTexImage);
3490 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3491 internalFormat, GL_NONE, GL_NONE,
3492 width, height, depth, border);
3493 }
3494 if (error) {
3495 /* if error, clear all proxy texture image parameters */
3496 struct gl_texture_image *texImage;
3497 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3498 if (texImage)
3499 clear_teximage_fields(texImage);
3500 }
3501 else {
3502 /* store the teximage parameters */
3503 struct gl_texture_unit *texUnit;
3504 struct gl_texture_object *texObj;
3505 struct gl_texture_image *texImage;
3506 texUnit = _mesa_get_current_tex_unit(ctx);
3507 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3508 _mesa_lock_texture(ctx, texObj);
3509 {
3510 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3511 _mesa_init_teximage_fields(ctx, target, texImage, width, height,
3512 depth, border, internalFormat);
3513 }
3514 _mesa_unlock_texture(ctx, texObj);
3515 }
3516 }
3517 else {
3518 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
3519 return;
3520 }
3521 }
3522
3523
3524 void GLAPIENTRY
3525 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3526 GLsizei width, GLenum format,
3527 GLsizei imageSize, const GLvoid *data)
3528 {
3529 struct gl_texture_unit *texUnit;
3530 struct gl_texture_object *texObj;
3531 struct gl_texture_image *texImage;
3532 GLenum error;
3533 GET_CURRENT_CONTEXT(ctx);
3534 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3535
3536 error = compressed_subtexture_error_check(ctx, 1, target, level,
3537 xoffset, 0, 0, /* pos */
3538 width, 1, 1, /* size */
3539 format, imageSize);
3540 if (error) {
3541 _mesa_error(ctx, error, "glCompressedTexSubImage1D");
3542 return;
3543 }
3544
3545 texUnit = _mesa_get_current_tex_unit(ctx);
3546 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3547
3548 _mesa_lock_texture(ctx, texObj);
3549 {
3550 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3551 assert(texImage);
3552
3553 if ((GLint) format != texImage->InternalFormat) {
3554 _mesa_error(ctx, GL_INVALID_OPERATION,
3555 "glCompressedTexSubImage1D(format)");
3556 }
3557 else if ((width == 1 || width == 2) &&
3558 (GLuint) width != texImage->Width) {
3559 _mesa_error(ctx, GL_INVALID_VALUE,
3560 "glCompressedTexSubImage1D(width)");
3561 }
3562 else if (width > 0) {
3563 if (ctx->Driver.CompressedTexSubImage1D) {
3564 ctx->Driver.CompressedTexSubImage1D(ctx, target, level,
3565 xoffset, width,
3566 format, imageSize, data,
3567 texObj, texImage);
3568 }
3569
3570 check_gen_mipmap(ctx, target, texObj, level);
3571
3572 ctx->NewState |= _NEW_TEXTURE;
3573 }
3574 }
3575 _mesa_unlock_texture(ctx, texObj);
3576 }
3577
3578
3579 void GLAPIENTRY
3580 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3581 GLint yoffset, GLsizei width, GLsizei height,
3582 GLenum format, GLsizei imageSize,
3583 const GLvoid *data)
3584 {
3585 struct gl_texture_unit *texUnit;
3586 struct gl_texture_object *texObj;
3587 struct gl_texture_image *texImage;
3588 GLenum error;
3589 GET_CURRENT_CONTEXT(ctx);
3590 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3591
3592 error = compressed_subtexture_error_check(ctx, 2, target, level,
3593 xoffset, yoffset, 0, /* pos */
3594 width, height, 1, /* size */
3595 format, imageSize);
3596 if (error) {
3597 /* XXX proxy target? */
3598 _mesa_error(ctx, error, "glCompressedTexSubImage2D");
3599 return;
3600 }
3601
3602 texUnit = _mesa_get_current_tex_unit(ctx);
3603 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3604
3605 _mesa_lock_texture(ctx, texObj);
3606 {
3607 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3608 assert(texImage);
3609
3610 if ((GLint) format != texImage->InternalFormat) {
3611 _mesa_error(ctx, GL_INVALID_OPERATION,
3612 "glCompressedTexSubImage2D(format)");
3613 }
3614 else if (((width == 1 || width == 2)
3615 && (GLuint) width != texImage->Width) ||
3616 ((height == 1 || height == 2)
3617 && (GLuint) height != texImage->Height)) {
3618 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)");
3619 }
3620 else if (width > 0 && height > 0) {
3621 if (ctx->Driver.CompressedTexSubImage2D) {
3622 ctx->Driver.CompressedTexSubImage2D(ctx, target, level,
3623 xoffset, yoffset, width, height,
3624 format, imageSize, data,
3625 texObj, texImage);
3626 }
3627
3628 check_gen_mipmap(ctx, target, texObj, level);
3629
3630 ctx->NewState |= _NEW_TEXTURE;
3631 }
3632 }
3633 _mesa_unlock_texture(ctx, texObj);
3634 }
3635
3636
3637 void GLAPIENTRY
3638 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3639 GLint yoffset, GLint zoffset, GLsizei width,
3640 GLsizei height, GLsizei depth, GLenum format,
3641 GLsizei imageSize, const GLvoid *data)
3642 {
3643 struct gl_texture_unit *texUnit;
3644 struct gl_texture_object *texObj;
3645 struct gl_texture_image *texImage;
3646 GLenum error;
3647 GET_CURRENT_CONTEXT(ctx);
3648 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3649
3650 error = compressed_subtexture_error_check(ctx, 3, target, level,
3651 xoffset, yoffset, zoffset,/*pos*/
3652 width, height, depth, /*size*/
3653 format, imageSize);
3654 if (error) {
3655 _mesa_error(ctx, error, "glCompressedTexSubImage3D");
3656 return;
3657 }
3658
3659 texUnit = _mesa_get_current_tex_unit(ctx);
3660 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3661
3662 _mesa_lock_texture(ctx, texObj);
3663 {
3664 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3665 assert(texImage);
3666
3667 if ((GLint) format != texImage->InternalFormat) {
3668 _mesa_error(ctx, GL_INVALID_OPERATION,
3669 "glCompressedTexSubImage3D(format)");
3670 }
3671 else if (((width == 1 || width == 2)
3672 && (GLuint) width != texImage->Width) ||
3673 ((height == 1 || height == 2)
3674 && (GLuint) height != texImage->Height) ||
3675 ((depth == 1 || depth == 2)
3676 && (GLuint) depth != texImage->Depth)) {
3677 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)");
3678 }
3679 else if (width > 0 && height > 0 && depth > 0) {
3680 if (ctx->Driver.CompressedTexSubImage3D) {
3681 ctx->Driver.CompressedTexSubImage3D(ctx, target, level,
3682 xoffset, yoffset, zoffset,
3683 width, height, depth,
3684 format, imageSize, data,
3685 texObj, texImage);
3686 }
3687
3688 check_gen_mipmap(ctx, target, texObj, level);
3689
3690 ctx->NewState |= _NEW_TEXTURE;
3691 }
3692 }
3693 _mesa_unlock_texture(ctx, texObj);
3694 }
3695
3696