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