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