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