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