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