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