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