2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
28 * Texture images manipulation functions.
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
34 * \note Device drivers are free to implement any internal format they want.
45 #include "texcompress.h"
46 #include "texformat.h"
54 static void PrintTexture(GLcontext
*ctx
, const struct gl_texture_image
*img
)
56 #if CHAN_TYPE == GL_FLOAT
57 _mesa_problem(NULL
, "PrintTexture doesn't support float channels");
60 const GLchan
*data
= (const GLchan
*) img
->Data
;
63 _mesa_printf("No texture data\n");
67 switch (img
->Format
) {
74 case GL_LUMINANCE_ALPHA
:
84 _mesa_problem(NULL
, "error in PrintTexture\n");
88 for (i
= 0; i
< img
->Height
; i
++) {
89 for (j
= 0; j
< img
->Width
; j
++) {
91 _mesa_printf("%02x ", data
[0]);
93 _mesa_printf("%02x%02x ", data
[0], data
[1]);
95 _mesa_printf("%02x%02x%02x ", data
[0], data
[1], data
[2]);
97 _mesa_printf("%02x%02x%02x%02x ", data
[0], data
[1], data
[2], data
[3]);
98 data
+= (img
->RowStride
- img
->Width
) * c
;
108 * Compute floor(log_base_2(n)).
109 * If n < 0 return -1.
138 * Get base internal format.
140 * \param ctx GL context.
141 * \param format internal texture format enum or 1, 2, 3, 4.
143 * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
144 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
146 * This is the format which is used during texture application (i.e. the
147 * texture format and env mode determine the arithmetic used.
150 _mesa_base_tex_format( GLcontext
*ctx
, GLint format
)
153 * Ask the driver for the base format, if it doesn't
154 * know, it will return -1;
171 case GL_LUMINANCE_ALPHA
:
172 case GL_LUMINANCE4_ALPHA4
:
173 case GL_LUMINANCE6_ALPHA2
:
174 case GL_LUMINANCE8_ALPHA8
:
175 case GL_LUMINANCE12_ALPHA4
:
176 case GL_LUMINANCE12_ALPHA12
:
177 case GL_LUMINANCE16_ALPHA16
:
178 return GL_LUMINANCE_ALPHA
;
206 case GL_COLOR_INDEX1_EXT
:
207 case GL_COLOR_INDEX2_EXT
:
208 case GL_COLOR_INDEX4_EXT
:
209 case GL_COLOR_INDEX8_EXT
:
210 case GL_COLOR_INDEX12_EXT
:
211 case GL_COLOR_INDEX16_EXT
:
212 if (ctx
->Extensions
.EXT_paletted_texture
)
213 return GL_COLOR_INDEX
;
216 case GL_DEPTH_COMPONENT
:
217 case GL_DEPTH_COMPONENT16_SGIX
:
218 case GL_DEPTH_COMPONENT24_SGIX
:
219 case GL_DEPTH_COMPONENT32_SGIX
:
220 if (ctx
->Extensions
.SGIX_depth_texture
)
221 return GL_DEPTH_COMPONENT
;
225 /* GL_ARB_texture_compression */
226 case GL_COMPRESSED_ALPHA
:
227 if (ctx
->Extensions
.ARB_texture_compression
)
231 case GL_COMPRESSED_LUMINANCE
:
232 if (ctx
->Extensions
.ARB_texture_compression
)
236 case GL_COMPRESSED_LUMINANCE_ALPHA
:
237 if (ctx
->Extensions
.ARB_texture_compression
)
238 return GL_LUMINANCE_ALPHA
;
241 case GL_COMPRESSED_INTENSITY
:
242 if (ctx
->Extensions
.ARB_texture_compression
)
246 case GL_COMPRESSED_RGB
:
247 if (ctx
->Extensions
.ARB_texture_compression
)
251 case GL_COMPRESSED_RGBA
:
252 if (ctx
->Extensions
.ARB_texture_compression
)
256 case GL_COMPRESSED_RGB_FXT1_3DFX
:
257 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
)
261 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
262 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
)
266 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
267 if (ctx
->Extensions
.EXT_texture_compression_s3tc
)
271 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
272 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
273 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
274 if (ctx
->Extensions
.EXT_texture_compression_s3tc
)
280 if (ctx
->Extensions
.S3_s3tc
)
286 if (ctx
->Extensions
.S3_s3tc
)
292 if (ctx
->Extensions
.MESA_ycbcr_texture
)
293 return GL_YCBCR_MESA
;
298 return -1; /* error */
304 * Test if the given image format is a color/RGBA format, i.e., not
305 * color index, depth, stencil, etc.
308 is_color_format(GLenum format
)
323 case GL_LUMINANCE_ALPHA
:
324 case GL_LUMINANCE4_ALPHA4
:
325 case GL_LUMINANCE6_ALPHA2
:
326 case GL_LUMINANCE8_ALPHA8
:
327 case GL_LUMINANCE12_ALPHA4
:
328 case GL_LUMINANCE12_ALPHA12
:
329 case GL_LUMINANCE16_ALPHA16
:
354 case GL_YCBCR_MESA
: /* not considered to be RGB */
362 * Test if the given image format is a color index format.
365 is_index_format(GLenum format
)
369 case GL_COLOR_INDEX1_EXT
:
370 case GL_COLOR_INDEX2_EXT
:
371 case GL_COLOR_INDEX4_EXT
:
372 case GL_COLOR_INDEX8_EXT
:
373 case GL_COLOR_INDEX12_EXT
:
374 case GL_COLOR_INDEX16_EXT
:
383 * Test if it is a supported compressed format.
385 * \param internalFormat the internal format token provided by the user.
387 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
388 * GL_FALSE otherwise.
390 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
394 is_compressed_format(GLcontext
*ctx
, GLenum internalFormat
)
396 switch (internalFormat
) {
397 case GL_COMPRESSED_RGB_FXT1_3DFX
:
398 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
399 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
400 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
401 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
402 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
409 if (ctx
->Driver
.IsCompressedFormat
) {
410 return ctx
->Driver
.IsCompressedFormat(ctx
, internalFormat
);
418 * Store a gl_texture_image pointer in a gl_texture_object structure
419 * according to the target and level parameters.
421 * \param tObj texture object.
422 * \param target texture target.
423 * \param level image level.
424 * \param texImage texture image.
426 * This was basically prompted by the introduction of cube maps.
429 _mesa_set_tex_image(struct gl_texture_object
*tObj
,
430 GLenum target
, GLint level
,
431 struct gl_texture_image
*texImage
)
439 tObj
->Image
[level
] = texImage
;
441 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
442 tObj
->Image
[level
] = texImage
;
444 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
445 tObj
->NegX
[level
] = texImage
;
447 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
448 tObj
->PosY
[level
] = texImage
;
450 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
451 tObj
->NegY
[level
] = texImage
;
453 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
454 tObj
->PosZ
[level
] = texImage
;
456 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
457 tObj
->NegZ
[level
] = texImage
;
459 case GL_TEXTURE_RECTANGLE_NV
:
461 tObj
->Image
[level
] = texImage
;
464 _mesa_problem(NULL
, "bad target in _mesa_set_tex_image()");
471 * Allocate a texture image structure.
473 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
476 * \return a pointer to gl_texture_image struct with all fields initialized to
479 struct gl_texture_image
*
480 _mesa_new_texture_image( GLcontext
*ctx
)
483 return CALLOC_STRUCT(gl_texture_image
);
488 * Free texture image.
490 * \param teximage texture image.
492 * Free the texture image structure and the associated image data if it's not
493 * marked as client data.
496 _mesa_delete_texture_image( struct gl_texture_image
*teximage
)
498 if (teximage
->Data
&& !teximage
->IsClientData
) {
499 MESA_PBUFFER_FREE( teximage
->Data
);
500 teximage
->Data
= NULL
;
507 * Test if a target is a proxy target.
509 * \param target texture target.
511 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
514 is_proxy_target(GLenum target
)
516 return (target
== GL_PROXY_TEXTURE_1D
||
517 target
== GL_PROXY_TEXTURE_2D
||
518 target
== GL_PROXY_TEXTURE_3D
||
519 target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
520 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
);
525 * Get the texture object that corresponds to the target of the given texture unit.
527 * \param ctx GL context.
528 * \param texUnit texture unit.
529 * \param target texture target.
531 * \return pointer to the texture object on success, or NULL on failure.
533 * \sa gl_texture_unit.
535 struct gl_texture_object
*
536 _mesa_select_tex_object(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
541 return texUnit
->Current1D
;
542 case GL_PROXY_TEXTURE_1D
:
543 return ctx
->Texture
.Proxy1D
;
545 return texUnit
->Current2D
;
546 case GL_PROXY_TEXTURE_2D
:
547 return ctx
->Texture
.Proxy2D
;
549 return texUnit
->Current3D
;
550 case GL_PROXY_TEXTURE_3D
:
551 return ctx
->Texture
.Proxy3D
;
552 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
553 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
554 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
555 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
556 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
557 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
558 case GL_TEXTURE_CUBE_MAP_ARB
:
559 return ctx
->Extensions
.ARB_texture_cube_map
560 ? texUnit
->CurrentCubeMap
: NULL
;
561 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
562 return ctx
->Extensions
.ARB_texture_cube_map
563 ? ctx
->Texture
.ProxyCubeMap
: NULL
;
564 case GL_TEXTURE_RECTANGLE_NV
:
565 return ctx
->Extensions
.NV_texture_rectangle
566 ? texUnit
->CurrentRect
: NULL
;
567 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
568 return ctx
->Extensions
.NV_texture_rectangle
569 ? ctx
->Texture
.ProxyRect
: NULL
;
571 _mesa_problem(NULL
, "bad target in _mesa_select_tex_object()");
578 * Get the texture image struct which corresponds to target and level
579 * of the given texture unit.
581 * \param ctx GL context.
582 * \param texUnit texture unit.
583 * \param target texture target.
584 * \param level image level.
586 * \return pointer to the texture image structure on success, or NULL on failure.
588 * \sa gl_texture_unit.
590 struct gl_texture_image
*
591 _mesa_select_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
592 GLenum target
, GLint level
)
595 ASSERT(level
< MAX_TEXTURE_LEVELS
);
598 return texUnit
->Current1D
->Image
[level
];
599 case GL_PROXY_TEXTURE_1D
:
600 return ctx
->Texture
.Proxy1D
->Image
[level
];
602 return texUnit
->Current2D
->Image
[level
];
603 case GL_PROXY_TEXTURE_2D
:
604 return ctx
->Texture
.Proxy2D
->Image
[level
];
606 return texUnit
->Current3D
->Image
[level
];
607 case GL_PROXY_TEXTURE_3D
:
608 return ctx
->Texture
.Proxy3D
->Image
[level
];
609 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
610 if (ctx
->Extensions
.ARB_texture_cube_map
)
611 return texUnit
->CurrentCubeMap
->Image
[level
];
614 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
615 if (ctx
->Extensions
.ARB_texture_cube_map
)
616 return texUnit
->CurrentCubeMap
->NegX
[level
];
619 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
620 if (ctx
->Extensions
.ARB_texture_cube_map
)
621 return texUnit
->CurrentCubeMap
->PosY
[level
];
624 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
625 if (ctx
->Extensions
.ARB_texture_cube_map
)
626 return texUnit
->CurrentCubeMap
->NegY
[level
];
629 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
630 if (ctx
->Extensions
.ARB_texture_cube_map
)
631 return texUnit
->CurrentCubeMap
->PosZ
[level
];
634 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
635 if (ctx
->Extensions
.ARB_texture_cube_map
)
636 return texUnit
->CurrentCubeMap
->NegZ
[level
];
639 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
640 if (ctx
->Extensions
.ARB_texture_cube_map
)
641 return ctx
->Texture
.ProxyCubeMap
->Image
[level
];
644 case GL_TEXTURE_RECTANGLE_NV
:
645 if (ctx
->Extensions
.NV_texture_rectangle
) {
647 return texUnit
->CurrentRect
->Image
[level
];
652 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
653 if (ctx
->Extensions
.NV_texture_rectangle
) {
655 return ctx
->Texture
.ProxyRect
->Image
[level
];
661 _mesa_problem(ctx
, "bad target in _mesa_select_tex_image()");
668 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
669 * it and install it. Only return NULL if passed a bad parameter or run
672 struct gl_texture_image
*
673 _mesa_get_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
674 GLenum target
, GLint level
)
676 struct gl_texture_image
*texImage
;
677 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
679 struct gl_texture_object
*texObj
;
680 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
682 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture image allocation");
685 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
687 _mesa_set_tex_image(texObj
, target
, level
, texImage
);
694 * Return pointer to the specified proxy texture image.
695 * Note that proxy textures are per-context, not per-texture unit.
696 * \return pointer to texture image or NULL if invalid target, invalid
697 * level, or out of memory.
699 struct gl_texture_image
*
700 _mesa_get_proxy_tex_image(GLcontext
*ctx
, GLenum target
, GLint level
)
702 struct gl_texture_image
*texImage
;
708 case GL_PROXY_TEXTURE_1D
:
709 if (level
>= ctx
->Const
.MaxTextureLevels
)
711 texImage
= ctx
->Texture
.Proxy1D
->Image
[level
];
713 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
715 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
718 ctx
->Texture
.Proxy1D
->Image
[level
] = texImage
;
721 case GL_PROXY_TEXTURE_2D
:
722 if (level
>= ctx
->Const
.MaxTextureLevels
)
724 texImage
= ctx
->Texture
.Proxy2D
->Image
[level
];
726 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
728 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
731 ctx
->Texture
.Proxy2D
->Image
[level
] = texImage
;
734 case GL_PROXY_TEXTURE_3D
:
735 if (level
>= ctx
->Const
.Max3DTextureLevels
)
737 texImage
= ctx
->Texture
.Proxy3D
->Image
[level
];
739 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
741 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
744 ctx
->Texture
.Proxy3D
->Image
[level
] = texImage
;
747 case GL_PROXY_TEXTURE_CUBE_MAP
:
748 if (level
>= ctx
->Const
.MaxCubeTextureLevels
)
750 texImage
= ctx
->Texture
.ProxyCubeMap
->Image
[level
];
752 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
754 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
757 ctx
->Texture
.ProxyCubeMap
->Image
[level
] = texImage
;
760 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
763 texImage
= ctx
->Texture
.ProxyRect
->Image
[level
];
765 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
767 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
770 ctx
->Texture
.ProxyRect
->Image
[level
] = texImage
;
780 * Get the maximum number of allowed mipmap levels.
782 * \param ctx GL context.
783 * \param target texture target.
785 * \return the maximum number of allowed mipmap levels for the given
786 * texture target, or zero if passed a bad target.
791 _mesa_max_texture_levels(GLcontext
*ctx
, GLenum target
)
795 case GL_PROXY_TEXTURE_1D
:
797 case GL_PROXY_TEXTURE_2D
:
798 return ctx
->Const
.MaxTextureLevels
;
800 case GL_PROXY_TEXTURE_3D
:
801 return ctx
->Const
.Max3DTextureLevels
;
802 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
803 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
804 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
805 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
806 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
807 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
808 case GL_TEXTURE_CUBE_MAP_ARB
:
809 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
810 return ctx
->Const
.MaxCubeTextureLevels
;
812 case GL_TEXTURE_RECTANGLE_NV
:
813 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
817 return 0; /* bad target */
823 #if 000 /* not used anymore */
825 * glTexImage[123]D can accept a NULL image pointer. In this case we
826 * create a texture image with unspecified image contents per the OpenGL
830 make_null_texture(GLint width
, GLint height
, GLint depth
, GLenum format
)
832 const GLint components
= _mesa_components_in_format(format
);
833 const GLint numPixels
= width
* height
* depth
;
834 GLubyte
*data
= (GLubyte
*) MALLOC(numPixels
* components
* sizeof(GLubyte
));
838 * Let's see if anyone finds this. If glTexImage2D() is called with
839 * a NULL image pointer then load the texture image with something
840 * interesting instead of leaving it indeterminate.
843 static const char message
[8][32] = {
847 " X X XXXX XXX XXXXX ",
850 " X X XXXXX XXX X X ",
854 GLubyte
*imgPtr
= data
;
856 for (h
= 0; h
< depth
; h
++) {
857 for (i
= 0; i
< height
; i
++) {
858 GLint srcRow
= 7 - (i
% 8);
859 for (j
= 0; j
< width
; j
++) {
860 GLint srcCol
= j
% 32;
861 GLubyte texel
= (message
[srcRow
][srcCol
]=='X') ? 255 : 70;
862 for (k
= 0; k
< components
; k
++) {
878 * Reset the fields of a gl_texture_image struct to zero.
880 * \param img texture image structure.
882 * This is called when a proxy texture test fails, we set all the
883 * image members (except DriverData) to zero.
884 * It's also used in glTexImage[123]D as a safeguard to be sure all
885 * required fields get initialized properly by the Driver.TexImage[123]D
889 clear_teximage_fields(struct gl_texture_image
*img
)
906 img
->TexFormat
= &_mesa_null_texformat
;
907 img
->FetchTexelc
= NULL
;
908 img
->FetchTexelf
= NULL
;
909 img
->IsCompressed
= 0;
910 img
->CompressedSize
= 0;
915 * Initialize basic fields of the gl_texture_image struct.
917 * \param ctx GL context.
918 * \param target texture target.
919 * \param img texture image structure to be initialized.
920 * \param width image width.
921 * \param height image height.
922 * \param depth image depth.
923 * \param border image border.
924 * \param internalFormat internal format.
926 * Fills in the fields of \p img with the given information.
927 * Note: width, height and depth include the border.
930 _mesa_init_teximage_fields(GLcontext
*ctx
, GLenum target
,
931 struct gl_texture_image
*img
,
932 GLsizei width
, GLsizei height
, GLsizei depth
,
933 GLint border
, GLenum internalFormat
)
936 img
->Format
= _mesa_base_tex_format( ctx
, internalFormat
);
937 ASSERT(img
->Format
> 0);
938 img
->IntFormat
= internalFormat
;
939 img
->Border
= border
;
941 img
->Height
= height
;
943 img
->RowStride
= width
;
944 img
->WidthLog2
= logbase2(width
- 2 * border
);
945 if (height
== 1) /* 1-D texture */
948 img
->HeightLog2
= logbase2(height
- 2 * border
);
949 if (depth
== 1) /* 2-D texture */
952 img
->DepthLog2
= logbase2(depth
- 2 * border
);
953 img
->Width2
= width
- 2 * border
; /*1 << img->WidthLog2;*/
954 img
->Height2
= height
- 2 * border
; /*1 << img->HeightLog2;*/
955 img
->Depth2
= depth
- 2 * border
; /*1 << img->DepthLog2;*/
956 img
->MaxLog2
= MAX2(img
->WidthLog2
, img
->HeightLog2
);
957 img
->IsCompressed
= is_compressed_format(ctx
, internalFormat
);
958 if (img
->IsCompressed
)
959 img
->CompressedSize
= _mesa_compressed_texture_size(ctx
, width
, height
,
960 depth
, internalFormat
);
962 img
->CompressedSize
= 0;
964 if ((width
== 1 || _mesa_bitcount(width
- 2 * border
) == 1) &&
965 (height
== 1 || _mesa_bitcount(height
- 2 * border
) == 1) &&
966 (depth
== 1 || _mesa_bitcount(depth
- 2 * border
) == 1))
967 img
->_IsPowerOfTwo
= GL_TRUE
;
969 img
->_IsPowerOfTwo
= GL_FALSE
;
971 /* Compute Width/Height/DepthScale for mipmap lod computation */
972 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
973 /* scale = 1.0 since texture coords directly map to texels */
974 img
->WidthScale
= 1.0;
975 img
->HeightScale
= 1.0;
976 img
->DepthScale
= 1.0;
979 img
->WidthScale
= (GLfloat
) img
->Width
;
980 img
->HeightScale
= (GLfloat
) img
->Height
;
981 img
->DepthScale
= (GLfloat
) img
->Depth
;
987 * This is the fallback for Driver.TestProxyTexImage(). Test the texture
988 * level, width, height and depth against the ctx->Const limits for textures.
990 * A hardware driver might override this function if, for example, the
991 * max 3D texture size is 512x512x64 (i.e. not a cube).
993 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
994 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
995 * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
996 * \param level as passed to glTexImage
997 * \param internalFormat as passed to glTexImage
998 * \param format as passed to glTexImage
999 * \param type as passed to glTexImage
1000 * \param width as passed to glTexImage
1001 * \param height as passed to glTexImage
1002 * \param depth as passed to glTexImage
1003 * \param border as passed to glTexImage
1004 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1007 _mesa_test_proxy_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
1008 GLint internalFormat
, GLenum format
, GLenum type
,
1009 GLint width
, GLint height
, GLint depth
, GLint border
)
1013 (void) internalFormat
;
1018 case GL_PROXY_TEXTURE_1D
:
1019 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1020 if (width
< 2 * border
|| width
> 2 + maxSize
||
1021 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1022 _mesa_bitcount(width
- 2 * border
) != 1) ||
1023 level
>= ctx
->Const
.MaxTextureLevels
) {
1024 /* bad width or level */
1028 case GL_PROXY_TEXTURE_2D
:
1029 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1030 if (width
< 2 * border
|| width
> 2 + maxSize
||
1031 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1032 _mesa_bitcount(width
- 2 * border
) != 1) ||
1033 height
< 2 * border
|| height
> 2 + maxSize
||
1034 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1035 _mesa_bitcount(height
- 2 * border
) != 1) ||
1036 level
>= ctx
->Const
.MaxTextureLevels
) {
1037 /* bad width or height or level */
1041 case GL_PROXY_TEXTURE_3D
:
1042 maxSize
= 1 << (ctx
->Const
.Max3DTextureLevels
- 1);
1043 if (width
< 2 * border
|| width
> 2 + maxSize
||
1044 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1045 _mesa_bitcount(width
- 2 * border
) != 1) ||
1046 height
< 2 * border
|| height
> 2 + maxSize
||
1047 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1048 _mesa_bitcount(height
- 2 * border
) != 1) ||
1049 depth
< 2 * border
|| depth
> 2 + maxSize
||
1050 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1051 _mesa_bitcount(depth
- 2 * border
) != 1) ||
1052 level
>= ctx
->Const
.Max3DTextureLevels
) {
1053 /* bad width or height or depth or level */
1057 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
1058 if (width
< 1 || width
> ctx
->Const
.MaxTextureRectSize
||
1059 height
< 1 || height
> ctx
->Const
.MaxTextureRectSize
||
1061 /* bad width or height or level */
1065 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
1066 maxSize
= 1 << (ctx
->Const
.MaxCubeTextureLevels
- 1);
1067 if (width
< 2 * border
|| width
> 2 + maxSize
||
1068 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1069 _mesa_bitcount(width
- 2 * border
) != 1) ||
1070 height
< 2 * border
|| height
> 2 + maxSize
||
1071 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1072 _mesa_bitcount(height
- 2 * border
) != 1) ||
1073 level
>= ctx
->Const
.MaxCubeTextureLevels
) {
1074 /* bad width or height */
1079 _mesa_problem(ctx
, "Invalid target in _mesa_test_proxy_teximage");
1086 * Test the glTexImage[123]D() parameters for errors.
1088 * \param ctx GL context.
1089 * \param target texture target given by the user.
1090 * \param level image level given by the user.
1091 * \param internalFormat internal format given by the user.
1092 * \param format pixel data format given by the user.
1093 * \param type pixel data type given by the user.
1094 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1095 * \param width image width given by the user.
1096 * \param height image height given by the user.
1097 * \param depth image depth given by the user.
1098 * \param border image border given by the user.
1100 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1102 * Verifies each of the parameters against the constants specified in
1103 * __GLcontextRec::Const and the supported extensions, and according to the
1104 * OpenGL specification.
1107 texture_error_check( GLcontext
*ctx
, GLenum target
,
1108 GLint level
, GLint internalFormat
,
1109 GLenum format
, GLenum type
,
1111 GLint width
, GLint height
,
1112 GLint depth
, GLint border
)
1114 const GLboolean isProxy
= is_proxy_target(target
);
1117 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1118 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1120 _mesa_error(ctx
, GL_INVALID_VALUE
,
1121 "glTexImage%dD(level=%d)", dimensions
, level
);
1127 if (border
< 0 || border
> 1 ||
1128 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1129 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1131 _mesa_error(ctx
, GL_INVALID_VALUE
,
1132 "glTexImage%dD(border=%d)", dimensions
, border
);
1137 if (width
< 0 || height
< 0 || depth
< 0) {
1139 _mesa_error(ctx
, GL_INVALID_VALUE
,
1140 "glTexImage%dD(width, height or depth < 0)", dimensions
);
1145 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1146 * level, width, height and depth.
1148 if (dimensions
== 1) {
1149 if (target
== GL_PROXY_TEXTURE_1D
|| target
== GL_TEXTURE_1D
) {
1150 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1151 level
, internalFormat
,
1153 width
, 1, 1, border
);
1156 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1160 else if (dimensions
== 2) {
1161 if (target
== GL_PROXY_TEXTURE_2D
|| target
== GL_TEXTURE_2D
) {
1162 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1163 level
, internalFormat
,
1165 width
, height
, 1, border
);
1167 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
1168 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1169 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
1170 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1171 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1174 sizeOK
= (width
== height
) &&
1175 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1176 level
, internalFormat
, format
, type
,
1177 width
, height
, 1, border
);
1179 else if (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
||
1180 target
== GL_TEXTURE_RECTANGLE_NV
) {
1181 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1182 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1185 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1186 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1187 level
, internalFormat
,
1189 width
, height
, 1, border
);
1192 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1196 else if (dimensions
== 3) {
1197 if (target
== GL_PROXY_TEXTURE_3D
|| target
== GL_TEXTURE_3D
) {
1198 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_3D
,
1199 level
, internalFormat
,
1201 width
, height
, depth
, border
);
1204 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1209 _mesa_problem( ctx
, "bad dims in texture_error_check" );
1215 _mesa_error(ctx
, GL_INVALID_VALUE
,
1216 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1217 dimensions
, level
, width
, height
, depth
);
1222 /* Check internalFormat */
1223 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1225 _mesa_error(ctx
, GL_INVALID_VALUE
,
1226 "glTexImage%dD(internalFormat=0x%x)",
1227 dimensions
, internalFormat
);
1232 /* Check incoming image format and type */
1233 if (!_mesa_is_legal_format_and_type(format
, type
)) {
1234 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1235 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1238 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1239 "glTexImage%dD(format or type)", dimensions
);
1244 if (format
== GL_YCBCR_MESA
|| internalFormat
== GL_YCBCR_MESA
) {
1245 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1246 if (format
!= GL_YCBCR_MESA
||
1247 internalFormat
!= GL_YCBCR_MESA
||
1248 (type
!= GL_UNSIGNED_SHORT_8_8_MESA
&&
1249 type
!= GL_UNSIGNED_SHORT_8_8_REV_MESA
)) {
1251 _mesa_sprintf(message
,
1252 "glTexImage%d(format/type/internalFormat YCBCR mismatch",
1254 _mesa_error(ctx
, GL_INVALID_ENUM
, message
);
1255 return GL_TRUE
; /* error */
1257 if (target
!= GL_TEXTURE_2D
&&
1258 target
!= GL_PROXY_TEXTURE_2D
&&
1259 target
!= GL_TEXTURE_RECTANGLE_NV
&&
1260 target
!= GL_PROXY_TEXTURE_RECTANGLE_NV
) {
1262 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage(target)");
1268 _mesa_sprintf(message
,
1269 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1270 dimensions
, border
);
1271 _mesa_error(ctx
, GL_INVALID_VALUE
, message
);
1277 if (is_compressed_format(ctx
, internalFormat
)) {
1278 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1281 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1282 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1283 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1284 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1289 _mesa_error(ctx
, GL_INVALID_ENUM
,
1290 "glTexImage%d(target)", dimensions
);
1296 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1297 "glTexImage%D(border!=0)", dimensions
);
1303 /* if we get here, the parameters are OK */
1309 * Test glTexSubImage[123]D() parameters for errors.
1311 * \param ctx GL context.
1312 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1313 * \param target texture target given by the user.
1314 * \param level image level given by the user.
1315 * \param xoffset sub-image x offset given by the user.
1316 * \param yoffset sub-image y offset given by the user.
1317 * \param zoffset sub-image z offset given by the user.
1318 * \param format pixel data format given by the user.
1319 * \param type pixel data type given by the user.
1320 * \param width image width given by the user.
1321 * \param height image height given by the user.
1322 * \param depth image depth given by the user.
1324 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1326 * Verifies each of the parameters against the constants specified in
1327 * __GLcontextRec::Const and the supported extensions, and according to the
1328 * OpenGL specification.
1331 subtexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1332 GLenum target
, GLint level
,
1333 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1334 GLint width
, GLint height
, GLint depth
,
1335 GLenum format
, GLenum type
)
1337 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1338 struct gl_texture_image
*destTex
;
1341 if (dimensions
== 1) {
1342 if (target
!= GL_TEXTURE_1D
) {
1343 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
1347 else if (dimensions
== 2) {
1348 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1349 target
<=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1350 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1351 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1355 else if (ctx
->Extensions
.NV_texture_rectangle
&&
1356 target
== GL_TEXTURE_RECTANGLE_NV
) {
1357 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1358 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1362 else if (target
!= GL_TEXTURE_2D
) {
1363 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1367 else if (dimensions
== 3) {
1368 if (target
!= GL_TEXTURE_3D
) {
1369 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
1374 _mesa_problem( ctx
, "invalid dims in texture_error_check" );
1378 /* Basic level check */
1379 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1380 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level=%d)", level
);
1385 _mesa_error(ctx
, GL_INVALID_VALUE
,
1386 "glTexSubImage%dD(width=%d)", dimensions
, width
);
1389 if (height
< 0 && dimensions
> 1) {
1390 _mesa_error(ctx
, GL_INVALID_VALUE
,
1391 "glTexSubImage%dD(height=%d)", dimensions
, height
);
1394 if (depth
< 0 && dimensions
> 2) {
1395 _mesa_error(ctx
, GL_INVALID_VALUE
,
1396 "glTexSubImage%dD(depth=%d)", dimensions
, depth
);
1400 destTex
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1403 /* undefined image level */
1404 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage%dD", dimensions
);
1408 if (xoffset
< -((GLint
)destTex
->Border
)) {
1409 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset)",
1413 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
1414 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset+width)",
1418 if (dimensions
> 1) {
1419 if (yoffset
< -((GLint
)destTex
->Border
)) {
1420 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset)",
1424 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
1425 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset+height)",
1430 if (dimensions
> 2) {
1431 if (zoffset
< -((GLint
)destTex
->Border
)) {
1432 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
1435 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+ destTex
->Border
)) {
1436 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
1441 if (!_mesa_is_legal_format_and_type(format
, type
)) {
1442 _mesa_error(ctx
, GL_INVALID_ENUM
,
1443 "glTexSubImage%dD(format or type)", dimensions
);
1447 if (destTex
->IsCompressed
) {
1448 const struct gl_texture_unit
*texUnit
;
1449 const struct gl_texture_image
*texImage
;
1450 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1451 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1453 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1456 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1457 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1458 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1459 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1463 _mesa_error(ctx
, GL_INVALID_ENUM
,
1464 "glTexSubImage%D(target)", dimensions
);
1467 /* offset must be multiple of 4 */
1468 if ((xoffset
& 3) || (yoffset
& 3)) {
1469 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1470 "glTexSubImage%D(xoffset or yoffset)", dimensions
);
1473 /* size must be multiple of 4 or equal to whole texture size */
1474 if ((width
& 3) && (GLuint
) width
!= texImage
->Width
) {
1475 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1476 "glTexSubImage%D(width)", dimensions
);
1479 if ((height
& 3) && (GLuint
) height
!= texImage
->Height
) {
1480 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1481 "glTexSubImage%D(width)", dimensions
);
1491 * Test glCopyTexImage[12]D() parameters for errors.
1493 * \param ctx GL context.
1494 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1495 * \param target texture target given by the user.
1496 * \param level image level given by the user.
1497 * \param internalFormat internal format given by the user.
1498 * \param width image width given by the user.
1499 * \param height image height given by the user.
1500 * \param depth image depth given by the user.
1501 * \param border texture border.
1503 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1505 * Verifies each of the parameters against the constants specified in
1506 * __GLcontextRec::Const and the supported extensions, and according to the
1507 * OpenGL specification.
1510 copytexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1511 GLenum target
, GLint level
, GLint internalFormat
,
1512 GLint width
, GLint height
, GLint border
)
1514 GLenum format
, type
;
1517 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1518 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1519 _mesa_error(ctx
, GL_INVALID_VALUE
,
1520 "glCopyTexImage%dD(level=%d)", dimensions
, level
);
1525 if (border
< 0 || border
> 1 ||
1526 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1527 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1531 /* The format and type aren't really significant here, but we need to pass
1532 * something to TestProxyTexImage().
1534 format
= _mesa_base_tex_format(ctx
, internalFormat
);
1537 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1538 * level, width, height and depth.
1540 if (dimensions
== 1) {
1541 if (target
== GL_TEXTURE_1D
) {
1542 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1543 level
, internalFormat
,
1545 width
, 1, 1, border
);
1548 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
1552 else if (dimensions
== 2) {
1553 if (target
== GL_TEXTURE_2D
) {
1554 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1555 level
, internalFormat
,
1557 width
, height
, 1, border
);
1559 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1560 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1561 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1562 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1565 sizeOK
= (width
== height
) &&
1566 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1567 level
, internalFormat
, format
, type
,
1568 width
, height
, 1, border
);
1570 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1571 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1572 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1575 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1576 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1577 level
, internalFormat
,
1579 width
, height
, 1, border
);
1582 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1587 _mesa_problem(ctx
, "invalid dimensions in copytexture_error_check");
1592 if (dimensions
== 1) {
1593 _mesa_error(ctx
, GL_INVALID_VALUE
,
1594 "glCopyTexImage1D(width=%d)", width
);
1597 ASSERT(dimensions
== 2);
1598 _mesa_error(ctx
, GL_INVALID_VALUE
,
1599 "glCopyTexImage2D(width=%d, height=%d)", width
, height
);
1604 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1605 _mesa_error(ctx
, GL_INVALID_VALUE
,
1606 "glCopyTexImage%dD(internalFormat)", dimensions
);
1610 if (is_compressed_format(ctx
, internalFormat
)) {
1611 if (target
!= GL_TEXTURE_2D
) {
1612 _mesa_error(ctx
, GL_INVALID_ENUM
,
1613 "glCopyTexImage%d(target)", dimensions
);
1617 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1618 "glCopyTexImage%D(border!=0)", dimensions
);
1623 /* if we get here, the parameters are OK */
1629 * Test glCopyTexImage[12]D() parameters for errors.
1631 * \param ctx GL context.
1632 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1633 * \param target texture target given by the user.
1634 * \param level image level given by the user.
1635 * \param xoffset sub-image x offset given by the user.
1636 * \param yoffset sub-image y offset given by the user.
1637 * \param zoffset sub-image z offset given by the user.
1638 * \param width image width given by the user.
1639 * \param height image height given by the user.
1641 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1643 * Verifies each of the parameters against the constants specified in
1644 * __GLcontextRec::Const and the supported extensions, and according to the
1645 * OpenGL specification.
1648 copytexsubimage_error_check( GLcontext
*ctx
, GLuint dimensions
,
1649 GLenum target
, GLint level
,
1650 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1651 GLsizei width
, GLsizei height
)
1653 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1654 struct gl_texture_image
*teximage
;
1657 if (dimensions
== 1) {
1658 if (target
!= GL_TEXTURE_1D
) {
1659 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
1663 else if (dimensions
== 2) {
1664 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1665 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1666 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1667 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1671 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1672 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1673 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1677 else if (target
!= GL_TEXTURE_2D
) {
1678 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1682 else if (dimensions
== 3) {
1683 if (target
!= GL_TEXTURE_3D
) {
1684 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
1690 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1691 _mesa_error(ctx
, GL_INVALID_VALUE
,
1692 "glCopyTexSubImage%dD(level=%d)", dimensions
, level
);
1698 _mesa_error(ctx
, GL_INVALID_VALUE
,
1699 "glCopyTexSubImage%dD(width=%d)", dimensions
, width
);
1702 if (dimensions
> 1 && height
< 0) {
1703 _mesa_error(ctx
, GL_INVALID_VALUE
,
1704 "glCopyTexSubImage%dD(height=%d)", dimensions
, height
);
1708 teximage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1710 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1711 "glCopyTexSubImage%dD(undefined texture level: %d)",
1716 if (xoffset
< -((GLint
)teximage
->Border
)) {
1717 _mesa_error(ctx
, GL_INVALID_VALUE
,
1718 "glCopyTexSubImage%dD(xoffset=%d)", dimensions
, xoffset
);
1721 if (xoffset
+ width
> (GLint
) (teximage
->Width
+ teximage
->Border
)) {
1722 _mesa_error(ctx
, GL_INVALID_VALUE
,
1723 "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
1726 if (dimensions
> 1) {
1727 if (yoffset
< -((GLint
)teximage
->Border
)) {
1728 _mesa_error(ctx
, GL_INVALID_VALUE
,
1729 "glCopyTexSubImage%dD(yoffset=%d)", dimensions
, yoffset
);
1732 /* NOTE: we're adding the border here, not subtracting! */
1733 if (yoffset
+ height
> (GLint
) (teximage
->Height
+ teximage
->Border
)) {
1734 _mesa_error(ctx
, GL_INVALID_VALUE
,
1735 "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
1740 if (dimensions
> 2) {
1741 if (zoffset
< -((GLint
)teximage
->Border
)) {
1742 _mesa_error(ctx
, GL_INVALID_VALUE
,
1743 "glCopyTexSubImage%dD(zoffset)", dimensions
);
1746 if (zoffset
> (GLint
) (teximage
->Depth
+ teximage
->Border
)) {
1747 _mesa_error(ctx
, GL_INVALID_VALUE
,
1748 "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
1753 if (teximage
->IsCompressed
) {
1754 if (target
!= GL_TEXTURE_2D
) {
1755 _mesa_error(ctx
, GL_INVALID_ENUM
,
1756 "glCopyTexSubImage%d(target)", dimensions
);
1759 /* offset must be multiple of 4 */
1760 if ((xoffset
& 3) || (yoffset
& 3)) {
1761 _mesa_error(ctx
, GL_INVALID_VALUE
,
1762 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions
);
1765 /* size must be multiple of 4 */
1766 if ((width
& 3) != 0 && (GLuint
) width
!= teximage
->Width
) {
1767 _mesa_error(ctx
, GL_INVALID_VALUE
,
1768 "glCopyTexSubImage%D(width)", dimensions
);
1771 if ((height
& 3) != 0 && (GLuint
) height
!= teximage
->Height
) {
1772 _mesa_error(ctx
, GL_INVALID_VALUE
,
1773 "glCopyTexSubImage%D(height)", dimensions
);
1778 if (teximage
->IntFormat
== GL_YCBCR_MESA
) {
1779 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glCopyTexSubImage2D");
1783 /* if we get here, the parameters are OK */
1789 * Get texture image.
1791 * \param target texture target.
1792 * \param level image level.
1793 * \param format pixel data format.
1794 * \param type pixel data type.
1795 * \param pixels pixel data.
1798 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
1799 GLenum type
, GLvoid
*pixels
)
1801 const struct gl_texture_unit
*texUnit
;
1802 const struct gl_texture_object
*texObj
;
1803 const struct gl_texture_image
*texImage
;
1804 GLint maxLevels
= 0;
1805 GET_CURRENT_CONTEXT(ctx
);
1806 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
1808 texUnit
= &(ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
]);
1809 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
1810 if (!texObj
|| is_proxy_target(target
)) {
1811 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)");
1815 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
1816 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
1818 if (level
< 0 || level
>= maxLevels
) {
1819 _mesa_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
1823 if (_mesa_sizeof_packed_type(type
) <= 0) {
1824 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
1828 if (_mesa_components_in_format(format
) <= 0 ||
1829 format
== GL_STENCIL_INDEX
) {
1830 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
1834 if (!ctx
->Extensions
.EXT_paletted_texture
&& is_index_format(format
)) {
1835 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1838 if (!ctx
->Extensions
.SGIX_depth_texture
&& format
== GL_DEPTH_COMPONENT
) {
1839 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1842 if (!ctx
->Extensions
.MESA_ycbcr_texture
&& format
== GL_YCBCR_MESA
) {
1843 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1846 /* XXX what if format/type doesn't match texture format/type? */
1851 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1853 /* invalid mipmap level, not an error */
1857 if (!texImage
->Data
) {
1858 /* no image data, not an error */
1863 const GLint width
= texImage
->Width
;
1864 const GLint height
= texImage
->Height
;
1865 const GLint depth
= texImage
->Depth
;
1867 for (img
= 0; img
< depth
; img
++) {
1868 for (row
= 0; row
< height
; row
++) {
1869 /* compute destination address in client memory */
1870 GLvoid
*dest
= _mesa_image_address( &ctx
->Pack
, pixels
,
1871 width
, height
, format
, type
,
1875 if (format
== GL_COLOR_INDEX
) {
1876 GLuint indexRow
[MAX_WIDTH
];
1878 for (col
= 0; col
< width
; col
++) {
1880 (*texImage
->FetchTexelc
)(texImage
, col
, row
, img
, &indx
);
1881 indexRow
[col
] = indx
;
1883 _mesa_pack_index_span(ctx
, width
, type
, dest
,
1884 indexRow
, &ctx
->Pack
,
1885 0 /* no image transfer */);
1887 else if (format
== GL_DEPTH_COMPONENT
) {
1888 GLfloat depthRow
[MAX_WIDTH
];
1890 for (col
= 0; col
< width
; col
++) {
1891 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
1892 (GLvoid
*) &depthRow
[col
]);
1894 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
1895 depthRow
, &ctx
->Pack
);
1897 else if (format
== GL_YCBCR_MESA
) {
1898 /* No pixel transfer */
1899 const GLint rowstride
= texImage
->RowStride
;
1901 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
1902 width
* sizeof(GLushort
));
1903 /* check for byte swapping */
1904 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
1905 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
1906 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
1907 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
1908 if (!ctx
->Pack
.SwapBytes
)
1909 _mesa_swap2((GLushort
*) dest
, width
);
1911 else if (ctx
->Pack
.SwapBytes
) {
1912 _mesa_swap2((GLushort
*) dest
, width
);
1916 /* general case: convert row to RGBA format */
1917 GLchan rgba
[MAX_WIDTH
][4];
1919 for (col
= 0; col
< width
; col
++) {
1920 (*texImage
->FetchTexelc
)(texImage
, col
, row
, img
, rgba
[col
]);
1922 _mesa_pack_rgba_span(ctx
, width
, (const GLchan (*)[4])rgba
,
1923 format
, type
, dest
, &ctx
->Pack
,
1924 0 /* no image transfer */);
1934 * Called from the API. Note that width includes the border.
1937 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalFormat
,
1938 GLsizei width
, GLint border
, GLenum format
,
1939 GLenum type
, const GLvoid
*pixels
)
1941 GLsizei postConvWidth
= width
;
1942 GET_CURRENT_CONTEXT(ctx
);
1943 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
1945 if (is_color_format(internalFormat
)) {
1946 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
1949 if (target
== GL_TEXTURE_1D
) {
1950 struct gl_texture_unit
*texUnit
;
1951 struct gl_texture_object
*texObj
;
1952 struct gl_texture_image
*texImage
;
1954 if (texture_error_check(ctx
, target
, level
, internalFormat
,
1955 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
1956 return; /* error was recorded */
1959 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1960 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
1961 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
1964 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
1967 else if (texImage
->Data
&& !texImage
->IsClientData
) {
1968 /* free the old texture data */
1969 MESA_PBUFFER_FREE(texImage
->Data
);
1971 texImage
->Data
= NULL
;
1972 clear_teximage_fields(texImage
); /* not really needed, but helpful */
1973 _mesa_init_teximage_fields(ctx
, target
, texImage
,
1974 postConvWidth
, 1, 1,
1975 border
, internalFormat
);
1977 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
1978 _mesa_update_state(ctx
);
1980 ASSERT(ctx
->Driver
.TexImage1D
);
1982 /* Give the texture to the driver! <pixels> may be null! */
1983 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
1984 width
, border
, format
, type
, pixels
,
1985 &ctx
->Unpack
, texObj
, texImage
);
1987 ASSERT(texImage
->TexFormat
);
1989 /* If driver didn't explicitly set this, use the defaults */
1990 if (!texImage
->FetchTexelc
)
1991 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
1992 if (!texImage
->FetchTexelf
)
1993 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
1994 ASSERT(texImage
->FetchTexelc
);
1995 ASSERT(texImage
->FetchTexelf
);
1998 texObj
->Complete
= GL_FALSE
;
1999 ctx
->NewState
|= _NEW_TEXTURE
;
2001 else if (target
== GL_PROXY_TEXTURE_1D
) {
2002 /* Proxy texture: check for errors and update proxy state */
2003 struct gl_texture_image
*texImage
;
2004 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2005 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2006 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2007 /* when error, clear all proxy texture image parameters */
2009 clear_teximage_fields(texImage
);
2012 /* no error, set the tex image parameters */
2014 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2015 postConvWidth
, 1, 1,
2016 border
, internalFormat
);
2017 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2018 internalFormat
, format
, type
);
2022 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
2029 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalFormat
,
2030 GLsizei width
, GLsizei height
, GLint border
,
2031 GLenum format
, GLenum type
,
2032 const GLvoid
*pixels
)
2034 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2035 GET_CURRENT_CONTEXT(ctx
);
2036 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2038 if (is_color_format(internalFormat
)) {
2039 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2043 if (target
== GL_TEXTURE_2D
||
2044 (ctx
->Extensions
.ARB_texture_cube_map
&&
2045 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2046 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) ||
2047 (ctx
->Extensions
.NV_texture_rectangle
&&
2048 target
== GL_TEXTURE_RECTANGLE_NV
)) {
2049 /* non-proxy target */
2050 struct gl_texture_unit
*texUnit
;
2051 struct gl_texture_object
*texObj
;
2052 struct gl_texture_image
*texImage
;
2054 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2055 format
, type
, 2, postConvWidth
, postConvHeight
,
2057 return; /* error was recorded */
2060 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2061 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2062 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2064 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2067 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2068 /* free the old texture data */
2069 MESA_PBUFFER_FREE(texImage
->Data
);
2071 texImage
->Data
= NULL
;
2072 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2073 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2074 postConvWidth
, postConvHeight
, 1,
2075 border
, internalFormat
);
2077 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2078 _mesa_update_state(ctx
);
2080 ASSERT(ctx
->Driver
.TexImage2D
);
2082 /* Give the texture to the driver! <pixels> may be null! */
2083 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
2084 width
, height
, border
, format
, type
, pixels
,
2085 &ctx
->Unpack
, texObj
, texImage
);
2087 ASSERT(texImage
->TexFormat
);
2089 /* If driver didn't explicitly set these, use the defaults */
2090 if (!texImage
->FetchTexelc
)
2091 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2092 if (!texImage
->FetchTexelf
)
2093 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2094 ASSERT(texImage
->FetchTexelc
);
2095 ASSERT(texImage
->FetchTexelf
);
2098 texObj
->Complete
= GL_FALSE
;
2099 ctx
->NewState
|= _NEW_TEXTURE
;
2101 else if (target
== GL_PROXY_TEXTURE_2D
||
2102 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2103 ctx
->Extensions
.ARB_texture_cube_map
) ||
2104 (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
&&
2105 ctx
->Extensions
.NV_texture_rectangle
)) {
2106 /* Proxy texture: check for errors and update proxy state */
2107 struct gl_texture_image
*texImage
;
2108 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2109 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2110 format
, type
, 2, postConvWidth
, postConvHeight
,
2112 /* when error, clear all proxy texture image parameters */
2114 clear_teximage_fields(ctx
->Texture
.Proxy2D
->Image
[level
]);
2117 /* no error, set the tex image parameters */
2118 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2119 postConvWidth
, postConvHeight
, 1,
2120 border
, internalFormat
);
2121 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2122 internalFormat
, format
, type
);
2126 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
2133 * Called by the API or display list executor.
2134 * Note that width and height include the border.
2137 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalFormat
,
2138 GLsizei width
, GLsizei height
, GLsizei depth
,
2139 GLint border
, GLenum format
, GLenum type
,
2140 const GLvoid
*pixels
)
2142 GET_CURRENT_CONTEXT(ctx
);
2143 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2145 if (target
== GL_TEXTURE_3D
) {
2146 struct gl_texture_unit
*texUnit
;
2147 struct gl_texture_object
*texObj
;
2148 struct gl_texture_image
*texImage
;
2150 if (texture_error_check(ctx
, target
, level
, (GLint
) internalFormat
,
2151 format
, type
, 3, width
, height
, depth
, border
)) {
2152 return; /* error was recorded */
2155 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2156 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2157 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2159 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2162 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2163 MESA_PBUFFER_FREE(texImage
->Data
);
2165 texImage
->Data
= NULL
;
2166 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2167 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2168 width
, height
, depth
,
2169 border
, internalFormat
);
2171 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2172 _mesa_update_state(ctx
);
2174 ASSERT(ctx
->Driver
.TexImage3D
);
2176 /* Give the texture to the driver! <pixels> may be null! */
2177 (*ctx
->Driver
.TexImage3D
)(ctx
, target
, level
, internalFormat
,
2178 width
, height
, depth
, border
, format
, type
,
2179 pixels
, &ctx
->Unpack
, texObj
, texImage
);
2181 ASSERT(texImage
->TexFormat
);
2183 /* If driver didn't explicitly set these, use the defaults */
2184 if (!texImage
->FetchTexelc
)
2185 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2186 if (!texImage
->FetchTexelf
)
2187 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2188 ASSERT(texImage
->FetchTexelc
);
2189 ASSERT(texImage
->FetchTexelf
);
2192 texObj
->Complete
= GL_FALSE
;
2193 ctx
->NewState
|= _NEW_TEXTURE
;
2195 else if (target
== GL_PROXY_TEXTURE_3D
) {
2196 /* Proxy texture: check for errors and update proxy state */
2197 struct gl_texture_image
*texImage
;
2198 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2199 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2200 format
, type
, 3, width
, height
, depth
, border
)) {
2201 /* when error, clear all proxy texture image parameters */
2203 clear_teximage_fields(texImage
);
2206 /* no error, set the tex image parameters */
2207 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2208 border
, internalFormat
);
2209 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2210 internalFormat
, format
, type
);
2214 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
2221 _mesa_TexImage3DEXT( GLenum target
, GLint level
, GLenum internalFormat
,
2222 GLsizei width
, GLsizei height
, GLsizei depth
,
2223 GLint border
, GLenum format
, GLenum type
,
2224 const GLvoid
*pixels
)
2226 _mesa_TexImage3D(target
, level
, (GLint
) internalFormat
, width
, height
,
2227 depth
, border
, format
, type
, pixels
);
2233 _mesa_TexSubImage1D( GLenum target
, GLint level
,
2234 GLint xoffset
, GLsizei width
,
2235 GLenum format
, GLenum type
,
2236 const GLvoid
*pixels
)
2238 GLsizei postConvWidth
= width
;
2239 struct gl_texture_unit
*texUnit
;
2240 struct gl_texture_object
*texObj
;
2241 struct gl_texture_image
*texImage
;
2242 GET_CURRENT_CONTEXT(ctx
);
2243 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2245 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2246 _mesa_update_state(ctx
);
2248 /* XXX should test internal format */
2249 if (is_color_format(format
)) {
2250 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2253 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
2254 postConvWidth
, 1, 1, format
, type
)) {
2255 return; /* error was detected */
2258 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2259 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2260 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2263 if (width
== 0 || !pixels
)
2264 return; /* no-op, not an error */
2266 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2267 xoffset
+= texImage
->Border
;
2269 ASSERT(ctx
->Driver
.TexSubImage1D
);
2270 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
2271 format
, type
, pixels
, &ctx
->Unpack
,
2273 ctx
->NewState
|= _NEW_TEXTURE
;
2278 _mesa_TexSubImage2D( GLenum target
, GLint level
,
2279 GLint xoffset
, GLint yoffset
,
2280 GLsizei width
, GLsizei height
,
2281 GLenum format
, GLenum type
,
2282 const GLvoid
*pixels
)
2284 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2285 struct gl_texture_unit
*texUnit
;
2286 struct gl_texture_object
*texObj
;
2287 struct gl_texture_image
*texImage
;
2288 GET_CURRENT_CONTEXT(ctx
);
2289 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2291 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2292 _mesa_update_state(ctx
);
2294 /* XXX should test internal format */
2295 if (is_color_format(format
)) {
2296 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2300 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2301 postConvWidth
, postConvHeight
, 1, format
, type
)) {
2302 return; /* error was detected */
2305 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2306 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2307 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2310 if (width
== 0 || height
== 0 || !pixels
)
2311 return; /* no-op, not an error */
2313 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2314 xoffset
+= texImage
->Border
;
2315 yoffset
+= texImage
->Border
;
2317 ASSERT(ctx
->Driver
.TexSubImage2D
);
2318 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
, xoffset
, yoffset
,
2319 width
, height
, format
, type
, pixels
,
2320 &ctx
->Unpack
, texObj
, texImage
);
2321 ctx
->NewState
|= _NEW_TEXTURE
;
2327 _mesa_TexSubImage3D( GLenum target
, GLint level
,
2328 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2329 GLsizei width
, GLsizei height
, GLsizei depth
,
2330 GLenum format
, GLenum type
,
2331 const GLvoid
*pixels
)
2333 struct gl_texture_unit
*texUnit
;
2334 struct gl_texture_object
*texObj
;
2335 struct gl_texture_image
*texImage
;
2336 GET_CURRENT_CONTEXT(ctx
);
2337 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2339 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2340 _mesa_update_state(ctx
);
2342 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2343 width
, height
, depth
, format
, type
)) {
2344 return; /* error was detected */
2347 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2348 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2349 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2352 if (width
== 0 || height
== 0 || height
== 0 || !pixels
)
2353 return; /* no-op, not an error */
2355 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2356 xoffset
+= texImage
->Border
;
2357 yoffset
+= texImage
->Border
;
2358 zoffset
+= texImage
->Border
;
2360 ASSERT(ctx
->Driver
.TexSubImage3D
);
2361 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
2362 xoffset
, yoffset
, zoffset
,
2363 width
, height
, depth
,
2364 format
, type
, pixels
,
2365 &ctx
->Unpack
, texObj
, texImage
);
2366 ctx
->NewState
|= _NEW_TEXTURE
;
2372 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
2373 GLenum internalFormat
,
2375 GLsizei width
, GLint border
)
2377 struct gl_texture_unit
*texUnit
;
2378 struct gl_texture_object
*texObj
;
2379 struct gl_texture_image
*texImage
;
2380 GLsizei postConvWidth
= width
;
2381 GET_CURRENT_CONTEXT(ctx
);
2382 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2384 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2385 _mesa_update_state(ctx
);
2387 if (is_color_format(internalFormat
)) {
2388 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2391 if (copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
2392 postConvWidth
, 1, border
))
2395 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2396 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2397 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2399 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
2402 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2403 /* free the old texture data */
2404 MESA_PBUFFER_FREE(texImage
->Data
);
2406 texImage
->Data
= NULL
;
2408 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2409 _mesa_init_teximage_fields(ctx
, target
, texImage
, postConvWidth
, 1, 1,
2410 border
, internalFormat
);
2413 ASSERT(ctx
->Driver
.CopyTexImage1D
);
2414 (*ctx
->Driver
.CopyTexImage1D
)(ctx
, target
, level
, internalFormat
,
2415 x
, y
, width
, border
);
2417 ASSERT(texImage
->TexFormat
);
2419 /* If driver didn't explicitly set these, use the defaults */
2420 if (!texImage
->FetchTexelc
)
2421 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2422 if (!texImage
->FetchTexelf
)
2423 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2424 ASSERT(texImage
->FetchTexelc
);
2425 ASSERT(texImage
->FetchTexelf
);
2428 texObj
->Complete
= GL_FALSE
;
2429 ctx
->NewState
|= _NEW_TEXTURE
;
2435 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
2436 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2439 struct gl_texture_unit
*texUnit
;
2440 struct gl_texture_object
*texObj
;
2441 struct gl_texture_image
*texImage
;
2442 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2443 GET_CURRENT_CONTEXT(ctx
);
2444 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2446 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2447 _mesa_update_state(ctx
);
2449 if (is_color_format(internalFormat
)) {
2450 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2454 if (copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
2455 postConvWidth
, postConvHeight
, border
))
2458 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2459 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2460 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2462 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
2465 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2466 /* free the old texture data */
2467 MESA_PBUFFER_FREE(texImage
->Data
);
2469 texImage
->Data
= NULL
;
2471 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2472 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2473 postConvWidth
, postConvHeight
, 1,
2474 border
, internalFormat
);
2476 ASSERT(ctx
->Driver
.CopyTexImage2D
);
2477 (*ctx
->Driver
.CopyTexImage2D
)(ctx
, target
, level
, internalFormat
,
2478 x
, y
, width
, height
, border
);
2480 ASSERT(texImage
->TexFormat
);
2482 /* If driver didn't explicitly set these, use the defaults */
2483 if (!texImage
->FetchTexelc
)
2484 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2485 if (!texImage
->FetchTexelf
)
2486 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2487 ASSERT(texImage
->FetchTexelc
);
2488 ASSERT(texImage
->FetchTexelf
);
2491 texObj
->Complete
= GL_FALSE
;
2492 ctx
->NewState
|= _NEW_TEXTURE
;
2498 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
2499 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
2501 struct gl_texture_unit
*texUnit
;
2502 struct gl_texture_image
*texImage
;
2503 GLsizei postConvWidth
= width
;
2504 GET_CURRENT_CONTEXT(ctx
);
2505 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2507 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2508 _mesa_update_state(ctx
);
2510 /* XXX should test internal format */
2511 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2513 if (copytexsubimage_error_check(ctx
, 1, target
, level
,
2514 xoffset
, 0, 0, postConvWidth
, 1))
2517 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2518 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2521 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2522 xoffset
+= texImage
->Border
;
2524 ASSERT(ctx
->Driver
.CopyTexSubImage1D
);
2525 (*ctx
->Driver
.CopyTexSubImage1D
)(ctx
, target
, level
, xoffset
, x
, y
, width
);
2526 ctx
->NewState
|= _NEW_TEXTURE
;
2532 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
2533 GLint xoffset
, GLint yoffset
,
2534 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2536 struct gl_texture_unit
*texUnit
;
2537 struct gl_texture_image
*texImage
;
2538 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2539 GET_CURRENT_CONTEXT(ctx
);
2540 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2542 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2543 _mesa_update_state(ctx
);
2545 /* XXX should test internal format */
2546 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2548 if (copytexsubimage_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2549 postConvWidth
, postConvHeight
))
2552 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2553 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2556 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2557 xoffset
+= texImage
->Border
;
2558 yoffset
+= texImage
->Border
;
2560 ASSERT(ctx
->Driver
.CopyTexSubImage2D
);
2561 (*ctx
->Driver
.CopyTexSubImage2D
)(ctx
, target
, level
,
2562 xoffset
, yoffset
, x
, y
, width
, height
);
2563 ctx
->NewState
|= _NEW_TEXTURE
;
2569 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
2570 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2571 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2573 struct gl_texture_unit
*texUnit
;
2574 struct gl_texture_image
*texImage
;
2575 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2576 GET_CURRENT_CONTEXT(ctx
);
2577 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2579 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2580 _mesa_update_state(ctx
);
2582 /* XXX should test internal format */
2583 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2585 if (copytexsubimage_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
,
2586 zoffset
, postConvWidth
, postConvHeight
))
2589 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2590 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2593 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2594 xoffset
+= texImage
->Border
;
2595 yoffset
+= texImage
->Border
;
2596 zoffset
+= texImage
->Border
;
2598 ASSERT(ctx
->Driver
.CopyTexSubImage3D
);
2599 (*ctx
->Driver
.CopyTexSubImage3D
)(ctx
, target
, level
,
2600 xoffset
, yoffset
, zoffset
,
2601 x
, y
, width
, height
);
2602 ctx
->NewState
|= _NEW_TEXTURE
;
2608 /**********************************************************************/
2609 /****** Compressed Textures ******/
2610 /**********************************************************************/
2614 * Error checking for glCompressedTexImage[123]D().
2615 * \return error code or GL_NO_ERROR.
2618 compressed_texture_error_check(GLcontext
*ctx
, GLint dimensions
,
2619 GLenum target
, GLint level
,
2620 GLenum internalFormat
, GLsizei width
,
2621 GLsizei height
, GLsizei depth
, GLint border
,
2624 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2626 if (dimensions
== 1) {
2627 /* 1D compressed textures not allowed */
2628 return GL_INVALID_ENUM
;
2630 else if (dimensions
== 2) {
2631 if (target
== GL_PROXY_TEXTURE_2D
) {
2632 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2634 else if (target
== GL_TEXTURE_2D
) {
2635 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2637 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2638 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2639 return GL_INVALID_ENUM
; /*target*/
2640 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2642 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2643 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2644 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2645 return GL_INVALID_ENUM
; /*target*/
2646 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2649 return GL_INVALID_ENUM
; /*target*/
2652 else if (dimensions
== 3) {
2653 /* 3D compressed textures not allowed */
2654 return GL_INVALID_ENUM
;
2657 maxTextureSize
= 1 << (maxLevels
- 1);
2659 if (!is_compressed_format(ctx
, internalFormat
))
2660 return GL_INVALID_ENUM
;
2663 return GL_INVALID_VALUE
;
2666 * XXX We should probably use the proxy texture error check function here.
2668 if (width
< 1 || width
> maxTextureSize
||
2669 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(width
) < 0))
2670 return GL_INVALID_VALUE
;
2672 if ((height
< 1 || height
> maxTextureSize
||
2673 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(height
) < 0))
2675 return GL_INVALID_VALUE
;
2677 if ((depth
< 1 || depth
> maxTextureSize
||
2678 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(depth
) < 0))
2680 return GL_INVALID_VALUE
;
2682 /* For cube map, width must equal height */
2683 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2684 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
&& width
!= height
)
2685 return GL_INVALID_VALUE
;
2687 if (level
< 0 || level
>= maxLevels
)
2688 return GL_INVALID_VALUE
;
2690 expectedSize
= _mesa_compressed_texture_size(ctx
, width
, height
, depth
,
2692 if (expectedSize
!= imageSize
)
2693 return GL_INVALID_VALUE
;
2700 * Error checking for glCompressedTexSubImage[123]D().
2701 * \return error code or GL_NO_ERROR.
2704 compressed_subtexture_error_check(GLcontext
*ctx
, GLint dimensions
,
2705 GLenum target
, GLint level
,
2706 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2707 GLsizei width
, GLsizei height
, GLsizei depth
,
2708 GLenum format
, GLsizei imageSize
)
2710 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2712 if (dimensions
== 1) {
2713 /* 1D compressed textures not allowed */
2714 return GL_INVALID_ENUM
;
2716 else if (dimensions
== 2) {
2717 if (target
== GL_PROXY_TEXTURE_2D
) {
2718 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2720 else if (target
== GL_TEXTURE_2D
) {
2721 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2723 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2724 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2725 return GL_INVALID_ENUM
; /*target*/
2726 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2728 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2729 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2730 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2731 return GL_INVALID_ENUM
; /*target*/
2732 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2735 return GL_INVALID_ENUM
; /*target*/
2738 else if (dimensions
== 3) {
2739 /* 3D compressed textures not allowed */
2740 return GL_INVALID_ENUM
;
2743 maxTextureSize
= 1 << (maxLevels
- 1);
2745 if (!is_compressed_format(ctx
, format
))
2746 return GL_INVALID_ENUM
;
2748 if (width
< 1 || width
> maxTextureSize
)
2749 return GL_INVALID_VALUE
;
2751 if ((height
< 1 || height
> maxTextureSize
)
2753 return GL_INVALID_VALUE
;
2755 if (level
< 0 || level
>= maxLevels
)
2756 return GL_INVALID_VALUE
;
2758 if ((xoffset
& 3) != 0 || (yoffset
& 3) != 0)
2759 return GL_INVALID_VALUE
;
2761 if ((width
& 3) != 0 && width
!= 2 && width
!= 1)
2762 return GL_INVALID_VALUE
;
2764 if ((height
& 3) != 0 && height
!= 2 && height
!= 1)
2765 return GL_INVALID_VALUE
;
2767 expectedSize
= _mesa_compressed_texture_size(ctx
, width
, height
, depth
,
2769 if (expectedSize
!= imageSize
)
2770 return GL_INVALID_VALUE
;
2778 _mesa_CompressedTexImage1DARB(GLenum target
, GLint level
,
2779 GLenum internalFormat
, GLsizei width
,
2780 GLint border
, GLsizei imageSize
,
2783 GET_CURRENT_CONTEXT(ctx
);
2784 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2786 if (target
== GL_TEXTURE_1D
) {
2787 struct gl_texture_unit
*texUnit
;
2788 struct gl_texture_object
*texObj
;
2789 struct gl_texture_image
*texImage
;
2790 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
2791 internalFormat
, width
, 1, 1, border
, imageSize
);
2793 _mesa_error(ctx
, error
, "glCompressedTexImage1D");
2797 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2798 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2799 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2801 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage1D");
2804 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2805 MESA_PBUFFER_FREE(texImage
->Data
);
2807 texImage
->Data
= NULL
;
2809 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
2810 border
, internalFormat
);
2812 ASSERT(ctx
->Driver
.CompressedTexImage1D
);
2813 (*ctx
->Driver
.CompressedTexImage1D
)(ctx
, target
, level
,
2814 internalFormat
, width
, border
,
2819 texObj
->Complete
= GL_FALSE
;
2820 ctx
->NewState
|= _NEW_TEXTURE
;
2822 else if (target
== GL_PROXY_TEXTURE_1D
) {
2823 /* Proxy texture: check for errors and update proxy state */
2824 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
2825 internalFormat
, width
, 1, 1, border
, imageSize
);
2827 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2828 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2829 internalFormat
, GL_NONE
, GL_NONE
,
2830 width
, 1, 1, border
);
2833 /* if error, clear all proxy texture image parameters */
2834 struct gl_texture_image
*texImage
;
2835 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2837 clear_teximage_fields(texImage
);
2840 /* store the teximage parameters */
2841 struct gl_texture_unit
*texUnit
;
2842 struct gl_texture_image
*texImage
;
2843 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2844 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2845 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
2846 border
, internalFormat
);
2850 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage1D(target)");
2857 _mesa_CompressedTexImage2DARB(GLenum target
, GLint level
,
2858 GLenum internalFormat
, GLsizei width
,
2859 GLsizei height
, GLint border
, GLsizei imageSize
,
2862 GET_CURRENT_CONTEXT(ctx
);
2863 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2865 if (target
== GL_TEXTURE_2D
||
2866 (ctx
->Extensions
.ARB_texture_cube_map
&&
2867 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2868 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
2869 struct gl_texture_unit
*texUnit
;
2870 struct gl_texture_object
*texObj
;
2871 struct gl_texture_image
*texImage
;
2872 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
2873 internalFormat
, width
, height
, 1, border
, imageSize
);
2875 _mesa_error(ctx
, error
, "glCompressedTexImage2D");
2879 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2880 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2881 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2883 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
2886 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2887 MESA_PBUFFER_FREE(texImage
->Data
);
2889 texImage
->Data
= NULL
;
2891 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2892 border
, internalFormat
);
2894 ASSERT(ctx
->Driver
.CompressedTexImage2D
);
2895 (*ctx
->Driver
.CompressedTexImage2D
)(ctx
, target
, level
,
2896 internalFormat
, width
, height
,
2897 border
, imageSize
, data
,
2901 texObj
->Complete
= GL_FALSE
;
2902 ctx
->NewState
|= _NEW_TEXTURE
;
2904 else if (target
== GL_PROXY_TEXTURE_2D
||
2905 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2906 ctx
->Extensions
.ARB_texture_cube_map
)) {
2907 /* Proxy texture: check for errors and update proxy state */
2908 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
2909 internalFormat
, width
, height
, 1, border
, imageSize
);
2911 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2912 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2913 internalFormat
, GL_NONE
, GL_NONE
,
2914 width
, height
, 1, border
);
2917 /* if error, clear all proxy texture image parameters */
2918 struct gl_texture_image
*texImage
;
2919 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2921 clear_teximage_fields(texImage
);
2924 /* store the teximage parameters */
2925 struct gl_texture_unit
*texUnit
;
2926 struct gl_texture_image
*texImage
;
2927 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2928 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2929 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2930 border
, internalFormat
);
2934 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(target)");
2941 _mesa_CompressedTexImage3DARB(GLenum target
, GLint level
,
2942 GLenum internalFormat
, GLsizei width
,
2943 GLsizei height
, GLsizei depth
, GLint border
,
2944 GLsizei imageSize
, const GLvoid
*data
)
2946 GET_CURRENT_CONTEXT(ctx
);
2947 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2949 if (target
== GL_TEXTURE_3D
) {
2950 struct gl_texture_unit
*texUnit
;
2951 struct gl_texture_object
*texObj
;
2952 struct gl_texture_image
*texImage
;
2953 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
2954 internalFormat
, width
, height
, depth
, border
, imageSize
);
2956 _mesa_error(ctx
, error
, "glCompressedTexImage3D");
2960 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2961 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2962 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2964 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage3D");
2967 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2968 MESA_PBUFFER_FREE(texImage
->Data
);
2970 texImage
->Data
= NULL
;
2972 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, depth
,
2973 border
, internalFormat
);
2975 ASSERT(ctx
->Driver
.CompressedTexImage3D
);
2976 (*ctx
->Driver
.CompressedTexImage3D
)(ctx
, target
, level
,
2978 width
, height
, depth
,
2979 border
, imageSize
, data
,
2983 texObj
->Complete
= GL_FALSE
;
2984 ctx
->NewState
|= _NEW_TEXTURE
;
2986 else if (target
== GL_PROXY_TEXTURE_3D
) {
2987 /* Proxy texture: check for errors and update proxy state */
2988 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
2989 internalFormat
, width
, height
, depth
, border
, imageSize
);
2991 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2992 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2993 internalFormat
, GL_NONE
, GL_NONE
,
2994 width
, height
, depth
, border
);
2997 /* if error, clear all proxy texture image parameters */
2998 struct gl_texture_image
*texImage
;
2999 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3001 clear_teximage_fields(texImage
);
3004 /* store the teximage parameters */
3005 struct gl_texture_unit
*texUnit
;
3006 struct gl_texture_image
*texImage
;
3007 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3008 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3009 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
,
3010 depth
, border
, internalFormat
);
3014 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage3D(target)");
3021 _mesa_CompressedTexSubImage1DARB(GLenum target
, GLint level
, GLint xoffset
,
3022 GLsizei width
, GLenum format
,
3023 GLsizei imageSize
, const GLvoid
*data
)
3025 struct gl_texture_unit
*texUnit
;
3026 struct gl_texture_object
*texObj
;
3027 struct gl_texture_image
*texImage
;
3029 GET_CURRENT_CONTEXT(ctx
);
3030 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3032 error
= compressed_subtexture_error_check(ctx
, 1, target
, level
,
3033 xoffset
, 0, 0, width
, 1, 1, format
, imageSize
);
3035 _mesa_error(ctx
, error
, "glCompressedTexSubImage1D");
3039 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3040 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3041 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3044 if ((GLint
) format
!= texImage
->IntFormat
) {
3045 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3046 "glCompressedTexSubImage1D(format)");
3050 if ((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) {
3051 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage1D(width)");
3055 if (width
== 0 || !data
)
3056 return; /* no-op, not an error */
3058 if (ctx
->Driver
.CompressedTexSubImage1D
) {
3059 (*ctx
->Driver
.CompressedTexSubImage1D
)(ctx
, target
, level
,
3061 format
, imageSize
, data
,
3064 ctx
->NewState
|= _NEW_TEXTURE
;
3069 _mesa_CompressedTexSubImage2DARB(GLenum target
, GLint level
, GLint xoffset
,
3070 GLint yoffset
, GLsizei width
, GLsizei height
,
3071 GLenum format
, GLsizei imageSize
,
3074 struct gl_texture_unit
*texUnit
;
3075 struct gl_texture_object
*texObj
;
3076 struct gl_texture_image
*texImage
;
3078 GET_CURRENT_CONTEXT(ctx
);
3079 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3081 error
= compressed_subtexture_error_check(ctx
, 2, target
, level
,
3082 xoffset
, yoffset
, 0, width
, height
, 1, format
, imageSize
);
3084 /* XXX proxy target? */
3085 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3089 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3090 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3091 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3094 if ((GLint
) format
!= texImage
->IntFormat
) {
3095 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3096 "glCompressedTexSubImage2D(format)");
3100 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3101 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
)) {
3102 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage2D(size)");
3106 if (width
== 0 || height
== 0 || !data
)
3107 return; /* no-op, not an error */
3109 if (ctx
->Driver
.CompressedTexSubImage2D
) {
3110 (*ctx
->Driver
.CompressedTexSubImage2D
)(ctx
, target
, level
,
3111 xoffset
, yoffset
, width
, height
,
3112 format
, imageSize
, data
,
3115 ctx
->NewState
|= _NEW_TEXTURE
;
3120 _mesa_CompressedTexSubImage3DARB(GLenum target
, GLint level
, GLint xoffset
,
3121 GLint yoffset
, GLint zoffset
, GLsizei width
,
3122 GLsizei height
, GLsizei depth
, GLenum format
,
3123 GLsizei imageSize
, const GLvoid
*data
)
3125 struct gl_texture_unit
*texUnit
;
3126 struct gl_texture_object
*texObj
;
3127 struct gl_texture_image
*texImage
;
3129 GET_CURRENT_CONTEXT(ctx
);
3130 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3132 error
= compressed_subtexture_error_check(ctx
, 3, target
, level
,
3133 xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
, imageSize
);
3135 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3139 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3140 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3141 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3144 if ((GLint
) format
!= texImage
->IntFormat
) {
3145 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3146 "glCompressedTexSubImage3D(format)");
3150 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3151 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
) ||
3152 ((depth
== 1 || depth
== 2) && (GLuint
) depth
!= texImage
->Depth
)) {
3153 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage3D(size)");
3157 if (width
== 0 || height
== 0 || depth
== 0 || !data
)
3158 return; /* no-op, not an error */
3160 if (ctx
->Driver
.CompressedTexSubImage3D
) {
3161 (*ctx
->Driver
.CompressedTexSubImage3D
)(ctx
, target
, level
,
3162 xoffset
, yoffset
, zoffset
,
3163 width
, height
, depth
,
3164 format
, imageSize
, data
,
3167 ctx
->NewState
|= _NEW_TEXTURE
;
3172 _mesa_GetCompressedTexImageARB(GLenum target
, GLint level
, GLvoid
*img
)
3174 const struct gl_texture_unit
*texUnit
;
3175 const struct gl_texture_object
*texObj
;
3176 struct gl_texture_image
*texImage
;
3178 GET_CURRENT_CONTEXT(ctx
);
3179 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3181 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3182 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3184 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB");
3188 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
3189 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
3191 if (level
< 0 || level
>= maxLevels
) {
3192 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3196 if (is_proxy_target(target
)) {
3197 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
3201 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3203 /* probably invalid mipmap level */
3204 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3208 if (!texImage
->IsCompressed
) {
3209 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetCompressedTexImageARB");
3216 /* just memcpy, no pixelstore or pixel transfer */
3217 MEMCPY(img
, texImage
->Data
, texImage
->CompressedSize
);