replaced __inline with INLINE
[mesa.git] / src / mesa / main / teximage.c
1 /* $Id: teximage.c,v 1.99 2001/07/13 15:44:21 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 #ifdef PC_HEADER
29 #include "all.h"
30 #else
31 #include "glheader.h"
32 #include "context.h"
33 #include "convolve.h"
34 #include "image.h"
35 #include "macros.h"
36 #include "mem.h"
37 #include "mmath.h"
38 #include "state.h"
39 #include "texformat.h"
40 #include "teximage.h"
41 #include "texstate.h"
42 #include "texstore.h"
43 #include "mtypes.h"
44 #include "swrast/s_span.h" /* XXX SWRAST hack */
45 #endif
46
47
48 /*
49 * NOTES:
50 *
51 * Mesa's native texture datatype is GLchan. Native formats are
52 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
53 * and GL_COLOR_INDEX.
54 * Device drivers are free to implement any internal format they want.
55 */
56
57
58 #ifdef DEBUG
59 static void PrintTexture(const struct gl_texture_image *img)
60 {
61 GLuint i, j, c;
62 const GLchan *data = (const GLchan *) img->Data;
63
64 if (!data) {
65 printf("No texture data\n");
66 return;
67 }
68
69 switch (img->Format) {
70 case GL_ALPHA:
71 case GL_LUMINANCE:
72 case GL_INTENSITY:
73 case GL_COLOR_INDEX:
74 c = 1;
75 break;
76 case GL_LUMINANCE_ALPHA:
77 c = 2;
78 break;
79 case GL_RGB:
80 c = 3;
81 break;
82 case GL_RGBA:
83 c = 4;
84 break;
85 default:
86 _mesa_problem(NULL, "error in PrintTexture\n");
87 return;
88 }
89
90 for (i = 0; i < img->Height; i++) {
91 for (j = 0; j < img->Width; j++) {
92 if (c==1)
93 printf("%02x ", data[0]);
94 else if (c==2)
95 printf("%02x%02x ", data[0], data[1]);
96 else if (c==3)
97 printf("%02x%02x%02x ", data[0], data[1], data[2]);
98 else if (c==4)
99 printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]);
100 data += c;
101 }
102 printf("\n");
103 }
104 }
105 #endif
106
107
108
109 /*
110 * Compute log base 2 of n.
111 * If n isn't an exact power of two return -1.
112 * If n < 0 return -1.
113 */
114 static int
115 logbase2( int n )
116 {
117 GLint i = 1;
118 GLint log2 = 0;
119
120 if (n < 0) {
121 return -1;
122 }
123
124 while ( n > i ) {
125 i *= 2;
126 log2++;
127 }
128 if (i != n) {
129 return -1;
130 }
131 else {
132 return log2;
133 }
134 }
135
136
137
138 /*
139 * Given an internal texture format enum or 1, 2, 3, 4 return the
140 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
141 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
142 * Return -1 if invalid enum.
143 */
144 GLint
145 _mesa_base_tex_format( GLcontext *ctx, GLint format )
146 {
147 /*
148 * Ask the driver for the base format, if it doesn't
149 * know, it will return -1;
150 */
151 if (ctx->Driver.BaseCompressedTexFormat) {
152 GLint ifmt = (*ctx->Driver.BaseCompressedTexFormat)(ctx, format);
153 if (ifmt >= 0) {
154 return ifmt;
155 }
156 }
157 switch (format) {
158 case GL_ALPHA:
159 case GL_ALPHA4:
160 case GL_ALPHA8:
161 case GL_ALPHA12:
162 case GL_ALPHA16:
163 return GL_ALPHA;
164 case 1:
165 case GL_LUMINANCE:
166 case GL_LUMINANCE4:
167 case GL_LUMINANCE8:
168 case GL_LUMINANCE12:
169 case GL_LUMINANCE16:
170 return GL_LUMINANCE;
171 case 2:
172 case GL_LUMINANCE_ALPHA:
173 case GL_LUMINANCE4_ALPHA4:
174 case GL_LUMINANCE6_ALPHA2:
175 case GL_LUMINANCE8_ALPHA8:
176 case GL_LUMINANCE12_ALPHA4:
177 case GL_LUMINANCE12_ALPHA12:
178 case GL_LUMINANCE16_ALPHA16:
179 return GL_LUMINANCE_ALPHA;
180 case GL_INTENSITY:
181 case GL_INTENSITY4:
182 case GL_INTENSITY8:
183 case GL_INTENSITY12:
184 case GL_INTENSITY16:
185 return GL_INTENSITY;
186 case 3:
187 case GL_RGB:
188 case GL_R3_G3_B2:
189 case GL_RGB4:
190 case GL_RGB5:
191 case GL_RGB8:
192 case GL_RGB10:
193 case GL_RGB12:
194 case GL_RGB16:
195 return GL_RGB;
196 case 4:
197 case GL_RGBA:
198 case GL_RGBA2:
199 case GL_RGBA4:
200 case GL_RGB5_A1:
201 case GL_RGBA8:
202 case GL_RGB10_A2:
203 case GL_RGBA12:
204 case GL_RGBA16:
205 return GL_RGBA;
206 case GL_COLOR_INDEX:
207 case GL_COLOR_INDEX1_EXT:
208 case GL_COLOR_INDEX2_EXT:
209 case GL_COLOR_INDEX4_EXT:
210 case GL_COLOR_INDEX8_EXT:
211 case GL_COLOR_INDEX12_EXT:
212 case GL_COLOR_INDEX16_EXT:
213 return GL_COLOR_INDEX;
214 case GL_DEPTH_COMPONENT:
215 case GL_DEPTH_COMPONENT16_SGIX:
216 case GL_DEPTH_COMPONENT24_SGIX:
217 case GL_DEPTH_COMPONENT32_SGIX:
218 if (ctx->Extensions.SGIX_depth_texture)
219 return GL_DEPTH_COMPONENT;
220 else
221 return -1;
222 default:
223 return -1; /* error */
224 }
225 }
226
227
228 /*
229 * Test if the given image format is a color/rgba format. That is,
230 * not color index, depth, stencil, etc.
231 */
232 static GLboolean
233 is_color_format(GLenum format)
234 {
235 switch (format) {
236 case GL_ALPHA:
237 case GL_ALPHA4:
238 case GL_ALPHA8:
239 case GL_ALPHA12:
240 case GL_ALPHA16:
241 case 1:
242 case GL_LUMINANCE:
243 case GL_LUMINANCE4:
244 case GL_LUMINANCE8:
245 case GL_LUMINANCE12:
246 case GL_LUMINANCE16:
247 case 2:
248 case GL_LUMINANCE_ALPHA:
249 case GL_LUMINANCE4_ALPHA4:
250 case GL_LUMINANCE6_ALPHA2:
251 case GL_LUMINANCE8_ALPHA8:
252 case GL_LUMINANCE12_ALPHA4:
253 case GL_LUMINANCE12_ALPHA12:
254 case GL_LUMINANCE16_ALPHA16:
255 case GL_INTENSITY:
256 case GL_INTENSITY4:
257 case GL_INTENSITY8:
258 case GL_INTENSITY12:
259 case GL_INTENSITY16:
260 case 3:
261 case GL_RGB:
262 case GL_R3_G3_B2:
263 case GL_RGB4:
264 case GL_RGB5:
265 case GL_RGB8:
266 case GL_RGB10:
267 case GL_RGB12:
268 case GL_RGB16:
269 case 4:
270 case GL_RGBA:
271 case GL_RGBA2:
272 case GL_RGBA4:
273 case GL_RGB5_A1:
274 case GL_RGBA8:
275 case GL_RGB10_A2:
276 case GL_RGBA12:
277 case GL_RGBA16:
278 return GL_TRUE;
279 default:
280 return GL_FALSE;
281 }
282 }
283
284
285 static GLboolean
286 is_index_format(GLenum format)
287 {
288 switch (format) {
289 case GL_COLOR_INDEX:
290 case GL_COLOR_INDEX1_EXT:
291 case GL_COLOR_INDEX2_EXT:
292 case GL_COLOR_INDEX4_EXT:
293 case GL_COLOR_INDEX8_EXT:
294 case GL_COLOR_INDEX12_EXT:
295 case GL_COLOR_INDEX16_EXT:
296 return GL_TRUE;
297 default:
298 return GL_FALSE;
299 }
300 }
301
302
303 /*
304 * Return GL_TRUE if internalFormat is a compressed format, return GL_FALSE
305 * otherwise.
306 */
307 static GLboolean
308 is_compressed_format(GLcontext *ctx, GLenum internalFormat)
309 {
310 if (ctx->Driver.BaseCompressedTexFormat) {
311 GLint b = (*ctx->Driver.BaseCompressedTexFormat)(ctx, internalFormat);
312 if (b > 0)
313 return GL_TRUE;
314 else
315 return GL_FALSE;
316 }
317 return GL_FALSE;
318 }
319
320
321
322 /*
323 * Store a gl_texture_image pointer in a gl_texture_object structure
324 * according to the target and level parameters.
325 * This was basically prompted by the introduction of cube maps.
326 */
327 void
328 _mesa_set_tex_image(struct gl_texture_object *tObj,
329 GLenum target, GLint level,
330 struct gl_texture_image *texImage)
331 {
332 ASSERT(tObj);
333 ASSERT(texImage);
334 switch (target) {
335 case GL_TEXTURE_1D:
336 case GL_TEXTURE_2D:
337 case GL_TEXTURE_3D:
338 tObj->Image[level] = texImage;
339 return;
340 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
341 tObj->Image[level] = texImage;
342 return;
343 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
344 tObj->NegX[level] = texImage;
345 return;
346 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
347 tObj->PosY[level] = texImage;
348 return;
349 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
350 tObj->NegY[level] = texImage;
351 return;
352 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
353 tObj->PosZ[level] = texImage;
354 return;
355 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
356 tObj->NegZ[level] = texImage;
357 return;
358 default:
359 _mesa_problem(NULL, "bad target in _mesa_set_tex_image()");
360 return;
361 }
362 }
363
364
365
366 /*
367 * Return new gl_texture_image struct with all fields initialized to zero.
368 */
369 struct gl_texture_image *
370 _mesa_alloc_texture_image( void )
371 {
372 return CALLOC_STRUCT(gl_texture_image);
373 }
374
375
376
377 void
378 _mesa_free_texture_image( struct gl_texture_image *teximage )
379 {
380 if (teximage->Data) {
381 FREE( teximage->Data );
382 teximage->Data = NULL;
383 }
384 FREE( teximage );
385 }
386
387
388 /*
389 * Return GL_TRUE if the target is a proxy target.
390 */
391 static GLboolean
392 is_proxy_target(GLenum target)
393 {
394 return (target == GL_PROXY_TEXTURE_1D ||
395 target == GL_PROXY_TEXTURE_2D ||
396 target == GL_PROXY_TEXTURE_3D ||
397 target == GL_PROXY_TEXTURE_CUBE_MAP_ARB);
398 }
399
400
401 /*
402 * Given a texture unit and a texture target, return the corresponding
403 * texture object.
404 */
405 struct gl_texture_object *
406 _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
407 GLenum target)
408 {
409 switch (target) {
410 case GL_TEXTURE_1D:
411 return texUnit->Current1D;
412 case GL_PROXY_TEXTURE_1D:
413 return ctx->Texture.Proxy1D;
414 case GL_TEXTURE_2D:
415 return texUnit->Current2D;
416 case GL_PROXY_TEXTURE_2D:
417 return ctx->Texture.Proxy2D;
418 case GL_TEXTURE_3D:
419 return texUnit->Current3D;
420 case GL_PROXY_TEXTURE_3D:
421 return ctx->Texture.Proxy3D;
422 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
423 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
424 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
425 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
426 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
427 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
428 case GL_TEXTURE_CUBE_MAP_ARB:
429 return ctx->Extensions.ARB_texture_cube_map
430 ? texUnit->CurrentCubeMap : NULL;
431 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
432 return ctx->Extensions.ARB_texture_cube_map
433 ? ctx->Texture.ProxyCubeMap : NULL;
434 default:
435 _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
436 return NULL;
437 }
438 }
439
440
441 /*
442 * Return the texture image struct which corresponds to target and level
443 * for the given texture unit.
444 */
445 struct gl_texture_image *
446 _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
447 GLenum target, GLint level)
448 {
449 ASSERT(texUnit);
450 ASSERT(level < MAX_TEXTURE_LEVELS);
451 switch (target) {
452 case GL_TEXTURE_1D:
453 return texUnit->Current1D->Image[level];
454 case GL_PROXY_TEXTURE_1D:
455 return ctx->Texture.Proxy1D->Image[level];
456 case GL_TEXTURE_2D:
457 return texUnit->Current2D->Image[level];
458 case GL_PROXY_TEXTURE_2D:
459 return ctx->Texture.Proxy2D->Image[level];
460 case GL_TEXTURE_3D:
461 return texUnit->Current3D->Image[level];
462 case GL_PROXY_TEXTURE_3D:
463 return ctx->Texture.Proxy3D->Image[level];
464 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
465 if (ctx->Extensions.ARB_texture_cube_map)
466 return texUnit->CurrentCubeMap->Image[level];
467 else
468 return NULL;
469 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
470 if (ctx->Extensions.ARB_texture_cube_map)
471 return texUnit->CurrentCubeMap->NegX[level];
472 else
473 return NULL;
474 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
475 if (ctx->Extensions.ARB_texture_cube_map)
476 return texUnit->CurrentCubeMap->PosY[level];
477 else
478 return NULL;
479 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
480 if (ctx->Extensions.ARB_texture_cube_map)
481 return texUnit->CurrentCubeMap->NegY[level];
482 else
483 return NULL;
484 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
485 if (ctx->Extensions.ARB_texture_cube_map)
486 return texUnit->CurrentCubeMap->PosZ[level];
487 else
488 return NULL;
489 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
490 if (ctx->Extensions.ARB_texture_cube_map)
491 return texUnit->CurrentCubeMap->NegZ[level];
492 else
493 return NULL;
494 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
495 if (ctx->Extensions.ARB_texture_cube_map)
496 return ctx->Texture.ProxyCubeMap->Image[level];
497 else
498 return NULL;
499 default:
500 _mesa_problem(ctx, "bad target in _mesa_select_tex_image()");
501 return NULL;
502 }
503 }
504
505
506
507 /*
508 * glTexImage[123]D can accept a NULL image pointer. In this case we
509 * create a texture image with unspecified image contents per the OpenGL
510 * spec.
511 */
512 static GLubyte *
513 make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
514 {
515 const GLint components = _mesa_components_in_format(format);
516 const GLint numPixels = width * height * depth;
517 GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
518
519 /*
520 * Let's see if anyone finds this. If glTexImage2D() is called with
521 * a NULL image pointer then load the texture image with something
522 * interesting instead of leaving it indeterminate.
523 */
524 if (data) {
525 static const char message[8][32] = {
526 " X X XXXXX XXX X ",
527 " XX XX X X X X X ",
528 " X X X X X X X ",
529 " X X XXXX XXX XXXXX ",
530 " X X X X X X ",
531 " X X X X X X X ",
532 " X X XXXXX XXX X X ",
533 " "
534 };
535
536 GLubyte *imgPtr = data;
537 GLint h, i, j, k;
538 for (h = 0; h < depth; h++) {
539 for (i = 0; i < height; i++) {
540 GLint srcRow = 7 - (i % 8);
541 for (j = 0; j < width; j++) {
542 GLint srcCol = j % 32;
543 GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
544 for (k = 0; k < components; k++) {
545 *imgPtr++ = texel;
546 }
547 }
548 }
549 }
550 }
551
552 return data;
553 }
554
555
556
557 /*
558 * Reset the fields of a gl_texture_image struct to zero.
559 * This is called when a proxy texture test fails, we set all the
560 * image members (except DriverData) to zero.
561 * It's also used in glTexImage[123]D as a safeguard to be sure all
562 * required fields get initialized properly by the Driver.TexImage[123]D
563 * functions.
564 */
565 static void
566 clear_teximage_fields(struct gl_texture_image *img)
567 {
568 ASSERT(img);
569 img->Format = 0;
570 img->IntFormat = 0;
571 img->Border = 0;
572 img->Width = 0;
573 img->Height = 0;
574 img->Depth = 0;
575 img->Width2 = 0;
576 img->Height2 = 0;
577 img->Depth2 = 0;
578 img->WidthLog2 = 0;
579 img->HeightLog2 = 0;
580 img->DepthLog2 = 0;
581 img->Data = NULL;
582 img->TexFormat = &_mesa_null_texformat;
583 img->FetchTexel = NULL;
584 img->IsCompressed = 0;
585 img->CompressedSize = 0;
586 }
587
588
589 /*
590 * Initialize basic fields of the gl_texture_image struct.
591 */
592 void
593 _mesa_init_teximage_fields(GLcontext *ctx,
594 struct gl_texture_image *img,
595 GLsizei width, GLsizei height, GLsizei depth,
596 GLint border, GLenum internalFormat)
597 {
598 ASSERT(img);
599 img->Format = _mesa_base_tex_format( ctx, internalFormat );
600 ASSERT(img->Format > 0);
601 img->IntFormat = internalFormat;
602 img->Border = border;
603 img->Width = width;
604 img->Height = height;
605 img->Depth = depth;
606 img->WidthLog2 = logbase2(width - 2 * border);
607 if (height == 1) /* 1-D texture */
608 img->HeightLog2 = 0;
609 else
610 img->HeightLog2 = logbase2(height - 2 * border);
611 if (depth == 1) /* 2-D texture */
612 img->DepthLog2 = 0;
613 else
614 img->DepthLog2 = logbase2(depth - 2 * border);
615 img->Width2 = 1 << img->WidthLog2;
616 img->Height2 = 1 << img->HeightLog2;
617 img->Depth2 = 1 << img->DepthLog2;
618 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
619 img->IsCompressed = is_compressed_format(ctx, internalFormat);
620 }
621
622
623
624 /*
625 * Test glTexImage[123]D() parameters for errors.
626 * Input:
627 * dimensions - must be 1 or 2 or 3
628 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
629 */
630 static GLboolean
631 texture_error_check( GLcontext *ctx, GLenum target,
632 GLint level, GLint internalFormat,
633 GLenum format, GLenum type,
634 GLuint dimensions,
635 GLint width, GLint height,
636 GLint depth, GLint border )
637 {
638 GLboolean isProxy;
639 GLint iformat;
640 GLint maxLevels = 0, maxTextureSize;
641
642 if (dimensions == 1) {
643 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
644 if (target != GL_TEXTURE_1D && !isProxy) {
645 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
646 return GL_TRUE;
647 }
648 maxLevels = ctx->Const.MaxTextureLevels;
649 }
650 else if (dimensions == 2) {
651 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D ||
652 target == GL_PROXY_TEXTURE_CUBE_MAP_ARB);
653 if (target != GL_TEXTURE_2D && !isProxy &&
654 !(ctx->Extensions.ARB_texture_cube_map &&
655 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
656 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
657 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
658 return GL_TRUE;
659 }
660 if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
661 maxLevels = ctx->Const.MaxTextureLevels;
662 else
663 maxLevels = ctx->Const.MaxCubeTextureLevels;
664 }
665 else if (dimensions == 3) {
666 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
667 if (target != GL_TEXTURE_3D && !isProxy) {
668 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
669 return GL_TRUE;
670 }
671 maxLevels = ctx->Const.Max3DTextureLevels;
672 }
673 else {
674 _mesa_problem( ctx, "bad dims in texture_error_check" );
675 return GL_TRUE;
676 }
677
678 ASSERT(maxLevels > 0);
679 maxTextureSize = 1 << (maxLevels - 1);
680
681 /* Border */
682 if (border != 0 && border != 1) {
683 if (!isProxy) {
684 char message[100];
685 sprintf(message, "glTexImage%dD(border=%d)", dimensions, border);
686 _mesa_error(ctx, GL_INVALID_VALUE, message);
687 }
688 return GL_TRUE;
689 }
690
691 /* Width */
692 if (width < 2 * border || width > 2 + maxTextureSize
693 || logbase2( width - 2 * border ) < 0) {
694 if (!isProxy) {
695 char message[100];
696 sprintf(message, "glTexImage%dD(width=%d)", dimensions, width);
697 _mesa_error(ctx, GL_INVALID_VALUE, message);
698 }
699 return GL_TRUE;
700 }
701
702 /* Height */
703 if (dimensions >= 2) {
704 if (height < 2 * border || height > 2 + maxTextureSize
705 || logbase2( height - 2 * border ) < 0) {
706 if (!isProxy) {
707 char message[100];
708 sprintf(message, "glTexImage%dD(height=%d)", dimensions, height);
709 _mesa_error(ctx, GL_INVALID_VALUE, message);
710 }
711 return GL_TRUE;
712 }
713 }
714
715 /* For cube map, width must equal height */
716 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
717 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
718 if (width != height) {
719 if (!isProxy) {
720 _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
721 }
722 return GL_TRUE;
723 }
724 }
725
726 /* Depth */
727 if (dimensions >= 3) {
728 if (depth < 2 * border || depth > 2 + maxTextureSize
729 || logbase2( depth - 2 * border ) < 0) {
730 if (!isProxy) {
731 char message[100];
732 sprintf(message, "glTexImage3D(depth=%d)", depth );
733 _mesa_error( ctx, GL_INVALID_VALUE, message );
734 }
735 return GL_TRUE;
736 }
737 }
738
739 /* Level */
740 if (level < 0 || level >= maxLevels) {
741 if (!isProxy) {
742 char message[100];
743 sprintf(message, "glTexImage%dD(level=%d)", dimensions, level);
744 _mesa_error(ctx, GL_INVALID_VALUE, message);
745 }
746 return GL_TRUE;
747 }
748
749 /* For cube map, width must equal height */
750 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
751 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
752 if (width != height) {
753 _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
754 return GL_TRUE;
755 }
756 }
757
758 iformat = _mesa_base_tex_format( ctx, internalFormat );
759 if (iformat < 0) {
760 if (!isProxy) {
761 char message[100];
762 sprintf(message, "glTexImage%dD(internalFormat=0x%x)", dimensions,
763 internalFormat);
764 _mesa_error(ctx, GL_INVALID_VALUE, message);
765 }
766 return GL_TRUE;
767 }
768
769 ASSERT(iformat > 0);
770
771 if (!is_compressed_format( ctx, internalFormat ) &&
772 !_mesa_is_legal_format_and_type( format, type )) {
773 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
774 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
775 */
776 if (!isProxy) {
777 char message[100];
778 sprintf(message, "glTexImage%dD(format or type)", dimensions);
779 _mesa_error(ctx, GL_INVALID_OPERATION, message);
780 }
781 return GL_TRUE;
782 }
783
784 /* if we get here, the parameters are OK */
785 return GL_FALSE;
786 }
787
788
789
790 /*
791 * Test glTexSubImage[123]D() parameters for errors.
792 * Input:
793 * dimensions - must be 1 or 2 or 3
794 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
795 */
796 static GLboolean
797 subtexture_error_check( GLcontext *ctx, GLuint dimensions,
798 GLenum target, GLint level,
799 GLint xoffset, GLint yoffset, GLint zoffset,
800 GLint width, GLint height, GLint depth,
801 GLenum format, GLenum type )
802 {
803 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
804 struct gl_texture_image *destTex;
805 GLint maxLevels = 0;
806 GLboolean compressed;
807
808 if (dimensions == 1) {
809 if (target != GL_TEXTURE_1D) {
810 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
811 return GL_TRUE;
812 }
813 maxLevels = ctx->Const.MaxTextureLevels;
814 }
815 else if (dimensions == 2) {
816 if (ctx->Extensions.ARB_texture_cube_map) {
817 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
818 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
819 target != GL_TEXTURE_2D) {
820 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
821 return GL_TRUE;
822 }
823 }
824 else if (target != GL_TEXTURE_2D) {
825 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
826 return GL_TRUE;
827 }
828 if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
829 maxLevels = ctx->Const.MaxTextureLevels;
830 else
831 maxLevels = ctx->Const.MaxCubeTextureLevels;
832 }
833 else if (dimensions == 3) {
834 if (target != GL_TEXTURE_3D) {
835 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
836 return GL_TRUE;
837 }
838 maxLevels = ctx->Const.Max3DTextureLevels;
839 }
840 else {
841 _mesa_problem( ctx, "bad dims in texture_error_check" );
842 return GL_TRUE;
843 }
844
845 ASSERT(maxLevels > 0);
846
847 if (level < 0 || level >= maxLevels) {
848 char message[100];
849 sprintf(message, "glTexSubImage2D(level=%d)", level);
850 _mesa_error(ctx, GL_INVALID_ENUM, message);
851 return GL_TRUE;
852 }
853
854 if (width < 0) {
855 char message[100];
856 sprintf(message, "glTexSubImage%dD(width=%d)", dimensions, width);
857 _mesa_error(ctx, GL_INVALID_VALUE, message);
858 return GL_TRUE;
859 }
860 if (height < 0 && dimensions > 1) {
861 char message[100];
862 sprintf(message, "glTexSubImage%dD(height=%d)", dimensions, height);
863 _mesa_error(ctx, GL_INVALID_VALUE, message);
864 return GL_TRUE;
865 }
866 if (depth < 0 && dimensions > 2) {
867 char message[100];
868 sprintf(message, "glTexSubImage%dD(depth=%d)", dimensions, depth);
869 _mesa_error(ctx, GL_INVALID_VALUE, message);
870 return GL_TRUE;
871 }
872
873 destTex = _mesa_select_tex_image(ctx, texUnit, target, level);
874
875 if (!destTex) {
876 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
877 return GL_TRUE;
878 }
879
880 if (xoffset < -((GLint)destTex->Border)) {
881 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
882 return GL_TRUE;
883 }
884 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
885 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
886 return GL_TRUE;
887 }
888 if (dimensions > 1) {
889 if (yoffset < -((GLint)destTex->Border)) {
890 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
891 return GL_TRUE;
892 }
893 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
894 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
895 return GL_TRUE;
896 }
897 }
898 if (dimensions > 2) {
899 if (zoffset < -((GLint)destTex->Border)) {
900 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
901 return GL_TRUE;
902 }
903 if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) {
904 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
905 return GL_TRUE;
906 }
907 }
908
909 compressed = is_compressed_format(ctx, destTex->IntFormat);
910
911 if (!compressed && !_mesa_is_legal_format_and_type(format, type)) {
912 char message[100];
913 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
914 _mesa_error(ctx, GL_INVALID_ENUM, message);
915 return GL_TRUE;
916 }
917
918 if (compressed) {
919 if (xoffset != -destTex->Border) {
920 _mesa_error(ctx, GL_INVALID_OPERATION,
921 "glTexSubImage1/2/3D(xoffset != -border");
922 return GL_TRUE;
923 }
924 if (dimensions > 1 && yoffset != -destTex->Border) {
925 _mesa_error(ctx, GL_INVALID_OPERATION,
926 "glTexSubImage2/3D(yoffset != -border");
927 return GL_TRUE;
928 }
929 if (dimensions > 2 && zoffset != -destTex->Border) {
930 _mesa_error(ctx, GL_INVALID_OPERATION,
931 "glTexSubImage3D(zoffset != -border");
932 return GL_TRUE;
933 }
934 }
935
936 return GL_FALSE;
937 }
938
939
940 /*
941 * Test glCopyTexImage[12]D() parameters for errors.
942 * Input: dimensions - must be 1 or 2 or 3
943 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
944 */
945 static GLboolean
946 copytexture_error_check( GLcontext *ctx, GLuint dimensions,
947 GLenum target, GLint level, GLint internalFormat,
948 GLint width, GLint height, GLint border )
949 {
950 GLint iformat;
951 GLint maxLevels = 0, maxTextureSize;
952
953 if (dimensions == 1) {
954 if (target != GL_TEXTURE_1D) {
955 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
956 return GL_TRUE;
957 }
958 maxLevels = ctx->Const.MaxTextureLevels;
959 }
960 else if (dimensions == 2) {
961 if (ctx->Extensions.ARB_texture_cube_map) {
962 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
963 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
964 target != GL_TEXTURE_2D) {
965 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
966 return GL_TRUE;
967 }
968 }
969 else if (target != GL_TEXTURE_2D) {
970 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
971 return GL_TRUE;
972 }
973 if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
974 maxLevels = ctx->Const.MaxTextureLevels;
975 else
976 maxLevels = ctx->Const.MaxCubeTextureLevels;
977 }
978
979 ASSERT(maxLevels > 0);
980 maxTextureSize = 1 << (maxLevels - 1);
981
982 /* Border */
983 if (border != 0 && border != 1) {
984 char message[100];
985 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
986 _mesa_error(ctx, GL_INVALID_VALUE, message);
987 return GL_TRUE;
988 }
989
990 /* Width */
991 if (width < 2 * border || width > 2 + maxTextureSize
992 || logbase2( width - 2 * border ) < 0) {
993 char message[100];
994 sprintf(message, "glCopyTexImage%dD(width=%d)", dimensions, width);
995 _mesa_error(ctx, GL_INVALID_VALUE, message);
996 return GL_TRUE;
997 }
998
999 /* Height */
1000 if (dimensions >= 2) {
1001 if (height < 2 * border || height > 2 + maxTextureSize
1002 || logbase2( height - 2 * border ) < 0) {
1003 char message[100];
1004 sprintf(message, "glCopyTexImage%dD(height=%d)", dimensions, height);
1005 _mesa_error(ctx, GL_INVALID_VALUE, message);
1006 return GL_TRUE;
1007 }
1008 }
1009
1010 /* For cube map, width must equal height */
1011 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1012 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1013 if (width != height) {
1014 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
1015 return GL_TRUE;
1016 }
1017 }
1018
1019 /* Level */
1020 if (level < 0 || level >= maxLevels) {
1021 char message[100];
1022 sprintf(message, "glCopyTexImage%dD(level=%d)", dimensions, level);
1023 _mesa_error(ctx, GL_INVALID_VALUE, message);
1024 return GL_TRUE;
1025 }
1026
1027 iformat = _mesa_base_tex_format(ctx, internalFormat);
1028 if (iformat < 0) {
1029 char message[100];
1030 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1031 _mesa_error(ctx, GL_INVALID_VALUE, message);
1032 return GL_TRUE;
1033 }
1034
1035 /* if we get here, the parameters are OK */
1036 return GL_FALSE;
1037 }
1038
1039
1040 static GLboolean
1041 copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
1042 GLenum target, GLint level,
1043 GLint xoffset, GLint yoffset, GLint zoffset,
1044 GLsizei width, GLsizei height )
1045 {
1046 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1047 struct gl_texture_image *teximage;
1048 GLint maxLevels = 0;
1049 GLboolean compressed;
1050
1051 if (dimensions == 1) {
1052 if (target != GL_TEXTURE_1D) {
1053 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1054 return GL_TRUE;
1055 }
1056 maxLevels = ctx->Const.MaxTextureLevels;
1057 }
1058 else if (dimensions == 2) {
1059 if (ctx->Extensions.ARB_texture_cube_map) {
1060 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1061 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1062 target != GL_TEXTURE_2D) {
1063 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1064 return GL_TRUE;
1065 }
1066 }
1067 else if (target != GL_TEXTURE_2D) {
1068 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1069 return GL_TRUE;
1070 }
1071 if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
1072 maxLevels = ctx->Const.MaxTextureLevels;
1073 else
1074 maxLevels = ctx->Const.MaxCubeTextureLevels;
1075 }
1076 else if (dimensions == 3) {
1077 if (target != GL_TEXTURE_3D) {
1078 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1079 return GL_TRUE;
1080 }
1081 maxLevels = ctx->Const.Max3DTextureLevels;
1082 }
1083
1084 ASSERT(maxLevels > 0);
1085
1086 if (level < 0 || level >= maxLevels) {
1087 char message[100];
1088 sprintf(message, "glCopyTexSubImage%dD(level=%d)", dimensions, level);
1089 _mesa_error(ctx, GL_INVALID_VALUE, message);
1090 return GL_TRUE;
1091 }
1092
1093 if (width < 0) {
1094 char message[100];
1095 sprintf(message, "glCopyTexSubImage%dD(width=%d)", dimensions, width);
1096 _mesa_error(ctx, GL_INVALID_VALUE, message);
1097 return GL_TRUE;
1098 }
1099 if (dimensions > 1 && height < 0) {
1100 char message[100];
1101 sprintf(message, "glCopyTexSubImage%dD(height=%d)", dimensions, height);
1102 _mesa_error(ctx, GL_INVALID_VALUE, message);
1103 return GL_TRUE;
1104 }
1105
1106 teximage = _mesa_select_tex_image(ctx, texUnit, target, level);
1107 if (!teximage) {
1108 char message[100];
1109 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1110 _mesa_error(ctx, GL_INVALID_OPERATION, message);
1111 return GL_TRUE;
1112 }
1113
1114 if (xoffset < -((GLint)teximage->Border)) {
1115 char message[100];
1116 sprintf(message, "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
1117 _mesa_error(ctx, GL_INVALID_VALUE, message);
1118 return GL_TRUE;
1119 }
1120 if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
1121 char message[100];
1122 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1123 _mesa_error(ctx, GL_INVALID_VALUE, message);
1124 return GL_TRUE;
1125 }
1126 if (dimensions > 1) {
1127 if (yoffset < -((GLint)teximage->Border)) {
1128 char message[100];
1129 sprintf(message, "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
1130 _mesa_error(ctx, GL_INVALID_VALUE, message);
1131 return GL_TRUE;
1132 }
1133 /* NOTE: we're adding the border here, not subtracting! */
1134 if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
1135 char message[100];
1136 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1137 _mesa_error(ctx, GL_INVALID_VALUE, message);
1138 return GL_TRUE;
1139 }
1140 }
1141
1142 if (dimensions > 2) {
1143 if (zoffset < -((GLint)teximage->Border)) {
1144 char message[100];
1145 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1146 _mesa_error(ctx, GL_INVALID_VALUE, message);
1147 return GL_TRUE;
1148 }
1149 if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
1150 char message[100];
1151 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1152 _mesa_error(ctx, GL_INVALID_VALUE, message);
1153 return GL_TRUE;
1154 }
1155 }
1156
1157 compressed = is_compressed_format(ctx, teximage->IntFormat);
1158 if (compressed) {
1159 if (xoffset != -teximage->Border) {
1160 _mesa_error(ctx, GL_INVALID_OPERATION,
1161 "glCopyTexSubImage1/2/3D(xoffset != -border");
1162 return GL_TRUE;
1163 }
1164 if (dimensions > 1 && yoffset != -teximage->Border) {
1165 _mesa_error(ctx, GL_INVALID_OPERATION,
1166 "glCopyTexSubImage2/3D(yoffset != -border");
1167 return GL_TRUE;
1168 }
1169 if (dimensions > 2 && zoffset != -teximage->Border) {
1170 _mesa_error(ctx, GL_INVALID_OPERATION,
1171 "glCopyTexSubImage3D(zoffset != -border");
1172 return GL_TRUE;
1173 }
1174 }
1175
1176 /* if we get here, the parameters are OK */
1177 return GL_FALSE;
1178 }
1179
1180
1181
1182 void
1183 _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1184 GLenum type, GLvoid *pixels )
1185 {
1186 const struct gl_texture_unit *texUnit;
1187 const struct gl_texture_object *texObj;
1188 struct gl_texture_image *texImage;
1189 GLint maxLevels = 0;
1190 GET_CURRENT_CONTEXT(ctx);
1191 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1192
1193 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
1194 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1195 if (!texObj || is_proxy_target(target)) {
1196 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
1197 return;
1198 }
1199
1200 if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D) {
1201 maxLevels = ctx->Const.MaxTextureLevels;
1202 }
1203 else if (target == GL_TEXTURE_3D) {
1204 maxLevels = ctx->Const.Max3DTextureLevels;
1205 }
1206 else {
1207 maxLevels = ctx->Const.MaxCubeTextureLevels;
1208 }
1209
1210 ASSERT(maxLevels > 0);
1211
1212 if (level < 0 || level >= maxLevels) {
1213 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1214 return;
1215 }
1216
1217 if (_mesa_sizeof_type(type) <= 0) {
1218 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1219 return;
1220 }
1221
1222 if (_mesa_components_in_format(format) <= 0 ||
1223 format == GL_STENCIL_INDEX) {
1224 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1225 return;
1226 }
1227
1228 if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) {
1229 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
1230 }
1231
1232 if (!ctx->Extensions.SGIX_depth_texture && format == GL_DEPTH_COMPONENT) {
1233 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
1234 }
1235
1236 /* XXX what if format/type doesn't match texture format/type? */
1237
1238 if (!pixels)
1239 return;
1240
1241 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1242 if (!texImage) {
1243 /* invalid mipmap level, not an error */
1244 return;
1245 }
1246
1247 if (!texImage->Data) {
1248 /* no image data, not an error */
1249 return;
1250 }
1251
1252 {
1253 const GLint width = texImage->Width;
1254 const GLint height = texImage->Height;
1255 const GLint depth = texImage->Depth;
1256 GLint img, row;
1257 for (img = 0; img < depth; img++) {
1258 for (row = 0; row < height; row++) {
1259 /* compute destination address in client memory */
1260 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
1261 width, height, format, type,
1262 img, row, 0);
1263 assert(dest);
1264
1265 if (format == GL_COLOR_INDEX) {
1266 GLuint indexRow[MAX_WIDTH];
1267 GLint col;
1268 for (col = 0; col < width; col++) {
1269 (*texImage->FetchTexel)(texImage, col, row, img,
1270 (GLvoid *) &indexRow[col]);
1271 }
1272 _mesa_pack_index_span(ctx, width, type, dest,
1273 indexRow, &ctx->Pack,
1274 0 /* no image transfer */);
1275 }
1276 else if (format == GL_DEPTH_COMPONENT) {
1277 GLfloat depthRow[MAX_WIDTH];
1278 GLint col;
1279 for (col = 0; col < width; col++) {
1280 (*texImage->FetchTexel)(texImage, col, row, img,
1281 (GLvoid *) &depthRow[col]);
1282 }
1283 _mesa_pack_depth_span(ctx, width, dest, type,
1284 depthRow, &ctx->Pack);
1285 }
1286 else {
1287 /* general case: convert row to RGBA format */
1288 GLchan rgba[MAX_WIDTH][4];
1289 GLint col;
1290 for (col = 0; col < width; col++) {
1291 (*texImage->FetchTexel)(texImage, col, row, img,
1292 (GLvoid *) rgba[col]);
1293 }
1294 _mesa_pack_rgba_span(ctx, width, (const GLchan (*)[4])rgba,
1295 format, type, dest, &ctx->Pack,
1296 0 /* no image transfer */);
1297 } /* format */
1298 } /* row */
1299 } /* img */
1300 }
1301 }
1302
1303
1304
1305 /*
1306 * Called from the API. Note that width includes the border.
1307 */
1308 void
1309 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1310 GLsizei width, GLint border, GLenum format,
1311 GLenum type, const GLvoid *pixels )
1312 {
1313 GLsizei postConvWidth = width;
1314 GET_CURRENT_CONTEXT(ctx);
1315 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1316
1317 if (is_color_format(internalFormat)) {
1318 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1319 }
1320
1321 if (target == GL_TEXTURE_1D) {
1322 struct gl_texture_unit *texUnit;
1323 struct gl_texture_object *texObj;
1324 struct gl_texture_image *texImage;
1325
1326 if (texture_error_check(ctx, target, level, internalFormat,
1327 format, type, 1, postConvWidth, 1, 1, border)) {
1328 return; /* error was recorded */
1329 }
1330
1331 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1332 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1333 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1334
1335 if (!texImage) {
1336 texImage = _mesa_alloc_texture_image();
1337 texObj->Image[level] = texImage;
1338 if (!texImage) {
1339 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1340 return;
1341 }
1342 }
1343 else if (texImage->Data) {
1344 /* free the old texture data */
1345 FREE(texImage->Data);
1346 texImage->Data = NULL;
1347 }
1348 clear_teximage_fields(texImage); /* not really needed, but helpful */
1349 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
1350 border, internalFormat);
1351
1352 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1353 _mesa_update_state(ctx);
1354
1355 ASSERT(ctx->Driver.TexImage1D);
1356 if (pixels) {
1357 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
1358 width, border, format, type, pixels,
1359 &ctx->Unpack, texObj, texImage);
1360 }
1361 else {
1362 GLubyte *dummy = make_null_texture(width, 1, 1, format);
1363 if (dummy) {
1364 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
1365 width, border,
1366 format, GL_UNSIGNED_BYTE, dummy,
1367 &_mesa_native_packing, texObj, texImage);
1368 FREE(dummy);
1369 }
1370 }
1371
1372 ASSERT(texImage->TexFormat);
1373 if (!texImage->FetchTexel) {
1374 /* If driver didn't explicitly set this, use the default */
1375 texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
1376 }
1377 ASSERT(texImage->FetchTexel);
1378
1379 if (texImage->IsCompressed) {
1380 ASSERT(texImage->CompressedSize > 0);
1381 }
1382
1383 /* state update */
1384 texObj->Complete = GL_FALSE;
1385 ctx->NewState |= _NEW_TEXTURE;
1386 }
1387 else if (target == GL_PROXY_TEXTURE_1D) {
1388 /* Proxy texture: check for errors and update proxy state */
1389 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1390 format, type, 1,
1391 postConvWidth, 1, 1, border);
1392 if (!error) {
1393 struct gl_texture_unit *texUnit;
1394 struct gl_texture_image *texImage;
1395 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1396 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1397 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
1398 border, internalFormat);
1399 ASSERT(ctx->Driver.TestProxyTexImage);
1400 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1401 internalFormat, format, type,
1402 postConvWidth, 1, 1, border);
1403 }
1404 if (error) {
1405 /* if error, clear all proxy texture image parameters */
1406 if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
1407 clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]);
1408 }
1409 }
1410 }
1411 else {
1412 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1413 return;
1414 }
1415 }
1416
1417
1418 void
1419 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1420 GLsizei width, GLsizei height, GLint border,
1421 GLenum format, GLenum type,
1422 const GLvoid *pixels )
1423 {
1424 GLsizei postConvWidth = width, postConvHeight = height;
1425 GET_CURRENT_CONTEXT(ctx);
1426 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1427
1428 if (is_color_format(internalFormat)) {
1429 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1430 &postConvHeight);
1431 }
1432
1433 if (target == GL_TEXTURE_2D ||
1434 (ctx->Extensions.ARB_texture_cube_map &&
1435 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1436 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1437 /* non-proxy target */
1438 struct gl_texture_unit *texUnit;
1439 struct gl_texture_object *texObj;
1440 struct gl_texture_image *texImage;
1441
1442 if (texture_error_check(ctx, target, level, internalFormat,
1443 format, type, 2, postConvWidth, postConvHeight,
1444 1, border)) {
1445 return; /* error was recorded */
1446 }
1447
1448 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1449 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1450 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1451
1452 if (!texImage) {
1453 texImage = _mesa_alloc_texture_image();
1454 _mesa_set_tex_image(texObj, target, level, texImage);
1455 if (!texImage) {
1456 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1457 return;
1458 }
1459 }
1460 else if (texImage->Data) {
1461 /* free the old texture data */
1462 FREE(texImage->Data);
1463 texImage->Data = NULL;
1464 }
1465 clear_teximage_fields(texImage); /* not really needed, but helpful */
1466 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight,
1467 1, border, internalFormat);
1468
1469 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1470 _mesa_update_state(ctx);
1471
1472 ASSERT(ctx->Driver.TexImage2D);
1473 if (pixels) {
1474 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
1475 width, height, border, format, type, pixels,
1476 &ctx->Unpack, texObj, texImage);
1477 }
1478 else {
1479 GLubyte *dummy = make_null_texture(width, height, 1, format);
1480 if (dummy) {
1481 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
1482 width, height, border,
1483 format, GL_UNSIGNED_BYTE, dummy,
1484 &_mesa_native_packing, texObj, texImage);
1485 FREE(dummy);
1486 }
1487 }
1488
1489 ASSERT(texImage->TexFormat);
1490 if (!texImage->FetchTexel) {
1491 /* If driver didn't explicitly set this, use the default */
1492 texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
1493 }
1494 ASSERT(texImage->FetchTexel);
1495
1496 if (texImage->IsCompressed) {
1497 ASSERT(texImage->CompressedSize > 0);
1498 }
1499
1500 /* state update */
1501 texObj->Complete = GL_FALSE;
1502 ctx->NewState |= _NEW_TEXTURE;
1503 }
1504 else if (target == GL_PROXY_TEXTURE_2D) {
1505 /* Proxy texture: check for errors and update proxy state */
1506 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1507 format, type, 2,
1508 postConvWidth, postConvHeight, 1, border);
1509 if (!error) {
1510 struct gl_texture_unit *texUnit;
1511 struct gl_texture_image *texImage;
1512 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1513 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1514 _mesa_init_teximage_fields(ctx, texImage, postConvWidth,
1515 postConvHeight, 1, border, internalFormat);
1516 ASSERT(ctx->Driver.TestProxyTexImage);
1517 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1518 internalFormat, format, type,
1519 postConvWidth, postConvHeight, 1, border);
1520 }
1521 if (error) {
1522 /* if error, clear all proxy texture image parameters */
1523 const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ?
1524 ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels;
1525 if (level >= 0 && level < maxLevels) {
1526 clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
1527 }
1528 }
1529 }
1530 else {
1531 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1532 return;
1533 }
1534 }
1535
1536
1537 /*
1538 * Called by the API or display list executor.
1539 * Note that width and height include the border.
1540 */
1541 void
1542 _mesa_TexImage3D( GLenum target, GLint level, GLenum internalFormat,
1543 GLsizei width, GLsizei height, GLsizei depth,
1544 GLint border, GLenum format, GLenum type,
1545 const GLvoid *pixels )
1546 {
1547 GET_CURRENT_CONTEXT(ctx);
1548 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1549
1550 if (target == GL_TEXTURE_3D) {
1551 struct gl_texture_unit *texUnit;
1552 struct gl_texture_object *texObj;
1553 struct gl_texture_image *texImage;
1554
1555 if (texture_error_check(ctx, target, level, (GLint) internalFormat,
1556 format, type, 3, width, height, depth, border)) {
1557 return; /* error was recorded */
1558 }
1559
1560 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1561 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1562 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1563
1564 if (!texImage) {
1565 texImage = _mesa_alloc_texture_image();
1566 texObj->Image[level] = texImage;
1567 if (!texImage) {
1568 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1569 return;
1570 }
1571 }
1572 else if (texImage->Data) {
1573 FREE(texImage->Data);
1574 texImage->Data = NULL;
1575 }
1576 clear_teximage_fields(texImage); /* not really needed, but helpful */
1577 _mesa_init_teximage_fields(ctx, texImage, width, height, depth, border,
1578 internalFormat);
1579
1580 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1581 _mesa_update_state(ctx);
1582
1583 ASSERT(ctx->Driver.TexImage3D);
1584 if (pixels) {
1585 (*ctx->Driver.TexImage3D)(ctx, target, level, (GLint) internalFormat,
1586 width, height, depth, border,
1587 format, type, pixels,
1588 &ctx->Unpack, texObj, texImage);
1589 }
1590 else {
1591 GLubyte *dummy = make_null_texture(width, height, depth, format);
1592 if (dummy) {
1593 (*ctx->Driver.TexImage3D)(ctx, target, level,
1594 (GLint) internalFormat,
1595 width, height, depth, border,
1596 format, GL_UNSIGNED_BYTE, dummy,
1597 &_mesa_native_packing, texObj, texImage);
1598 FREE(dummy);
1599 }
1600 }
1601
1602 ASSERT(texImage->TexFormat);
1603 if (!texImage->FetchTexel) {
1604 /* If driver didn't explicitly set this, use the default */
1605 texImage->FetchTexel = texImage->TexFormat->FetchTexel3D;
1606 }
1607 ASSERT(texImage->FetchTexel);
1608
1609 if (texImage->IsCompressed) {
1610 ASSERT(texImage->CompressedSize > 0);
1611 }
1612
1613 /* state update */
1614 texObj->Complete = GL_FALSE;
1615 ctx->NewState |= _NEW_TEXTURE;
1616 }
1617 else if (target == GL_PROXY_TEXTURE_3D) {
1618 /* Proxy texture: check for errors and update proxy state */
1619 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1620 format, type, 3, width, height, depth, border);
1621 if (!error) {
1622 struct gl_texture_unit *texUnit;
1623 struct gl_texture_image *texImage;
1624 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1625 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1626 _mesa_init_teximage_fields(ctx, texImage, width, height, 1,
1627 border, internalFormat);
1628 ASSERT(ctx->Driver.TestProxyTexImage);
1629 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1630 internalFormat, format, type,
1631 width, height, depth, border);
1632 }
1633 if (error) {
1634 /* if error, clear all proxy texture image parameters */
1635 if (level >= 0 && level < ctx->Const.Max3DTextureLevels) {
1636 clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
1637 }
1638 }
1639 }
1640 else {
1641 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1642 return;
1643 }
1644 }
1645
1646
1647 void
1648 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
1649 GLsizei width, GLsizei height, GLsizei depth,
1650 GLint border, GLenum format, GLenum type,
1651 const GLvoid *pixels )
1652 {
1653 _mesa_TexImage3D(target, level, internalFormat, width, height,
1654 depth, border, format, type, pixels);
1655 }
1656
1657
1658
1659 void
1660 _mesa_TexSubImage1D( GLenum target, GLint level,
1661 GLint xoffset, GLsizei width,
1662 GLenum format, GLenum type,
1663 const GLvoid *pixels )
1664 {
1665 GLsizei postConvWidth = width;
1666 struct gl_texture_unit *texUnit;
1667 struct gl_texture_object *texObj;
1668 struct gl_texture_image *texImage;
1669 GET_CURRENT_CONTEXT(ctx);
1670 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1671
1672 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1673 _mesa_update_state(ctx);
1674
1675 /* XXX should test internal format */
1676 if (is_color_format(format)) {
1677 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1678 }
1679
1680 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1681 postConvWidth, 1, 1, format, type)) {
1682 return; /* error was detected */
1683 }
1684
1685 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1686 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1687 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1688 assert(texImage);
1689
1690 if (width == 0 || !pixels)
1691 return; /* no-op, not an error */
1692
1693 /* If we have a border, xoffset=-1 is legal. Bias by border width */
1694 xoffset += texImage->Border;
1695
1696 ASSERT(ctx->Driver.TexSubImage1D);
1697 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
1698 format, type, pixels, &ctx->Unpack,
1699 texObj, texImage);
1700 ctx->NewState |= _NEW_TEXTURE;
1701 }
1702
1703
1704 void
1705 _mesa_TexSubImage2D( GLenum target, GLint level,
1706 GLint xoffset, GLint yoffset,
1707 GLsizei width, GLsizei height,
1708 GLenum format, GLenum type,
1709 const GLvoid *pixels )
1710 {
1711 GLsizei postConvWidth = width, postConvHeight = height;
1712 struct gl_texture_unit *texUnit;
1713 struct gl_texture_object *texObj;
1714 struct gl_texture_image *texImage;
1715 GET_CURRENT_CONTEXT(ctx);
1716 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1717
1718 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1719 _mesa_update_state(ctx);
1720
1721 /* XXX should test internal format */
1722 if (is_color_format(format)) {
1723 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1724 &postConvHeight);
1725 }
1726
1727 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1728 postConvWidth, postConvHeight, 1, format, type)) {
1729 return; /* error was detected */
1730 }
1731
1732 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1733 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1734 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1735 assert(texImage);
1736
1737 if (width == 0 || height == 0 || !pixels)
1738 return; /* no-op, not an error */
1739
1740 /* If we have a border, xoffset=-1 is legal. Bias by border width */
1741 xoffset += texImage->Border;
1742 yoffset += texImage->Border;
1743
1744 ASSERT(ctx->Driver.TexSubImage2D);
1745 (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
1746 width, height, format, type, pixels,
1747 &ctx->Unpack, texObj, texImage);
1748 ctx->NewState |= _NEW_TEXTURE;
1749 }
1750
1751
1752
1753 void
1754 _mesa_TexSubImage3D( GLenum target, GLint level,
1755 GLint xoffset, GLint yoffset, GLint zoffset,
1756 GLsizei width, GLsizei height, GLsizei depth,
1757 GLenum format, GLenum type,
1758 const GLvoid *pixels )
1759 {
1760 struct gl_texture_unit *texUnit;
1761 struct gl_texture_object *texObj;
1762 struct gl_texture_image *texImage;
1763 GET_CURRENT_CONTEXT(ctx);
1764 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1765
1766 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1767 _mesa_update_state(ctx);
1768
1769 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
1770 width, height, depth, format, type)) {
1771 return; /* error was detected */
1772 }
1773
1774 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1775 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1776 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1777 assert(texImage);
1778
1779 if (width == 0 || height == 0 || height == 0 || !pixels)
1780 return; /* no-op, not an error */
1781
1782 /* If we have a border, xoffset=-1 is legal. Bias by border width */
1783 xoffset += texImage->Border;
1784 yoffset += texImage->Border;
1785 zoffset += texImage->Border;
1786
1787 ASSERT(ctx->Driver.TexSubImage3D);
1788 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
1789 xoffset, yoffset, zoffset,
1790 width, height, depth,
1791 format, type, pixels,
1792 &ctx->Unpack, texObj, texImage );
1793 ctx->NewState |= _NEW_TEXTURE;
1794 }
1795
1796
1797
1798 void
1799 _mesa_CopyTexImage1D( GLenum target, GLint level,
1800 GLenum internalFormat,
1801 GLint x, GLint y,
1802 GLsizei width, GLint border )
1803 {
1804 struct gl_texture_unit *texUnit;
1805 struct gl_texture_object *texObj;
1806 struct gl_texture_image *texImage;
1807 GLsizei postConvWidth = width;
1808 GET_CURRENT_CONTEXT(ctx);
1809 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1810
1811 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1812 _mesa_update_state(ctx);
1813
1814 if (is_color_format(internalFormat)) {
1815 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1816 }
1817
1818 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
1819 postConvWidth, 1, border))
1820 return;
1821
1822 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1823 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1824 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1825 if (!texImage) {
1826 texImage = _mesa_alloc_texture_image();
1827 _mesa_set_tex_image(texObj, target, level, texImage);
1828 if (!texImage) {
1829 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
1830 return;
1831 }
1832 }
1833 else if (texImage->Data) {
1834 /* free the old texture data */
1835 FREE(texImage->Data);
1836 texImage->Data = NULL;
1837 }
1838
1839 clear_teximage_fields(texImage); /* not really needed, but helpful */
1840 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
1841 border, internalFormat);
1842
1843
1844 ASSERT(ctx->Driver.CopyTexImage1D);
1845 (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
1846 x, y, width, border);
1847
1848 ASSERT(texImage->TexFormat);
1849 if (!texImage->FetchTexel) {
1850 /* If driver didn't explicitly set this, use the default */
1851 texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
1852 }
1853 ASSERT(texImage->FetchTexel);
1854
1855 /* state update */
1856 texObj->Complete = GL_FALSE;
1857 ctx->NewState |= _NEW_TEXTURE;
1858 }
1859
1860
1861
1862 void
1863 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
1864 GLint x, GLint y, GLsizei width, GLsizei height,
1865 GLint border )
1866 {
1867 struct gl_texture_unit *texUnit;
1868 struct gl_texture_object *texObj;
1869 struct gl_texture_image *texImage;
1870 GLsizei postConvWidth = width, postConvHeight = height;
1871 GET_CURRENT_CONTEXT(ctx);
1872 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1873
1874 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1875 _mesa_update_state(ctx);
1876
1877 if (is_color_format(internalFormat)) {
1878 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1879 &postConvHeight);
1880 }
1881
1882 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
1883 postConvWidth, postConvHeight, border))
1884 return;
1885
1886 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1887 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1888 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1889 if (!texImage) {
1890 texImage = _mesa_alloc_texture_image();
1891 _mesa_set_tex_image(texObj, target, level, texImage);
1892 if (!texImage) {
1893 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
1894 return;
1895 }
1896 }
1897 else if (texImage->Data) {
1898 /* free the old texture data */
1899 FREE(texImage->Data);
1900 texImage->Data = NULL;
1901 }
1902
1903 clear_teximage_fields(texImage); /* not really needed, but helpful */
1904 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight, 1,
1905 border, internalFormat);
1906
1907 ASSERT(ctx->Driver.CopyTexImage2D);
1908 (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
1909 x, y, width, height, border);
1910
1911 ASSERT(texImage->TexFormat);
1912 if (!texImage->FetchTexel) {
1913 /* If driver didn't explicitly set this, use the default */
1914 texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
1915 }
1916 ASSERT(texImage->FetchTexel);
1917
1918 /* state update */
1919 texObj->Complete = GL_FALSE;
1920 ctx->NewState |= _NEW_TEXTURE;
1921 }
1922
1923
1924
1925 void
1926 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
1927 GLint xoffset, GLint x, GLint y, GLsizei width )
1928 {
1929 struct gl_texture_unit *texUnit;
1930 struct gl_texture_object *texObj;
1931 struct gl_texture_image *texImage;
1932 GLsizei postConvWidth = width;
1933 GET_CURRENT_CONTEXT(ctx);
1934 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1935
1936 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1937 _mesa_update_state(ctx);
1938
1939 /* XXX should test internal format */
1940 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1941
1942 if (copytexsubimage_error_check(ctx, 1, target, level,
1943 xoffset, 0, 0, postConvWidth, 1))
1944 return;
1945
1946 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1947 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1948 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1949
1950 /* If we have a border, xoffset=-1 is legal. Bias by border width */
1951 xoffset += texImage->Border;
1952
1953 ASSERT(ctx->Driver.CopyTexSubImage1D);
1954 (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width);
1955 ctx->NewState |= _NEW_TEXTURE;
1956 }
1957
1958
1959
1960 void
1961 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
1962 GLint xoffset, GLint yoffset,
1963 GLint x, GLint y, GLsizei width, GLsizei height )
1964 {
1965 struct gl_texture_unit *texUnit;
1966 struct gl_texture_object *texObj;
1967 struct gl_texture_image *texImage;
1968 GLsizei postConvWidth = width, postConvHeight = height;
1969 GET_CURRENT_CONTEXT(ctx);
1970 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1971
1972 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1973 _mesa_update_state(ctx);
1974
1975 /* XXX should test internal format */
1976 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
1977
1978 if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1979 postConvWidth, postConvHeight))
1980 return;
1981
1982 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1983 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1984 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1985
1986 /* If we have a border, xoffset=-1 is legal. Bias by border width */
1987 xoffset += texImage->Border;
1988 yoffset += texImage->Border;
1989
1990 ASSERT(ctx->Driver.CopyTexSubImage2D);
1991 (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
1992 xoffset, yoffset, x, y, width, height);
1993 ctx->NewState |= _NEW_TEXTURE;
1994 }
1995
1996
1997
1998 void
1999 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2000 GLint xoffset, GLint yoffset, GLint zoffset,
2001 GLint x, GLint y, GLsizei width, GLsizei height )
2002 {
2003 struct gl_texture_unit *texUnit;
2004 struct gl_texture_object *texObj;
2005 struct gl_texture_image *texImage;
2006 GLsizei postConvWidth = width, postConvHeight = height;
2007 GET_CURRENT_CONTEXT(ctx);
2008 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2009
2010 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2011 _mesa_update_state(ctx);
2012
2013 /* XXX should test internal format */
2014 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
2015
2016 if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset,
2017 zoffset, postConvWidth, postConvHeight))
2018 return;
2019
2020 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2021 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2022 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2023
2024 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2025 xoffset += texImage->Border;
2026 yoffset += texImage->Border;
2027 zoffset += texImage->Border;
2028
2029 ASSERT(ctx->Driver.CopyTexSubImage3D);
2030 (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2031 xoffset, yoffset, zoffset,
2032 x, y, width, height);
2033 ctx->NewState |= _NEW_TEXTURE;
2034 }
2035
2036
2037
2038 void
2039 _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
2040 GLenum internalFormat, GLsizei width,
2041 GLint border, GLsizei imageSize,
2042 const GLvoid *data)
2043 {
2044 GET_CURRENT_CONTEXT(ctx);
2045 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2046
2047 switch (internalFormat) {
2048 case GL_COMPRESSED_ALPHA_ARB:
2049 case GL_COMPRESSED_LUMINANCE_ARB:
2050 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2051 case GL_COMPRESSED_INTENSITY_ARB:
2052 case GL_COMPRESSED_RGB_ARB:
2053 case GL_COMPRESSED_RGBA_ARB:
2054 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2055 return;
2056 default:
2057 /* silence compiler warning */
2058 ;
2059 }
2060
2061 if (target == GL_TEXTURE_1D) {
2062 struct gl_texture_unit *texUnit;
2063 struct gl_texture_object *texObj;
2064 struct gl_texture_image *texImage;
2065
2066 if (texture_error_check(ctx, target, level, internalFormat,
2067 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2068 return; /* error in texture image was detected */
2069 }
2070
2071 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2072 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2073 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2074
2075 if (!texImage) {
2076 texImage = _mesa_alloc_texture_image();
2077 texObj->Image[level] = texImage;
2078 if (!texImage) {
2079 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2080 return;
2081 }
2082 }
2083 else if (texImage->Data) {
2084 FREE(texImage->Data);
2085 texImage->Data = NULL;
2086 }
2087
2088 _mesa_init_teximage_fields(ctx, texImage, width, 1, 1,
2089 border, internalFormat);
2090
2091 if (ctx->Extensions.ARB_texture_compression) {
2092 ASSERT(ctx->Driver.CompressedTexImage1D);
2093 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2094 internalFormat, width, border,
2095 imageSize, data,
2096 texObj, texImage);
2097 ASSERT(texImage->CompressedSize > 0); /* sanity */
2098 }
2099
2100 /* state update */
2101 texObj->Complete = GL_FALSE;
2102 ctx->NewState |= _NEW_TEXTURE;
2103 }
2104 else if (target == GL_PROXY_TEXTURE_1D) {
2105 /* Proxy texture: check for errors and update proxy state */
2106 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2107 GL_NONE, GL_NONE, 1, width, 1, 1, border);
2108 if (!error) {
2109 struct gl_texture_unit *texUnit;
2110 struct gl_texture_image *texImage;
2111 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2112 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2113 _mesa_init_teximage_fields(ctx, texImage, width, 1, 1,
2114 border, internalFormat);
2115 ASSERT(ctx->Driver.TestProxyTexImage);
2116 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2117 internalFormat, GL_NONE, GL_NONE,
2118 width, 1, 1, border);
2119 }
2120 if (error) {
2121 /* if error, clear all proxy texture image parameters */
2122 if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
2123 clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]);
2124 }
2125 }
2126 }
2127 else {
2128 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)");
2129 return;
2130 }
2131 }
2132
2133
2134 void
2135 _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
2136 GLenum internalFormat, GLsizei width,
2137 GLsizei height, GLint border, GLsizei imageSize,
2138 const GLvoid *data)
2139 {
2140 GET_CURRENT_CONTEXT(ctx);
2141 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2142
2143 switch (internalFormat) {
2144 case GL_COMPRESSED_ALPHA_ARB:
2145 case GL_COMPRESSED_LUMINANCE_ARB:
2146 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2147 case GL_COMPRESSED_INTENSITY_ARB:
2148 case GL_COMPRESSED_RGB_ARB:
2149 case GL_COMPRESSED_RGBA_ARB:
2150 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
2151 return;
2152 default:
2153 /* silence compiler warning */
2154 ;
2155 }
2156
2157 if (target == GL_TEXTURE_2D ||
2158 (ctx->Extensions.ARB_texture_cube_map &&
2159 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2160 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
2161 struct gl_texture_unit *texUnit;
2162 struct gl_texture_object *texObj;
2163 struct gl_texture_image *texImage;
2164
2165 if (texture_error_check(ctx, target, level, internalFormat,
2166 GL_NONE, GL_NONE, 1, width, height, 1, border)) {
2167 return; /* error in texture image was detected */
2168 }
2169
2170 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2171 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2172 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2173
2174 if (!texImage) {
2175 texImage = _mesa_alloc_texture_image();
2176 texObj->Image[level] = texImage;
2177 if (!texImage) {
2178 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
2179 return;
2180 }
2181 }
2182 else if (texImage->Data) {
2183 FREE(texImage->Data);
2184 texImage->Data = NULL;
2185 }
2186
2187 _mesa_init_teximage_fields(ctx, texImage, width, height, 1, border,
2188 internalFormat);
2189
2190 if (ctx->Extensions.ARB_texture_compression) {
2191 ASSERT(ctx->Driver.CompressedTexImage2D);
2192 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
2193 internalFormat, width, height,
2194 border, imageSize, data,
2195 texObj, texImage);
2196 ASSERT(texImage->CompressedSize > 0); /* sanity */
2197 }
2198
2199 /* state update */
2200 texObj->Complete = GL_FALSE;
2201 ctx->NewState |= _NEW_TEXTURE;
2202 }
2203 else if (target == GL_PROXY_TEXTURE_2D) {
2204 /* Proxy texture: check for errors and update proxy state */
2205 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2206 GL_NONE, GL_NONE, 2, width, height, 1, border);
2207 if (!error) {
2208 struct gl_texture_unit *texUnit;
2209 struct gl_texture_image *texImage;
2210 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2211 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2212 _mesa_init_teximage_fields(ctx, texImage, width, height, 1,
2213 border, internalFormat);
2214 ASSERT(ctx->Driver.TestProxyTexImage);
2215 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2216 internalFormat, GL_NONE, GL_NONE,
2217 width, height, 1, border);
2218 }
2219 if (error) {
2220 /* if error, clear all proxy texture image parameters */
2221 const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ?
2222 ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels;
2223 if (level >= 0 && level < maxLevels) {
2224 clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
2225 }
2226 }
2227 }
2228 else {
2229 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)");
2230 return;
2231 }
2232 }
2233
2234
2235 void
2236 _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
2237 GLenum internalFormat, GLsizei width,
2238 GLsizei height, GLsizei depth, GLint border,
2239 GLsizei imageSize, const GLvoid *data)
2240 {
2241 GET_CURRENT_CONTEXT(ctx);
2242 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2243
2244 switch (internalFormat) {
2245 case GL_COMPRESSED_ALPHA_ARB:
2246 case GL_COMPRESSED_LUMINANCE_ARB:
2247 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2248 case GL_COMPRESSED_INTENSITY_ARB:
2249 case GL_COMPRESSED_RGB_ARB:
2250 case GL_COMPRESSED_RGBA_ARB:
2251 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
2252 return;
2253 default:
2254 /* silence compiler warning */
2255 ;
2256 }
2257
2258 if (target == GL_TEXTURE_3D) {
2259 struct gl_texture_unit *texUnit;
2260 struct gl_texture_object *texObj;
2261 struct gl_texture_image *texImage;
2262
2263 if (texture_error_check(ctx, target, level, internalFormat,
2264 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
2265 return; /* error in texture image was detected */
2266 }
2267
2268 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2269 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2270 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2271
2272 if (!texImage) {
2273 texImage = _mesa_alloc_texture_image();
2274 texObj->Image[level] = texImage;
2275 if (!texImage) {
2276 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
2277 return;
2278 }
2279 }
2280 else if (texImage->Data) {
2281 FREE(texImage->Data);
2282 texImage->Data = NULL;
2283 }
2284
2285 _mesa_init_teximage_fields(ctx, texImage, width, height, depth, border,
2286 internalFormat);
2287
2288 if (ctx->Extensions.ARB_texture_compression) {
2289 ASSERT(ctx->Driver.CompressedTexImage3D);
2290 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
2291 internalFormat,
2292 width, height, depth,
2293 border, imageSize, data,
2294 texObj, texImage);
2295 ASSERT(texImage->CompressedSize > 0); /* sanity */
2296 }
2297
2298 /* state update */
2299 texObj->Complete = GL_FALSE;
2300 ctx->NewState |= _NEW_TEXTURE;
2301 }
2302 else if (target == GL_PROXY_TEXTURE_3D) {
2303 /* Proxy texture: check for errors and update proxy state */
2304 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2305 GL_NONE, GL_NONE, 1, width, height, depth, border);
2306 if (!error) {
2307 struct gl_texture_unit *texUnit;
2308 struct gl_texture_image *texImage;
2309 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2310 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2311 _mesa_init_teximage_fields(ctx, texImage, width, height, depth,
2312 border, internalFormat);
2313 ASSERT(ctx->Driver.TestProxyTexImage);
2314 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2315 internalFormat, GL_NONE, GL_NONE,
2316 width, height, depth, border);
2317 }
2318 if (error) {
2319 /* if error, clear all proxy texture image parameters */
2320 if (level >= 0 && level < ctx->Const.Max3DTextureLevels) {
2321 clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
2322 }
2323 }
2324 }
2325 else {
2326 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)");
2327 return;
2328 }
2329 }
2330
2331
2332 void
2333 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
2334 GLsizei width, GLenum format,
2335 GLsizei imageSize, const GLvoid *data)
2336 {
2337 struct gl_texture_unit *texUnit;
2338 struct gl_texture_object *texObj;
2339 struct gl_texture_image *texImage;
2340 GET_CURRENT_CONTEXT(ctx);
2341 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2342
2343 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2344 width, 1, 1, format, GL_NONE)) {
2345 return; /* error was detected */
2346 }
2347
2348 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2349 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2350 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2351 assert(texImage);
2352
2353 if (width == 0 || !data)
2354 return; /* no-op, not an error */
2355
2356 if (ctx->Driver.CompressedTexSubImage1D) {
2357 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
2358 xoffset, width,
2359 format, imageSize, data,
2360 texObj, texImage);
2361 }
2362 ctx->NewState |= _NEW_TEXTURE;
2363 }
2364
2365
2366 void
2367 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
2368 GLint yoffset, GLsizei width, GLsizei height,
2369 GLenum format, GLsizei imageSize,
2370 const GLvoid *data)
2371 {
2372 struct gl_texture_unit *texUnit;
2373 struct gl_texture_object *texObj;
2374 struct gl_texture_image *texImage;
2375 GET_CURRENT_CONTEXT(ctx);
2376 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2377
2378 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2379 width, height, 1, format, GL_NONE)) {
2380 return; /* error was detected */
2381 }
2382
2383 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2384 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2385 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2386 assert(texImage);
2387
2388 if (width == 0 || height == 0 || !data)
2389 return; /* no-op, not an error */
2390
2391 if (ctx->Driver.CompressedTexSubImage2D) {
2392 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
2393 xoffset, yoffset, width, height,
2394 format, imageSize, data,
2395 texObj, texImage);
2396 }
2397 ctx->NewState |= _NEW_TEXTURE;
2398 }
2399
2400
2401 void
2402 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
2403 GLint yoffset, GLint zoffset, GLsizei width,
2404 GLsizei height, GLsizei depth, GLenum format,
2405 GLsizei imageSize, const GLvoid *data)
2406 {
2407 struct gl_texture_unit *texUnit;
2408 struct gl_texture_object *texObj;
2409 struct gl_texture_image *texImage;
2410 GET_CURRENT_CONTEXT(ctx);
2411 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2412
2413 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2414 width, height, depth, format, GL_NONE)) {
2415 return; /* error was detected */
2416 }
2417
2418 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2419 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2420 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2421 assert(texImage);
2422
2423 if (width == 0 || height == 0 || depth == 0 || !data)
2424 return; /* no-op, not an error */
2425
2426 if (ctx->Driver.CompressedTexSubImage3D) {
2427 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
2428 xoffset, yoffset, zoffset,
2429 width, height, depth,
2430 format, imageSize, data,
2431 texObj, texImage);
2432 }
2433 ctx->NewState |= _NEW_TEXTURE;
2434 }
2435
2436
2437 void
2438 _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
2439 {
2440 const struct gl_texture_unit *texUnit;
2441 const struct gl_texture_object *texObj;
2442 struct gl_texture_image *texImage;
2443 GLint maxLevels;
2444 GET_CURRENT_CONTEXT(ctx);
2445 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2446
2447 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2448 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2449 if (!texObj) {
2450 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
2451 return;
2452 }
2453
2454 if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D) {
2455 maxLevels = ctx->Const.MaxTextureLevels;
2456 }
2457 else if (target == GL_TEXTURE_3D) {
2458 maxLevels = ctx->Const.Max3DTextureLevels;
2459 }
2460 else {
2461 maxLevels = ctx->Const.MaxCubeTextureLevels;
2462 }
2463
2464 ASSERT(maxLevels > 0);
2465
2466 if (level < 0 || level >= maxLevels) {
2467 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
2468 return;
2469 }
2470
2471 if (is_proxy_target(target)) {
2472 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
2473 return;
2474 }
2475
2476 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2477 if (!texImage) {
2478 /* probably invalid mipmap level */
2479 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
2480 return;
2481 }
2482
2483 if (!texImage->IsCompressed) {
2484 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
2485 return;
2486 }
2487
2488 if (!img)
2489 return;
2490
2491 if (ctx->Extensions.ARB_texture_compression) {
2492 ASSERT(ctx->Driver.GetCompressedTexImage);
2493 (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
2494 texImage);
2495 }
2496 }