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