call _mesa_sizeof_packed_type() in _mesa_GetTexImage() (bug 547203)
[mesa.git] / src / mesa / main / teximage.c
1 /* $Id: teximage.c,v 1.108 2002/04/23 16:44:46 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 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 MESA_PBUFFER_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 #if 000 /* not used anymore */
512 /*
513 * glTexImage[123]D can accept a NULL image pointer. In this case we
514 * create a texture image with unspecified image contents per the OpenGL
515 * spec.
516 */
517 static GLubyte *
518 make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
519 {
520 const GLint components = _mesa_components_in_format(format);
521 const GLint numPixels = width * height * depth;
522 GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
523
524 #ifdef DEBUG
525 /*
526 * Let's see if anyone finds this. If glTexImage2D() is called with
527 * a NULL image pointer then load the texture image with something
528 * interesting instead of leaving it indeterminate.
529 */
530 if (data) {
531 static const char message[8][32] = {
532 " X X XXXXX XXX X ",
533 " XX XX X X X X X ",
534 " X X X X X X X ",
535 " X X XXXX XXX XXXXX ",
536 " X X X X X X ",
537 " X X X X X X X ",
538 " X X XXXXX XXX X X ",
539 " "
540 };
541
542 GLubyte *imgPtr = data;
543 GLint h, i, j, k;
544 for (h = 0; h < depth; h++) {
545 for (i = 0; i < height; i++) {
546 GLint srcRow = 7 - (i % 8);
547 for (j = 0; j < width; j++) {
548 GLint srcCol = j % 32;
549 GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
550 for (k = 0; k < components; k++) {
551 *imgPtr++ = texel;
552 }
553 }
554 }
555 }
556 }
557 #endif
558
559 return data;
560 }
561 #endif
562
563
564
565 /*
566 * Reset the fields of a gl_texture_image struct to zero.
567 * This is called when a proxy texture test fails, we set all the
568 * image members (except DriverData) to zero.
569 * It's also used in glTexImage[123]D as a safeguard to be sure all
570 * required fields get initialized properly by the Driver.TexImage[123]D
571 * functions.
572 */
573 static void
574 clear_teximage_fields(struct gl_texture_image *img)
575 {
576 ASSERT(img);
577 img->Format = 0;
578 img->IntFormat = 0;
579 img->Border = 0;
580 img->Width = 0;
581 img->Height = 0;
582 img->Depth = 0;
583 img->Width2 = 0;
584 img->Height2 = 0;
585 img->Depth2 = 0;
586 img->WidthLog2 = 0;
587 img->HeightLog2 = 0;
588 img->DepthLog2 = 0;
589 img->Data = NULL;
590 img->TexFormat = &_mesa_null_texformat;
591 img->FetchTexel = NULL;
592 img->IsCompressed = 0;
593 img->CompressedSize = 0;
594 }
595
596
597 /*
598 * Initialize basic fields of the gl_texture_image struct.
599 */
600 void
601 _mesa_init_teximage_fields(GLcontext *ctx,
602 struct gl_texture_image *img,
603 GLsizei width, GLsizei height, GLsizei depth,
604 GLint border, GLenum internalFormat)
605 {
606 ASSERT(img);
607 img->Format = _mesa_base_tex_format( ctx, internalFormat );
608 ASSERT(img->Format > 0);
609 img->IntFormat = internalFormat;
610 img->Border = border;
611 img->Width = width;
612 img->Height = height;
613 img->Depth = depth;
614 img->WidthLog2 = logbase2(width - 2 * border);
615 if (height == 1) /* 1-D texture */
616 img->HeightLog2 = 0;
617 else
618 img->HeightLog2 = logbase2(height - 2 * border);
619 if (depth == 1) /* 2-D texture */
620 img->DepthLog2 = 0;
621 else
622 img->DepthLog2 = logbase2(depth - 2 * border);
623 img->Width2 = 1 << img->WidthLog2;
624 img->Height2 = 1 << img->HeightLog2;
625 img->Depth2 = 1 << img->DepthLog2;
626 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
627 img->IsCompressed = is_compressed_format(ctx, internalFormat);
628 }
629
630
631
632 /*
633 * Test glTexImage[123]D() parameters for errors.
634 * Input:
635 * dimensions - must be 1 or 2 or 3
636 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
637 */
638 static GLboolean
639 texture_error_check( GLcontext *ctx, GLenum target,
640 GLint level, GLint internalFormat,
641 GLenum format, GLenum type,
642 GLuint dimensions,
643 GLint width, GLint height,
644 GLint depth, GLint border )
645 {
646 GLboolean isProxy;
647 GLint iformat;
648 GLint maxLevels = 0, maxTextureSize;
649
650 if (dimensions == 1) {
651 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
652 if (target != GL_TEXTURE_1D && !isProxy) {
653 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
654 return GL_TRUE;
655 }
656 maxLevels = ctx->Const.MaxTextureLevels;
657 }
658 else if (dimensions == 2) {
659 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D ||
660 target == GL_PROXY_TEXTURE_CUBE_MAP_ARB);
661 if (target != GL_TEXTURE_2D && !isProxy &&
662 !(ctx->Extensions.ARB_texture_cube_map &&
663 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
664 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
665 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
666 return GL_TRUE;
667 }
668 if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D)
669 maxLevels = ctx->Const.MaxTextureLevels;
670 else
671 maxLevels = ctx->Const.MaxCubeTextureLevels;
672 }
673 else if (dimensions == 3) {
674 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
675 if (target != GL_TEXTURE_3D && !isProxy) {
676 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
677 return GL_TRUE;
678 }
679 maxLevels = ctx->Const.Max3DTextureLevels;
680 }
681 else {
682 _mesa_problem( ctx, "bad dims in texture_error_check" );
683 return GL_TRUE;
684 }
685
686 ASSERT(maxLevels > 0);
687 maxTextureSize = 1 << (maxLevels - 1);
688
689 /* Border */
690 if (border != 0 && border != 1) {
691 if (!isProxy) {
692 char message[100];
693 sprintf(message, "glTexImage%dD(border=%d)", dimensions, border);
694 _mesa_error(ctx, GL_INVALID_VALUE, message);
695 }
696 return GL_TRUE;
697 }
698
699 /* Width */
700 if (width < 2 * border || width > 2 + maxTextureSize
701 || logbase2( width - 2 * border ) < 0) {
702 if (!isProxy) {
703 char message[100];
704 sprintf(message, "glTexImage%dD(width=%d)", dimensions, width);
705 _mesa_error(ctx, GL_INVALID_VALUE, message);
706 }
707 return GL_TRUE;
708 }
709
710 /* Height */
711 if (dimensions >= 2) {
712 if (height < 2 * border || height > 2 + maxTextureSize
713 || logbase2( height - 2 * border ) < 0) {
714 if (!isProxy) {
715 char message[100];
716 sprintf(message, "glTexImage%dD(height=%d)", dimensions, height);
717 _mesa_error(ctx, GL_INVALID_VALUE, message);
718 }
719 return GL_TRUE;
720 }
721 }
722
723 /* For cube map, width must equal height */
724 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
725 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
726 if (width != height) {
727 if (!isProxy) {
728 _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
729 }
730 return GL_TRUE;
731 }
732 }
733
734 /* Depth */
735 if (dimensions >= 3) {
736 if (depth < 2 * border || depth > 2 + maxTextureSize
737 || logbase2( depth - 2 * border ) < 0) {
738 if (!isProxy) {
739 char message[100];
740 sprintf(message, "glTexImage3D(depth=%d)", depth );
741 _mesa_error( ctx, GL_INVALID_VALUE, message );
742 }
743 return GL_TRUE;
744 }
745 }
746
747 /* Level */
748 if (level < 0 || level >= maxLevels) {
749 if (!isProxy) {
750 char message[100];
751 sprintf(message, "glTexImage%dD(level=%d)", dimensions, level);
752 _mesa_error(ctx, GL_INVALID_VALUE, message);
753 }
754 return GL_TRUE;
755 }
756
757 /* For cube map, width must equal height */
758 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
759 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
760 if (width != height) {
761 _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
762 return GL_TRUE;
763 }
764 }
765
766 iformat = _mesa_base_tex_format( ctx, internalFormat );
767 if (iformat < 0) {
768 if (!isProxy) {
769 char message[100];
770 sprintf(message, "glTexImage%dD(internalFormat=0x%x)", dimensions,
771 internalFormat);
772 _mesa_error(ctx, GL_INVALID_VALUE, message);
773 }
774 return GL_TRUE;
775 }
776
777 ASSERT(iformat > 0);
778
779 if (!is_compressed_format( ctx, internalFormat ) &&
780 !_mesa_is_legal_format_and_type( format, type )) {
781 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
782 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
783 */
784 if (!isProxy) {
785 char message[100];
786 sprintf(message, "glTexImage%dD(format or type)", dimensions);
787 _mesa_error(ctx, GL_INVALID_OPERATION, message);
788 }
789 return GL_TRUE;
790 }
791
792 /* if we get here, the parameters are OK */
793 return GL_FALSE;
794 }
795
796
797
798 /*
799 * Test glTexSubImage[123]D() parameters for errors.
800 * Input:
801 * dimensions - must be 1 or 2 or 3
802 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
803 */
804 static GLboolean
805 subtexture_error_check( GLcontext *ctx, GLuint dimensions,
806 GLenum target, GLint level,
807 GLint xoffset, GLint yoffset, GLint zoffset,
808 GLint width, GLint height, GLint depth,
809 GLenum format, GLenum type )
810 {
811 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
812 struct gl_texture_image *destTex;
813 GLint maxLevels = 0;
814 GLboolean compressed;
815
816 if (dimensions == 1) {
817 if (target != GL_TEXTURE_1D) {
818 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
819 return GL_TRUE;
820 }
821 maxLevels = ctx->Const.MaxTextureLevels;
822 }
823 else if (dimensions == 2) {
824 if (ctx->Extensions.ARB_texture_cube_map) {
825 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
826 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
827 target != GL_TEXTURE_2D) {
828 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
829 return GL_TRUE;
830 }
831 }
832 else if (target != GL_TEXTURE_2D) {
833 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
834 return GL_TRUE;
835 }
836 if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
837 maxLevels = ctx->Const.MaxTextureLevels;
838 else
839 maxLevels = ctx->Const.MaxCubeTextureLevels;
840 }
841 else if (dimensions == 3) {
842 if (target != GL_TEXTURE_3D) {
843 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
844 return GL_TRUE;
845 }
846 maxLevels = ctx->Const.Max3DTextureLevels;
847 }
848 else {
849 _mesa_problem( ctx, "bad dims in texture_error_check" );
850 return GL_TRUE;
851 }
852
853 ASSERT(maxLevels > 0);
854
855 if (level < 0 || level >= maxLevels) {
856 char message[100];
857 sprintf(message, "glTexSubImage2D(level=%d)", level);
858 _mesa_error(ctx, GL_INVALID_ENUM, message);
859 return GL_TRUE;
860 }
861
862 if (width < 0) {
863 char message[100];
864 sprintf(message, "glTexSubImage%dD(width=%d)", dimensions, width);
865 _mesa_error(ctx, GL_INVALID_VALUE, message);
866 return GL_TRUE;
867 }
868 if (height < 0 && dimensions > 1) {
869 char message[100];
870 sprintf(message, "glTexSubImage%dD(height=%d)", dimensions, height);
871 _mesa_error(ctx, GL_INVALID_VALUE, message);
872 return GL_TRUE;
873 }
874 if (depth < 0 && dimensions > 2) {
875 char message[100];
876 sprintf(message, "glTexSubImage%dD(depth=%d)", dimensions, depth);
877 _mesa_error(ctx, GL_INVALID_VALUE, message);
878 return GL_TRUE;
879 }
880
881 destTex = _mesa_select_tex_image(ctx, texUnit, target, level);
882
883 if (!destTex) {
884 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
885 return GL_TRUE;
886 }
887
888 if (xoffset < -((GLint)destTex->Border)) {
889 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
890 return GL_TRUE;
891 }
892 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
893 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
894 return GL_TRUE;
895 }
896 if (dimensions > 1) {
897 if (yoffset < -((GLint)destTex->Border)) {
898 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
899 return GL_TRUE;
900 }
901 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
902 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
903 return GL_TRUE;
904 }
905 }
906 if (dimensions > 2) {
907 if (zoffset < -((GLint)destTex->Border)) {
908 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
909 return GL_TRUE;
910 }
911 if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) {
912 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
913 return GL_TRUE;
914 }
915 }
916
917 compressed = is_compressed_format(ctx, destTex->IntFormat);
918
919 if (!compressed && !_mesa_is_legal_format_and_type(format, type)) {
920 char message[100];
921 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
922 _mesa_error(ctx, GL_INVALID_ENUM, message);
923 return GL_TRUE;
924 }
925
926 if (compressed) {
927 if (xoffset != -((GLint)destTex->Border)) {
928 _mesa_error(ctx, GL_INVALID_OPERATION,
929 "glTexSubImage1/2/3D(xoffset != -border");
930 return GL_TRUE;
931 }
932 if (dimensions > 1 && yoffset != -((GLint)destTex->Border)) {
933 _mesa_error(ctx, GL_INVALID_OPERATION,
934 "glTexSubImage2/3D(yoffset != -border");
935 return GL_TRUE;
936 }
937 if (dimensions > 2 && zoffset != -((GLint)destTex->Border)) {
938 _mesa_error(ctx, GL_INVALID_OPERATION,
939 "glTexSubImage3D(zoffset != -border");
940 return GL_TRUE;
941 }
942 }
943
944 return GL_FALSE;
945 }
946
947
948 /*
949 * Test glCopyTexImage[12]D() parameters for errors.
950 * Input: dimensions - must be 1 or 2 or 3
951 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
952 */
953 static GLboolean
954 copytexture_error_check( GLcontext *ctx, GLuint dimensions,
955 GLenum target, GLint level, GLint internalFormat,
956 GLint width, GLint height, GLint border )
957 {
958 GLint iformat;
959 GLint maxLevels = 0, maxTextureSize;
960
961 if (dimensions == 1) {
962 if (target != GL_TEXTURE_1D) {
963 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
964 return GL_TRUE;
965 }
966 maxLevels = ctx->Const.MaxTextureLevels;
967 }
968 else if (dimensions == 2) {
969 if (ctx->Extensions.ARB_texture_cube_map) {
970 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
971 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
972 target != GL_TEXTURE_2D) {
973 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
974 return GL_TRUE;
975 }
976 }
977 else if (target != GL_TEXTURE_2D) {
978 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
979 return GL_TRUE;
980 }
981 if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
982 maxLevels = ctx->Const.MaxTextureLevels;
983 else
984 maxLevels = ctx->Const.MaxCubeTextureLevels;
985 }
986
987 ASSERT(maxLevels > 0);
988 maxTextureSize = 1 << (maxLevels - 1);
989
990 /* Border */
991 if (border != 0 && border != 1) {
992 char message[100];
993 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
994 _mesa_error(ctx, GL_INVALID_VALUE, message);
995 return GL_TRUE;
996 }
997
998 /* Width */
999 if (width < 2 * border || width > 2 + maxTextureSize
1000 || logbase2( width - 2 * border ) < 0) {
1001 char message[100];
1002 sprintf(message, "glCopyTexImage%dD(width=%d)", dimensions, width);
1003 _mesa_error(ctx, GL_INVALID_VALUE, message);
1004 return GL_TRUE;
1005 }
1006
1007 /* Height */
1008 if (dimensions >= 2) {
1009 if (height < 2 * border || height > 2 + maxTextureSize
1010 || logbase2( height - 2 * border ) < 0) {
1011 char message[100];
1012 sprintf(message, "glCopyTexImage%dD(height=%d)", dimensions, height);
1013 _mesa_error(ctx, GL_INVALID_VALUE, message);
1014 return GL_TRUE;
1015 }
1016 }
1017
1018 /* For cube map, width must equal height */
1019 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1020 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1021 if (width != height) {
1022 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
1023 return GL_TRUE;
1024 }
1025 }
1026
1027 /* Level */
1028 if (level < 0 || level >= maxLevels) {
1029 char message[100];
1030 sprintf(message, "glCopyTexImage%dD(level=%d)", dimensions, level);
1031 _mesa_error(ctx, GL_INVALID_VALUE, message);
1032 return GL_TRUE;
1033 }
1034
1035 iformat = _mesa_base_tex_format(ctx, internalFormat);
1036 if (iformat < 0) {
1037 char message[100];
1038 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1039 _mesa_error(ctx, GL_INVALID_VALUE, message);
1040 return GL_TRUE;
1041 }
1042
1043 /* if we get here, the parameters are OK */
1044 return GL_FALSE;
1045 }
1046
1047
1048 static GLboolean
1049 copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
1050 GLenum target, GLint level,
1051 GLint xoffset, GLint yoffset, GLint zoffset,
1052 GLsizei width, GLsizei height )
1053 {
1054 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1055 struct gl_texture_image *teximage;
1056 GLint maxLevels = 0;
1057 GLboolean compressed;
1058
1059 if (dimensions == 1) {
1060 if (target != GL_TEXTURE_1D) {
1061 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1062 return GL_TRUE;
1063 }
1064 maxLevels = ctx->Const.MaxTextureLevels;
1065 }
1066 else if (dimensions == 2) {
1067 if (ctx->Extensions.ARB_texture_cube_map) {
1068 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1069 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1070 target != GL_TEXTURE_2D) {
1071 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1072 return GL_TRUE;
1073 }
1074 }
1075 else if (target != GL_TEXTURE_2D) {
1076 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1077 return GL_TRUE;
1078 }
1079 if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D)
1080 maxLevels = ctx->Const.MaxTextureLevels;
1081 else
1082 maxLevels = ctx->Const.MaxCubeTextureLevels;
1083 }
1084 else if (dimensions == 3) {
1085 if (target != GL_TEXTURE_3D) {
1086 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1087 return GL_TRUE;
1088 }
1089 maxLevels = ctx->Const.Max3DTextureLevels;
1090 }
1091
1092 ASSERT(maxLevels > 0);
1093
1094 if (level < 0 || level >= maxLevels) {
1095 char message[100];
1096 sprintf(message, "glCopyTexSubImage%dD(level=%d)", dimensions, level);
1097 _mesa_error(ctx, GL_INVALID_VALUE, message);
1098 return GL_TRUE;
1099 }
1100
1101 if (width < 0) {
1102 char message[100];
1103 sprintf(message, "glCopyTexSubImage%dD(width=%d)", dimensions, width);
1104 _mesa_error(ctx, GL_INVALID_VALUE, message);
1105 return GL_TRUE;
1106 }
1107 if (dimensions > 1 && height < 0) {
1108 char message[100];
1109 sprintf(message, "glCopyTexSubImage%dD(height=%d)", dimensions, height);
1110 _mesa_error(ctx, GL_INVALID_VALUE, message);
1111 return GL_TRUE;
1112 }
1113
1114 teximage = _mesa_select_tex_image(ctx, texUnit, target, level);
1115 if (!teximage) {
1116 char message[100];
1117 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1118 _mesa_error(ctx, GL_INVALID_OPERATION, message);
1119 return GL_TRUE;
1120 }
1121
1122 if (xoffset < -((GLint)teximage->Border)) {
1123 char message[100];
1124 sprintf(message, "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
1125 _mesa_error(ctx, GL_INVALID_VALUE, message);
1126 return GL_TRUE;
1127 }
1128 if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
1129 char message[100];
1130 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1131 _mesa_error(ctx, GL_INVALID_VALUE, message);
1132 return GL_TRUE;
1133 }
1134 if (dimensions > 1) {
1135 if (yoffset < -((GLint)teximage->Border)) {
1136 char message[100];
1137 sprintf(message, "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
1138 _mesa_error(ctx, GL_INVALID_VALUE, message);
1139 return GL_TRUE;
1140 }
1141 /* NOTE: we're adding the border here, not subtracting! */
1142 if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
1143 char message[100];
1144 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1145 _mesa_error(ctx, GL_INVALID_VALUE, message);
1146 return GL_TRUE;
1147 }
1148 }
1149
1150 if (dimensions > 2) {
1151 if (zoffset < -((GLint)teximage->Border)) {
1152 char message[100];
1153 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1154 _mesa_error(ctx, GL_INVALID_VALUE, message);
1155 return GL_TRUE;
1156 }
1157 if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
1158 char message[100];
1159 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1160 _mesa_error(ctx, GL_INVALID_VALUE, message);
1161 return GL_TRUE;
1162 }
1163 }
1164
1165 compressed = is_compressed_format(ctx, teximage->IntFormat);
1166 if (compressed) {
1167 if (xoffset != -((GLint)teximage->Border)) {
1168 _mesa_error(ctx, GL_INVALID_OPERATION,
1169 "glCopyTexSubImage1/2/3D(xoffset != -border");
1170 return GL_TRUE;
1171 }
1172 if (dimensions > 1 && yoffset != -((GLint)teximage->Border)) {
1173 _mesa_error(ctx, GL_INVALID_OPERATION,
1174 "glCopyTexSubImage2/3D(yoffset != -border");
1175 return GL_TRUE;
1176 }
1177 if (dimensions > 2 && zoffset != -((GLint)teximage->Border)) {
1178 _mesa_error(ctx, GL_INVALID_OPERATION,
1179 "glCopyTexSubImage3D(zoffset != -border");
1180 return GL_TRUE;
1181 }
1182 }
1183
1184 /* if we get here, the parameters are OK */
1185 return GL_FALSE;
1186 }
1187
1188
1189
1190 void
1191 _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1192 GLenum type, GLvoid *pixels )
1193 {
1194 const struct gl_texture_unit *texUnit;
1195 const struct gl_texture_object *texObj;
1196 struct gl_texture_image *texImage;
1197 GLint maxLevels = 0;
1198 GET_CURRENT_CONTEXT(ctx);
1199 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1200
1201 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
1202 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1203 if (!texObj || is_proxy_target(target)) {
1204 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
1205 return;
1206 }
1207
1208 if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D) {
1209 maxLevels = ctx->Const.MaxTextureLevels;
1210 }
1211 else if (target == GL_TEXTURE_3D) {
1212 maxLevels = ctx->Const.Max3DTextureLevels;
1213 }
1214 else {
1215 maxLevels = ctx->Const.MaxCubeTextureLevels;
1216 }
1217
1218 ASSERT(maxLevels > 0);
1219
1220 if (level < 0 || level >= maxLevels) {
1221 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1222 return;
1223 }
1224
1225 if (_mesa_sizeof_packed_type(type) <= 0) {
1226 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1227 return;
1228 }
1229
1230 if (_mesa_components_in_format(format) <= 0 ||
1231 format == GL_STENCIL_INDEX) {
1232 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1233 return;
1234 }
1235
1236 if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) {
1237 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
1238 }
1239
1240 if (!ctx->Extensions.SGIX_depth_texture && format == GL_DEPTH_COMPONENT) {
1241 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
1242 }
1243
1244 /* XXX what if format/type doesn't match texture format/type? */
1245
1246 if (!pixels)
1247 return;
1248
1249 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1250 if (!texImage) {
1251 /* invalid mipmap level, not an error */
1252 return;
1253 }
1254
1255 if (!texImage->Data) {
1256 /* no image data, not an error */
1257 return;
1258 }
1259
1260 {
1261 const GLint width = texImage->Width;
1262 const GLint height = texImage->Height;
1263 const GLint depth = texImage->Depth;
1264 GLint img, row;
1265 for (img = 0; img < depth; img++) {
1266 for (row = 0; row < height; row++) {
1267 /* compute destination address in client memory */
1268 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
1269 width, height, format, type,
1270 img, row, 0);
1271 assert(dest);
1272
1273 if (format == GL_COLOR_INDEX) {
1274 GLuint indexRow[MAX_WIDTH];
1275 GLint col;
1276 for (col = 0; col < width; col++) {
1277 (*texImage->FetchTexel)(texImage, col, row, img,
1278 (GLvoid *) &indexRow[col]);
1279 }
1280 _mesa_pack_index_span(ctx, width, type, dest,
1281 indexRow, &ctx->Pack,
1282 0 /* no image transfer */);
1283 }
1284 else if (format == GL_DEPTH_COMPONENT) {
1285 GLfloat depthRow[MAX_WIDTH];
1286 GLint col;
1287 for (col = 0; col < width; col++) {
1288 (*texImage->FetchTexel)(texImage, col, row, img,
1289 (GLvoid *) &depthRow[col]);
1290 }
1291 _mesa_pack_depth_span(ctx, width, dest, type,
1292 depthRow, &ctx->Pack);
1293 }
1294 else {
1295 /* general case: convert row to RGBA format */
1296 GLchan rgba[MAX_WIDTH][4];
1297 GLint col;
1298 for (col = 0; col < width; col++) {
1299 (*texImage->FetchTexel)(texImage, col, row, img,
1300 (GLvoid *) rgba[col]);
1301 }
1302 _mesa_pack_rgba_span(ctx, width, (const GLchan (*)[4])rgba,
1303 format, type, dest, &ctx->Pack,
1304 0 /* no image transfer */);
1305 } /* format */
1306 } /* row */
1307 } /* img */
1308 }
1309 }
1310
1311
1312
1313 /*
1314 * Called from the API. Note that width includes the border.
1315 */
1316 void
1317 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1318 GLsizei width, GLint border, GLenum format,
1319 GLenum type, const GLvoid *pixels )
1320 {
1321 GLsizei postConvWidth = width;
1322 GET_CURRENT_CONTEXT(ctx);
1323 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1324
1325 if (is_color_format(internalFormat)) {
1326 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1327 }
1328
1329 if (target == GL_TEXTURE_1D) {
1330 struct gl_texture_unit *texUnit;
1331 struct gl_texture_object *texObj;
1332 struct gl_texture_image *texImage;
1333
1334 if (texture_error_check(ctx, target, level, internalFormat,
1335 format, type, 1, postConvWidth, 1, 1, border)) {
1336 return; /* error was recorded */
1337 }
1338
1339 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1340 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1341 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1342
1343 if (!texImage) {
1344 texImage = _mesa_alloc_texture_image();
1345 texObj->Image[level] = texImage;
1346 if (!texImage) {
1347 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1348 return;
1349 }
1350 }
1351 else if (texImage->Data) {
1352 /* free the old texture data */
1353 MESA_PBUFFER_FREE(texImage->Data);
1354 texImage->Data = NULL;
1355 }
1356 clear_teximage_fields(texImage); /* not really needed, but helpful */
1357 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
1358 border, internalFormat);
1359
1360 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1361 _mesa_update_state(ctx);
1362
1363 ASSERT(ctx->Driver.TexImage1D);
1364
1365 #if 0 /* don't make default teximage anymore */
1366 if (pixels) {
1367 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
1368 width, border, format, type, pixels,
1369 &ctx->Unpack, texObj, texImage);
1370 }
1371 else {
1372 GLubyte *dummy = make_null_texture(width, 1, 1, format);
1373 if (dummy) {
1374 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
1375 width, border,
1376 format, GL_UNSIGNED_BYTE, dummy,
1377 &_mesa_native_packing, texObj, texImage);
1378 FREE(dummy);
1379 }
1380 }
1381 #else
1382 /* <pixels> may be null! */
1383 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
1384 width, border, format, type, pixels,
1385 &ctx->Unpack, texObj, texImage);
1386 #endif
1387
1388 ASSERT(texImage->TexFormat);
1389 if (!texImage->FetchTexel) {
1390 /* If driver didn't explicitly set this, use the default */
1391 texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
1392 }
1393 ASSERT(texImage->FetchTexel);
1394
1395 if (texImage->IsCompressed) {
1396 ASSERT(texImage->CompressedSize > 0);
1397 }
1398
1399 /* state update */
1400 texObj->Complete = GL_FALSE;
1401 ctx->NewState |= _NEW_TEXTURE;
1402 }
1403 else if (target == GL_PROXY_TEXTURE_1D) {
1404 /* Proxy texture: check for errors and update proxy state */
1405 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1406 format, type, 1,
1407 postConvWidth, 1, 1, border);
1408 if (!error) {
1409 struct gl_texture_unit *texUnit;
1410 struct gl_texture_image *texImage;
1411 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1412 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1413 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
1414 border, internalFormat);
1415 ASSERT(ctx->Driver.TestProxyTexImage);
1416 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1417 internalFormat, format, type,
1418 postConvWidth, 1, 1, border);
1419 }
1420 if (error) {
1421 /* if error, clear all proxy texture image parameters */
1422 if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
1423 clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]);
1424 }
1425 }
1426 }
1427 else {
1428 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1429 return;
1430 }
1431 }
1432
1433
1434 void
1435 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1436 GLsizei width, GLsizei height, GLint border,
1437 GLenum format, GLenum type,
1438 const GLvoid *pixels )
1439 {
1440 GLsizei postConvWidth = width, postConvHeight = height;
1441 GET_CURRENT_CONTEXT(ctx);
1442 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1443
1444 if (is_color_format(internalFormat)) {
1445 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1446 &postConvHeight);
1447 }
1448
1449 if (target == GL_TEXTURE_2D ||
1450 (ctx->Extensions.ARB_texture_cube_map &&
1451 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1452 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1453 /* non-proxy target */
1454 struct gl_texture_unit *texUnit;
1455 struct gl_texture_object *texObj;
1456 struct gl_texture_image *texImage;
1457
1458 if (texture_error_check(ctx, target, level, internalFormat,
1459 format, type, 2, postConvWidth, postConvHeight,
1460 1, border)) {
1461 return; /* error was recorded */
1462 }
1463
1464 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1465 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1466 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1467
1468 if (!texImage) {
1469 texImage = _mesa_alloc_texture_image();
1470 _mesa_set_tex_image(texObj, target, level, texImage);
1471 if (!texImage) {
1472 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1473 return;
1474 }
1475 }
1476 else if (texImage->Data) {
1477 /* free the old texture data */
1478 MESA_PBUFFER_FREE(texImage->Data);
1479 texImage->Data = NULL;
1480 }
1481 clear_teximage_fields(texImage); /* not really needed, but helpful */
1482 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight,
1483 1, border, internalFormat);
1484
1485 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1486 _mesa_update_state(ctx);
1487
1488 ASSERT(ctx->Driver.TexImage2D);
1489
1490 #if 0 /* don't make default teximage anymore */
1491 if (pixels) {
1492 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
1493 width, height, border, format, type, pixels,
1494 &ctx->Unpack, texObj, texImage);
1495 }
1496 else {
1497 GLubyte *dummy = make_null_texture(width, height, 1, format);
1498 if (dummy) {
1499 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
1500 width, height, border,
1501 format, GL_UNSIGNED_BYTE, dummy,
1502 &_mesa_native_packing, texObj, texImage);
1503 FREE(dummy);
1504 }
1505 }
1506 #else
1507 /* <pixels> may be null! */
1508 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
1509 width, height, border, format, type, pixels,
1510 &ctx->Unpack, texObj, texImage);
1511 #endif
1512
1513 ASSERT(texImage->TexFormat);
1514 if (!texImage->FetchTexel) {
1515 /* If driver didn't explicitly set this, use the default */
1516 texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
1517 }
1518 ASSERT(texImage->FetchTexel);
1519
1520 if (texImage->IsCompressed) {
1521 ASSERT(texImage->CompressedSize > 0);
1522 }
1523
1524 /* state update */
1525 texObj->Complete = GL_FALSE;
1526 ctx->NewState |= _NEW_TEXTURE;
1527 }
1528 else if (target == GL_PROXY_TEXTURE_2D ||
1529 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
1530 ctx->Extensions.ARB_texture_cube_map)) {
1531 /* Proxy texture: check for errors and update proxy state */
1532 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1533 format, type, 2,
1534 postConvWidth, postConvHeight, 1, border);
1535 if (!error) {
1536 struct gl_texture_unit *texUnit;
1537 struct gl_texture_image *texImage;
1538 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1539 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1540 _mesa_init_teximage_fields(ctx, texImage, postConvWidth,
1541 postConvHeight, 1, border, internalFormat);
1542 ASSERT(ctx->Driver.TestProxyTexImage);
1543 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1544 internalFormat, format, type,
1545 postConvWidth, postConvHeight, 1, border);
1546 }
1547 if (error) {
1548 /* if error, clear all proxy texture image parameters */
1549 const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ?
1550 ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels;
1551 if (level >= 0 && level < maxLevels) {
1552 clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
1553 }
1554 }
1555 }
1556 else {
1557 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1558 return;
1559 }
1560 }
1561
1562
1563 /*
1564 * Called by the API or display list executor.
1565 * Note that width and height include the border.
1566 */
1567 void
1568 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
1569 GLsizei width, GLsizei height, GLsizei depth,
1570 GLint border, GLenum format, GLenum type,
1571 const GLvoid *pixels )
1572 {
1573 GET_CURRENT_CONTEXT(ctx);
1574 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1575
1576 if (target == GL_TEXTURE_3D) {
1577 struct gl_texture_unit *texUnit;
1578 struct gl_texture_object *texObj;
1579 struct gl_texture_image *texImage;
1580
1581 if (texture_error_check(ctx, target, level, (GLint) internalFormat,
1582 format, type, 3, width, height, depth, border)) {
1583 return; /* error was recorded */
1584 }
1585
1586 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1587 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1588 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1589
1590 if (!texImage) {
1591 texImage = _mesa_alloc_texture_image();
1592 texObj->Image[level] = texImage;
1593 if (!texImage) {
1594 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1595 return;
1596 }
1597 }
1598 else if (texImage->Data) {
1599 MESA_PBUFFER_FREE(texImage->Data);
1600 texImage->Data = NULL;
1601 }
1602 clear_teximage_fields(texImage); /* not really needed, but helpful */
1603 _mesa_init_teximage_fields(ctx, texImage, width, height, depth, border,
1604 internalFormat);
1605
1606 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1607 _mesa_update_state(ctx);
1608
1609 ASSERT(ctx->Driver.TexImage3D);
1610
1611 #if 0 /* don't make default teximage anymore */
1612 if (pixels) {
1613 (*ctx->Driver.TexImage3D)(ctx, target, level, (GLint) internalFormat,
1614 width, height, depth, border,
1615 format, type, pixels,
1616 &ctx->Unpack, texObj, texImage);
1617 }
1618 else {
1619 GLubyte *dummy = make_null_texture(width, height, depth, format);
1620 if (dummy) {
1621 (*ctx->Driver.TexImage3D)(ctx, target, level,
1622 (GLint) internalFormat,
1623 width, height, depth, border,
1624 format, GL_UNSIGNED_BYTE, dummy,
1625 &_mesa_native_packing, texObj, texImage);
1626 FREE(dummy);
1627 }
1628 }
1629 #else
1630 /* <pixels> may be null! */
1631 (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat,
1632 width, height, depth, border, format, type,
1633 pixels, &ctx->Unpack, texObj, texImage);
1634 #endif
1635
1636 ASSERT(texImage->TexFormat);
1637 if (!texImage->FetchTexel) {
1638 /* If driver didn't explicitly set this, use the default */
1639 texImage->FetchTexel = texImage->TexFormat->FetchTexel3D;
1640 }
1641 ASSERT(texImage->FetchTexel);
1642
1643 if (texImage->IsCompressed) {
1644 ASSERT(texImage->CompressedSize > 0);
1645 }
1646
1647 /* state update */
1648 texObj->Complete = GL_FALSE;
1649 ctx->NewState |= _NEW_TEXTURE;
1650 }
1651 else if (target == GL_PROXY_TEXTURE_3D) {
1652 /* Proxy texture: check for errors and update proxy state */
1653 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1654 format, type, 3, width, height, depth, border);
1655 if (!error) {
1656 struct gl_texture_unit *texUnit;
1657 struct gl_texture_image *texImage;
1658 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1659 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1660 _mesa_init_teximage_fields(ctx, texImage, width, height, 1,
1661 border, internalFormat);
1662 ASSERT(ctx->Driver.TestProxyTexImage);
1663 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1664 internalFormat, format, type,
1665 width, height, depth, border);
1666 }
1667 if (error) {
1668 /* if error, clear all proxy texture image parameters */
1669 if (level >= 0 && level < ctx->Const.Max3DTextureLevels) {
1670 clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
1671 }
1672 }
1673 }
1674 else {
1675 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1676 return;
1677 }
1678 }
1679
1680
1681 void
1682 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
1683 GLsizei width, GLsizei height, GLsizei depth,
1684 GLint border, GLenum format, GLenum type,
1685 const GLvoid *pixels )
1686 {
1687 _mesa_TexImage3D(target, level, internalFormat, width, height,
1688 depth, border, format, type, pixels);
1689 }
1690
1691
1692
1693 void
1694 _mesa_TexSubImage1D( GLenum target, GLint level,
1695 GLint xoffset, GLsizei width,
1696 GLenum format, GLenum type,
1697 const GLvoid *pixels )
1698 {
1699 GLsizei postConvWidth = width;
1700 struct gl_texture_unit *texUnit;
1701 struct gl_texture_object *texObj;
1702 struct gl_texture_image *texImage;
1703 GET_CURRENT_CONTEXT(ctx);
1704 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1705
1706 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1707 _mesa_update_state(ctx);
1708
1709 /* XXX should test internal format */
1710 if (is_color_format(format)) {
1711 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1712 }
1713
1714 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1715 postConvWidth, 1, 1, format, type)) {
1716 return; /* error was detected */
1717 }
1718
1719 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1720 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1721 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1722 assert(texImage);
1723
1724 if (width == 0 || !pixels)
1725 return; /* no-op, not an error */
1726
1727 /* If we have a border, xoffset=-1 is legal. Bias by border width */
1728 xoffset += texImage->Border;
1729
1730 ASSERT(ctx->Driver.TexSubImage1D);
1731 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
1732 format, type, pixels, &ctx->Unpack,
1733 texObj, texImage);
1734 ctx->NewState |= _NEW_TEXTURE;
1735 }
1736
1737
1738 void
1739 _mesa_TexSubImage2D( GLenum target, GLint level,
1740 GLint xoffset, GLint yoffset,
1741 GLsizei width, GLsizei height,
1742 GLenum format, GLenum type,
1743 const GLvoid *pixels )
1744 {
1745 GLsizei postConvWidth = width, postConvHeight = height;
1746 struct gl_texture_unit *texUnit;
1747 struct gl_texture_object *texObj;
1748 struct gl_texture_image *texImage;
1749 GET_CURRENT_CONTEXT(ctx);
1750 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1751
1752 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1753 _mesa_update_state(ctx);
1754
1755 /* XXX should test internal format */
1756 if (is_color_format(format)) {
1757 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1758 &postConvHeight);
1759 }
1760
1761 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1762 postConvWidth, postConvHeight, 1, format, type)) {
1763 return; /* error was detected */
1764 }
1765
1766 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1767 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1768 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1769 assert(texImage);
1770
1771 if (width == 0 || height == 0 || !pixels)
1772 return; /* no-op, not an error */
1773
1774 /* If we have a border, xoffset=-1 is legal. Bias by border width */
1775 xoffset += texImage->Border;
1776 yoffset += texImage->Border;
1777
1778 ASSERT(ctx->Driver.TexSubImage2D);
1779 (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
1780 width, height, format, type, pixels,
1781 &ctx->Unpack, texObj, texImage);
1782 ctx->NewState |= _NEW_TEXTURE;
1783 }
1784
1785
1786
1787 void
1788 _mesa_TexSubImage3D( GLenum target, GLint level,
1789 GLint xoffset, GLint yoffset, GLint zoffset,
1790 GLsizei width, GLsizei height, GLsizei depth,
1791 GLenum format, GLenum type,
1792 const GLvoid *pixels )
1793 {
1794 struct gl_texture_unit *texUnit;
1795 struct gl_texture_object *texObj;
1796 struct gl_texture_image *texImage;
1797 GET_CURRENT_CONTEXT(ctx);
1798 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1799
1800 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1801 _mesa_update_state(ctx);
1802
1803 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
1804 width, height, depth, format, type)) {
1805 return; /* error was detected */
1806 }
1807
1808 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1809 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1810 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1811 assert(texImage);
1812
1813 if (width == 0 || height == 0 || height == 0 || !pixels)
1814 return; /* no-op, not an error */
1815
1816 /* If we have a border, xoffset=-1 is legal. Bias by border width */
1817 xoffset += texImage->Border;
1818 yoffset += texImage->Border;
1819 zoffset += texImage->Border;
1820
1821 ASSERT(ctx->Driver.TexSubImage3D);
1822 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
1823 xoffset, yoffset, zoffset,
1824 width, height, depth,
1825 format, type, pixels,
1826 &ctx->Unpack, texObj, texImage );
1827 ctx->NewState |= _NEW_TEXTURE;
1828 }
1829
1830
1831
1832 void
1833 _mesa_CopyTexImage1D( GLenum target, GLint level,
1834 GLenum internalFormat,
1835 GLint x, GLint y,
1836 GLsizei width, GLint border )
1837 {
1838 struct gl_texture_unit *texUnit;
1839 struct gl_texture_object *texObj;
1840 struct gl_texture_image *texImage;
1841 GLsizei postConvWidth = width;
1842 GET_CURRENT_CONTEXT(ctx);
1843 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1844
1845 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1846 _mesa_update_state(ctx);
1847
1848 if (is_color_format(internalFormat)) {
1849 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1850 }
1851
1852 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
1853 postConvWidth, 1, border))
1854 return;
1855
1856 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1857 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1858 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1859 if (!texImage) {
1860 texImage = _mesa_alloc_texture_image();
1861 _mesa_set_tex_image(texObj, target, level, texImage);
1862 if (!texImage) {
1863 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
1864 return;
1865 }
1866 }
1867 else if (texImage->Data) {
1868 /* free the old texture data */
1869 MESA_PBUFFER_FREE(texImage->Data);
1870 texImage->Data = NULL;
1871 }
1872
1873 clear_teximage_fields(texImage); /* not really needed, but helpful */
1874 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
1875 border, internalFormat);
1876
1877
1878 ASSERT(ctx->Driver.CopyTexImage1D);
1879 (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
1880 x, y, width, border);
1881
1882 ASSERT(texImage->TexFormat);
1883 if (!texImage->FetchTexel) {
1884 /* If driver didn't explicitly set this, use the default */
1885 texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
1886 }
1887 ASSERT(texImage->FetchTexel);
1888
1889 /* state update */
1890 texObj->Complete = GL_FALSE;
1891 ctx->NewState |= _NEW_TEXTURE;
1892 }
1893
1894
1895
1896 void
1897 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
1898 GLint x, GLint y, GLsizei width, GLsizei height,
1899 GLint border )
1900 {
1901 struct gl_texture_unit *texUnit;
1902 struct gl_texture_object *texObj;
1903 struct gl_texture_image *texImage;
1904 GLsizei postConvWidth = width, postConvHeight = height;
1905 GET_CURRENT_CONTEXT(ctx);
1906 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1907
1908 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1909 _mesa_update_state(ctx);
1910
1911 if (is_color_format(internalFormat)) {
1912 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1913 &postConvHeight);
1914 }
1915
1916 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
1917 postConvWidth, postConvHeight, border))
1918 return;
1919
1920 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1921 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1922 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1923 if (!texImage) {
1924 texImage = _mesa_alloc_texture_image();
1925 _mesa_set_tex_image(texObj, target, level, texImage);
1926 if (!texImage) {
1927 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
1928 return;
1929 }
1930 }
1931 else if (texImage->Data) {
1932 /* free the old texture data */
1933 MESA_PBUFFER_FREE(texImage->Data);
1934 texImage->Data = NULL;
1935 }
1936
1937 clear_teximage_fields(texImage); /* not really needed, but helpful */
1938 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight, 1,
1939 border, internalFormat);
1940
1941 ASSERT(ctx->Driver.CopyTexImage2D);
1942 (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
1943 x, y, width, height, border);
1944
1945 ASSERT(texImage->TexFormat);
1946 if (!texImage->FetchTexel) {
1947 /* If driver didn't explicitly set this, use the default */
1948 texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
1949 }
1950 ASSERT(texImage->FetchTexel);
1951
1952 /* state update */
1953 texObj->Complete = GL_FALSE;
1954 ctx->NewState |= _NEW_TEXTURE;
1955 }
1956
1957
1958
1959 void
1960 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
1961 GLint xoffset, GLint x, GLint y, GLsizei width )
1962 {
1963 struct gl_texture_unit *texUnit;
1964 struct gl_texture_object *texObj;
1965 struct gl_texture_image *texImage;
1966 GLsizei postConvWidth = width;
1967 GET_CURRENT_CONTEXT(ctx);
1968 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1969
1970 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
1971 _mesa_update_state(ctx);
1972
1973 /* XXX should test internal format */
1974 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1975
1976 if (copytexsubimage_error_check(ctx, 1, target, level,
1977 xoffset, 0, 0, postConvWidth, 1))
1978 return;
1979
1980 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1981 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1982 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1983
1984 /* If we have a border, xoffset=-1 is legal. Bias by border width */
1985 xoffset += texImage->Border;
1986
1987 ASSERT(ctx->Driver.CopyTexSubImage1D);
1988 (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width);
1989 ctx->NewState |= _NEW_TEXTURE;
1990 }
1991
1992
1993
1994 void
1995 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
1996 GLint xoffset, GLint yoffset,
1997 GLint x, GLint y, GLsizei width, GLsizei height )
1998 {
1999 struct gl_texture_unit *texUnit;
2000 struct gl_texture_object *texObj;
2001 struct gl_texture_image *texImage;
2002 GLsizei postConvWidth = width, postConvHeight = height;
2003 GET_CURRENT_CONTEXT(ctx);
2004 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2005
2006 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2007 _mesa_update_state(ctx);
2008
2009 /* XXX should test internal format */
2010 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
2011
2012 if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2013 postConvWidth, postConvHeight))
2014 return;
2015
2016 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2017 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2018 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2019
2020 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2021 xoffset += texImage->Border;
2022 yoffset += texImage->Border;
2023
2024 ASSERT(ctx->Driver.CopyTexSubImage2D);
2025 (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2026 xoffset, yoffset, x, y, width, height);
2027 ctx->NewState |= _NEW_TEXTURE;
2028 }
2029
2030
2031
2032 void
2033 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2034 GLint xoffset, GLint yoffset, GLint zoffset,
2035 GLint x, GLint y, GLsizei width, GLsizei height )
2036 {
2037 struct gl_texture_unit *texUnit;
2038 struct gl_texture_object *texObj;
2039 struct gl_texture_image *texImage;
2040 GLsizei postConvWidth = width, postConvHeight = height;
2041 GET_CURRENT_CONTEXT(ctx);
2042 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2043
2044 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2045 _mesa_update_state(ctx);
2046
2047 /* XXX should test internal format */
2048 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
2049
2050 if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset,
2051 zoffset, postConvWidth, postConvHeight))
2052 return;
2053
2054 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2055 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2056 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2057
2058 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2059 xoffset += texImage->Border;
2060 yoffset += texImage->Border;
2061 zoffset += texImage->Border;
2062
2063 ASSERT(ctx->Driver.CopyTexSubImage3D);
2064 (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2065 xoffset, yoffset, zoffset,
2066 x, y, width, height);
2067 ctx->NewState |= _NEW_TEXTURE;
2068 }
2069
2070
2071
2072 void
2073 _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
2074 GLenum internalFormat, GLsizei width,
2075 GLint border, GLsizei imageSize,
2076 const GLvoid *data)
2077 {
2078 GET_CURRENT_CONTEXT(ctx);
2079 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2080
2081 switch (internalFormat) {
2082 case GL_COMPRESSED_ALPHA_ARB:
2083 case GL_COMPRESSED_LUMINANCE_ARB:
2084 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2085 case GL_COMPRESSED_INTENSITY_ARB:
2086 case GL_COMPRESSED_RGB_ARB:
2087 case GL_COMPRESSED_RGBA_ARB:
2088 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2089 return;
2090 default:
2091 /* silence compiler warning */
2092 ;
2093 }
2094
2095 if (target == GL_TEXTURE_1D) {
2096 struct gl_texture_unit *texUnit;
2097 struct gl_texture_object *texObj;
2098 struct gl_texture_image *texImage;
2099
2100 if (texture_error_check(ctx, target, level, internalFormat,
2101 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2102 return; /* error in texture image was detected */
2103 }
2104
2105 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2106 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2107 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2108
2109 if (!texImage) {
2110 texImage = _mesa_alloc_texture_image();
2111 texObj->Image[level] = texImage;
2112 if (!texImage) {
2113 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2114 return;
2115 }
2116 }
2117 else if (texImage->Data) {
2118 MESA_PBUFFER_FREE(texImage->Data);
2119 texImage->Data = NULL;
2120 }
2121
2122 _mesa_init_teximage_fields(ctx, texImage, width, 1, 1,
2123 border, internalFormat);
2124
2125 if (ctx->Extensions.ARB_texture_compression) {
2126 ASSERT(ctx->Driver.CompressedTexImage1D);
2127 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2128 internalFormat, width, border,
2129 imageSize, data,
2130 texObj, texImage);
2131 ASSERT(texImage->CompressedSize > 0); /* sanity */
2132 }
2133
2134 /* state update */
2135 texObj->Complete = GL_FALSE;
2136 ctx->NewState |= _NEW_TEXTURE;
2137 }
2138 else if (target == GL_PROXY_TEXTURE_1D) {
2139 /* Proxy texture: check for errors and update proxy state */
2140 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2141 GL_NONE, GL_NONE, 1, width, 1, 1, border);
2142 if (!error) {
2143 struct gl_texture_unit *texUnit;
2144 struct gl_texture_image *texImage;
2145 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2146 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2147 _mesa_init_teximage_fields(ctx, texImage, width, 1, 1,
2148 border, internalFormat);
2149 ASSERT(ctx->Driver.TestProxyTexImage);
2150 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2151 internalFormat, GL_NONE, GL_NONE,
2152 width, 1, 1, border);
2153 }
2154 if (error) {
2155 /* if error, clear all proxy texture image parameters */
2156 if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
2157 clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]);
2158 }
2159 }
2160 }
2161 else {
2162 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)");
2163 return;
2164 }
2165 }
2166
2167
2168 void
2169 _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
2170 GLenum internalFormat, GLsizei width,
2171 GLsizei height, GLint border, GLsizei imageSize,
2172 const GLvoid *data)
2173 {
2174 GET_CURRENT_CONTEXT(ctx);
2175 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2176
2177 switch (internalFormat) {
2178 case GL_COMPRESSED_ALPHA_ARB:
2179 case GL_COMPRESSED_LUMINANCE_ARB:
2180 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2181 case GL_COMPRESSED_INTENSITY_ARB:
2182 case GL_COMPRESSED_RGB_ARB:
2183 case GL_COMPRESSED_RGBA_ARB:
2184 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
2185 return;
2186 default:
2187 /* silence compiler warning */
2188 ;
2189 }
2190
2191 if (target == GL_TEXTURE_2D ||
2192 (ctx->Extensions.ARB_texture_cube_map &&
2193 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2194 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
2195 struct gl_texture_unit *texUnit;
2196 struct gl_texture_object *texObj;
2197 struct gl_texture_image *texImage;
2198
2199 if (texture_error_check(ctx, target, level, internalFormat,
2200 GL_NONE, GL_NONE, 1, width, height, 1, border)) {
2201 return; /* error in texture image was detected */
2202 }
2203
2204 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2205 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2206 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2207
2208 if (!texImage) {
2209 texImage = _mesa_alloc_texture_image();
2210 texObj->Image[level] = texImage;
2211 if (!texImage) {
2212 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
2213 return;
2214 }
2215 }
2216 else if (texImage->Data) {
2217 MESA_PBUFFER_FREE(texImage->Data);
2218 texImage->Data = NULL;
2219 }
2220
2221 _mesa_init_teximage_fields(ctx, texImage, width, height, 1, border,
2222 internalFormat);
2223
2224 if (ctx->Extensions.ARB_texture_compression) {
2225 ASSERT(ctx->Driver.CompressedTexImage2D);
2226 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
2227 internalFormat, width, height,
2228 border, imageSize, data,
2229 texObj, texImage);
2230 ASSERT(texImage->CompressedSize > 0); /* sanity */
2231 }
2232
2233 /* state update */
2234 texObj->Complete = GL_FALSE;
2235 ctx->NewState |= _NEW_TEXTURE;
2236 }
2237 else if (target == GL_PROXY_TEXTURE_2D) {
2238 /* Proxy texture: check for errors and update proxy state */
2239 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2240 GL_NONE, GL_NONE, 2, width, height, 1, border);
2241 if (!error) {
2242 struct gl_texture_unit *texUnit;
2243 struct gl_texture_image *texImage;
2244 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2245 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2246 _mesa_init_teximage_fields(ctx, texImage, width, height, 1,
2247 border, internalFormat);
2248 ASSERT(ctx->Driver.TestProxyTexImage);
2249 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2250 internalFormat, GL_NONE, GL_NONE,
2251 width, height, 1, border);
2252 }
2253 if (error) {
2254 /* if error, clear all proxy texture image parameters */
2255 const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ?
2256 ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels;
2257 if (level >= 0 && level < maxLevels) {
2258 clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
2259 }
2260 }
2261 }
2262 else {
2263 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)");
2264 return;
2265 }
2266 }
2267
2268
2269 void
2270 _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
2271 GLenum internalFormat, GLsizei width,
2272 GLsizei height, GLsizei depth, GLint border,
2273 GLsizei imageSize, const GLvoid *data)
2274 {
2275 GET_CURRENT_CONTEXT(ctx);
2276 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2277
2278 switch (internalFormat) {
2279 case GL_COMPRESSED_ALPHA_ARB:
2280 case GL_COMPRESSED_LUMINANCE_ARB:
2281 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2282 case GL_COMPRESSED_INTENSITY_ARB:
2283 case GL_COMPRESSED_RGB_ARB:
2284 case GL_COMPRESSED_RGBA_ARB:
2285 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
2286 return;
2287 default:
2288 /* silence compiler warning */
2289 ;
2290 }
2291
2292 if (target == GL_TEXTURE_3D) {
2293 struct gl_texture_unit *texUnit;
2294 struct gl_texture_object *texObj;
2295 struct gl_texture_image *texImage;
2296
2297 if (texture_error_check(ctx, target, level, internalFormat,
2298 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
2299 return; /* error in texture image was detected */
2300 }
2301
2302 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2303 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2304 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2305
2306 if (!texImage) {
2307 texImage = _mesa_alloc_texture_image();
2308 texObj->Image[level] = texImage;
2309 if (!texImage) {
2310 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
2311 return;
2312 }
2313 }
2314 else if (texImage->Data) {
2315 MESA_PBUFFER_FREE(texImage->Data);
2316 texImage->Data = NULL;
2317 }
2318
2319 _mesa_init_teximage_fields(ctx, texImage, width, height, depth, border,
2320 internalFormat);
2321
2322 if (ctx->Extensions.ARB_texture_compression) {
2323 ASSERT(ctx->Driver.CompressedTexImage3D);
2324 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
2325 internalFormat,
2326 width, height, depth,
2327 border, imageSize, data,
2328 texObj, texImage);
2329 ASSERT(texImage->CompressedSize > 0); /* sanity */
2330 }
2331
2332 /* state update */
2333 texObj->Complete = GL_FALSE;
2334 ctx->NewState |= _NEW_TEXTURE;
2335 }
2336 else if (target == GL_PROXY_TEXTURE_3D) {
2337 /* Proxy texture: check for errors and update proxy state */
2338 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2339 GL_NONE, GL_NONE, 1, width, height, depth, border);
2340 if (!error) {
2341 struct gl_texture_unit *texUnit;
2342 struct gl_texture_image *texImage;
2343 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2344 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2345 _mesa_init_teximage_fields(ctx, texImage, width, height, depth,
2346 border, internalFormat);
2347 ASSERT(ctx->Driver.TestProxyTexImage);
2348 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2349 internalFormat, GL_NONE, GL_NONE,
2350 width, height, depth, border);
2351 }
2352 if (error) {
2353 /* if error, clear all proxy texture image parameters */
2354 if (level >= 0 && level < ctx->Const.Max3DTextureLevels) {
2355 clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
2356 }
2357 }
2358 }
2359 else {
2360 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)");
2361 return;
2362 }
2363 }
2364
2365
2366 void
2367 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
2368 GLsizei width, GLenum format,
2369 GLsizei imageSize, const GLvoid *data)
2370 {
2371 struct gl_texture_unit *texUnit;
2372 struct gl_texture_object *texObj;
2373 struct gl_texture_image *texImage;
2374 GET_CURRENT_CONTEXT(ctx);
2375 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2376
2377 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2378 width, 1, 1, format, GL_NONE)) {
2379 return; /* error was detected */
2380 }
2381
2382 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2383 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2384 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2385 assert(texImage);
2386
2387 if (width == 0 || !data)
2388 return; /* no-op, not an error */
2389
2390 if (ctx->Driver.CompressedTexSubImage1D) {
2391 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
2392 xoffset, width,
2393 format, imageSize, data,
2394 texObj, texImage);
2395 }
2396 ctx->NewState |= _NEW_TEXTURE;
2397 }
2398
2399
2400 void
2401 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
2402 GLint yoffset, GLsizei width, GLsizei height,
2403 GLenum format, GLsizei imageSize,
2404 const GLvoid *data)
2405 {
2406 struct gl_texture_unit *texUnit;
2407 struct gl_texture_object *texObj;
2408 struct gl_texture_image *texImage;
2409 GET_CURRENT_CONTEXT(ctx);
2410 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2411
2412 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2413 width, height, 1, format, GL_NONE)) {
2414 return; /* error was detected */
2415 }
2416
2417 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2418 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2419 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2420 assert(texImage);
2421
2422 if (width == 0 || height == 0 || !data)
2423 return; /* no-op, not an error */
2424
2425 if (ctx->Driver.CompressedTexSubImage2D) {
2426 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
2427 xoffset, yoffset, width, height,
2428 format, imageSize, data,
2429 texObj, texImage);
2430 }
2431 ctx->NewState |= _NEW_TEXTURE;
2432 }
2433
2434
2435 void
2436 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
2437 GLint yoffset, GLint zoffset, GLsizei width,
2438 GLsizei height, GLsizei depth, GLenum format,
2439 GLsizei imageSize, const GLvoid *data)
2440 {
2441 struct gl_texture_unit *texUnit;
2442 struct gl_texture_object *texObj;
2443 struct gl_texture_image *texImage;
2444 GET_CURRENT_CONTEXT(ctx);
2445 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2446
2447 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2448 width, height, depth, format, GL_NONE)) {
2449 return; /* error was detected */
2450 }
2451
2452 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2453 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2454 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2455 assert(texImage);
2456
2457 if (width == 0 || height == 0 || depth == 0 || !data)
2458 return; /* no-op, not an error */
2459
2460 if (ctx->Driver.CompressedTexSubImage3D) {
2461 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
2462 xoffset, yoffset, zoffset,
2463 width, height, depth,
2464 format, imageSize, data,
2465 texObj, texImage);
2466 }
2467 ctx->NewState |= _NEW_TEXTURE;
2468 }
2469
2470
2471 void
2472 _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
2473 {
2474 const struct gl_texture_unit *texUnit;
2475 const struct gl_texture_object *texObj;
2476 struct gl_texture_image *texImage;
2477 GLint maxLevels;
2478 GET_CURRENT_CONTEXT(ctx);
2479 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2480
2481 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2482 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2483 if (!texObj) {
2484 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
2485 return;
2486 }
2487
2488 if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D) {
2489 maxLevels = ctx->Const.MaxTextureLevels;
2490 }
2491 else if (target == GL_TEXTURE_3D) {
2492 maxLevels = ctx->Const.Max3DTextureLevels;
2493 }
2494 else {
2495 maxLevels = ctx->Const.MaxCubeTextureLevels;
2496 }
2497
2498 ASSERT(maxLevels > 0);
2499
2500 if (level < 0 || level >= maxLevels) {
2501 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
2502 return;
2503 }
2504
2505 if (is_proxy_target(target)) {
2506 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
2507 return;
2508 }
2509
2510 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2511 if (!texImage) {
2512 /* probably invalid mipmap level */
2513 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
2514 return;
2515 }
2516
2517 if (!texImage->IsCompressed) {
2518 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
2519 return;
2520 }
2521
2522 if (!img)
2523 return;
2524
2525 if (ctx->Extensions.ARB_texture_compression) {
2526 ASSERT(ctx->Driver.GetCompressedTexImage);
2527 (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
2528 texImage);
2529 }
2530 }