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