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