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