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