fix depth-component test to allow rectangular textures
[mesa.git] / src / mesa / main / teximage.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
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 }
2105
2106 if (!ctx->Extensions.SGIX_depth_texture &&
2107 !ctx->Extensions.ARB_depth_texture && is_depth_format(format)) {
2108 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2109 }
2110
2111 if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) {
2112 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2113 }
2114
2115 if (!ctx->Extensions.EXT_packed_depth_stencil
2116 && is_depthstencil_format(format)) {
2117 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2118 }
2119
2120 if (!pixels)
2121 return;
2122
2123 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2124 if (!texImage) {
2125 /* invalid mipmap level, not an error */
2126 return;
2127 }
2128
2129 /* Make sure the requested image format is compatible with the
2130 * texture's format. Note that a color index texture can be converted
2131 * to RGBA so that combo is allowed.
2132 */
2133 if (is_color_format(format)
2134 && !is_color_format(texImage->TexFormat->BaseFormat)
2135 && !is_index_format(texImage->TexFormat->BaseFormat)) {
2136 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2137 return;
2138 }
2139 else if (is_index_format(format)
2140 && !is_index_format(texImage->TexFormat->BaseFormat)) {
2141 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2142 return;
2143 }
2144 else if (is_depth_format(format)
2145 && !is_depth_format(texImage->TexFormat->BaseFormat)
2146 && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
2147 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2148 return;
2149 }
2150 else if (is_ycbcr_format(format)
2151 && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) {
2152 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2153 return;
2154 }
2155 else if (is_depthstencil_format(format)
2156 && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
2157 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2158 return;
2159 }
2160
2161 /* typically, this will call _mesa_get_teximage() */
2162 ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
2163 texObj, texImage);
2164 }
2165
2166
2167
2168 /**
2169 * Check if the given texture image is bound to any framebuffer objects
2170 * and update/invalidate them.
2171 * XXX We're only checking the currently bound framebuffer object for now.
2172 * In the future, perhaps struct gl_texture_image should have a pointer (or
2173 * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to.
2174 */
2175 static void
2176 update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj,
2177 GLuint face, GLuint level)
2178 {
2179 if (ctx->DrawBuffer->Name) {
2180 GLuint i;
2181 for (i = 0; i < BUFFER_COUNT; i++) {
2182 struct gl_renderbuffer_attachment *att =
2183 ctx->DrawBuffer->Attachment + i;
2184 if (att->Type == GL_TEXTURE &&
2185 att->Texture == texObj &&
2186 att->TextureLevel == level &&
2187 att->CubeMapFace == face) {
2188 ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
2189 /* Tell driver about the new renderbuffer texture */
2190 ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
2191 }
2192 }
2193 }
2194 }
2195
2196
2197
2198 /*
2199 * Called from the API. Note that width includes the border.
2200 */
2201 void GLAPIENTRY
2202 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
2203 GLsizei width, GLint border, GLenum format,
2204 GLenum type, const GLvoid *pixels )
2205 {
2206 GLsizei postConvWidth = width;
2207 GET_CURRENT_CONTEXT(ctx);
2208 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2209
2210 if (is_color_format(internalFormat)) {
2211 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2212 }
2213
2214 if (target == GL_TEXTURE_1D) {
2215 /* non-proxy target */
2216 struct gl_texture_unit *texUnit;
2217 struct gl_texture_object *texObj;
2218 struct gl_texture_image *texImage;
2219 const GLuint face = texture_face(target);
2220
2221 if (texture_error_check(ctx, target, level, internalFormat,
2222 format, type, 1, postConvWidth, 1, 1, border)) {
2223 return; /* error was recorded */
2224 }
2225
2226 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2227 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2228 texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
2229
2230 if (!texImage) {
2231 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2232 return;
2233 }
2234 else if (texImage->Data) {
2235 ctx->Driver.FreeTexImageData( ctx, texImage );
2236 }
2237 ASSERT(texImage->Data == NULL);
2238 clear_teximage_fields(texImage); /* not really needed, but helpful */
2239 _mesa_init_teximage_fields(ctx, target, texImage,
2240 postConvWidth, 1, 1,
2241 border, internalFormat);
2242
2243 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2244 _mesa_update_state(ctx);
2245
2246 ASSERT(ctx->Driver.TexImage1D);
2247
2248 /* Give the texture to the driver! <pixels> may be null! */
2249 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
2250 width, border, format, type, pixels,
2251 &ctx->Unpack, texObj, texImage);
2252
2253 ASSERT(texImage->TexFormat);
2254
2255 update_fbo_texture(ctx, texObj, face, level);
2256
2257 /* state update */
2258 texObj->Complete = GL_FALSE;
2259 ctx->NewState |= _NEW_TEXTURE;
2260 }
2261 else if (target == GL_PROXY_TEXTURE_1D) {
2262 /* Proxy texture: check for errors and update proxy state */
2263 struct gl_texture_image *texImage;
2264 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2265 if (texture_error_check(ctx, target, level, internalFormat,
2266 format, type, 1, postConvWidth, 1, 1, border)) {
2267 /* when error, clear all proxy texture image parameters */
2268 if (texImage)
2269 clear_teximage_fields(texImage);
2270 }
2271 else {
2272 /* no error, set the tex image parameters */
2273 ASSERT(texImage);
2274 _mesa_init_teximage_fields(ctx, target, texImage,
2275 postConvWidth, 1, 1,
2276 border, internalFormat);
2277 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2278 internalFormat, format, type);
2279 }
2280 }
2281 else {
2282 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
2283 return;
2284 }
2285 }
2286
2287
2288 void GLAPIENTRY
2289 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
2290 GLsizei width, GLsizei height, GLint border,
2291 GLenum format, GLenum type,
2292 const GLvoid *pixels )
2293 {
2294 GLsizei postConvWidth = width, postConvHeight = height;
2295 GET_CURRENT_CONTEXT(ctx);
2296 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2297
2298 if (is_color_format(internalFormat)) {
2299 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2300 &postConvHeight);
2301 }
2302
2303 if (target == GL_TEXTURE_2D ||
2304 (ctx->Extensions.ARB_texture_cube_map &&
2305 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2306 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ||
2307 (ctx->Extensions.NV_texture_rectangle &&
2308 target == GL_TEXTURE_RECTANGLE_NV)) {
2309 /* non-proxy target */
2310 struct gl_texture_unit *texUnit;
2311 struct gl_texture_object *texObj;
2312 struct gl_texture_image *texImage;
2313 const GLuint face = texture_face(target);
2314
2315 if (texture_error_check(ctx, target, level, internalFormat,
2316 format, type, 2, postConvWidth, postConvHeight,
2317 1, border)) {
2318 return; /* error was recorded */
2319 }
2320
2321 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2322 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2323 texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
2324 if (!texImage) {
2325 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2326 return;
2327 }
2328 else if (texImage->Data) {
2329 ctx->Driver.FreeTexImageData( ctx, texImage );
2330 }
2331 ASSERT(texImage->Data == NULL);
2332 clear_teximage_fields(texImage); /* not really needed, but helpful */
2333 _mesa_init_teximage_fields(ctx, target, texImage,
2334 postConvWidth, postConvHeight, 1,
2335 border, internalFormat);
2336
2337 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2338 _mesa_update_state(ctx);
2339
2340 ASSERT(ctx->Driver.TexImage2D);
2341
2342 /* Give the texture to the driver! <pixels> may be null! */
2343 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
2344 width, height, border, format, type, pixels,
2345 &ctx->Unpack, texObj, texImage);
2346
2347 ASSERT(texImage->TexFormat);
2348
2349 update_fbo_texture(ctx, texObj, face, level);
2350
2351 /* state update */
2352 texObj->Complete = GL_FALSE;
2353 ctx->NewState |= _NEW_TEXTURE;
2354 }
2355 else if (target == GL_PROXY_TEXTURE_2D ||
2356 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
2357 ctx->Extensions.ARB_texture_cube_map) ||
2358 (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
2359 ctx->Extensions.NV_texture_rectangle)) {
2360 /* Proxy texture: check for errors and update proxy state */
2361 struct gl_texture_image *texImage;
2362 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2363 if (texture_error_check(ctx, target, level, internalFormat,
2364 format, type, 2, postConvWidth, postConvHeight,
2365 1, border)) {
2366 /* when error, clear all proxy texture image parameters */
2367 if (texImage)
2368 clear_teximage_fields(ctx->Texture.Proxy2D->Image[0][level]);
2369 }
2370 else {
2371 /* no error, set the tex image parameters */
2372 _mesa_init_teximage_fields(ctx, target, texImage,
2373 postConvWidth, postConvHeight, 1,
2374 border, internalFormat);
2375 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2376 internalFormat, format, type);
2377 }
2378 }
2379 else {
2380 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
2381 return;
2382 }
2383 }
2384
2385
2386 /*
2387 * Called by the API or display list executor.
2388 * Note that width and height include the border.
2389 */
2390 void GLAPIENTRY
2391 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
2392 GLsizei width, GLsizei height, GLsizei depth,
2393 GLint border, GLenum format, GLenum type,
2394 const GLvoid *pixels )
2395 {
2396 GET_CURRENT_CONTEXT(ctx);
2397 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2398
2399 if (target == GL_TEXTURE_3D) {
2400 /* non-proxy target */
2401 struct gl_texture_unit *texUnit;
2402 struct gl_texture_object *texObj;
2403 struct gl_texture_image *texImage;
2404 const GLuint face = texture_face(target);
2405
2406 if (texture_error_check(ctx, target, level, (GLint) internalFormat,
2407 format, type, 3, width, height, depth, border)) {
2408 return; /* error was recorded */
2409 }
2410
2411 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2412 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2413 texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
2414 if (!texImage) {
2415 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2416 return;
2417 }
2418 else if (texImage->Data) {
2419 ctx->Driver.FreeTexImageData( ctx, texImage );
2420 }
2421 ASSERT(texImage->Data == NULL);
2422 clear_teximage_fields(texImage); /* not really needed, but helpful */
2423 _mesa_init_teximage_fields(ctx, target, texImage,
2424 width, height, depth,
2425 border, internalFormat);
2426
2427 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2428 _mesa_update_state(ctx);
2429
2430 ASSERT(ctx->Driver.TexImage3D);
2431
2432 /* Give the texture to the driver! <pixels> may be null! */
2433 (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat,
2434 width, height, depth, border, format, type,
2435 pixels, &ctx->Unpack, texObj, texImage);
2436
2437 ASSERT(texImage->TexFormat);
2438
2439 update_fbo_texture(ctx, texObj, face, level);
2440
2441 /* state update */
2442 texObj->Complete = GL_FALSE;
2443 ctx->NewState |= _NEW_TEXTURE;
2444 }
2445 else if (target == GL_PROXY_TEXTURE_3D) {
2446 /* Proxy texture: check for errors and update proxy state */
2447 struct gl_texture_image *texImage;
2448 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2449 if (texture_error_check(ctx, target, level, internalFormat,
2450 format, type, 3, width, height, depth, border)) {
2451 /* when error, clear all proxy texture image parameters */
2452 if (texImage)
2453 clear_teximage_fields(texImage);
2454 }
2455 else {
2456 /* no error, set the tex image parameters */
2457 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
2458 border, internalFormat);
2459 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2460 internalFormat, format, type);
2461 }
2462 }
2463 else {
2464 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
2465 return;
2466 }
2467 }
2468
2469
2470 void GLAPIENTRY
2471 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2472 GLsizei width, GLsizei height, GLsizei depth,
2473 GLint border, GLenum format, GLenum type,
2474 const GLvoid *pixels )
2475 {
2476 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2477 depth, border, format, type, pixels);
2478 }
2479
2480
2481
2482 void GLAPIENTRY
2483 _mesa_TexSubImage1D( GLenum target, GLint level,
2484 GLint xoffset, GLsizei width,
2485 GLenum format, GLenum type,
2486 const GLvoid *pixels )
2487 {
2488 GLsizei postConvWidth = width;
2489 struct gl_texture_unit *texUnit;
2490 struct gl_texture_object *texObj;
2491 struct gl_texture_image *texImage;
2492 GET_CURRENT_CONTEXT(ctx);
2493 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2494
2495 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2496 _mesa_update_state(ctx);
2497
2498 /* XXX should test internal format */
2499 if (is_color_format(format)) {
2500 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2501 }
2502
2503 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2504 postConvWidth, 1, 1, format, type)) {
2505 return; /* error was detected */
2506 }
2507
2508 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2509 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2510 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2511 assert(texImage);
2512
2513 if (width == 0)
2514 return; /* no-op, not an error */
2515
2516 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2517 xoffset += texImage->Border;
2518
2519 ASSERT(ctx->Driver.TexSubImage1D);
2520 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
2521 format, type, pixels, &ctx->Unpack,
2522 texObj, texImage);
2523 ctx->NewState |= _NEW_TEXTURE;
2524 }
2525
2526
2527 void GLAPIENTRY
2528 _mesa_TexSubImage2D( GLenum target, GLint level,
2529 GLint xoffset, GLint yoffset,
2530 GLsizei width, GLsizei height,
2531 GLenum format, GLenum type,
2532 const GLvoid *pixels )
2533 {
2534 GLsizei postConvWidth = width, postConvHeight = height;
2535 struct gl_texture_unit *texUnit;
2536 struct gl_texture_object *texObj;
2537 struct gl_texture_image *texImage;
2538 GET_CURRENT_CONTEXT(ctx);
2539 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2540
2541 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2542 _mesa_update_state(ctx);
2543
2544 /* XXX should test internal format */
2545 if (is_color_format(format)) {
2546 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2547 &postConvHeight);
2548 }
2549
2550 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2551 postConvWidth, postConvHeight, 1, format, type)) {
2552 return; /* error was detected */
2553 }
2554
2555 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2556 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2557 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2558 assert(texImage);
2559
2560 if (width == 0 || height == 0)
2561 return; /* no-op, not an error */
2562
2563 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2564 xoffset += texImage->Border;
2565 yoffset += texImage->Border;
2566
2567 ASSERT(ctx->Driver.TexSubImage2D);
2568 (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
2569 width, height, format, type, pixels,
2570 &ctx->Unpack, texObj, texImage);
2571 ctx->NewState |= _NEW_TEXTURE;
2572 }
2573
2574
2575
2576 void GLAPIENTRY
2577 _mesa_TexSubImage3D( GLenum target, GLint level,
2578 GLint xoffset, GLint yoffset, GLint zoffset,
2579 GLsizei width, GLsizei height, GLsizei depth,
2580 GLenum format, GLenum type,
2581 const GLvoid *pixels )
2582 {
2583 struct gl_texture_unit *texUnit;
2584 struct gl_texture_object *texObj;
2585 struct gl_texture_image *texImage;
2586 GET_CURRENT_CONTEXT(ctx);
2587 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2588
2589 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2590 _mesa_update_state(ctx);
2591
2592 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2593 width, height, depth, format, type)) {
2594 return; /* error was detected */
2595 }
2596
2597 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2598 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2599 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2600 assert(texImage);
2601
2602 if (width == 0 || height == 0 || height == 0)
2603 return; /* no-op, not an error */
2604
2605 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2606 xoffset += texImage->Border;
2607 yoffset += texImage->Border;
2608 zoffset += texImage->Border;
2609
2610 ASSERT(ctx->Driver.TexSubImage3D);
2611 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
2612 xoffset, yoffset, zoffset,
2613 width, height, depth,
2614 format, type, pixels,
2615 &ctx->Unpack, texObj, texImage );
2616 ctx->NewState |= _NEW_TEXTURE;
2617 }
2618
2619
2620
2621 void GLAPIENTRY
2622 _mesa_CopyTexImage1D( GLenum target, GLint level,
2623 GLenum internalFormat,
2624 GLint x, GLint y,
2625 GLsizei width, GLint border )
2626 {
2627 struct gl_texture_unit *texUnit;
2628 struct gl_texture_object *texObj;
2629 struct gl_texture_image *texImage;
2630 GLsizei postConvWidth = width;
2631 const GLuint face = texture_face(target);
2632 GET_CURRENT_CONTEXT(ctx);
2633 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2634
2635 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2636 _mesa_update_state(ctx);
2637
2638 if (is_color_format(internalFormat)) {
2639 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2640 }
2641
2642 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2643 postConvWidth, 1, border))
2644 return;
2645
2646 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2647 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2648 texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
2649 if (!texImage) {
2650 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
2651 return;
2652 }
2653 else if (texImage->Data) {
2654 ctx->Driver.FreeTexImageData( ctx, texImage );
2655 }
2656 ASSERT(texImage->Data == NULL);
2657
2658 clear_teximage_fields(texImage); /* not really needed, but helpful */
2659 _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
2660 border, internalFormat);
2661
2662
2663 ASSERT(ctx->Driver.CopyTexImage1D);
2664 (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
2665 x, y, width, border);
2666
2667 ASSERT(texImage->TexFormat);
2668
2669 update_fbo_texture(ctx, texObj, face, level);
2670
2671 /* state update */
2672 texObj->Complete = GL_FALSE;
2673 ctx->NewState |= _NEW_TEXTURE;
2674 }
2675
2676
2677
2678 void GLAPIENTRY
2679 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2680 GLint x, GLint y, GLsizei width, GLsizei height,
2681 GLint border )
2682 {
2683 struct gl_texture_unit *texUnit;
2684 struct gl_texture_object *texObj;
2685 struct gl_texture_image *texImage;
2686 GLsizei postConvWidth = width, postConvHeight = height;
2687 const GLuint face = texture_face(target);
2688 GET_CURRENT_CONTEXT(ctx);
2689 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2690
2691 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2692 _mesa_update_state(ctx);
2693
2694 if (is_color_format(internalFormat)) {
2695 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2696 &postConvHeight);
2697 }
2698
2699 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2700 postConvWidth, postConvHeight, border))
2701 return;
2702
2703 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2704 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2705 texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
2706 if (!texImage) {
2707 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
2708 return;
2709 }
2710 else if (texImage->Data) {
2711 ctx->Driver.FreeTexImageData( ctx, texImage );
2712 }
2713 ASSERT(texImage->Data == NULL);
2714
2715 clear_teximage_fields(texImage); /* not really needed, but helpful */
2716 _mesa_init_teximage_fields(ctx, target, texImage,
2717 postConvWidth, postConvHeight, 1,
2718 border, internalFormat);
2719
2720 ASSERT(ctx->Driver.CopyTexImage2D);
2721 (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
2722 x, y, width, height, border);
2723
2724 ASSERT(texImage->TexFormat);
2725
2726 update_fbo_texture(ctx, texObj, face, level);
2727
2728 /* state update */
2729 texObj->Complete = GL_FALSE;
2730 ctx->NewState |= _NEW_TEXTURE;
2731 }
2732
2733
2734
2735 void GLAPIENTRY
2736 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
2737 GLint xoffset, GLint x, GLint y, GLsizei width )
2738 {
2739 struct gl_texture_unit *texUnit;
2740 struct gl_texture_image *texImage;
2741 GLsizei postConvWidth = width;
2742 GET_CURRENT_CONTEXT(ctx);
2743 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2744
2745 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2746 _mesa_update_state(ctx);
2747
2748 /* XXX should test internal format */
2749 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2750
2751 if (copytexsubimage_error_check(ctx, 1, target, level,
2752 xoffset, 0, 0, postConvWidth, 1))
2753 return;
2754
2755 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2756 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2757 ASSERT(texImage);
2758
2759 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2760 xoffset += texImage->Border;
2761
2762 ASSERT(ctx->Driver.CopyTexSubImage1D);
2763 (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width);
2764 ctx->NewState |= _NEW_TEXTURE;
2765 }
2766
2767
2768
2769 void GLAPIENTRY
2770 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
2771 GLint xoffset, GLint yoffset,
2772 GLint x, GLint y, GLsizei width, GLsizei height )
2773 {
2774 struct gl_texture_unit *texUnit;
2775 struct gl_texture_image *texImage;
2776 GLsizei postConvWidth = width, postConvHeight = height;
2777 GET_CURRENT_CONTEXT(ctx);
2778 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2779
2780 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2781 _mesa_update_state(ctx);
2782
2783 /* XXX should test internal format */
2784 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
2785
2786 if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2787 postConvWidth, postConvHeight))
2788 return;
2789
2790 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2791 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2792 ASSERT(texImage);
2793
2794 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2795 xoffset += texImage->Border;
2796 yoffset += texImage->Border;
2797
2798 ASSERT(ctx->Driver.CopyTexSubImage2D);
2799 (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2800 xoffset, yoffset, x, y, width, height);
2801 ctx->NewState |= _NEW_TEXTURE;
2802 }
2803
2804
2805
2806 void GLAPIENTRY
2807 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2808 GLint xoffset, GLint yoffset, GLint zoffset,
2809 GLint x, GLint y, GLsizei width, GLsizei height )
2810 {
2811 struct gl_texture_unit *texUnit;
2812 struct gl_texture_image *texImage;
2813 GLsizei postConvWidth = width, postConvHeight = height;
2814 GET_CURRENT_CONTEXT(ctx);
2815 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2816
2817 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
2818 _mesa_update_state(ctx);
2819
2820 /* XXX should test internal format */
2821 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight);
2822
2823 if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset,
2824 zoffset, postConvWidth, postConvHeight))
2825 return;
2826
2827 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2828 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2829 ASSERT(texImage);
2830
2831 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2832 xoffset += texImage->Border;
2833 yoffset += texImage->Border;
2834 zoffset += texImage->Border;
2835
2836 ASSERT(ctx->Driver.CopyTexSubImage3D);
2837 (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2838 xoffset, yoffset, zoffset,
2839 x, y, width, height);
2840 ctx->NewState |= _NEW_TEXTURE;
2841 }
2842
2843
2844
2845
2846 /**********************************************************************/
2847 /****** Compressed Textures ******/
2848 /**********************************************************************/
2849
2850
2851 /**
2852 * Error checking for glCompressedTexImage[123]D().
2853 * \return error code or GL_NO_ERROR.
2854 */
2855 static GLenum
2856 compressed_texture_error_check(GLcontext *ctx, GLint dimensions,
2857 GLenum target, GLint level,
2858 GLenum internalFormat, GLsizei width,
2859 GLsizei height, GLsizei depth, GLint border,
2860 GLsizei imageSize)
2861 {
2862 GLint expectedSize, maxLevels = 0, maxTextureSize;
2863
2864 if (dimensions == 1) {
2865 /* 1D compressed textures not allowed */
2866 return GL_INVALID_ENUM;
2867 }
2868 else if (dimensions == 2) {
2869 if (target == GL_PROXY_TEXTURE_2D) {
2870 maxLevels = ctx->Const.MaxTextureLevels;
2871 }
2872 else if (target == GL_TEXTURE_2D) {
2873 maxLevels = ctx->Const.MaxTextureLevels;
2874 }
2875 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
2876 if (!ctx->Extensions.ARB_texture_cube_map)
2877 return GL_INVALID_ENUM; /*target*/
2878 maxLevels = ctx->Const.MaxCubeTextureLevels;
2879 }
2880 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2881 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
2882 if (!ctx->Extensions.ARB_texture_cube_map)
2883 return GL_INVALID_ENUM; /*target*/
2884 maxLevels = ctx->Const.MaxCubeTextureLevels;
2885 }
2886 else {
2887 return GL_INVALID_ENUM; /*target*/
2888 }
2889 }
2890 else if (dimensions == 3) {
2891 /* 3D compressed textures not allowed */
2892 return GL_INVALID_ENUM;
2893 }
2894
2895 maxTextureSize = 1 << (maxLevels - 1);
2896
2897 /* This will detect any invalid internalFormat value */
2898 if (!is_compressed_format(ctx, internalFormat))
2899 return GL_INVALID_ENUM;
2900
2901 /* This should really never fail */
2902 if (_mesa_base_tex_format(ctx, internalFormat) < 0)
2903 return GL_INVALID_ENUM;
2904
2905 if (border != 0)
2906 return GL_INVALID_VALUE;
2907
2908 /*
2909 * XXX We should probably use the proxy texture error check function here.
2910 */
2911 if (width < 1 || width > maxTextureSize ||
2912 (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(width) != 1))
2913 return GL_INVALID_VALUE;
2914
2915 if ((height < 1 || height > maxTextureSize ||
2916 (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(height) != 1))
2917 && dimensions > 1)
2918 return GL_INVALID_VALUE;
2919
2920 if ((depth < 1 || depth > maxTextureSize ||
2921 (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(depth) != 1))
2922 && dimensions > 2)
2923 return GL_INVALID_VALUE;
2924
2925 /* For cube map, width must equal height */
2926 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2927 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
2928 return GL_INVALID_VALUE;
2929
2930 if (level < 0 || level >= maxLevels)
2931 return GL_INVALID_VALUE;
2932
2933 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
2934 depth, internalFormat);
2935 if (expectedSize != imageSize)
2936 return GL_INVALID_VALUE;
2937
2938 return GL_NO_ERROR;
2939 }
2940
2941
2942 /**
2943 * Error checking for glCompressedTexSubImage[123]D().
2944 * \warning There are some bad assumptions here about the size of compressed
2945 * texture tiles (multiple of 4) used to test the validity of the
2946 * offset and size parameters.
2947 * \return error code or GL_NO_ERROR.
2948 */
2949 static GLenum
2950 compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions,
2951 GLenum target, GLint level,
2952 GLint xoffset, GLint yoffset, GLint zoffset,
2953 GLsizei width, GLsizei height, GLsizei depth,
2954 GLenum format, GLsizei imageSize)
2955 {
2956 GLint expectedSize, maxLevels = 0, maxTextureSize;
2957 (void) zoffset;
2958
2959 if (dimensions == 1) {
2960 /* 1D compressed textures not allowed */
2961 return GL_INVALID_ENUM;
2962 }
2963 else if (dimensions == 2) {
2964 if (target == GL_PROXY_TEXTURE_2D) {
2965 maxLevels = ctx->Const.MaxTextureLevels;
2966 }
2967 else if (target == GL_TEXTURE_2D) {
2968 maxLevels = ctx->Const.MaxTextureLevels;
2969 }
2970 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
2971 if (!ctx->Extensions.ARB_texture_cube_map)
2972 return GL_INVALID_ENUM; /*target*/
2973 maxLevels = ctx->Const.MaxCubeTextureLevels;
2974 }
2975 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2976 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
2977 if (!ctx->Extensions.ARB_texture_cube_map)
2978 return GL_INVALID_ENUM; /*target*/
2979 maxLevels = ctx->Const.MaxCubeTextureLevels;
2980 }
2981 else {
2982 return GL_INVALID_ENUM; /*target*/
2983 }
2984 }
2985 else if (dimensions == 3) {
2986 /* 3D compressed textures not allowed */
2987 return GL_INVALID_ENUM;
2988 }
2989
2990 maxTextureSize = 1 << (maxLevels - 1);
2991
2992 /* this will catch any invalid compressed format token */
2993 if (!is_compressed_format(ctx, format))
2994 return GL_INVALID_ENUM;
2995
2996 if (width < 1 || width > maxTextureSize)
2997 return GL_INVALID_VALUE;
2998
2999 if ((height < 1 || height > maxTextureSize)
3000 && dimensions > 1)
3001 return GL_INVALID_VALUE;
3002
3003 if (level < 0 || level >= maxLevels)
3004 return GL_INVALID_VALUE;
3005
3006 /* XXX these tests are specific to the compressed format.
3007 * this code should be generalized in some way.
3008 */
3009 if ((xoffset & 3) != 0 || (yoffset & 3) != 0)
3010 return GL_INVALID_VALUE;
3011
3012 if ((width & 3) != 0 && width != 2 && width != 1)
3013 return GL_INVALID_VALUE;
3014
3015 if ((height & 3) != 0 && height != 2 && height != 1)
3016 return GL_INVALID_VALUE;
3017
3018 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
3019 depth, format);
3020 if (expectedSize != imageSize)
3021 return GL_INVALID_VALUE;
3022
3023 return GL_NO_ERROR;
3024 }
3025
3026
3027
3028 void GLAPIENTRY
3029 _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
3030 GLenum internalFormat, GLsizei width,
3031 GLint border, GLsizei imageSize,
3032 const GLvoid *data)
3033 {
3034 GET_CURRENT_CONTEXT(ctx);
3035 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3036
3037 if (target == GL_TEXTURE_1D) {
3038 /* non-proxy target */
3039 struct gl_texture_unit *texUnit;
3040 struct gl_texture_object *texObj;
3041 struct gl_texture_image *texImage;
3042 GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3043 internalFormat, width, 1, 1, border, imageSize);
3044 if (error) {
3045 _mesa_error(ctx, error, "glCompressedTexImage1D");
3046 return;
3047 }
3048
3049 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3050 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3051 texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
3052 if (!texImage) {
3053 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
3054 return;
3055 }
3056 else if (texImage->Data) {
3057 ctx->Driver.FreeTexImageData( ctx, texImage );
3058 }
3059 ASSERT(texImage->Data == NULL);
3060
3061 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3062 border, internalFormat);
3063
3064 ASSERT(ctx->Driver.CompressedTexImage1D);
3065 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
3066 internalFormat, width, border,
3067 imageSize, data,
3068 texObj, texImage);
3069
3070 /* state update */
3071 texObj->Complete = GL_FALSE;
3072 ctx->NewState |= _NEW_TEXTURE;
3073 }
3074 else if (target == GL_PROXY_TEXTURE_1D) {
3075 /* Proxy texture: check for errors and update proxy state */
3076 GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3077 internalFormat, width, 1, 1, border, imageSize);
3078 if (!error) {
3079 ASSERT(ctx->Driver.TestProxyTexImage);
3080 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3081 internalFormat, GL_NONE, GL_NONE,
3082 width, 1, 1, border);
3083 }
3084 if (error) {
3085 /* if error, clear all proxy texture image parameters */
3086 struct gl_texture_image *texImage;
3087 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3088 if (texImage)
3089 clear_teximage_fields(texImage);
3090 }
3091 else {
3092 /* store the teximage parameters */
3093 struct gl_texture_unit *texUnit;
3094 struct gl_texture_image *texImage;
3095 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3096 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3097 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3098 border, internalFormat);
3099 }
3100 }
3101 else {
3102 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
3103 return;
3104 }
3105 }
3106
3107
3108 void GLAPIENTRY
3109 _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3110 GLenum internalFormat, GLsizei width,
3111 GLsizei height, GLint border, GLsizei imageSize,
3112 const GLvoid *data)
3113 {
3114 GET_CURRENT_CONTEXT(ctx);
3115 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3116
3117 if (target == GL_TEXTURE_2D ||
3118 (ctx->Extensions.ARB_texture_cube_map &&
3119 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3120 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3121 /* non-proxy target */
3122 struct gl_texture_unit *texUnit;
3123 struct gl_texture_object *texObj;
3124 struct gl_texture_image *texImage;
3125 GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3126 internalFormat, width, height, 1, border, imageSize);
3127 if (error) {
3128 _mesa_error(ctx, error, "glCompressedTexImage2D");
3129 return;
3130 }
3131
3132 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3133 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3134 texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
3135 if (!texImage) {
3136 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
3137 return;
3138 }
3139 else if (texImage->Data) {
3140 ctx->Driver.FreeTexImageData( ctx, texImage );
3141 }
3142 ASSERT(texImage->Data == NULL);
3143
3144 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3145 border, internalFormat);
3146
3147 ASSERT(ctx->Driver.CompressedTexImage2D);
3148 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
3149 internalFormat, width, height,
3150 border, imageSize, data,
3151 texObj, texImage);
3152
3153 /* state update */
3154 texObj->Complete = GL_FALSE;
3155 ctx->NewState |= _NEW_TEXTURE;
3156 }
3157 else if (target == GL_PROXY_TEXTURE_2D ||
3158 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
3159 ctx->Extensions.ARB_texture_cube_map)) {
3160 /* Proxy texture: check for errors and update proxy state */
3161 GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3162 internalFormat, width, height, 1, border, imageSize);
3163 if (!error) {
3164 ASSERT(ctx->Driver.TestProxyTexImage);
3165 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3166 internalFormat, GL_NONE, GL_NONE,
3167 width, height, 1, border);
3168 }
3169 if (error) {
3170 /* if error, clear all proxy texture image parameters */
3171 struct gl_texture_image *texImage;
3172 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3173 if (texImage)
3174 clear_teximage_fields(texImage);
3175 }
3176 else {
3177 /* store the teximage parameters */
3178 struct gl_texture_unit *texUnit;
3179 struct gl_texture_image *texImage;
3180 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3181 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3182 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3183 border, internalFormat);
3184 }
3185 }
3186 else {
3187 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
3188 return;
3189 }
3190 }
3191
3192
3193 void GLAPIENTRY
3194 _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3195 GLenum internalFormat, GLsizei width,
3196 GLsizei height, GLsizei depth, GLint border,
3197 GLsizei imageSize, const GLvoid *data)
3198 {
3199 GET_CURRENT_CONTEXT(ctx);
3200 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3201
3202 if (target == GL_TEXTURE_3D) {
3203 /* non-proxy target */
3204 struct gl_texture_unit *texUnit;
3205 struct gl_texture_object *texObj;
3206 struct gl_texture_image *texImage;
3207 GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3208 internalFormat, width, height, depth, border, imageSize);
3209 if (error) {
3210 _mesa_error(ctx, error, "glCompressedTexImage3D");
3211 return;
3212 }
3213
3214 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3215 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3216 texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
3217 if (!texImage) {
3218 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
3219 return;
3220 }
3221 else if (texImage->Data) {
3222 ctx->Driver.FreeTexImageData( ctx, texImage );
3223 }
3224 ASSERT(texImage->Data == NULL);
3225
3226 _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth,
3227 border, internalFormat);
3228
3229 ASSERT(ctx->Driver.CompressedTexImage3D);
3230 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3231 internalFormat,
3232 width, height, depth,
3233 border, imageSize, data,
3234 texObj, texImage);
3235
3236 /* state update */
3237 texObj->Complete = GL_FALSE;
3238 ctx->NewState |= _NEW_TEXTURE;
3239 }
3240 else if (target == GL_PROXY_TEXTURE_3D) {
3241 /* Proxy texture: check for errors and update proxy state */
3242 GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3243 internalFormat, width, height, depth, border, imageSize);
3244 if (!error) {
3245 ASSERT(ctx->Driver.TestProxyTexImage);
3246 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3247 internalFormat, GL_NONE, GL_NONE,
3248 width, height, depth, border);
3249 }
3250 if (error) {
3251 /* if error, clear all proxy texture image parameters */
3252 struct gl_texture_image *texImage;
3253 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3254 if (texImage)
3255 clear_teximage_fields(texImage);
3256 }
3257 else {
3258 /* store the teximage parameters */
3259 struct gl_texture_unit *texUnit;
3260 struct gl_texture_image *texImage;
3261 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3262 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3263 _mesa_init_teximage_fields(ctx, target, texImage, width, height,
3264 depth, border, internalFormat);
3265 }
3266 }
3267 else {
3268 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
3269 return;
3270 }
3271 }
3272
3273
3274 void GLAPIENTRY
3275 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3276 GLsizei width, GLenum format,
3277 GLsizei imageSize, const GLvoid *data)
3278 {
3279 struct gl_texture_unit *texUnit;
3280 struct gl_texture_object *texObj;
3281 struct gl_texture_image *texImage;
3282 GLenum error;
3283 GET_CURRENT_CONTEXT(ctx);
3284 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3285
3286 error = compressed_subtexture_error_check(ctx, 1, target, level,
3287 xoffset, 0, 0, /* pos */
3288 width, 1, 1, /* size */
3289 format, imageSize);
3290 if (error) {
3291 _mesa_error(ctx, error, "glCompressedTexSubImage1D");
3292 return;
3293 }
3294
3295 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3296 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3297 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3298 assert(texImage);
3299
3300 if ((GLint) format != texImage->InternalFormat) {
3301 _mesa_error(ctx, GL_INVALID_OPERATION,
3302 "glCompressedTexSubImage1D(format)");
3303 return;
3304 }
3305
3306 if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) {
3307 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)");
3308 return;
3309 }
3310
3311 if (width == 0)
3312 return; /* no-op, not an error */
3313
3314 if (ctx->Driver.CompressedTexSubImage1D) {
3315 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3316 xoffset, width,
3317 format, imageSize, data,
3318 texObj, texImage);
3319 }
3320 ctx->NewState |= _NEW_TEXTURE;
3321 }
3322
3323
3324 void GLAPIENTRY
3325 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3326 GLint yoffset, GLsizei width, GLsizei height,
3327 GLenum format, GLsizei imageSize,
3328 const GLvoid *data)
3329 {
3330 struct gl_texture_unit *texUnit;
3331 struct gl_texture_object *texObj;
3332 struct gl_texture_image *texImage;
3333 GLenum error;
3334 GET_CURRENT_CONTEXT(ctx);
3335 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3336
3337 error = compressed_subtexture_error_check(ctx, 2, target, level,
3338 xoffset, yoffset, 0, /* pos */
3339 width, height, 1, /* size */
3340 format, imageSize);
3341 if (error) {
3342 /* XXX proxy target? */
3343 _mesa_error(ctx, error, "glCompressedTexSubImage2D");
3344 return;
3345 }
3346
3347 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3348 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3349 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3350 assert(texImage);
3351
3352 if ((GLint) format != texImage->InternalFormat) {
3353 _mesa_error(ctx, GL_INVALID_OPERATION,
3354 "glCompressedTexSubImage2D(format)");
3355 return;
3356 }
3357
3358 if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
3359 ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) {
3360 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)");
3361 return;
3362 }
3363
3364 if (width == 0 || height == 0)
3365 return; /* no-op, not an error */
3366
3367 if (ctx->Driver.CompressedTexSubImage2D) {
3368 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3369 xoffset, yoffset, width, height,
3370 format, imageSize, data,
3371 texObj, texImage);
3372 }
3373 ctx->NewState |= _NEW_TEXTURE;
3374 }
3375
3376
3377 void GLAPIENTRY
3378 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3379 GLint yoffset, GLint zoffset, GLsizei width,
3380 GLsizei height, GLsizei depth, GLenum format,
3381 GLsizei imageSize, const GLvoid *data)
3382 {
3383 struct gl_texture_unit *texUnit;
3384 struct gl_texture_object *texObj;
3385 struct gl_texture_image *texImage;
3386 GLenum error;
3387 GET_CURRENT_CONTEXT(ctx);
3388 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3389
3390 error = compressed_subtexture_error_check(ctx, 3, target, level,
3391 xoffset, yoffset, zoffset,/*pos*/
3392 width, height, depth, /*size*/
3393 format, imageSize);
3394 if (error) {
3395 _mesa_error(ctx, error, "glCompressedTexSubImage2D");
3396 return;
3397 }
3398
3399 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3400 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3401 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3402 assert(texImage);
3403
3404 if ((GLint) format != texImage->InternalFormat) {
3405 _mesa_error(ctx, GL_INVALID_OPERATION,
3406 "glCompressedTexSubImage3D(format)");
3407 return;
3408 }
3409
3410 if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
3411 ((height == 1 || height == 2) && (GLuint) height != texImage->Height) ||
3412 ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) {
3413 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)");
3414 return;
3415 }
3416
3417 if (width == 0 || height == 0 || depth == 0)
3418 return; /* no-op, not an error */
3419
3420 if (ctx->Driver.CompressedTexSubImage3D) {
3421 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3422 xoffset, yoffset, zoffset,
3423 width, height, depth,
3424 format, imageSize, data,
3425 texObj, texImage);
3426 }
3427 ctx->NewState |= _NEW_TEXTURE;
3428 }
3429
3430
3431 void GLAPIENTRY
3432 _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
3433 {
3434 const struct gl_texture_unit *texUnit;
3435 const struct gl_texture_object *texObj;
3436 struct gl_texture_image *texImage;
3437 GLint maxLevels;
3438 GET_CURRENT_CONTEXT(ctx);
3439 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3440
3441 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3442 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3443 if (!texObj) {
3444 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
3445 return;
3446 }
3447
3448 maxLevels = _mesa_max_texture_levels(ctx, target);
3449 ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */
3450
3451 if (level < 0 || level >= maxLevels) {
3452 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3453 return;
3454 }
3455
3456 if (_mesa_is_proxy_texture(target)) {
3457 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3458 return;
3459 }
3460
3461 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3462 if (!texImage) {
3463 /* probably invalid mipmap level */
3464 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3465 return;
3466 }
3467
3468 if (!texImage->IsCompressed) {
3469 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3470 return;
3471 }
3472
3473 /* this typically calls _mesa_get_compressed_teximage() */
3474 ctx->Driver.GetCompressedTexImage(ctx, target, level, img, texObj,texImage);
3475 }