change glTexImage3D() internalFormat to GLenum to match other OpenGLs
[mesa.git] / src / mesa / main / teximage.c
1 /* $Id: teximage.c,v 1.87 2001/03/26 20:02:38 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 #ifdef PC_HEADER
29 #include "all.h"
30 #else
31 #include "glheader.h"
32 #include "context.h"
33 #include "convolve.h"
34 #include "image.h"
35 #include "macros.h"
36 #include "mem.h"
37 #include "mmath.h"
38 #include "state.h"
39 #include "texformat.h"
40 #include "teximage.h"
41 #include "texstate.h"
42 #include "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, GLenum 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, (GLint) 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, (GLint) 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,
1566 (GLint) internalFormat,
1567 width, height, depth, border,
1568 format, GL_UNSIGNED_BYTE, dummy,
1569 &_mesa_native_packing, texObj, texImage);
1570 FREE(dummy);
1571 }
1572 }
1573
1574 #if 0
1575 /* one of these has to be non-zero! */
1576 ASSERT(texImage->RedBits || texImage->IndexBits || texImage->AlphaBits ||
1577 texImage->LuminanceBits || texImage->IntensityBits ||
1578 texImage->DepthBits);
1579 ASSERT(texImage->FetchTexel);
1580 #endif
1581
1582 /* state update */
1583 texObj->Complete = GL_FALSE;
1584 ctx->NewState |= _NEW_TEXTURE;
1585 }
1586 else if (target == GL_PROXY_TEXTURE_3D) {
1587 /* Proxy texture: check for errors and update proxy state */
1588 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1589 format, type, 3, width, height, depth, border);
1590 if (!error) {
1591 struct gl_texture_unit *texUnit;
1592 struct gl_texture_image *texImage;
1593 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1594 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1595 init_teximage_fields(ctx, texImage, width, height, 1,
1596 border, internalFormat);
1597 ASSERT(ctx->Driver.TestProxyTexImage);
1598 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1599 internalFormat, format, type,
1600 width, height, depth, border);
1601 }
1602 if (error) {
1603 /* if error, clear all proxy texture image parameters */
1604 if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
1605 clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
1606 }
1607 }
1608 }
1609 else {
1610 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1611 return;
1612 }
1613 }
1614
1615
1616 void
1617 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
1618 GLsizei width, GLsizei height, GLsizei depth,
1619 GLint border, GLenum format, GLenum type,
1620 const GLvoid *pixels )
1621 {
1622 _mesa_TexImage3D(target, level, internalFormat, width, height,
1623 depth, border, format, type, pixels);
1624 }
1625
1626
1627
1628 void
1629 _mesa_TexSubImage1D( GLenum target, GLint level,
1630 GLint xoffset, GLsizei width,
1631 GLenum format, GLenum type,
1632 const GLvoid *pixels )
1633 {
1634 GLsizei postConvWidth = width;
1635 struct gl_texture_unit *texUnit;
1636 struct gl_texture_object *texObj;
1637 struct gl_texture_image *texImage;
1638 GET_CURRENT_CONTEXT(ctx);
1639 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1640
1641 if (ctx->NewState & _NEW_PIXEL)
1642 _mesa_update_state(ctx);
1643
1644 /* XXX should test internal format */
1645 if (is_color_format(format)) {
1646 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1647 }
1648
1649 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1650 postConvWidth, 1, 1, format, type)) {
1651 return; /* error was detected */
1652 }
1653
1654 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1655 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1656 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1657 assert(texImage);
1658
1659 if (width == 0 || !pixels)
1660 return; /* no-op, not an error */
1661
1662 ASSERT(ctx->Driver.TexSubImage1D);
1663 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
1664 format, type, pixels, &ctx->Unpack,
1665 texObj, texImage);
1666 ctx->NewState |= _NEW_TEXTURE;
1667 }
1668
1669
1670 void
1671 _mesa_TexSubImage2D( GLenum target, GLint level,
1672 GLint xoffset, GLint yoffset,
1673 GLsizei width, GLsizei height,
1674 GLenum format, GLenum type,
1675 const GLvoid *pixels )
1676 {
1677 GLsizei postConvWidth = width, postConvHeight = height;
1678 struct gl_texture_unit *texUnit;
1679 struct gl_texture_object *texObj;
1680 struct gl_texture_image *texImage;
1681 GET_CURRENT_CONTEXT(ctx);
1682 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1683
1684 if (ctx->NewState & _NEW_PIXEL)
1685 _mesa_update_state(ctx);
1686
1687 /* XXX should test internal format */
1688 if (is_color_format(format)) {
1689 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1690 &postConvHeight);
1691 }
1692
1693 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1694 postConvWidth, postConvHeight, 1, format, type)) {
1695 return; /* error was detected */
1696 }
1697
1698 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1699 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1700 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1701 assert(texImage);
1702
1703 if (width == 0 || height == 0 || !pixels)
1704 return; /* no-op, not an error */
1705
1706 ASSERT(ctx->Driver.TexSubImage2D);
1707 (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
1708 width, height, format, type, pixels,
1709 &ctx->Unpack, texObj, texImage);
1710 ctx->NewState |= _NEW_TEXTURE;
1711 }
1712
1713
1714
1715 void
1716 _mesa_TexSubImage3D( GLenum target, GLint level,
1717 GLint xoffset, GLint yoffset, GLint zoffset,
1718 GLsizei width, GLsizei height, GLsizei depth,
1719 GLenum format, GLenum type,
1720 const GLvoid *pixels )
1721 {
1722 struct gl_texture_unit *texUnit;
1723 struct gl_texture_object *texObj;
1724 struct gl_texture_image *texImage;
1725 GET_CURRENT_CONTEXT(ctx);
1726 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1727
1728 if (ctx->NewState & _NEW_PIXEL)
1729 _mesa_update_state(ctx);
1730
1731 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
1732 width, height, depth, format, type)) {
1733 return; /* error was detected */
1734 }
1735
1736 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1737 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1738 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1739 assert(texImage);
1740
1741 if (width == 0 || height == 0 || height == 0 || !pixels)
1742 return; /* no-op, not an error */
1743
1744 ASSERT(ctx->Driver.TexSubImage3D);
1745 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
1746 xoffset, yoffset, zoffset,
1747 width, height, depth,
1748 format, type, pixels,
1749 &ctx->Unpack, texObj, texImage );
1750 ctx->NewState |= _NEW_TEXTURE;
1751 }
1752
1753
1754
1755 void
1756 _mesa_CopyTexImage1D( GLenum target, GLint level,
1757 GLenum internalFormat,
1758 GLint x, GLint y,
1759 GLsizei width, GLint border )
1760 {
1761 struct gl_texture_unit *texUnit;
1762 struct gl_texture_object *texObj;
1763 struct gl_texture_image *texImage;
1764 GLsizei postConvWidth = width;
1765 GET_CURRENT_CONTEXT(ctx);
1766 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1767
1768 if (ctx->NewState & _NEW_PIXEL)
1769 _mesa_update_state(ctx);
1770
1771 if (is_color_format(internalFormat)) {
1772 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1773 }
1774
1775 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
1776 postConvWidth, 1, border))
1777 return;
1778
1779 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1780 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1781 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1782 if (!texImage) {
1783 texImage = _mesa_alloc_texture_image();
1784 set_tex_image(texObj, target, level, texImage);
1785 if (!texImage) {
1786 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
1787 return;
1788 }
1789 }
1790 else if (texImage->Data) {
1791 /* free the old texture data */
1792 FREE(texImage->Data);
1793 texImage->Data = NULL;
1794 }
1795
1796 clear_teximage_fields(texImage); /* not really needed, but helpful */
1797 init_teximage_fields(ctx, texImage, postConvWidth, 1, 1,
1798 border, internalFormat);
1799
1800
1801 ASSERT(ctx->Driver.CopyTexImage1D);
1802 (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
1803 x, y, width, border);
1804
1805 /* state update */
1806 texObj->Complete = GL_FALSE;
1807 ctx->NewState |= _NEW_TEXTURE;
1808 }
1809
1810
1811
1812 void
1813 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
1814 GLint x, GLint y, GLsizei width, GLsizei height,
1815 GLint border )
1816 {
1817 struct gl_texture_unit *texUnit;
1818 struct gl_texture_object *texObj;
1819 struct gl_texture_image *texImage;
1820 GLsizei postConvWidth = width, postConvHeight = height;
1821 GET_CURRENT_CONTEXT(ctx);
1822 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1823
1824 if (ctx->NewState & _NEW_PIXEL)
1825 _mesa_update_state(ctx);
1826
1827 if (is_color_format(internalFormat)) {
1828 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
1829 &postConvHeight);
1830 }
1831
1832 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
1833 postConvWidth, postConvHeight, border))
1834 return;
1835
1836 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1837 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1838 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1839 if (!texImage) {
1840 texImage = _mesa_alloc_texture_image();
1841 set_tex_image(texObj, target, level, texImage);
1842 if (!texImage) {
1843 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
1844 return;
1845 }
1846 }
1847 else if (texImage->Data) {
1848 /* free the old texture data */
1849 FREE(texImage->Data);
1850 texImage->Data = NULL;
1851 }
1852
1853 clear_teximage_fields(texImage); /* not really needed, but helpful */
1854 init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight, 1,
1855 border, internalFormat);
1856
1857 ASSERT(ctx->Driver.CopyTexImage2D);
1858 (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
1859 x, y, width, height, border);
1860
1861 /* state update */
1862 texObj->Complete = GL_FALSE;
1863 ctx->NewState |= _NEW_TEXTURE;
1864 }
1865
1866
1867
1868 void
1869 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
1870 GLint xoffset, GLint x, GLint y, GLsizei width )
1871 {
1872 GLsizei postConvWidth = width;
1873 GET_CURRENT_CONTEXT(ctx);
1874 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1875
1876 if (ctx->NewState & _NEW_PIXEL)
1877 _mesa_update_state(ctx);
1878
1879 /* XXX should test internal format */
1880 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
1881
1882 if (copytexsubimage_error_check(ctx, 1, target, level,
1883 xoffset, 0, 0, postConvWidth, 1))
1884 return;
1885
1886 ASSERT(ctx->Driver.CopyTexSubImage1D);
1887 (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width);
1888 ctx->NewState |= _NEW_TEXTURE;
1889 }
1890
1891
1892
1893 void
1894 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
1895 GLint xoffset, GLint yoffset,
1896 GLint x, GLint y, GLsizei width, GLsizei height )
1897 {
1898 GLsizei postConvWidth = width, postConvHeight = height;
1899 GET_CURRENT_CONTEXT(ctx);
1900 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1901
1902 if (ctx->NewState & _NEW_PIXEL)
1903 _mesa_update_state(ctx);
1904
1905 /* XXX should test internal format */
1906 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
1907
1908 if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1909 postConvWidth, postConvHeight))
1910 return;
1911
1912 ASSERT(ctx->Driver.CopyTexSubImage2D);
1913 (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
1914 xoffset, yoffset, x, y, width, height);
1915 ctx->NewState |= _NEW_TEXTURE;
1916 }
1917
1918
1919
1920 void
1921 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
1922 GLint xoffset, GLint yoffset, GLint zoffset,
1923 GLint x, GLint y, GLsizei width, GLsizei height )
1924 {
1925 GLsizei postConvWidth = width, postConvHeight = height;
1926 GET_CURRENT_CONTEXT(ctx);
1927 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1928
1929 if (ctx->NewState & _NEW_PIXEL)
1930 _mesa_update_state(ctx);
1931
1932 /* XXX should test internal format */
1933 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
1934
1935 if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset,
1936 zoffset, postConvWidth, postConvHeight))
1937 return;
1938
1939 ASSERT(ctx->Driver.CopyTexSubImage3D);
1940 (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
1941 xoffset, yoffset, zoffset,
1942 x, y, width, height);
1943 ctx->NewState |= _NEW_TEXTURE;
1944 }
1945
1946
1947
1948 void
1949 _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
1950 GLenum internalFormat, GLsizei width,
1951 GLint border, GLsizei imageSize,
1952 const GLvoid *data)
1953 {
1954 GET_CURRENT_CONTEXT(ctx);
1955 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1956
1957 switch (internalFormat) {
1958 case GL_COMPRESSED_ALPHA_ARB:
1959 case GL_COMPRESSED_LUMINANCE_ARB:
1960 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
1961 case GL_COMPRESSED_INTENSITY_ARB:
1962 case GL_COMPRESSED_RGB_ARB:
1963 case GL_COMPRESSED_RGBA_ARB:
1964 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
1965 return;
1966 default:
1967 /* silence compiler warning */
1968 ;
1969 }
1970
1971 if (target == GL_TEXTURE_1D) {
1972 struct gl_texture_unit *texUnit;
1973 struct gl_texture_object *texObj;
1974 struct gl_texture_image *texImage;
1975
1976 if (texture_error_check(ctx, target, level, internalFormat,
1977 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
1978 return; /* error in texture image was detected */
1979 }
1980
1981 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1982 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1983 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1984
1985 if (!texImage) {
1986 texImage = _mesa_alloc_texture_image();
1987 texObj->Image[level] = texImage;
1988 if (!texImage) {
1989 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
1990 return;
1991 }
1992 }
1993 else if (texImage->Data) {
1994 FREE(texImage->Data);
1995 texImage->Data = NULL;
1996 }
1997
1998 init_teximage_fields(ctx, texImage, width, 1, 1, border, internalFormat);
1999
2000 if (ctx->Extensions.ARB_texture_compression) {
2001 ASSERT(ctx->Driver.CompressedTexImage1D);
2002 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2003 internalFormat, width, border,
2004 imageSize, data,
2005 texObj, texImage);
2006 ASSERT(texImage->CompressedSize > 0); /* sanity */
2007 }
2008
2009 /* state update */
2010 texObj->Complete = GL_FALSE;
2011 ctx->NewState |= _NEW_TEXTURE;
2012 }
2013 else if (target == GL_PROXY_TEXTURE_1D) {
2014 /* Proxy texture: check for errors and update proxy state */
2015 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2016 GL_NONE, GL_NONE, 1, width, 1, 1, border);
2017 if (!error) {
2018 struct gl_texture_unit *texUnit;
2019 struct gl_texture_image *texImage;
2020 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2021 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2022 init_teximage_fields(ctx, texImage, width, 1, 1,
2023 border, internalFormat);
2024 ASSERT(ctx->Driver.TestProxyTexImage);
2025 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2026 internalFormat, GL_NONE, GL_NONE,
2027 width, 1, 1, border);
2028 }
2029 if (error) {
2030 /* if error, clear all proxy texture image parameters */
2031 if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
2032 clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]);
2033 }
2034 }
2035 }
2036 else {
2037 _mesa_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
2038 return;
2039 }
2040 }
2041
2042
2043 void
2044 _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
2045 GLenum internalFormat, GLsizei width,
2046 GLsizei height, GLint border, GLsizei imageSize,
2047 const GLvoid *data)
2048 {
2049 GET_CURRENT_CONTEXT(ctx);
2050 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2051
2052 switch (internalFormat) {
2053 case GL_COMPRESSED_ALPHA_ARB:
2054 case GL_COMPRESSED_LUMINANCE_ARB:
2055 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2056 case GL_COMPRESSED_INTENSITY_ARB:
2057 case GL_COMPRESSED_RGB_ARB:
2058 case GL_COMPRESSED_RGBA_ARB:
2059 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
2060 return;
2061 default:
2062 /* silence compiler warning */
2063 ;
2064 }
2065
2066 if (target == GL_TEXTURE_2D ||
2067 (ctx->Extensions.ARB_texture_cube_map &&
2068 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2069 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
2070 struct gl_texture_unit *texUnit;
2071 struct gl_texture_object *texObj;
2072 struct gl_texture_image *texImage;
2073
2074 if (texture_error_check(ctx, target, level, internalFormat,
2075 GL_NONE, GL_NONE, 1, width, height, 1, border)) {
2076 return; /* error in texture image was detected */
2077 }
2078
2079 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2080 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2081 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2082
2083 if (!texImage) {
2084 texImage = _mesa_alloc_texture_image();
2085 texObj->Image[level] = texImage;
2086 if (!texImage) {
2087 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
2088 return;
2089 }
2090 }
2091 else if (texImage->Data) {
2092 FREE(texImage->Data);
2093 texImage->Data = NULL;
2094 }
2095
2096 init_teximage_fields(ctx, texImage, width, height, 1, border,
2097 internalFormat);
2098
2099 if (ctx->Extensions.ARB_texture_compression) {
2100 ASSERT(ctx->Driver.CompressedTexImage2D);
2101 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
2102 internalFormat, width, height,
2103 border, imageSize, data,
2104 texObj, texImage);
2105 ASSERT(texImage->CompressedSize > 0); /* sanity */
2106 }
2107
2108 /* state update */
2109 texObj->Complete = GL_FALSE;
2110 ctx->NewState |= _NEW_TEXTURE;
2111 }
2112 else if (target == GL_PROXY_TEXTURE_2D) {
2113 /* Proxy texture: check for errors and update proxy state */
2114 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2115 GL_NONE, GL_NONE, 2, width, height, 1, border);
2116 if (!error) {
2117 struct gl_texture_unit *texUnit;
2118 struct gl_texture_image *texImage;
2119 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2120 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2121 init_teximage_fields(ctx, texImage, width, height, 1,
2122 border, internalFormat);
2123 ASSERT(ctx->Driver.TestProxyTexImage);
2124 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2125 internalFormat, GL_NONE, GL_NONE,
2126 width, height, 1, border);
2127 }
2128 if (error) {
2129 /* if error, clear all proxy texture image parameters */
2130 if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
2131 clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]);
2132 }
2133 }
2134 }
2135 else {
2136 _mesa_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
2137 return;
2138 }
2139 }
2140
2141
2142 void
2143 _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
2144 GLenum internalFormat, GLsizei width,
2145 GLsizei height, GLsizei depth, GLint border,
2146 GLsizei imageSize, const GLvoid *data)
2147 {
2148 GET_CURRENT_CONTEXT(ctx);
2149 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2150
2151 switch (internalFormat) {
2152 case GL_COMPRESSED_ALPHA_ARB:
2153 case GL_COMPRESSED_LUMINANCE_ARB:
2154 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2155 case GL_COMPRESSED_INTENSITY_ARB:
2156 case GL_COMPRESSED_RGB_ARB:
2157 case GL_COMPRESSED_RGBA_ARB:
2158 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
2159 return;
2160 default:
2161 /* silence compiler warning */
2162 ;
2163 }
2164
2165 if (target == GL_TEXTURE_3D) {
2166 struct gl_texture_unit *texUnit;
2167 struct gl_texture_object *texObj;
2168 struct gl_texture_image *texImage;
2169
2170 if (texture_error_check(ctx, target, level, internalFormat,
2171 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
2172 return; /* error in texture image was detected */
2173 }
2174
2175 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2176 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2177 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2178
2179 if (!texImage) {
2180 texImage = _mesa_alloc_texture_image();
2181 texObj->Image[level] = texImage;
2182 if (!texImage) {
2183 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
2184 return;
2185 }
2186 }
2187 else if (texImage->Data) {
2188 FREE(texImage->Data);
2189 texImage->Data = NULL;
2190 }
2191
2192 init_teximage_fields(ctx, texImage, width, height, depth, border,
2193 internalFormat);
2194
2195 if (ctx->Extensions.ARB_texture_compression) {
2196 ASSERT(ctx->Driver.CompressedTexImage3D);
2197 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
2198 internalFormat,
2199 width, height, depth,
2200 border, imageSize, data,
2201 texObj, texImage);
2202 ASSERT(texImage->CompressedSize > 0); /* sanity */
2203 }
2204
2205 /* state update */
2206 texObj->Complete = GL_FALSE;
2207 ctx->NewState |= _NEW_TEXTURE;
2208 }
2209 else if (target == GL_PROXY_TEXTURE_3D) {
2210 /* Proxy texture: check for errors and update proxy state */
2211 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2212 GL_NONE, GL_NONE, 1, width, height, depth, border);
2213 if (!error) {
2214 struct gl_texture_unit *texUnit;
2215 struct gl_texture_image *texImage;
2216 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2217 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2218 init_teximage_fields(ctx, texImage, width, height, depth,
2219 border, internalFormat);
2220 ASSERT(ctx->Driver.TestProxyTexImage);
2221 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2222 internalFormat, GL_NONE, GL_NONE,
2223 width, height, depth, border);
2224 }
2225 if (error) {
2226 /* if error, clear all proxy texture image parameters */
2227 if (level >= 0 && level < ctx->Const.MaxTextureLevels) {
2228 clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]);
2229 }
2230 }
2231 }
2232 else {
2233 _mesa_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
2234 return;
2235 }
2236 }
2237
2238
2239 void
2240 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
2241 GLsizei width, GLenum format,
2242 GLsizei imageSize, const GLvoid *data)
2243 {
2244 struct gl_texture_unit *texUnit;
2245 struct gl_texture_object *texObj;
2246 struct gl_texture_image *texImage;
2247 GET_CURRENT_CONTEXT(ctx);
2248 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2249
2250 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2251 width, 1, 1, format, GL_NONE)) {
2252 return; /* error was detected */
2253 }
2254
2255 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2256 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2257 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2258 assert(texImage);
2259
2260 if (width == 0 || !data)
2261 return; /* no-op, not an error */
2262
2263 if (ctx->Driver.CompressedTexSubImage1D) {
2264 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
2265 xoffset, width,
2266 format, imageSize, data,
2267 texObj, texImage);
2268 }
2269 ctx->NewState |= _NEW_TEXTURE;
2270 }
2271
2272
2273 void
2274 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
2275 GLint yoffset, GLsizei width, GLsizei height,
2276 GLenum format, GLsizei imageSize,
2277 const GLvoid *data)
2278 {
2279 struct gl_texture_unit *texUnit;
2280 struct gl_texture_object *texObj;
2281 struct gl_texture_image *texImage;
2282 GET_CURRENT_CONTEXT(ctx);
2283 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2284
2285 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2286 width, height, 1, format, GL_NONE)) {
2287 return; /* error was detected */
2288 }
2289
2290 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2291 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2292 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2293 assert(texImage);
2294
2295 if (width == 0 || height == 0 || !data)
2296 return; /* no-op, not an error */
2297
2298 if (ctx->Driver.CompressedTexSubImage2D) {
2299 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
2300 xoffset, yoffset, width, height,
2301 format, imageSize, data,
2302 texObj, texImage);
2303 }
2304 ctx->NewState |= _NEW_TEXTURE;
2305 }
2306
2307
2308 void
2309 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
2310 GLint yoffset, GLint zoffset, GLsizei width,
2311 GLsizei height, GLsizei depth, GLenum format,
2312 GLsizei imageSize, const GLvoid *data)
2313 {
2314 struct gl_texture_unit *texUnit;
2315 struct gl_texture_object *texObj;
2316 struct gl_texture_image *texImage;
2317 GET_CURRENT_CONTEXT(ctx);
2318 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2319
2320 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2321 width, height, depth, format, GL_NONE)) {
2322 return; /* error was detected */
2323 }
2324
2325 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2326 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2327 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2328 assert(texImage);
2329
2330 if (width == 0 || height == 0 || depth == 0 || !data)
2331 return; /* no-op, not an error */
2332
2333 if (ctx->Driver.CompressedTexSubImage3D) {
2334 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
2335 xoffset, yoffset, zoffset,
2336 width, height, depth,
2337 format, imageSize, data,
2338 texObj, texImage);
2339 }
2340 ctx->NewState |= _NEW_TEXTURE;
2341 }
2342
2343
2344 void
2345 _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
2346 {
2347 const struct gl_texture_unit *texUnit;
2348 const struct gl_texture_object *texObj;
2349 struct gl_texture_image *texImage;
2350 GET_CURRENT_CONTEXT(ctx);
2351 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2352
2353 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
2354 _mesa_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
2355 return;
2356 }
2357
2358 if (is_proxy_target(target)) {
2359 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
2360 return;
2361 }
2362
2363 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2364 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2365 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2366
2367 if (!texImage) {
2368 /* invalid mipmap level */
2369 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
2370 return;
2371 }
2372
2373 if (!texImage->IsCompressed) {
2374 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
2375 return;
2376 }
2377
2378 if (!img)
2379 return;
2380
2381 if (ctx->Extensions.ARB_texture_compression) {
2382 ASSERT(ctx->Driver.GetCompressedTexImage);
2383 (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
2384 texImage);
2385 }
2386 }