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