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