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