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