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