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