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