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