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