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