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