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