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