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