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