Merge texmem-0-3-branch.
[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 /* Free texImage->Data and/or any other driver-specific texture
710 * image storage.
711 */
712 ASSERT(ctx->Driver.FreeTexImageData);
713 ctx->Driver.FreeTexImageData( ctx, texImage );
714
715 ASSERT(texImage->Data == NULL);
716 if (texImage->ImageOffsets)
717 _mesa_free(texImage->ImageOffsets);
718 _mesa_free(texImage);
719 }
720
721
722 /**
723 * Test if a target is a proxy target.
724 *
725 * \param target texture target.
726 *
727 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
728 */
729 GLboolean
730 _mesa_is_proxy_texture(GLenum target)
731 {
732 return (target == GL_PROXY_TEXTURE_1D ||
733 target == GL_PROXY_TEXTURE_2D ||
734 target == GL_PROXY_TEXTURE_3D ||
735 target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
736 target == GL_PROXY_TEXTURE_RECTANGLE_NV);
737 }
738
739
740 /**
741 * Get the texture object that corresponds to the target of the given texture unit.
742 *
743 * \param ctx GL context.
744 * \param texUnit texture unit.
745 * \param target texture target.
746 *
747 * \return pointer to the texture object on success, or NULL on failure.
748 *
749 * \sa gl_texture_unit.
750 */
751 struct gl_texture_object *
752 _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
753 GLenum target)
754 {
755 switch (target) {
756 case GL_TEXTURE_1D:
757 return texUnit->Current1D;
758 case GL_PROXY_TEXTURE_1D:
759 return ctx->Texture.Proxy1D;
760 case GL_TEXTURE_2D:
761 return texUnit->Current2D;
762 case GL_PROXY_TEXTURE_2D:
763 return ctx->Texture.Proxy2D;
764 case GL_TEXTURE_3D:
765 return texUnit->Current3D;
766 case GL_PROXY_TEXTURE_3D:
767 return ctx->Texture.Proxy3D;
768 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
769 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
770 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
771 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
772 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
773 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
774 case GL_TEXTURE_CUBE_MAP_ARB:
775 return ctx->Extensions.ARB_texture_cube_map
776 ? texUnit->CurrentCubeMap : NULL;
777 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
778 return ctx->Extensions.ARB_texture_cube_map
779 ? ctx->Texture.ProxyCubeMap : NULL;
780 case GL_TEXTURE_RECTANGLE_NV:
781 return ctx->Extensions.NV_texture_rectangle
782 ? texUnit->CurrentRect : NULL;
783 case GL_PROXY_TEXTURE_RECTANGLE_NV:
784 return ctx->Extensions.NV_texture_rectangle
785 ? ctx->Texture.ProxyRect : NULL;
786 default:
787 _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
788 return NULL;
789 }
790 }
791
792
793 /**
794 * Get the texture image struct which corresponds to target and level
795 * of the given texture unit.
796 *
797 * \param ctx GL context.
798 * \param texUnit texture unit.
799 * \param target texture target.
800 * \param level image level.
801 *
802 * \return pointer to the texture image structure on success, or NULL on failure.
803 *
804 * \sa gl_texture_unit.
805 */
806 struct gl_texture_image *
807 _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj,
808 GLenum target, GLint level)
809 {
810 ASSERT(texObj);
811
812 if (level < 0 || level >= MAX_TEXTURE_LEVELS)
813 return NULL;
814
815 switch (target) {
816 case GL_TEXTURE_1D:
817 case GL_PROXY_TEXTURE_1D:
818 case GL_TEXTURE_2D:
819 case GL_PROXY_TEXTURE_2D:
820 case GL_TEXTURE_3D:
821 case GL_PROXY_TEXTURE_3D:
822 return texObj->Image[0][level];
823
824 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
825 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
826 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
827 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
828 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
829 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
830 if (ctx->Extensions.ARB_texture_cube_map) {
831 GLuint face = ((GLuint) target -
832 (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
833 return texObj->Image[face][level];
834 }
835 else
836 return NULL;
837
838 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
839 if (ctx->Extensions.ARB_texture_cube_map)
840 return texObj->Image[0][level];
841 else
842 return NULL;
843
844 case GL_TEXTURE_RECTANGLE_NV:
845 case GL_PROXY_TEXTURE_RECTANGLE_NV:
846 if (ctx->Extensions.NV_texture_rectangle && level == 0)
847 return texObj->Image[0][level];
848 else
849 return NULL;
850
851 default:
852 return NULL;
853 }
854 }
855
856
857 /**
858 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
859 * it and install it. Only return NULL if passed a bad parameter or run
860 * out of memory.
861 */
862 struct gl_texture_image *
863 _mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj,
864 GLenum target, GLint level)
865 {
866 struct gl_texture_image *texImage;
867
868 if (!texObj)
869 return NULL;
870
871 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
872 if (!texImage) {
873 texImage = ctx->Driver.NewTextureImage(ctx);
874 if (!texImage) {
875 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
876 return NULL;
877 }
878
879 _mesa_set_tex_image(texObj, target, level, texImage);
880 }
881
882 return texImage;
883 }
884
885
886 /**
887 * Return pointer to the specified proxy texture image.
888 * Note that proxy textures are per-context, not per-texture unit.
889 * \return pointer to texture image or NULL if invalid target, invalid
890 * level, or out of memory.
891 */
892 struct gl_texture_image *
893 _mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level)
894 {
895 struct gl_texture_image *texImage;
896
897 if (level < 0 )
898 return NULL;
899
900 switch (target) {
901 case GL_PROXY_TEXTURE_1D:
902 if (level >= ctx->Const.MaxTextureLevels)
903 return NULL;
904 texImage = ctx->Texture.Proxy1D->Image[0][level];
905 if (!texImage) {
906 texImage = ctx->Driver.NewTextureImage(ctx);
907 if (!texImage) {
908 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
909 return NULL;
910 }
911 ctx->Texture.Proxy1D->Image[0][level] = texImage;
912 /* Set the 'back' pointer */
913 texImage->TexObject = ctx->Texture.Proxy1D;
914 }
915 return texImage;
916 case GL_PROXY_TEXTURE_2D:
917 if (level >= ctx->Const.MaxTextureLevels)
918 return NULL;
919 texImage = ctx->Texture.Proxy2D->Image[0][level];
920 if (!texImage) {
921 texImage = ctx->Driver.NewTextureImage(ctx);
922 if (!texImage) {
923 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
924 return NULL;
925 }
926 ctx->Texture.Proxy2D->Image[0][level] = texImage;
927 /* Set the 'back' pointer */
928 texImage->TexObject = ctx->Texture.Proxy2D;
929 }
930 return texImage;
931 case GL_PROXY_TEXTURE_3D:
932 if (level >= ctx->Const.Max3DTextureLevels)
933 return NULL;
934 texImage = ctx->Texture.Proxy3D->Image[0][level];
935 if (!texImage) {
936 texImage = ctx->Driver.NewTextureImage(ctx);
937 if (!texImage) {
938 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
939 return NULL;
940 }
941 ctx->Texture.Proxy3D->Image[0][level] = texImage;
942 /* Set the 'back' pointer */
943 texImage->TexObject = ctx->Texture.Proxy3D;
944 }
945 return texImage;
946 case GL_PROXY_TEXTURE_CUBE_MAP:
947 if (level >= ctx->Const.MaxCubeTextureLevels)
948 return NULL;
949 texImage = ctx->Texture.ProxyCubeMap->Image[0][level];
950 if (!texImage) {
951 texImage = ctx->Driver.NewTextureImage(ctx);
952 if (!texImage) {
953 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
954 return NULL;
955 }
956 ctx->Texture.ProxyCubeMap->Image[0][level] = texImage;
957 /* Set the 'back' pointer */
958 texImage->TexObject = ctx->Texture.ProxyCubeMap;
959 }
960 return texImage;
961 case GL_PROXY_TEXTURE_RECTANGLE_NV:
962 if (level > 0)
963 return NULL;
964 texImage = ctx->Texture.ProxyRect->Image[0][level];
965 if (!texImage) {
966 texImage = ctx->Driver.NewTextureImage(ctx);
967 if (!texImage) {
968 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
969 return NULL;
970 }
971 ctx->Texture.ProxyRect->Image[0][level] = texImage;
972 /* Set the 'back' pointer */
973 texImage->TexObject = ctx->Texture.ProxyRect;
974 }
975 return texImage;
976 default:
977 return NULL;
978 }
979 }
980
981
982 /**
983 * Get the maximum number of allowed mipmap levels.
984 *
985 * \param ctx GL context.
986 * \param target texture target.
987 *
988 * \return the maximum number of allowed mipmap levels for the given
989 * texture target, or zero if passed a bad target.
990 *
991 * \sa gl_constants.
992 */
993 GLint
994 _mesa_max_texture_levels(GLcontext *ctx, GLenum target)
995 {
996 switch (target) {
997 case GL_TEXTURE_1D:
998 case GL_PROXY_TEXTURE_1D:
999 case GL_TEXTURE_2D:
1000 case GL_PROXY_TEXTURE_2D:
1001 return ctx->Const.MaxTextureLevels;
1002 case GL_TEXTURE_3D:
1003 case GL_PROXY_TEXTURE_3D:
1004 return ctx->Const.Max3DTextureLevels;
1005 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
1006 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
1007 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
1008 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
1009 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
1010 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
1011 case GL_TEXTURE_CUBE_MAP_ARB:
1012 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
1013 return ctx->Const.MaxCubeTextureLevels;
1014 case GL_TEXTURE_RECTANGLE_NV:
1015 case GL_PROXY_TEXTURE_RECTANGLE_NV:
1016 return 1;
1017 default:
1018 return 0; /* bad target */
1019 }
1020 }
1021
1022
1023
1024 #if 000 /* not used anymore */
1025 /*
1026 * glTexImage[123]D can accept a NULL image pointer. In this case we
1027 * create a texture image with unspecified image contents per the OpenGL
1028 * spec.
1029 */
1030 static GLubyte *
1031 make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
1032 {
1033 const GLint components = _mesa_components_in_format(format);
1034 const GLint numPixels = width * height * depth;
1035 GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
1036
1037 #ifdef DEBUG
1038 /*
1039 * Let's see if anyone finds this. If glTexImage2D() is called with
1040 * a NULL image pointer then load the texture image with something
1041 * interesting instead of leaving it indeterminate.
1042 */
1043 if (data) {
1044 static const char message[8][32] = {
1045 " X X XXXXX XXX X ",
1046 " XX XX X X X X X ",
1047 " X X X X X X X ",
1048 " X X XXXX XXX XXXXX ",
1049 " X X X X X X ",
1050 " X X X X X X X ",
1051 " X X XXXXX XXX X X ",
1052 " "
1053 };
1054
1055 GLubyte *imgPtr = data;
1056 GLint h, i, j, k;
1057 for (h = 0; h < depth; h++) {
1058 for (i = 0; i < height; i++) {
1059 GLint srcRow = 7 - (i % 8);
1060 for (j = 0; j < width; j++) {
1061 GLint srcCol = j % 32;
1062 GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
1063 for (k = 0; k < components; k++) {
1064 *imgPtr++ = texel;
1065 }
1066 }
1067 }
1068 }
1069 }
1070 #endif
1071
1072 return data;
1073 }
1074 #endif
1075
1076
1077
1078 /**
1079 * Reset the fields of a gl_texture_image struct to zero.
1080 *
1081 * \param img texture image structure.
1082 *
1083 * This is called when a proxy texture test fails, we set all the
1084 * image members (except DriverData) to zero.
1085 * It's also used in glTexImage[123]D as a safeguard to be sure all
1086 * required fields get initialized properly by the Driver.TexImage[123]D
1087 * functions.
1088 */
1089 static void
1090 clear_teximage_fields(struct gl_texture_image *img)
1091 {
1092 ASSERT(img);
1093 img->_BaseFormat = 0;
1094 img->InternalFormat = 0;
1095 img->Border = 0;
1096 img->Width = 0;
1097 img->Height = 0;
1098 img->Depth = 0;
1099 img->RowStride = 0;
1100 if (img->ImageOffsets) {
1101 _mesa_free(img->ImageOffsets);
1102 img->ImageOffsets = NULL;
1103 }
1104 img->Width2 = 0;
1105 img->Height2 = 0;
1106 img->Depth2 = 0;
1107 img->WidthLog2 = 0;
1108 img->HeightLog2 = 0;
1109 img->DepthLog2 = 0;
1110 img->Data = NULL;
1111 img->TexFormat = &_mesa_null_texformat;
1112 img->FetchTexelc = NULL;
1113 img->FetchTexelf = NULL;
1114 img->IsCompressed = 0;
1115 img->CompressedSize = 0;
1116 }
1117
1118
1119 /**
1120 * Initialize basic fields of the gl_texture_image struct.
1121 *
1122 * \param ctx GL context.
1123 * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
1124 * \param img texture image structure to be initialized.
1125 * \param width image width.
1126 * \param height image height.
1127 * \param depth image depth.
1128 * \param border image border.
1129 * \param internalFormat internal format.
1130 *
1131 * Fills in the fields of \p img with the given information.
1132 * Note: width, height and depth include the border.
1133 */
1134 void
1135 _mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
1136 struct gl_texture_image *img,
1137 GLsizei width, GLsizei height, GLsizei depth,
1138 GLint border, GLenum internalFormat)
1139 {
1140 GLint i;
1141
1142 ASSERT(img);
1143 ASSERT(width >= 0);
1144 ASSERT(height >= 0);
1145 ASSERT(depth >= 0);
1146
1147 img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
1148 ASSERT(img->_BaseFormat > 0);
1149 img->InternalFormat = internalFormat;
1150 img->Border = border;
1151 img->Width = width;
1152 img->Height = height;
1153 img->Depth = depth;
1154 img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */
1155 img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
1156 img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */
1157 img->WidthLog2 = logbase2(img->Width2);
1158 if (height == 1) /* 1-D texture */
1159 img->HeightLog2 = 0;
1160 else
1161 img->HeightLog2 = logbase2(img->Height2);
1162 if (depth == 1) /* 2-D texture */
1163 img->DepthLog2 = 0;
1164 else
1165 img->DepthLog2 = logbase2(img->Depth2);
1166 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
1167 img->IsCompressed = GL_FALSE;
1168 img->CompressedSize = 0;
1169
1170 if ((width == 1 || _mesa_bitcount(img->Width2) == 1) &&
1171 (height == 1 || _mesa_bitcount(img->Height2) == 1) &&
1172 (depth == 1 || _mesa_bitcount(img->Depth2) == 1))
1173 img->_IsPowerOfTwo = GL_TRUE;
1174 else
1175 img->_IsPowerOfTwo = GL_FALSE;
1176
1177 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
1178 img->RowStride = width;
1179 /* Allocate the ImageOffsets array and initialize to typical values.
1180 * We allocate the array for 1D/2D textures too in order to avoid special-
1181 * case code in the texstore routines.
1182 */
1183 img->ImageOffsets = (GLuint *) _mesa_malloc(depth * sizeof(GLuint));
1184 for (i = 0; i < depth; i++) {
1185 img->ImageOffsets[i] = i * width * height;
1186 }
1187
1188 /* Compute Width/Height/DepthScale for mipmap lod computation */
1189 if (target == GL_TEXTURE_RECTANGLE_NV) {
1190 /* scale = 1.0 since texture coords directly map to texels */
1191 img->WidthScale = 1.0;
1192 img->HeightScale = 1.0;
1193 img->DepthScale = 1.0;
1194 }
1195 else {
1196 img->WidthScale = (GLfloat) img->Width;
1197 img->HeightScale = (GLfloat) img->Height;
1198 img->DepthScale = (GLfloat) img->Depth;
1199 }
1200 }
1201
1202
1203 /**
1204 * This is the fallback for Driver.TestProxyTexImage(). Test the texture
1205 * level, width, height and depth against the ctx->Const limits for textures.
1206 *
1207 * A hardware driver might override this function if, for example, the
1208 * max 3D texture size is 512x512x64 (i.e. not a cube).
1209 *
1210 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
1211 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
1212 * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
1213 * \param level as passed to glTexImage
1214 * \param internalFormat as passed to glTexImage
1215 * \param format as passed to glTexImage
1216 * \param type as passed to glTexImage
1217 * \param width as passed to glTexImage
1218 * \param height as passed to glTexImage
1219 * \param depth as passed to glTexImage
1220 * \param border as passed to glTexImage
1221 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1222 */
1223 GLboolean
1224 _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
1225 GLint internalFormat, GLenum format, GLenum type,
1226 GLint width, GLint height, GLint depth, GLint border)
1227 {
1228 GLint maxSize;
1229
1230 (void) internalFormat;
1231 (void) format;
1232 (void) type;
1233
1234 switch (target) {
1235 case GL_PROXY_TEXTURE_1D:
1236 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1237 if (width < 2 * border || width > 2 + maxSize ||
1238 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1239 _mesa_bitcount(width - 2 * border) != 1) ||
1240 level >= ctx->Const.MaxTextureLevels) {
1241 /* bad width or level */
1242 return GL_FALSE;
1243 }
1244 return GL_TRUE;
1245 case GL_PROXY_TEXTURE_2D:
1246 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1247 if (width < 2 * border || width > 2 + maxSize ||
1248 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1249 _mesa_bitcount(width - 2 * border) != 1) ||
1250 height < 2 * border || height > 2 + maxSize ||
1251 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1252 _mesa_bitcount(height - 2 * border) != 1) ||
1253 level >= ctx->Const.MaxTextureLevels) {
1254 /* bad width or height or level */
1255 return GL_FALSE;
1256 }
1257 return GL_TRUE;
1258 case GL_PROXY_TEXTURE_3D:
1259 maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
1260 if (width < 2 * border || width > 2 + maxSize ||
1261 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1262 _mesa_bitcount(width - 2 * border) != 1) ||
1263 height < 2 * border || height > 2 + maxSize ||
1264 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1265 _mesa_bitcount(height - 2 * border) != 1) ||
1266 depth < 2 * border || depth > 2 + maxSize ||
1267 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1268 _mesa_bitcount(depth - 2 * border) != 1) ||
1269 level >= ctx->Const.Max3DTextureLevels) {
1270 /* bad width or height or depth or level */
1271 return GL_FALSE;
1272 }
1273 return GL_TRUE;
1274 case GL_PROXY_TEXTURE_RECTANGLE_NV:
1275 if (width < 1 || width > ctx->Const.MaxTextureRectSize ||
1276 height < 1 || height > ctx->Const.MaxTextureRectSize ||
1277 level != 0) {
1278 /* bad width or height or level */
1279 return GL_FALSE;
1280 }
1281 return GL_TRUE;
1282 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
1283 maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
1284 if (width < 2 * border || width > 2 + maxSize ||
1285 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1286 _mesa_bitcount(width - 2 * border) != 1) ||
1287 height < 2 * border || height > 2 + maxSize ||
1288 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1289 _mesa_bitcount(height - 2 * border) != 1) ||
1290 level >= ctx->Const.MaxCubeTextureLevels) {
1291 /* bad width or height */
1292 return GL_FALSE;
1293 }
1294 return GL_TRUE;
1295 default:
1296 _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
1297 return GL_FALSE;
1298 }
1299 }
1300
1301
1302 /**
1303 * Test the glTexImage[123]D() parameters for errors.
1304 *
1305 * \param ctx GL context.
1306 * \param target texture target given by the user.
1307 * \param level image level given by the user.
1308 * \param internalFormat internal format given by the user.
1309 * \param format pixel data format given by the user.
1310 * \param type pixel data type given by the user.
1311 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1312 * \param width image width given by the user.
1313 * \param height image height given by the user.
1314 * \param depth image depth given by the user.
1315 * \param border image border given by the user.
1316 *
1317 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1318 *
1319 * Verifies each of the parameters against the constants specified in
1320 * __GLcontextRec::Const and the supported extensions, and according to the
1321 * OpenGL specification.
1322 */
1323 static GLboolean
1324 texture_error_check( GLcontext *ctx, GLenum target,
1325 GLint level, GLint internalFormat,
1326 GLenum format, GLenum type,
1327 GLuint dimensions,
1328 GLint width, GLint height,
1329 GLint depth, GLint border )
1330 {
1331 const GLboolean isProxy = _mesa_is_proxy_texture(target);
1332 GLboolean sizeOK;
1333 GLboolean colorFormat, indexFormat;
1334
1335 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1336 if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1337 if (!isProxy) {
1338 _mesa_error(ctx, GL_INVALID_VALUE,
1339 "glTexImage%dD(level=%d)", dimensions, level);
1340 }
1341 return GL_TRUE;
1342 }
1343
1344 /* Check border */
1345 if (border < 0 || border > 1 ||
1346 ((target == GL_TEXTURE_RECTANGLE_NV ||
1347 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1348 if (!isProxy) {
1349 _mesa_error(ctx, GL_INVALID_VALUE,
1350 "glTexImage%dD(border=%d)", dimensions, border);
1351 }
1352 return GL_TRUE;
1353 }
1354
1355 if (width < 0 || height < 0 || depth < 0) {
1356 if (!isProxy) {
1357 _mesa_error(ctx, GL_INVALID_VALUE,
1358 "glTexImage%dD(width, height or depth < 0)", dimensions);
1359 }
1360 return GL_TRUE;
1361 }
1362
1363 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1364 * level, width, height and depth.
1365 */
1366 if (dimensions == 1) {
1367 if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
1368 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
1369 level, internalFormat,
1370 format, type,
1371 width, 1, 1, border);
1372 }
1373 else {
1374 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1375 return GL_TRUE;
1376 }
1377 }
1378 else if (dimensions == 2) {
1379 if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
1380 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
1381 level, internalFormat,
1382 format, type,
1383 width, height, 1, border);
1384 }
1385 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
1386 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1387 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1388 if (!ctx->Extensions.ARB_texture_cube_map) {
1389 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1390 return GL_TRUE;
1391 }
1392 sizeOK = (width == height) &&
1393 ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
1394 level, internalFormat, format, type,
1395 width, height, 1, border);
1396 }
1397 else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
1398 target == GL_TEXTURE_RECTANGLE_NV) {
1399 if (!ctx->Extensions.NV_texture_rectangle) {
1400 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1401 return GL_TRUE;
1402 }
1403 sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1404 GL_PROXY_TEXTURE_RECTANGLE_NV,
1405 level, internalFormat,
1406 format, type,
1407 width, height, 1, border);
1408 }
1409 else {
1410 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1411 return GL_TRUE;
1412 }
1413 }
1414 else if (dimensions == 3) {
1415 if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
1416 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_3D,
1417 level, internalFormat,
1418 format, type,
1419 width, height, depth, border);
1420 }
1421 else {
1422 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1423 return GL_TRUE;
1424 }
1425 }
1426 else {
1427 _mesa_problem( ctx, "bad dims in texture_error_check" );
1428 return GL_TRUE;
1429 }
1430
1431 if (!sizeOK) {
1432 if (!isProxy) {
1433 _mesa_error(ctx, GL_INVALID_VALUE,
1434 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1435 dimensions, level, width, height, depth);
1436 }
1437 return GL_TRUE;
1438 }
1439
1440 /* Check internalFormat */
1441 if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
1442 if (!isProxy) {
1443 _mesa_error(ctx, GL_INVALID_VALUE,
1444 "glTexImage%dD(internalFormat=0x%x)",
1445 dimensions, internalFormat);
1446 }
1447 return GL_TRUE;
1448 }
1449
1450 /* Check incoming image format and type */
1451 if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
1452 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1453 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1454 */
1455 if (!isProxy) {
1456 _mesa_error(ctx, GL_INVALID_OPERATION,
1457 "glTexImage%dD(format or type)", dimensions);
1458 }
1459 return GL_TRUE;
1460 }
1461
1462 /* make sure internal format and format basically agree */
1463 colorFormat = is_color_format(format);
1464 indexFormat = is_index_format(format);
1465 if ((is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
1466 (is_index_format(internalFormat) && !indexFormat) ||
1467 (is_depth_format(internalFormat) != is_depth_format(format)) ||
1468 (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) ||
1469 (is_depthstencil_format(internalFormat) != is_depthstencil_format(format))) {
1470 if (!isProxy)
1471 _mesa_error(ctx, GL_INVALID_OPERATION,
1472 "glTexImage(internalFormat/format)");
1473 return GL_TRUE;
1474 }
1475
1476 /* additional checks for ycbcr textures */
1477 if (internalFormat == GL_YCBCR_MESA) {
1478 ASSERT(ctx->Extensions.MESA_ycbcr_texture);
1479 if (type != GL_UNSIGNED_SHORT_8_8_MESA &&
1480 type != GL_UNSIGNED_SHORT_8_8_REV_MESA) {
1481 char message[100];
1482 _mesa_sprintf(message,
1483 "glTexImage%d(format/type YCBCR mismatch", dimensions);
1484 _mesa_error(ctx, GL_INVALID_ENUM, message);
1485 return GL_TRUE; /* error */
1486 }
1487 if (target != GL_TEXTURE_2D &&
1488 target != GL_PROXY_TEXTURE_2D &&
1489 target != GL_TEXTURE_RECTANGLE_NV &&
1490 target != GL_PROXY_TEXTURE_RECTANGLE_NV) {
1491 if (!isProxy)
1492 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)");
1493 return GL_TRUE;
1494 }
1495 if (border != 0) {
1496 if (!isProxy) {
1497 char message[100];
1498 _mesa_sprintf(message,
1499 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1500 dimensions, border);
1501 _mesa_error(ctx, GL_INVALID_VALUE, message);
1502 }
1503 return GL_TRUE;
1504 }
1505 }
1506
1507 /* additional checks for depth textures */
1508 if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) {
1509 /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
1510 if (target != GL_TEXTURE_1D &&
1511 target != GL_PROXY_TEXTURE_1D &&
1512 target != GL_TEXTURE_2D &&
1513 target != GL_PROXY_TEXTURE_2D &&
1514 target != GL_TEXTURE_RECTANGLE_ARB &&
1515 target != GL_PROXY_TEXTURE_RECTANGLE_ARB) {
1516 if (!isProxy)
1517 _mesa_error(ctx, GL_INVALID_ENUM,
1518 "glTexImage(target/internalFormat)");
1519 return GL_TRUE;
1520 }
1521 }
1522
1523 /* additional checks for compressed textures */
1524 if (is_compressed_format(ctx, internalFormat)) {
1525 if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
1526 /* OK */
1527 }
1528 else if (ctx->Extensions.ARB_texture_cube_map &&
1529 (target == GL_PROXY_TEXTURE_CUBE_MAP ||
1530 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1531 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
1532 /* OK */
1533 }
1534 else {
1535 if (!isProxy) {
1536 _mesa_error(ctx, GL_INVALID_ENUM,
1537 "glTexImage%d(target)", dimensions);
1538 return GL_TRUE;
1539 }
1540 }
1541 if (border != 0) {
1542 if (!isProxy) {
1543 _mesa_error(ctx, GL_INVALID_OPERATION,
1544 "glTexImage%D(border!=0)", dimensions);
1545 }
1546 return GL_TRUE;
1547 }
1548 }
1549
1550 /* if we get here, the parameters are OK */
1551 return GL_FALSE;
1552 }
1553
1554
1555 /**
1556 * Test glTexSubImage[123]D() parameters for errors.
1557 *
1558 * \param ctx GL context.
1559 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1560 * \param target texture target given by the user.
1561 * \param level image level given by the user.
1562 * \param xoffset sub-image x offset given by the user.
1563 * \param yoffset sub-image y offset given by the user.
1564 * \param zoffset sub-image z offset given by the user.
1565 * \param format pixel data format given by the user.
1566 * \param type pixel data type given by the user.
1567 * \param width image width given by the user.
1568 * \param height image height given by the user.
1569 * \param depth image depth given by the user.
1570 *
1571 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1572 *
1573 * Verifies each of the parameters against the constants specified in
1574 * __GLcontextRec::Const and the supported extensions, and according to the
1575 * OpenGL specification.
1576 */
1577 static GLboolean
1578 subtexture_error_check( GLcontext *ctx, GLuint dimensions,
1579 GLenum target, GLint level,
1580 GLint xoffset, GLint yoffset, GLint zoffset,
1581 GLint width, GLint height, GLint depth,
1582 GLenum format, GLenum type )
1583 {
1584 /* Check target */
1585 if (dimensions == 1) {
1586 if (target != GL_TEXTURE_1D) {
1587 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1588 return GL_TRUE;
1589 }
1590 }
1591 else if (dimensions == 2) {
1592 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1593 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1594 if (!ctx->Extensions.ARB_texture_cube_map) {
1595 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1596 return GL_TRUE;
1597 }
1598 }
1599 else if (target == GL_TEXTURE_RECTANGLE_NV) {
1600 if (!ctx->Extensions.NV_texture_rectangle) {
1601 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1602 return GL_TRUE;
1603 }
1604 }
1605 else if (target != GL_TEXTURE_2D) {
1606 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1607 return GL_TRUE;
1608 }
1609 }
1610 else if (dimensions == 3) {
1611 if (target != GL_TEXTURE_3D) {
1612 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1613 return GL_TRUE;
1614 }
1615 }
1616 else {
1617 _mesa_problem( ctx, "invalid dims in texture_error_check" );
1618 return GL_TRUE;
1619 }
1620
1621 /* Basic level check */
1622 if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1623 _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
1624 return GL_TRUE;
1625 }
1626
1627 if (width < 0) {
1628 _mesa_error(ctx, GL_INVALID_VALUE,
1629 "glTexSubImage%dD(width=%d)", dimensions, width);
1630 return GL_TRUE;
1631 }
1632 if (height < 0 && dimensions > 1) {
1633 _mesa_error(ctx, GL_INVALID_VALUE,
1634 "glTexSubImage%dD(height=%d)", dimensions, height);
1635 return GL_TRUE;
1636 }
1637 if (depth < 0 && dimensions > 2) {
1638 _mesa_error(ctx, GL_INVALID_VALUE,
1639 "glTexSubImage%dD(depth=%d)", dimensions, depth);
1640 return GL_TRUE;
1641 }
1642
1643 if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
1644 _mesa_error(ctx, GL_INVALID_ENUM,
1645 "glTexSubImage%dD(format or type)", dimensions);
1646 return GL_TRUE;
1647 }
1648
1649 return GL_FALSE;
1650 }
1651
1652 static GLboolean
1653 subtexture_error_check2( GLcontext *ctx, GLuint dimensions,
1654 GLenum target, GLint level,
1655 GLint xoffset, GLint yoffset, GLint zoffset,
1656 GLint width, GLint height, GLint depth,
1657 GLenum format, GLenum type,
1658 const struct gl_texture_image *destTex )
1659 {
1660 if (!destTex) {
1661 /* undefined image level */
1662 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions);
1663 return GL_TRUE;
1664 }
1665
1666 if (xoffset < -((GLint)destTex->Border)) {
1667 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)",
1668 dimensions);
1669 return GL_TRUE;
1670 }
1671 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1672 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)",
1673 dimensions);
1674 return GL_TRUE;
1675 }
1676 if (dimensions > 1) {
1677 if (yoffset < -((GLint)destTex->Border)) {
1678 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)",
1679 dimensions);
1680 return GL_TRUE;
1681 }
1682 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1683 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)",
1684 dimensions);
1685 return GL_TRUE;
1686 }
1687 }
1688 if (dimensions > 2) {
1689 if (zoffset < -((GLint)destTex->Border)) {
1690 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1691 return GL_TRUE;
1692 }
1693 if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) {
1694 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1695 return GL_TRUE;
1696 }
1697 }
1698
1699 #if FEATURE_EXT_texture_sRGB
1700 if (destTex->InternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
1701 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
1702 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
1703 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) {
1704 if ((width & 0x3) || (height & 0x3) ||
1705 (xoffset & 0x3) || (yoffset & 0x3))
1706 _mesa_error(ctx, GL_INVALID_OPERATION,
1707 "glTexSubImage%dD(size or offset not multiple of 4)",
1708 dimensions);
1709 return GL_TRUE;
1710 }
1711 #endif
1712
1713 if (destTex->IsCompressed) {
1714 if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
1715 /* OK */
1716 }
1717 else if (ctx->Extensions.ARB_texture_cube_map &&
1718 (target == GL_PROXY_TEXTURE_CUBE_MAP ||
1719 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1720 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
1721 /* OK */
1722 }
1723 else {
1724 _mesa_error(ctx, GL_INVALID_ENUM,
1725 "glTexSubImage%D(target)", dimensions);
1726 return GL_TRUE;
1727 }
1728 /* offset must be multiple of 4 */
1729 if ((xoffset & 3) || (yoffset & 3)) {
1730 _mesa_error(ctx, GL_INVALID_OPERATION,
1731 "glTexSubImage%D(xoffset or yoffset)", dimensions);
1732 return GL_TRUE;
1733 }
1734 /* size must be multiple of 4 or equal to whole texture size */
1735 if ((width & 3) && (GLuint) width != destTex->Width) {
1736 _mesa_error(ctx, GL_INVALID_OPERATION,
1737 "glTexSubImage%D(width)", dimensions);
1738 return GL_TRUE;
1739 }
1740 if ((height & 3) && (GLuint) height != destTex->Height) {
1741 _mesa_error(ctx, GL_INVALID_OPERATION,
1742 "glTexSubImage%D(width)", dimensions);
1743 return GL_TRUE;
1744 }
1745 }
1746
1747 return GL_FALSE;
1748 }
1749
1750
1751 /**
1752 * Test glCopyTexImage[12]D() parameters for errors.
1753 *
1754 * \param ctx GL context.
1755 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1756 * \param target texture target given by the user.
1757 * \param level image level given by the user.
1758 * \param internalFormat internal format given by the user.
1759 * \param width image width given by the user.
1760 * \param height image height given by the user.
1761 * \param depth image depth given by the user.
1762 * \param border texture border.
1763 *
1764 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1765 *
1766 * Verifies each of the parameters against the constants specified in
1767 * __GLcontextRec::Const and the supported extensions, and according to the
1768 * OpenGL specification.
1769 */
1770 static GLboolean
1771 copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1772 GLenum target, GLint level, GLint internalFormat,
1773 GLint width, GLint height, GLint border )
1774 {
1775 GLenum type;
1776 GLboolean sizeOK;
1777 GLint format;
1778
1779 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1780 if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1781 _mesa_error(ctx, GL_INVALID_VALUE,
1782 "glCopyTexImage%dD(level=%d)", dimensions, level);
1783 return GL_TRUE;
1784 }
1785
1786 /* Check that the source buffer is complete */
1787 if (ctx->ReadBuffer->Name) {
1788 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
1789 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1790 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1791 "glCopyTexImage%dD(invalid readbuffer)", dimensions);
1792 return GL_TRUE;
1793 }
1794 }
1795
1796 /* Check border */
1797 if (border < 0 || border > 1 ||
1798 ((target == GL_TEXTURE_RECTANGLE_NV ||
1799 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1800 return GL_TRUE;
1801 }
1802
1803 format = _mesa_base_tex_format(ctx, internalFormat);
1804 if (format < 0) {
1805 _mesa_error(ctx, GL_INVALID_VALUE,
1806 "glCopyTexImage%dD(internalFormat)", dimensions);
1807 return GL_TRUE;
1808 }
1809
1810 /* NOTE: the format and type aren't really significant for
1811 * TestProxyTexImage(). Only the internalformat really matters.
1812 if (!_mesa_source_buffer_exists(ctx, format)) {
1813 _mesa_error(ctx, GL_INVALID_OPERATION,
1814 "glCopyTexImage%dD(missing readbuffer)", dimensions);
1815 return GL_TRUE;
1816 }
1817
1818 */
1819 type = GL_FLOAT;
1820
1821 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1822 * level, width, height and depth.
1823 */
1824 if (dimensions == 1) {
1825 if (target == GL_TEXTURE_1D) {
1826 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
1827 level, internalFormat,
1828 format, type,
1829 width, 1, 1, border);
1830 }
1831 else {
1832 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1833 return GL_TRUE;
1834 }
1835 }
1836 else if (dimensions == 2) {
1837 if (target == GL_TEXTURE_2D) {
1838 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
1839 level, internalFormat,
1840 format, type,
1841 width, height, 1, border);
1842 }
1843 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1844 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1845 if (!ctx->Extensions.ARB_texture_cube_map) {
1846 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1847 return GL_TRUE;
1848 }
1849 sizeOK = (width == height) &&
1850 ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
1851 level, internalFormat, format, type,
1852 width, height, 1, border);
1853 }
1854 else if (target == GL_TEXTURE_RECTANGLE_NV) {
1855 if (!ctx->Extensions.NV_texture_rectangle) {
1856 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1857 return GL_TRUE;
1858 }
1859 sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1860 GL_PROXY_TEXTURE_RECTANGLE_NV,
1861 level, internalFormat,
1862 format, type,
1863 width, height, 1, border);
1864 }
1865 else {
1866 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1867 return GL_TRUE;
1868 }
1869 }
1870 else {
1871 _mesa_problem(ctx, "invalid dimensions in copytexture_error_check");
1872 return GL_TRUE;
1873 }
1874
1875 if (!sizeOK) {
1876 if (dimensions == 1) {
1877 _mesa_error(ctx, GL_INVALID_VALUE,
1878 "glCopyTexImage1D(width=%d)", width);
1879 }
1880 else {
1881 ASSERT(dimensions == 2);
1882 _mesa_error(ctx, GL_INVALID_VALUE,
1883 "glCopyTexImage2D(width=%d, height=%d)", width, height);
1884 }
1885 return GL_TRUE;
1886 }
1887
1888 if (is_compressed_format(ctx, internalFormat)) {
1889 if (target != GL_TEXTURE_2D) {
1890 _mesa_error(ctx, GL_INVALID_ENUM,
1891 "glCopyTexImage%d(target)", dimensions);
1892 return GL_TRUE;
1893 }
1894 if (border != 0) {
1895 _mesa_error(ctx, GL_INVALID_OPERATION,
1896 "glCopyTexImage%D(border!=0)", dimensions);
1897 return GL_TRUE;
1898 }
1899 }
1900 else if (is_depth_format(internalFormat)) {
1901 /* make sure we have depth/stencil buffers */
1902 if (!ctx->ReadBuffer->_DepthBuffer) {
1903 _mesa_error(ctx, GL_INVALID_OPERATION,
1904 "glCopyTexImage%D(no depth)", dimensions);
1905 return GL_TRUE;
1906 }
1907 }
1908 else if (is_depthstencil_format(internalFormat)) {
1909 /* make sure we have depth/stencil buffers */
1910 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
1911 _mesa_error(ctx, GL_INVALID_OPERATION,
1912 "glCopyTexImage%D(no depth/stencil buffer)", dimensions);
1913 return GL_TRUE;
1914 }
1915 }
1916
1917 /* if we get here, the parameters are OK */
1918 return GL_FALSE;
1919 }
1920
1921
1922 /**
1923 * Test glCopyTexSubImage[12]D() parameters for errors.
1924 *
1925 * \param ctx GL context.
1926 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1927 * \param target texture target given by the user.
1928 * \param level image level given by the user.
1929 * \param xoffset sub-image x offset given by the user.
1930 * \param yoffset sub-image y offset given by the user.
1931 * \param zoffset sub-image z offset given by the user.
1932 * \param width image width given by the user.
1933 * \param height image height given by the user.
1934 *
1935 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1936 *
1937 * Verifies each of the parameters against the constants specified in
1938 * __GLcontextRec::Const and the supported extensions, and according to the
1939 * OpenGL specification.
1940 */
1941 static GLboolean
1942 copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
1943 GLenum target, GLint level,
1944 GLint xoffset, GLint yoffset, GLint zoffset,
1945 GLsizei width, GLsizei height)
1946 {
1947 /* Check target */
1948 /* Check that the source buffer is complete */
1949 if (ctx->ReadBuffer->Name) {
1950 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
1951 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1952 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1953 "glCopyTexImage%dD(invalid readbuffer)", dimensions);
1954 return GL_TRUE;
1955 }
1956 }
1957
1958 if (dimensions == 1) {
1959 if (target != GL_TEXTURE_1D) {
1960 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1961 return GL_TRUE;
1962 }
1963 }
1964 else if (dimensions == 2) {
1965 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1966 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1967 if (!ctx->Extensions.ARB_texture_cube_map) {
1968 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1969 return GL_TRUE;
1970 }
1971 }
1972 else if (target == GL_TEXTURE_RECTANGLE_NV) {
1973 if (!ctx->Extensions.NV_texture_rectangle) {
1974 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1975 return GL_TRUE;
1976 }
1977 }
1978 else if (target != GL_TEXTURE_2D) {
1979 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1980 return GL_TRUE;
1981 }
1982 }
1983 else if (dimensions == 3) {
1984 if (target != GL_TEXTURE_3D) {
1985 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1986 return GL_TRUE;
1987 }
1988 }
1989
1990 /* Check level */
1991 if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1992 _mesa_error(ctx, GL_INVALID_VALUE,
1993 "glCopyTexSubImage%dD(level=%d)", dimensions, level);
1994 return GL_TRUE;
1995 }
1996
1997 /* Check size */
1998 if (width < 0) {
1999 _mesa_error(ctx, GL_INVALID_VALUE,
2000 "glCopyTexSubImage%dD(width=%d)", dimensions, width);
2001 return GL_TRUE;
2002 }
2003 if (dimensions > 1 && height < 0) {
2004 _mesa_error(ctx, GL_INVALID_VALUE,
2005 "glCopyTexSubImage%dD(height=%d)", dimensions, height);
2006 return GL_TRUE;
2007 }
2008
2009 return GL_FALSE;
2010 }
2011
2012 static GLboolean
2013 copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
2014 GLenum target, GLint level,
2015 GLint xoffset, GLint yoffset, GLint zoffset,
2016 GLsizei width, GLsizei height,
2017 const struct gl_texture_image *teximage )
2018 {
2019 if (!teximage) {
2020 _mesa_error(ctx, GL_INVALID_OPERATION,
2021 "glCopyTexSubImage%dD(undefined texture level: %d)",
2022 dimensions, level);
2023 return GL_TRUE;
2024 }
2025
2026 if (xoffset < -((GLint)teximage->Border)) {
2027 _mesa_error(ctx, GL_INVALID_VALUE,
2028 "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
2029 return GL_TRUE;
2030 }
2031 if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
2032 _mesa_error(ctx, GL_INVALID_VALUE,
2033 "glCopyTexSubImage%dD(xoffset+width)", dimensions);
2034 return GL_TRUE;
2035 }
2036 if (dimensions > 1) {
2037 if (yoffset < -((GLint)teximage->Border)) {
2038 _mesa_error(ctx, GL_INVALID_VALUE,
2039 "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
2040 return GL_TRUE;
2041 }
2042 /* NOTE: we're adding the border here, not subtracting! */
2043 if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
2044 _mesa_error(ctx, GL_INVALID_VALUE,
2045 "glCopyTexSubImage%dD(yoffset+height)", dimensions);
2046 return GL_TRUE;
2047 }
2048 }
2049
2050 if (dimensions > 2) {
2051 if (zoffset < -((GLint)teximage->Border)) {
2052 _mesa_error(ctx, GL_INVALID_VALUE,
2053 "glCopyTexSubImage%dD(zoffset)", dimensions);
2054 return GL_TRUE;
2055 }
2056 if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
2057 _mesa_error(ctx, GL_INVALID_VALUE,
2058 "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
2059 return GL_TRUE;
2060 }
2061 }
2062
2063 if (teximage->IsCompressed) {
2064 if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) {
2065 _mesa_error(ctx, GL_INVALID_OPERATION,
2066 "glCopyTexSubImage%dD(missing readbuffer)", dimensions);
2067 return GL_TRUE;
2068 }
2069
2070 if (target != GL_TEXTURE_2D) {
2071 _mesa_error(ctx, GL_INVALID_ENUM,
2072 "glCopyTexSubImage%d(target)", dimensions);
2073 return GL_TRUE;
2074 }
2075 /* offset must be multiple of 4 */
2076 if ((xoffset & 3) || (yoffset & 3)) {
2077 _mesa_error(ctx, GL_INVALID_VALUE,
2078 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions);
2079 return GL_TRUE;
2080 }
2081 /* size must be multiple of 4 */
2082 if ((width & 3) != 0 && (GLuint) width != teximage->Width) {
2083 _mesa_error(ctx, GL_INVALID_VALUE,
2084 "glCopyTexSubImage%D(width)", dimensions);
2085 return GL_TRUE;
2086 }
2087 if ((height & 3) != 0 && (GLuint) height != teximage->Height) {
2088 _mesa_error(ctx, GL_INVALID_VALUE,
2089 "glCopyTexSubImage%D(height)", dimensions);
2090 return GL_TRUE;
2091 }
2092 }
2093
2094 if (teximage->InternalFormat == GL_YCBCR_MESA) {
2095 _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D");
2096 return GL_TRUE;
2097 }
2098
2099 if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) {
2100 if (!ctx->ReadBuffer->_DepthBuffer) {
2101 _mesa_error(ctx, GL_INVALID_OPERATION,
2102 "glCopyTexSubImage%D(no depth buffer)",
2103 dimensions);
2104 return GL_TRUE;
2105 }
2106 }
2107 else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
2108 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
2109 _mesa_error(ctx, GL_INVALID_OPERATION,
2110 "glCopyTexSubImage%D(no depth/stencil buffer)",
2111 dimensions);
2112 return GL_TRUE;
2113 }
2114 }
2115
2116 /* if we get here, the parameters are OK */
2117 return GL_FALSE;
2118 }
2119
2120
2121 /**
2122 * Get texture image. Called by glGetTexImage.
2123 *
2124 * \param target texture target.
2125 * \param level image level.
2126 * \param format pixel data format for returned image.
2127 * \param type pixel data type for returned image.
2128 * \param pixels returned pixel data.
2129 */
2130 void GLAPIENTRY
2131 _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2132 GLenum type, GLvoid *pixels )
2133 {
2134 const struct gl_texture_unit *texUnit;
2135 struct gl_texture_object *texObj;
2136 struct gl_texture_image *texImage;
2137 GLint maxLevels = 0;
2138 GET_CURRENT_CONTEXT(ctx);
2139 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2140
2141 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
2142 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2143 if (!texObj || _mesa_is_proxy_texture(target)) {
2144 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2145 return;
2146 }
2147
2148 maxLevels = _mesa_max_texture_levels(ctx, target);
2149 ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */
2150
2151 if (level < 0 || level >= maxLevels) {
2152 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2153 return;
2154 }
2155
2156 if (_mesa_sizeof_packed_type(type) <= 0) {
2157 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2158 return;
2159 }
2160
2161 if (_mesa_components_in_format(format) <= 0 ||
2162 format == GL_STENCIL_INDEX) {
2163 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2164 return;
2165 }
2166
2167 if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) {
2168 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2169 return;
2170 }
2171
2172 if (!ctx->Extensions.SGIX_depth_texture &&
2173 !ctx->Extensions.ARB_depth_texture && is_depth_format(format)) {
2174 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2175 return;
2176 }
2177
2178 if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) {
2179 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2180 return;
2181 }
2182
2183 if (!ctx->Extensions.EXT_packed_depth_stencil
2184 && is_depthstencil_format(format)) {
2185 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2186 return;
2187 }
2188
2189 if (!pixels)
2190 return;
2191
2192 _mesa_lock_texture(ctx, texObj);
2193 {
2194 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2195 if (!texImage) {
2196 /* invalid mipmap level, not an error */
2197 goto out;
2198 }
2199
2200
2201 /* Make sure the requested image format is compatible with the
2202 * texture's format. Note that a color index texture can be converted
2203 * to RGBA so that combo is allowed.
2204 */
2205 if (is_color_format(format)
2206 && !is_color_format(texImage->TexFormat->BaseFormat)
2207 && !is_index_format(texImage->TexFormat->BaseFormat)) {
2208 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2209 goto out;
2210 }
2211 else if (is_index_format(format)
2212 && !is_index_format(texImage->TexFormat->BaseFormat)) {
2213 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2214 goto out;
2215 }
2216 else if (is_depth_format(format)
2217 && !is_depth_format(texImage->TexFormat->BaseFormat)
2218 && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
2219 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2220 goto out;
2221 }
2222 else if (is_ycbcr_format(format)
2223 && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) {
2224 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2225 goto out;
2226 }
2227 else if (is_depthstencil_format(format)
2228 && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
2229 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2230 goto out;
2231 }
2232
2233 if (ctx->Pack.BufferObj->Name) {
2234 /* packing texture image into a PBO */
2235 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
2236 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
2237 texImage->Height, texImage->Depth,
2238 format, type, pixels)) {
2239 _mesa_error(ctx, GL_INVALID_OPERATION,
2240 "glGetTexImage(invalid PBO access)");
2241 goto out;
2242 }
2243 }
2244
2245 /* typically, this will call _mesa_get_teximage() */
2246 ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
2247 texObj, texImage);
2248
2249 }
2250 out:
2251 _mesa_unlock_texture(ctx, texObj);
2252 }
2253
2254
2255
2256 /**
2257 * Check if the given texture image is bound to any framebuffer objects
2258 * and update/invalidate them.
2259 * XXX We're only checking the currently bound framebuffer object for now.
2260 * In the future, perhaps struct gl_texture_image should have a pointer (or
2261 * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to.
2262 */
2263 static void
2264 update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj,
2265 GLuint face, GLuint level)
2266 {
2267 if (ctx->DrawBuffer->Name) {
2268 GLuint i;
2269 for (i = 0; i < BUFFER_COUNT; i++) {
2270 struct gl_renderbuffer_attachment *att =
2271 ctx->DrawBuffer->Attachment + i;
2272 if (att->Type == GL_TEXTURE &&
2273 att->Texture == texObj &&
2274 att->TextureLevel == level &&
2275 att->CubeMapFace == face) {
2276 ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
2277 /* Tell driver about the new renderbuffer texture */
2278 ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
2279 }
2280 }
2281 }
2282 }
2283
2284
2285
2286 /*
2287 * Called from the API. Note that width includes the border.
2288 */
2289 void GLAPIENTRY
2290 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
2291 GLsizei width, GLint border, GLenum format,
2292 GLenum type, const GLvoid *pixels )
2293 {
2294 GLsizei postConvWidth = width;
2295 GET_CURRENT_CONTEXT(ctx);
2296 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2297
2298 if (is_color_format(internalFormat)) {
2299 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2300 }
2301
2302 if (target == GL_TEXTURE_1D) {
2303 /* non-proxy target */
2304 struct gl_texture_unit *texUnit;
2305 struct gl_texture_object *texObj;
2306 struct gl_texture_image *texImage;
2307 const GLuint face = texture_face(target);
2308
2309 if (texture_error_check(ctx, target, level, internalFormat,
2310 format, type, 1, postConvWidth, 1, 1, border)) {
2311 return; /* error was recorded */
2312 }
2313
2314 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2315 _mesa_update_state(ctx);
2316
2317 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2318 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2319 _mesa_lock_texture(ctx, texObj);
2320 {
2321 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2322 if (!texImage) {
2323 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2324 goto out;
2325 }
2326
2327 if (texImage->Data) {
2328 ctx->Driver.FreeTexImageData( ctx, texImage );
2329 }
2330
2331 ASSERT(texImage->Data == NULL);
2332
2333 clear_teximage_fields(texImage); /* not really needed, but helpful */
2334 _mesa_init_teximage_fields(ctx, target, texImage,
2335 postConvWidth, 1, 1,
2336 border, internalFormat);
2337
2338 ASSERT(ctx->Driver.TexImage1D);
2339
2340 /* Give the texture to the driver! <pixels> may be null! */
2341 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
2342 width, border, format, type, pixels,
2343 &ctx->Unpack, texObj, texImage);
2344
2345 ASSERT(texImage->TexFormat);
2346
2347 update_fbo_texture(ctx, texObj, face, level);
2348
2349 /* state update */
2350 texObj->Complete = GL_FALSE;
2351 ctx->NewState |= _NEW_TEXTURE;
2352 }
2353 out:
2354 _mesa_unlock_texture(ctx, texObj);
2355 }
2356 else if (target == GL_PROXY_TEXTURE_1D) {
2357 /* Proxy texture: check for errors and update proxy state */
2358 struct gl_texture_image *texImage;
2359 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2360 if (texture_error_check(ctx, target, level, internalFormat,
2361 format, type, 1, postConvWidth, 1, 1, border)) {
2362 /* when error, clear all proxy texture image parameters */
2363 if (texImage)
2364 clear_teximage_fields(texImage);
2365 }
2366 else {
2367 /* no error, set the tex image parameters */
2368 ASSERT(texImage);
2369 _mesa_init_teximage_fields(ctx, target, texImage,
2370 postConvWidth, 1, 1,
2371 border, internalFormat);
2372 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2373 internalFormat, format, type);
2374 }
2375 }
2376 else {
2377 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
2378 return;
2379 }
2380 }
2381
2382
2383 void GLAPIENTRY
2384 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
2385 GLsizei width, GLsizei height, GLint border,
2386 GLenum format, GLenum type,
2387 const GLvoid *pixels )
2388 {
2389 GLsizei postConvWidth = width, postConvHeight = height;
2390 GET_CURRENT_CONTEXT(ctx);
2391 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2392
2393 if (is_color_format(internalFormat)) {
2394 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2395 &postConvHeight);
2396 }
2397
2398 if (target == GL_TEXTURE_2D ||
2399 (ctx->Extensions.ARB_texture_cube_map &&
2400 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2401 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ||
2402 (ctx->Extensions.NV_texture_rectangle &&
2403 target == GL_TEXTURE_RECTANGLE_NV)) {
2404 /* non-proxy target */
2405 struct gl_texture_unit *texUnit;
2406 struct gl_texture_object *texObj;
2407 struct gl_texture_image *texImage;
2408 const GLuint face = texture_face(target);
2409
2410 if (texture_error_check(ctx, target, level, internalFormat,
2411 format, type, 2, postConvWidth, postConvHeight,
2412 1, border)) {
2413 return; /* error was recorded */
2414 }
2415
2416 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2417 _mesa_update_state(ctx);
2418
2419 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2420 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2421 _mesa_lock_texture(ctx, texObj);
2422 {
2423 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2424 if (!texImage) {
2425 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2426 goto out;
2427 }
2428
2429 if (texImage->Data) {
2430 ctx->Driver.FreeTexImageData( ctx, texImage );
2431 }
2432
2433 ASSERT(texImage->Data == NULL);
2434 clear_teximage_fields(texImage); /* not really needed, but helpful */
2435 _mesa_init_teximage_fields(ctx, target, texImage,
2436 postConvWidth, postConvHeight, 1,
2437 border, internalFormat);
2438
2439 ASSERT(ctx->Driver.TexImage2D);
2440
2441 /* Give the texture to the driver! <pixels> may be null! */
2442 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
2443 width, height, border, format, type, pixels,
2444 &ctx->Unpack, texObj, texImage);
2445
2446 ASSERT(texImage->TexFormat);
2447
2448 update_fbo_texture(ctx, texObj, face, level);
2449
2450 /* state update */
2451 texObj->Complete = GL_FALSE;
2452 ctx->NewState |= _NEW_TEXTURE;
2453 }
2454 out:
2455 _mesa_unlock_texture(ctx, texObj);
2456 }
2457 else if (target == GL_PROXY_TEXTURE_2D ||
2458 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
2459 ctx->Extensions.ARB_texture_cube_map) ||
2460 (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
2461 ctx->Extensions.NV_texture_rectangle)) {
2462 /* Proxy texture: check for errors and update proxy state */
2463 struct gl_texture_image *texImage;
2464 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2465 if (texture_error_check(ctx, target, level, internalFormat,
2466 format, type, 2, postConvWidth, postConvHeight,
2467 1, border)) {
2468 /* when error, clear all proxy texture image parameters */
2469 if (texImage)
2470 clear_teximage_fields(ctx->Texture.Proxy2D->Image[0][level]);
2471 }
2472 else {
2473 /* no error, set the tex image parameters */
2474 _mesa_init_teximage_fields(ctx, target, texImage,
2475 postConvWidth, postConvHeight, 1,
2476 border, internalFormat);
2477 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2478 internalFormat, format, type);
2479 }
2480 }
2481 else {
2482 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
2483 return;
2484 }
2485 }
2486
2487
2488 /*
2489 * Called by the API or display list executor.
2490 * Note that width and height include the border.
2491 */
2492 void GLAPIENTRY
2493 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
2494 GLsizei width, GLsizei height, GLsizei depth,
2495 GLint border, GLenum format, GLenum type,
2496 const GLvoid *pixels )
2497 {
2498 GET_CURRENT_CONTEXT(ctx);
2499 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2500
2501 if (target == GL_TEXTURE_3D) {
2502 /* non-proxy target */
2503 struct gl_texture_unit *texUnit;
2504 struct gl_texture_object *texObj;
2505 struct gl_texture_image *texImage;
2506 const GLuint face = texture_face(target);
2507
2508 if (texture_error_check(ctx, target, level, (GLint) internalFormat,
2509 format, type, 3, width, height, depth, border)) {
2510 return; /* error was recorded */
2511 }
2512
2513 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2514 _mesa_update_state(ctx);
2515
2516 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2517 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2518 _mesa_lock_texture(ctx, texObj);
2519 {
2520 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2521 if (!texImage) {
2522 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2523 goto out;
2524 }
2525
2526 if (texImage->Data) {
2527 ctx->Driver.FreeTexImageData( ctx, texImage );
2528 }
2529
2530 ASSERT(texImage->Data == NULL);
2531 clear_teximage_fields(texImage); /* not really needed, but helpful */
2532 _mesa_init_teximage_fields(ctx, target, texImage,
2533 width, height, depth,
2534 border, internalFormat);
2535
2536 ASSERT(ctx->Driver.TexImage3D);
2537
2538 /* Give the texture to the driver! <pixels> may be null! */
2539 (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat,
2540 width, height, depth, border, format, type,
2541 pixels, &ctx->Unpack, texObj, texImage);
2542
2543 ASSERT(texImage->TexFormat);
2544
2545 update_fbo_texture(ctx, texObj, face, level);
2546
2547 /* state update */
2548 texObj->Complete = GL_FALSE;
2549 ctx->NewState |= _NEW_TEXTURE;
2550 }
2551 out:
2552 _mesa_unlock_texture(ctx, texObj);
2553 }
2554 else if (target == GL_PROXY_TEXTURE_3D) {
2555 /* Proxy texture: check for errors and update proxy state */
2556 struct gl_texture_image *texImage;
2557 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2558 if (texture_error_check(ctx, target, level, internalFormat,
2559 format, type, 3, width, height, depth, border)) {
2560 /* when error, clear all proxy texture image parameters */
2561 if (texImage)
2562 clear_teximage_fields(texImage);
2563 }
2564 else {
2565 /* no error, set the tex image parameters */
2566 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
2567 border, internalFormat);
2568 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2569 internalFormat, format, type);
2570 }
2571 }
2572 else {
2573 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
2574 return;
2575 }
2576 }
2577
2578
2579 void GLAPIENTRY
2580 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2581 GLsizei width, GLsizei height, GLsizei depth,
2582 GLint border, GLenum format, GLenum type,
2583 const GLvoid *pixels )
2584 {
2585 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2586 depth, border, format, type, pixels);
2587 }
2588
2589
2590
2591 void GLAPIENTRY
2592 _mesa_TexSubImage1D( GLenum target, GLint level,
2593 GLint xoffset, GLsizei width,
2594 GLenum format, GLenum type,
2595 const GLvoid *pixels )
2596 {
2597 GLsizei postConvWidth = width;
2598 struct gl_texture_unit *texUnit;
2599 struct gl_texture_object *texObj;
2600 struct gl_texture_image *texImage = NULL;
2601 GET_CURRENT_CONTEXT(ctx);
2602 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2603
2604 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2605 _mesa_update_state(ctx);
2606
2607 /* XXX should test internal format */
2608 if (is_color_format(format)) {
2609 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2610 }
2611
2612 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2613 postConvWidth, 1, 1, format, type)) {
2614 return; /* error was detected */
2615 }
2616
2617
2618 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2619 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2620 assert(texObj);
2621
2622 _mesa_lock_texture(ctx, texObj);
2623 {
2624 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2625
2626 if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0,
2627 postConvWidth, 1, 1, format, type, texImage)) {
2628 goto out; /* error was detected */
2629 }
2630
2631 if (width == 0)
2632 goto out; /* no-op, not an error */
2633
2634 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2635 xoffset += texImage->Border;
2636
2637 ASSERT(ctx->Driver.TexSubImage1D);
2638 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
2639 format, type, pixels, &ctx->Unpack,
2640 texObj, texImage);
2641 ctx->NewState |= _NEW_TEXTURE;
2642 }
2643 out:
2644 _mesa_unlock_texture(ctx, texObj);
2645 }
2646
2647
2648 void GLAPIENTRY
2649 _mesa_TexSubImage2D( GLenum target, GLint level,
2650 GLint xoffset, GLint yoffset,
2651 GLsizei width, GLsizei height,
2652 GLenum format, GLenum type,
2653 const GLvoid *pixels )
2654 {
2655 GLsizei postConvWidth = width, postConvHeight = height;
2656 struct gl_texture_unit *texUnit;
2657 struct gl_texture_object *texObj;
2658 struct gl_texture_image *texImage;
2659 GET_CURRENT_CONTEXT(ctx);
2660 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2661
2662 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2663 _mesa_update_state(ctx);
2664
2665 /* XXX should test internal format */
2666 if (is_color_format(format)) {
2667 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2668 &postConvHeight);
2669 }
2670
2671 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2672 postConvWidth, postConvHeight, 1, format, type)) {
2673 return; /* error was detected */
2674 }
2675
2676 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2677 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2678 _mesa_lock_texture(ctx, texObj);
2679 {
2680 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2681
2682 if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
2683 postConvWidth, postConvHeight, 1, format, type,
2684 texImage)) {
2685 goto out; /* error was detected */
2686 }
2687
2688 if (width == 0 || height == 0)
2689 goto out; /* no-op, not an error */
2690
2691 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2692 xoffset += texImage->Border;
2693 yoffset += texImage->Border;
2694
2695 ASSERT(ctx->Driver.TexSubImage2D);
2696 (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
2697 width, height, format, type, pixels,
2698 &ctx->Unpack, texObj, texImage);
2699 ctx->NewState |= _NEW_TEXTURE;
2700 }
2701 out:
2702 _mesa_unlock_texture(ctx, texObj);
2703 }
2704
2705
2706
2707 void GLAPIENTRY
2708 _mesa_TexSubImage3D( GLenum target, GLint level,
2709 GLint xoffset, GLint yoffset, GLint zoffset,
2710 GLsizei width, GLsizei height, GLsizei depth,
2711 GLenum format, GLenum type,
2712 const GLvoid *pixels )
2713 {
2714 struct gl_texture_unit *texUnit;
2715 struct gl_texture_object *texObj;
2716 struct gl_texture_image *texImage;
2717 GET_CURRENT_CONTEXT(ctx);
2718 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2719
2720 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2721 _mesa_update_state(ctx);
2722
2723 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2724 width, height, depth, format, type)) {
2725 return; /* error was detected */
2726 }
2727
2728 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2729 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2730
2731 _mesa_lock_texture(ctx, texObj);
2732 {
2733 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2734
2735 if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset,
2736 width, height, depth, format, type, texImage)) {
2737 goto out; /* error was detected */
2738 }
2739
2740 if (width == 0 || height == 0 || height == 0)
2741 goto out; /* no-op, not an error */
2742
2743 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2744 xoffset += texImage->Border;
2745 yoffset += texImage->Border;
2746 zoffset += texImage->Border;
2747
2748 ASSERT(ctx->Driver.TexSubImage3D);
2749 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
2750 xoffset, yoffset, zoffset,
2751 width, height, depth,
2752 format, type, pixels,
2753 &ctx->Unpack, texObj, texImage );
2754 ctx->NewState |= _NEW_TEXTURE;
2755 }
2756 out:
2757 _mesa_unlock_texture(ctx, texObj);
2758 }
2759
2760
2761
2762 void GLAPIENTRY
2763 _mesa_CopyTexImage1D( GLenum target, GLint level,
2764 GLenum internalFormat,
2765 GLint x, GLint y,
2766 GLsizei width, GLint border )
2767 {
2768 struct gl_texture_unit *texUnit;
2769 struct gl_texture_object *texObj;
2770 struct gl_texture_image *texImage;
2771 GLsizei postConvWidth = width;
2772 const GLuint face = texture_face(target);
2773 GET_CURRENT_CONTEXT(ctx);
2774 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2775
2776 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2777 _mesa_update_state(ctx);
2778
2779 if (is_color_format(internalFormat)) {
2780 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2781 }
2782
2783 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2784 postConvWidth, 1, border))
2785 return;
2786
2787 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2788 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2789 _mesa_lock_texture(ctx, texObj);
2790 {
2791 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2792 if (!texImage) {
2793 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
2794 goto out;
2795 }
2796
2797 if (texImage->Data) {
2798 ctx->Driver.FreeTexImageData( ctx, texImage );
2799 }
2800
2801 ASSERT(texImage->Data == NULL);
2802
2803 clear_teximage_fields(texImage); /* not really needed, but helpful */
2804 _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
2805 border, internalFormat);
2806
2807
2808 ASSERT(ctx->Driver.CopyTexImage1D);
2809 (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
2810 x, y, width, border);
2811
2812 ASSERT(texImage->TexFormat);
2813
2814 update_fbo_texture(ctx, texObj, face, level);
2815
2816 /* state update */
2817 texObj->Complete = GL_FALSE;
2818 ctx->NewState |= _NEW_TEXTURE;
2819 }
2820 out:
2821 _mesa_unlock_texture(ctx, texObj);
2822 }
2823
2824
2825
2826 void GLAPIENTRY
2827 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2828 GLint x, GLint y, GLsizei width, GLsizei height,
2829 GLint border )
2830 {
2831 struct gl_texture_unit *texUnit;
2832 struct gl_texture_object *texObj;
2833 struct gl_texture_image *texImage;
2834 GLsizei postConvWidth = width, postConvHeight = height;
2835 const GLuint face = texture_face(target);
2836 GET_CURRENT_CONTEXT(ctx);
2837 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2838
2839 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2840 _mesa_update_state(ctx);
2841
2842 if (is_color_format(internalFormat)) {
2843 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2844 &postConvHeight);
2845 }
2846
2847 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2848 postConvWidth, postConvHeight, border))
2849 return;
2850
2851 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2852 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2853
2854 _mesa_lock_texture(ctx, texObj);
2855 {
2856 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2857
2858 if (!texImage) {
2859 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
2860 goto out;
2861 }
2862
2863 if (texImage->Data) {
2864 ctx->Driver.FreeTexImageData( ctx, texImage );
2865 }
2866
2867 ASSERT(texImage->Data == NULL);
2868
2869 clear_teximage_fields(texImage); /* not really needed, but helpful */
2870 _mesa_init_teximage_fields(ctx, target, texImage,
2871 postConvWidth, postConvHeight, 1,
2872 border, internalFormat);
2873
2874 ASSERT(ctx->Driver.CopyTexImage2D);
2875 (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
2876 x, y, width, height, border);
2877
2878 ASSERT(texImage->TexFormat);
2879
2880 update_fbo_texture(ctx, texObj, face, level);
2881
2882 /* state update */
2883 texObj->Complete = GL_FALSE;
2884 ctx->NewState |= _NEW_TEXTURE;
2885 }
2886 out:
2887 _mesa_unlock_texture(ctx, texObj);
2888 }
2889
2890
2891 void GLAPIENTRY
2892 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
2893 GLint xoffset, GLint x, GLint y, GLsizei width )
2894 {
2895 struct gl_texture_unit *texUnit;
2896 struct gl_texture_object *texObj;
2897 struct gl_texture_image *texImage;
2898 GLsizei postConvWidth = width;
2899 GET_CURRENT_CONTEXT(ctx);
2900 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2901
2902 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2903 _mesa_update_state(ctx);
2904
2905 /* XXX should test internal format */
2906 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2907
2908 if (copytexsubimage_error_check(ctx, 1, target, level,
2909 xoffset, 0, 0, postConvWidth, 1))
2910 return;
2911
2912 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2913 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2914
2915 _mesa_lock_texture(ctx, texObj);
2916 {
2917 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2918
2919 if (copytexsubimage_error_check2(ctx, 1, target, level,
2920 xoffset, 0, 0, postConvWidth, 1,
2921 texImage))
2922 goto out;
2923
2924
2925 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2926 xoffset += texImage->Border;
2927
2928 ASSERT(ctx->Driver.CopyTexSubImage1D);
2929 (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width);
2930 ctx->NewState |= _NEW_TEXTURE;
2931 }
2932 out:
2933 _mesa_unlock_texture(ctx, texObj);
2934 }
2935
2936
2937
2938 void GLAPIENTRY
2939 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
2940 GLint xoffset, GLint yoffset,
2941 GLint x, GLint y, GLsizei width, GLsizei height )
2942 {
2943 struct gl_texture_unit *texUnit;
2944 struct gl_texture_object *texObj;
2945 struct gl_texture_image *texImage;
2946 GLsizei postConvWidth = width, postConvHeight = height;
2947 GET_CURRENT_CONTEXT(ctx);
2948 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2949
2950 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2951 _mesa_update_state(ctx);
2952
2953 /* XXX should test internal format */
2954 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
2955
2956 if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2957 postConvWidth, postConvHeight))
2958 return;
2959
2960 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2961 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2962
2963 _mesa_lock_texture(ctx, texObj);
2964 {
2965 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2966
2967 if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
2968 postConvWidth, postConvHeight, texImage))
2969 goto out;
2970
2971 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2972 xoffset += texImage->Border;
2973 yoffset += texImage->Border;
2974
2975 ASSERT(ctx->Driver.CopyTexSubImage2D);
2976 (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2977 xoffset, yoffset, x, y, width, height);
2978 ctx->NewState |= _NEW_TEXTURE;
2979 }
2980 out:
2981 _mesa_unlock_texture(ctx, texObj);
2982 }
2983
2984
2985
2986 void GLAPIENTRY
2987 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2988 GLint xoffset, GLint yoffset, GLint zoffset,
2989 GLint x, GLint y, GLsizei width, GLsizei height )
2990 {
2991 struct gl_texture_unit *texUnit;
2992 struct gl_texture_object *texObj;
2993 struct gl_texture_image *texImage;
2994 GLsizei postConvWidth = width, postConvHeight = height;
2995 GET_CURRENT_CONTEXT(ctx);
2996 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2997
2998 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2999 _mesa_update_state(ctx);
3000
3001 /* XXX should test internal format */
3002 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
3003
3004 if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset,
3005 zoffset, postConvWidth, postConvHeight))
3006 return;
3007
3008 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3009 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3010
3011 _mesa_lock_texture(ctx, texObj);
3012 {
3013 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3014
3015 if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
3016 zoffset, postConvWidth, postConvHeight,
3017 texImage))
3018 goto out;
3019
3020 /* If we have a border, xoffset=-1 is legal. Bias by border width */
3021 xoffset += texImage->Border;
3022 yoffset += texImage->Border;
3023 zoffset += texImage->Border;
3024
3025 ASSERT(ctx->Driver.CopyTexSubImage3D);
3026 (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
3027 xoffset, yoffset, zoffset,
3028 x, y, width, height);
3029 ctx->NewState |= _NEW_TEXTURE;
3030 }
3031 out:
3032 _mesa_unlock_texture(ctx, texObj);
3033 }
3034
3035
3036
3037
3038 /**********************************************************************/
3039 /****** Compressed Textures ******/
3040 /**********************************************************************/
3041
3042
3043 /**
3044 * Error checking for glCompressedTexImage[123]D().
3045 * \return error code or GL_NO_ERROR.
3046 */
3047 static GLenum
3048 compressed_texture_error_check(GLcontext *ctx, GLint dimensions,
3049 GLenum target, GLint level,
3050 GLenum internalFormat, GLsizei width,
3051 GLsizei height, GLsizei depth, GLint border,
3052 GLsizei imageSize)
3053 {
3054 GLint expectedSize, maxLevels = 0, maxTextureSize;
3055
3056 if (dimensions == 1) {
3057 /* 1D compressed textures not allowed */
3058 return GL_INVALID_ENUM;
3059 }
3060 else if (dimensions == 2) {
3061 if (target == GL_PROXY_TEXTURE_2D) {
3062 maxLevels = ctx->Const.MaxTextureLevels;
3063 }
3064 else if (target == GL_TEXTURE_2D) {
3065 maxLevels = ctx->Const.MaxTextureLevels;
3066 }
3067 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3068 if (!ctx->Extensions.ARB_texture_cube_map)
3069 return GL_INVALID_ENUM; /*target*/
3070 maxLevels = ctx->Const.MaxCubeTextureLevels;
3071 }
3072 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3073 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3074 if (!ctx->Extensions.ARB_texture_cube_map)
3075 return GL_INVALID_ENUM; /*target*/
3076 maxLevels = ctx->Const.MaxCubeTextureLevels;
3077 }
3078 else {
3079 return GL_INVALID_ENUM; /*target*/
3080 }
3081 }
3082 else if (dimensions == 3) {
3083 /* 3D compressed textures not allowed */
3084 return GL_INVALID_ENUM;
3085 }
3086
3087 maxTextureSize = 1 << (maxLevels - 1);
3088
3089 /* This will detect any invalid internalFormat value */
3090 if (!is_compressed_format(ctx, internalFormat))
3091 return GL_INVALID_ENUM;
3092
3093 /* This should really never fail */
3094 if (_mesa_base_tex_format(ctx, internalFormat) < 0)
3095 return GL_INVALID_ENUM;
3096
3097 if (border != 0)
3098 return GL_INVALID_VALUE;
3099
3100 /*
3101 * XXX We should probably use the proxy texture error check function here.
3102 */
3103 if (width < 1 || width > maxTextureSize ||
3104 (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(width) != 1))
3105 return GL_INVALID_VALUE;
3106
3107 if ((height < 1 || height > maxTextureSize ||
3108 (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(height) != 1))
3109 && dimensions > 1)
3110 return GL_INVALID_VALUE;
3111
3112 if ((depth < 1 || depth > maxTextureSize ||
3113 (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(depth) != 1))
3114 && dimensions > 2)
3115 return GL_INVALID_VALUE;
3116
3117 /* For cube map, width must equal height */
3118 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3119 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
3120 return GL_INVALID_VALUE;
3121
3122 if (level < 0 || level >= maxLevels)
3123 return GL_INVALID_VALUE;
3124
3125 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
3126 depth, internalFormat);
3127 if (expectedSize != imageSize)
3128 return GL_INVALID_VALUE;
3129
3130 #if FEATURE_EXT_texture_sRGB
3131 if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
3132 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
3133 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
3134 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
3135 && border != 0) {
3136 return GL_INVALID_OPERATION;
3137 }
3138 #endif
3139
3140 return GL_NO_ERROR;
3141 }
3142
3143
3144 /**
3145 * Error checking for glCompressedTexSubImage[123]D().
3146 * \warning There are some bad assumptions here about the size of compressed
3147 * texture tiles (multiple of 4) used to test the validity of the
3148 * offset and size parameters.
3149 * \return error code or GL_NO_ERROR.
3150 */
3151 static GLenum
3152 compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions,
3153 GLenum target, GLint level,
3154 GLint xoffset, GLint yoffset, GLint zoffset,
3155 GLsizei width, GLsizei height, GLsizei depth,
3156 GLenum format, GLsizei imageSize)
3157 {
3158 GLint expectedSize, maxLevels = 0, maxTextureSize;
3159 (void) zoffset;
3160
3161 if (dimensions == 1) {
3162 /* 1D compressed textures not allowed */
3163 return GL_INVALID_ENUM;
3164 }
3165 else if (dimensions == 2) {
3166 if (target == GL_PROXY_TEXTURE_2D) {
3167 maxLevels = ctx->Const.MaxTextureLevels;
3168 }
3169 else if (target == GL_TEXTURE_2D) {
3170 maxLevels = ctx->Const.MaxTextureLevels;
3171 }
3172 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3173 if (!ctx->Extensions.ARB_texture_cube_map)
3174 return GL_INVALID_ENUM; /*target*/
3175 maxLevels = ctx->Const.MaxCubeTextureLevels;
3176 }
3177 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3178 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3179 if (!ctx->Extensions.ARB_texture_cube_map)
3180 return GL_INVALID_ENUM; /*target*/
3181 maxLevels = ctx->Const.MaxCubeTextureLevels;
3182 }
3183 else {
3184 return GL_INVALID_ENUM; /*target*/
3185 }
3186 }
3187 else if (dimensions == 3) {
3188 /* 3D compressed textures not allowed */
3189 return GL_INVALID_ENUM;
3190 }
3191
3192 maxTextureSize = 1 << (maxLevels - 1);
3193
3194 /* this will catch any invalid compressed format token */
3195 if (!is_compressed_format(ctx, format))
3196 return GL_INVALID_ENUM;
3197
3198 if (width < 1 || width > maxTextureSize)
3199 return GL_INVALID_VALUE;
3200
3201 if ((height < 1 || height > maxTextureSize)
3202 && dimensions > 1)
3203 return GL_INVALID_VALUE;
3204
3205 if (level < 0 || level >= maxLevels)
3206 return GL_INVALID_VALUE;
3207
3208 /* XXX these tests are specific to the compressed format.
3209 * this code should be generalized in some way.
3210 */
3211 if ((xoffset & 3) != 0 || (yoffset & 3) != 0)
3212 return GL_INVALID_VALUE;
3213
3214 if ((width & 3) != 0 && width != 2 && width != 1)
3215 return GL_INVALID_VALUE;
3216
3217 if ((height & 3) != 0 && height != 2 && height != 1)
3218 return GL_INVALID_VALUE;
3219
3220 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
3221 depth, format);
3222 if (expectedSize != imageSize)
3223 return GL_INVALID_VALUE;
3224
3225 return GL_NO_ERROR;
3226 }
3227
3228
3229
3230 void GLAPIENTRY
3231 _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
3232 GLenum internalFormat, GLsizei width,
3233 GLint border, GLsizei imageSize,
3234 const GLvoid *data)
3235 {
3236 GET_CURRENT_CONTEXT(ctx);
3237 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3238
3239 if (target == GL_TEXTURE_1D) {
3240 /* non-proxy target */
3241 struct gl_texture_unit *texUnit;
3242 struct gl_texture_object *texObj;
3243 struct gl_texture_image *texImage;
3244 GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3245 internalFormat, width, 1, 1, border, imageSize);
3246 if (error) {
3247 _mesa_error(ctx, error, "glCompressedTexImage1D");
3248 return;
3249 }
3250
3251 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3252 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3253
3254 _mesa_lock_texture(ctx, texObj);
3255 {
3256 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3257 if (!texImage) {
3258 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
3259 goto out;
3260 }
3261
3262 if (texImage->Data) {
3263 ctx->Driver.FreeTexImageData( ctx, texImage );
3264 }
3265 ASSERT(texImage->Data == NULL);
3266
3267 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3268 border, internalFormat);
3269
3270 ASSERT(ctx->Driver.CompressedTexImage1D);
3271 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
3272 internalFormat, width, border,
3273 imageSize, data,
3274 texObj, texImage);
3275
3276 /* state update */
3277 texObj->Complete = GL_FALSE;
3278 ctx->NewState |= _NEW_TEXTURE;
3279 }
3280 out:
3281 _mesa_unlock_texture(ctx, texObj);
3282 }
3283 else if (target == GL_PROXY_TEXTURE_1D) {
3284 /* Proxy texture: check for errors and update proxy state */
3285 GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3286 internalFormat, width, 1, 1, border, imageSize);
3287 if (!error) {
3288 ASSERT(ctx->Driver.TestProxyTexImage);
3289 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3290 internalFormat, GL_NONE, GL_NONE,
3291 width, 1, 1, border);
3292 }
3293 if (error) {
3294 /* if error, clear all proxy texture image parameters */
3295 struct gl_texture_image *texImage;
3296 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3297 if (texImage)
3298 clear_teximage_fields(texImage);
3299 }
3300 else {
3301 /* store the teximage parameters */
3302 struct gl_texture_unit *texUnit;
3303 struct gl_texture_object *texObj;
3304 struct gl_texture_image *texImage;
3305 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3306 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3307
3308 _mesa_lock_texture(ctx, texObj);
3309 {
3310 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3311 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3312 border, internalFormat);
3313 }
3314 _mesa_unlock_texture(ctx, texObj);
3315 }
3316 }
3317 else {
3318 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
3319 return;
3320 }
3321 }
3322
3323
3324 void GLAPIENTRY
3325 _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3326 GLenum internalFormat, GLsizei width,
3327 GLsizei height, GLint border, GLsizei imageSize,
3328 const GLvoid *data)
3329 {
3330 GET_CURRENT_CONTEXT(ctx);
3331 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3332
3333 if (target == GL_TEXTURE_2D ||
3334 (ctx->Extensions.ARB_texture_cube_map &&
3335 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3336 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3337 /* non-proxy target */
3338 struct gl_texture_unit *texUnit;
3339 struct gl_texture_object *texObj;
3340 struct gl_texture_image *texImage;
3341 GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3342 internalFormat, width, height, 1, border, imageSize);
3343 if (error) {
3344 _mesa_error(ctx, error, "glCompressedTexImage2D");
3345 return;
3346 }
3347
3348 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3349 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3350
3351 _mesa_lock_texture(ctx, texObj);
3352 {
3353 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3354 if (!texImage) {
3355 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
3356 goto out;
3357 }
3358
3359 if (texImage->Data) {
3360 ctx->Driver.FreeTexImageData( ctx, texImage );
3361 }
3362 ASSERT(texImage->Data == NULL);
3363
3364 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3365 border, internalFormat);
3366
3367 ASSERT(ctx->Driver.CompressedTexImage2D);
3368 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
3369 internalFormat, width, height,
3370 border, imageSize, data,
3371 texObj, texImage);
3372
3373 /* state update */
3374 texObj->Complete = GL_FALSE;
3375 ctx->NewState |= _NEW_TEXTURE;
3376 }
3377 out:
3378 _mesa_unlock_texture(ctx, texObj);
3379 }
3380 else if (target == GL_PROXY_TEXTURE_2D ||
3381 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
3382 ctx->Extensions.ARB_texture_cube_map)) {
3383 /* Proxy texture: check for errors and update proxy state */
3384 GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3385 internalFormat, width, height, 1, border, imageSize);
3386 if (!error) {
3387 ASSERT(ctx->Driver.TestProxyTexImage);
3388 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3389 internalFormat, GL_NONE, GL_NONE,
3390 width, height, 1, border);
3391 }
3392 if (error) {
3393 /* if error, clear all proxy texture image parameters */
3394 struct gl_texture_image *texImage;
3395 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3396 if (texImage)
3397 clear_teximage_fields(texImage);
3398 }
3399 else {
3400 /* store the teximage parameters */
3401 struct gl_texture_unit *texUnit;
3402 struct gl_texture_object *texObj;
3403 struct gl_texture_image *texImage;
3404 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3405 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3406
3407 _mesa_lock_texture(ctx, texObj);
3408 {
3409 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3410 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3411 border, internalFormat);
3412 }
3413 _mesa_unlock_texture(ctx, texObj);
3414 }
3415 }
3416 else {
3417 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
3418 return;
3419 }
3420 }
3421
3422
3423 void GLAPIENTRY
3424 _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3425 GLenum internalFormat, GLsizei width,
3426 GLsizei height, GLsizei depth, GLint border,
3427 GLsizei imageSize, const GLvoid *data)
3428 {
3429 GET_CURRENT_CONTEXT(ctx);
3430 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3431
3432 if (target == GL_TEXTURE_3D) {
3433 /* non-proxy target */
3434 struct gl_texture_unit *texUnit;
3435 struct gl_texture_object *texObj;
3436 struct gl_texture_image *texImage;
3437 GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3438 internalFormat, width, height, depth, border, imageSize);
3439 if (error) {
3440 _mesa_error(ctx, error, "glCompressedTexImage3D");
3441 return;
3442 }
3443
3444 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3445 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3446 _mesa_lock_texture(ctx, texObj);
3447 {
3448 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3449 if (!texImage) {
3450 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
3451 goto out;
3452 }
3453
3454 if (texImage->Data) {
3455 ctx->Driver.FreeTexImageData( ctx, texImage );
3456 }
3457 ASSERT(texImage->Data == NULL);
3458
3459 _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth,
3460 border, internalFormat);
3461
3462 ASSERT(ctx->Driver.CompressedTexImage3D);
3463 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3464 internalFormat,
3465 width, height, depth,
3466 border, imageSize, data,
3467 texObj, texImage);
3468
3469 /* state update */
3470 texObj->Complete = GL_FALSE;
3471 ctx->NewState |= _NEW_TEXTURE;
3472 }
3473 out:
3474 _mesa_unlock_texture(ctx, texObj);
3475 }
3476 else if (target == GL_PROXY_TEXTURE_3D) {
3477 /* Proxy texture: check for errors and update proxy state */
3478 GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3479 internalFormat, width, height, depth, border, imageSize);
3480 if (!error) {
3481 ASSERT(ctx->Driver.TestProxyTexImage);
3482 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3483 internalFormat, GL_NONE, GL_NONE,
3484 width, height, depth, border);
3485 }
3486 if (error) {
3487 /* if error, clear all proxy texture image parameters */
3488 struct gl_texture_image *texImage;
3489 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3490 if (texImage)
3491 clear_teximage_fields(texImage);
3492 }
3493 else {
3494 /* store the teximage parameters */
3495 struct gl_texture_unit *texUnit;
3496 struct gl_texture_object *texObj;
3497 struct gl_texture_image *texImage;
3498 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3499 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3500 _mesa_lock_texture(ctx, texObj);
3501 {
3502 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3503 _mesa_init_teximage_fields(ctx, target, texImage, width, height,
3504 depth, border, internalFormat);
3505 }
3506 _mesa_unlock_texture(ctx, texObj);
3507 }
3508 }
3509 else {
3510 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
3511 return;
3512 }
3513 }
3514
3515
3516 void GLAPIENTRY
3517 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3518 GLsizei width, GLenum format,
3519 GLsizei imageSize, const GLvoid *data)
3520 {
3521 struct gl_texture_unit *texUnit;
3522 struct gl_texture_object *texObj;
3523 struct gl_texture_image *texImage;
3524 GLenum error;
3525 GET_CURRENT_CONTEXT(ctx);
3526 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3527
3528 error = compressed_subtexture_error_check(ctx, 1, target, level,
3529 xoffset, 0, 0, /* pos */
3530 width, 1, 1, /* size */
3531 format, imageSize);
3532 if (error) {
3533 _mesa_error(ctx, error, "glCompressedTexSubImage1D");
3534 return;
3535 }
3536
3537 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3538 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3539 _mesa_lock_texture(ctx, texObj);
3540 {
3541 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3542 assert(texImage);
3543
3544 if ((GLint) format != texImage->InternalFormat) {
3545 _mesa_error(ctx, GL_INVALID_OPERATION,
3546 "glCompressedTexSubImage1D(format)");
3547 goto out;
3548 }
3549
3550 if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) {
3551 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)");
3552 goto out;
3553 }
3554
3555 if (width == 0)
3556 goto out; /* no-op, not an error */
3557
3558 if (ctx->Driver.CompressedTexSubImage1D) {
3559 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3560 xoffset, width,
3561 format, imageSize, data,
3562 texObj, texImage);
3563 }
3564 ctx->NewState |= _NEW_TEXTURE;
3565 }
3566 out:
3567 _mesa_unlock_texture(ctx, texObj);
3568 }
3569
3570
3571 void GLAPIENTRY
3572 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3573 GLint yoffset, GLsizei width, GLsizei height,
3574 GLenum format, GLsizei imageSize,
3575 const GLvoid *data)
3576 {
3577 struct gl_texture_unit *texUnit;
3578 struct gl_texture_object *texObj;
3579 struct gl_texture_image *texImage;
3580 GLenum error;
3581 GET_CURRENT_CONTEXT(ctx);
3582 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3583
3584 error = compressed_subtexture_error_check(ctx, 2, target, level,
3585 xoffset, yoffset, 0, /* pos */
3586 width, height, 1, /* size */
3587 format, imageSize);
3588 if (error) {
3589 /* XXX proxy target? */
3590 _mesa_error(ctx, error, "glCompressedTexSubImage2D");
3591 return;
3592 }
3593
3594 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3595 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3596 _mesa_lock_texture(ctx, texObj);
3597 {
3598 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3599 assert(texImage);
3600
3601 if ((GLint) format != texImage->InternalFormat) {
3602 _mesa_error(ctx, GL_INVALID_OPERATION,
3603 "glCompressedTexSubImage2D(format)");
3604 goto out;
3605 }
3606
3607 if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
3608 ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) {
3609 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)");
3610 goto out;
3611 }
3612
3613 if (width == 0 || height == 0)
3614 goto out; /* no-op, not an error */
3615
3616 if (ctx->Driver.CompressedTexSubImage2D) {
3617 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3618 xoffset, yoffset, width, height,
3619 format, imageSize, data,
3620 texObj, texImage);
3621 }
3622 ctx->NewState |= _NEW_TEXTURE;
3623 }
3624 out:
3625 _mesa_unlock_texture(ctx, texObj);
3626 }
3627
3628
3629 void GLAPIENTRY
3630 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3631 GLint yoffset, GLint zoffset, GLsizei width,
3632 GLsizei height, GLsizei depth, GLenum format,
3633 GLsizei imageSize, const GLvoid *data)
3634 {
3635 struct gl_texture_unit *texUnit;
3636 struct gl_texture_object *texObj;
3637 struct gl_texture_image *texImage;
3638 GLenum error;
3639 GET_CURRENT_CONTEXT(ctx);
3640 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3641
3642 error = compressed_subtexture_error_check(ctx, 3, target, level,
3643 xoffset, yoffset, zoffset,/*pos*/
3644 width, height, depth, /*size*/
3645 format, imageSize);
3646 if (error) {
3647 _mesa_error(ctx, error, "glCompressedTexSubImage2D");
3648 return;
3649 }
3650
3651 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3652 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3653 _mesa_lock_texture(ctx, texObj);
3654 {
3655 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3656 assert(texImage);
3657
3658 if ((GLint) format != texImage->InternalFormat) {
3659 _mesa_error(ctx, GL_INVALID_OPERATION,
3660 "glCompressedTexSubImage3D(format)");
3661 goto out;
3662 }
3663
3664 if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
3665 ((height == 1 || height == 2) && (GLuint) height != texImage->Height) ||
3666 ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) {
3667 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)");
3668 goto out;
3669 }
3670
3671 if (width == 0 || height == 0 || depth == 0)
3672 goto out; /* no-op, not an error */
3673
3674 if (ctx->Driver.CompressedTexSubImage3D) {
3675 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3676 xoffset, yoffset, zoffset,
3677 width, height, depth,
3678 format, imageSize, data,
3679 texObj, texImage);
3680 }
3681 ctx->NewState |= _NEW_TEXTURE;
3682 }
3683 out:
3684 _mesa_unlock_texture(ctx, texObj);
3685 }
3686
3687
3688 void GLAPIENTRY
3689 _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
3690 {
3691 const struct gl_texture_unit *texUnit;
3692 struct gl_texture_object *texObj;
3693 struct gl_texture_image *texImage;
3694 GLint maxLevels;
3695 GET_CURRENT_CONTEXT(ctx);
3696 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3697
3698
3699 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3700 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3701 if (!texObj) {
3702 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
3703 return;
3704 }
3705
3706 maxLevels = _mesa_max_texture_levels(ctx, target);
3707 ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */
3708
3709 if (level < 0 || level >= maxLevels) {
3710 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3711 return;
3712 }
3713
3714 if (_mesa_is_proxy_texture(target)) {
3715 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3716 return;
3717 }
3718
3719
3720 _mesa_lock_texture(ctx, texObj);
3721 {
3722 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3723 if (!texImage) {
3724 /* probably invalid mipmap level */
3725 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3726 goto out;
3727 }
3728
3729 if (!texImage->IsCompressed) {
3730 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3731 goto out;
3732 }
3733
3734 /* this typically calls _mesa_get_compressed_teximage() */
3735 ctx->Driver.GetCompressedTexImage(ctx, target, level, img, texObj,texImage);
3736 }
3737 out:
3738 _mesa_unlock_texture(ctx, texObj);
3739 }