2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 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 image-related functions.
33 #include "bufferobj.h"
37 #include "framebuffer.h"
42 #include "texcompress.h"
43 #include "texformat.h"
51 * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
55 _mesa_alloc_texmemory(GLsizei bytes
)
57 return _mesa_align_malloc(bytes
, 512);
62 * Free texture memory allocated with _mesa_alloc_texmemory()
65 _mesa_free_texmemory(void *m
)
74 static void PrintTexture(GLcontext
*ctx
, const struct gl_texture_image
*img
)
76 #if CHAN_TYPE == GL_FLOAT
77 _mesa_problem(NULL
, "PrintTexture doesn't support float channels");
80 const GLchan
*data
= (const GLchan
*) img
->Data
;
83 _mesa_printf("No texture data\n");
87 switch (img
->Format
) {
94 case GL_LUMINANCE_ALPHA
:
104 _mesa_problem(NULL
, "error in PrintTexture\n");
108 for (i
= 0; i
< img
->Height
; i
++) {
109 for (j
= 0; j
< img
->Width
; j
++) {
111 _mesa_printf("%02x ", data
[0]);
113 _mesa_printf("%02x%02x ", data
[0], data
[1]);
115 _mesa_printf("%02x%02x%02x ", data
[0], data
[1], data
[2]);
117 _mesa_printf("%02x%02x%02x%02x ", data
[0], data
[1], data
[2], data
[3]);
118 data
+= (img
->RowStride
- img
->Width
) * c
;
120 /* XXX use img->ImageStride here */
129 * Compute floor(log_base_2(n)).
130 * If n < 0 return -1.
159 * Return the simple base format for a given internal texture format.
160 * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
162 * \param ctx GL context.
163 * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
165 * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
166 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
168 * This is the format which is used during texture application (i.e. the
169 * texture format and env mode determine the arithmetic used.
172 _mesa_base_tex_format( GLcontext
*ctx
, GLint internalFormat
)
174 switch (internalFormat
) {
189 case GL_LUMINANCE_ALPHA
:
190 case GL_LUMINANCE4_ALPHA4
:
191 case GL_LUMINANCE6_ALPHA2
:
192 case GL_LUMINANCE8_ALPHA8
:
193 case GL_LUMINANCE12_ALPHA4
:
194 case GL_LUMINANCE12_ALPHA12
:
195 case GL_LUMINANCE16_ALPHA16
:
196 return GL_LUMINANCE_ALPHA
;
227 if (ctx
->Extensions
.EXT_paletted_texture
) {
228 switch (internalFormat
) {
230 case GL_COLOR_INDEX1_EXT
:
231 case GL_COLOR_INDEX2_EXT
:
232 case GL_COLOR_INDEX4_EXT
:
233 case GL_COLOR_INDEX8_EXT
:
234 case GL_COLOR_INDEX12_EXT
:
235 case GL_COLOR_INDEX16_EXT
:
236 return GL_COLOR_INDEX
;
242 if (ctx
->Extensions
.SGIX_depth_texture
||
243 ctx
->Extensions
.ARB_depth_texture
) {
244 switch (internalFormat
) {
245 case GL_DEPTH_COMPONENT
:
246 case GL_DEPTH_COMPONENT16_SGIX
:
247 case GL_DEPTH_COMPONENT24_SGIX
:
248 case GL_DEPTH_COMPONENT32_SGIX
:
249 return GL_DEPTH_COMPONENT
;
255 if (ctx
->Extensions
.ARB_texture_compression
) {
256 switch (internalFormat
) {
257 case GL_COMPRESSED_ALPHA
:
259 case GL_COMPRESSED_LUMINANCE
:
261 case GL_COMPRESSED_LUMINANCE_ALPHA
:
262 return GL_LUMINANCE_ALPHA
;
263 case GL_COMPRESSED_INTENSITY
:
265 case GL_COMPRESSED_RGB
:
267 case GL_COMPRESSED_RGBA
:
274 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
) {
275 switch (internalFormat
) {
276 case GL_COMPRESSED_RGB_FXT1_3DFX
:
278 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
285 if (ctx
->Extensions
.EXT_texture_compression_s3tc
) {
286 switch (internalFormat
) {
287 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
289 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
290 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
291 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
298 if (ctx
->Extensions
.S3_s3tc
) {
299 switch (internalFormat
) {
311 if (ctx
->Extensions
.MESA_ycbcr_texture
) {
312 if (internalFormat
== GL_YCBCR_MESA
)
313 return GL_YCBCR_MESA
;
316 if (ctx
->Extensions
.ARB_texture_float
) {
317 switch (internalFormat
) {
318 case GL_ALPHA16F_ARB
:
319 case GL_ALPHA32F_ARB
:
327 case GL_INTENSITY16F_ARB
:
328 case GL_INTENSITY32F_ARB
:
330 case GL_LUMINANCE16F_ARB
:
331 case GL_LUMINANCE32F_ARB
:
333 case GL_LUMINANCE_ALPHA16F_ARB
:
334 case GL_LUMINANCE_ALPHA32F_ARB
:
335 return GL_LUMINANCE_ALPHA
;
341 if (ctx
->Extensions
.EXT_packed_depth_stencil
) {
342 switch (internalFormat
) {
343 case GL_DEPTH_STENCIL_EXT
:
344 case GL_DEPTH24_STENCIL8_EXT
:
345 return GL_DEPTH_STENCIL_EXT
;
351 return -1; /* error */
356 * Test if the given image format is a color/RGBA format (i.e., not color
357 * index, depth, stencil, etc).
358 * \param format the image format value (may by an internal texture format)
359 * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
362 is_color_format(GLenum format
)
380 case GL_LUMINANCE_ALPHA
:
381 case GL_LUMINANCE4_ALPHA4
:
382 case GL_LUMINANCE6_ALPHA2
:
383 case GL_LUMINANCE8_ALPHA8
:
384 case GL_LUMINANCE12_ALPHA4
:
385 case GL_LUMINANCE12_ALPHA12
:
386 case GL_LUMINANCE16_ALPHA16
:
413 /* float texture formats */
414 case GL_ALPHA16F_ARB
:
415 case GL_ALPHA32F_ARB
:
416 case GL_LUMINANCE16F_ARB
:
417 case GL_LUMINANCE32F_ARB
:
418 case GL_LUMINANCE_ALPHA16F_ARB
:
419 case GL_LUMINANCE_ALPHA32F_ARB
:
420 case GL_INTENSITY16F_ARB
:
421 case GL_INTENSITY32F_ARB
:
426 /* compressed formats */
427 case GL_COMPRESSED_ALPHA
:
428 case GL_COMPRESSED_LUMINANCE
:
429 case GL_COMPRESSED_LUMINANCE_ALPHA
:
430 case GL_COMPRESSED_INTENSITY
:
431 case GL_COMPRESSED_RGB
:
432 case GL_COMPRESSED_RGBA
:
437 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
438 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
439 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
440 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
441 case GL_COMPRESSED_RGB_FXT1_3DFX
:
442 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
444 case GL_YCBCR_MESA
: /* not considered to be RGB */
452 * Test if the given image format is a color index format.
455 is_index_format(GLenum format
)
459 case GL_COLOR_INDEX1_EXT
:
460 case GL_COLOR_INDEX2_EXT
:
461 case GL_COLOR_INDEX4_EXT
:
462 case GL_COLOR_INDEX8_EXT
:
463 case GL_COLOR_INDEX12_EXT
:
464 case GL_COLOR_INDEX16_EXT
:
473 * Test if the given image format is a depth component format.
476 is_depth_format(GLenum format
)
479 case GL_DEPTH_COMPONENT16_ARB
:
480 case GL_DEPTH_COMPONENT24_ARB
:
481 case GL_DEPTH_COMPONENT32_ARB
:
482 case GL_DEPTH_COMPONENT
:
491 * Test if the given image format is a YCbCr format.
494 is_ycbcr_format(GLenum format
)
506 * Test if the given image format is a Depth/Stencil format.
509 is_depthstencil_format(GLenum format
)
512 case GL_DEPTH24_STENCIL8_EXT
:
513 case GL_DEPTH_STENCIL_EXT
:
523 * Test if it is a supported compressed format.
525 * \param internalFormat the internal format token provided by the user.
527 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
528 * GL_FALSE otherwise.
530 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
534 is_compressed_format(GLcontext
*ctx
, GLenum internalFormat
)
536 GLint supported
[100]; /* 100 should be plenty */
539 n
= _mesa_get_compressed_formats(ctx
, supported
, GL_TRUE
);
541 for (i
= 0; i
< n
; i
++) {
542 if ((GLint
) internalFormat
== supported
[i
]) {
551 texture_face(GLenum target
)
553 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
554 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)
555 return (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
563 * Store a gl_texture_image pointer in a gl_texture_object structure
564 * according to the target and level parameters.
566 * \param tObj texture object.
567 * \param target texture target.
568 * \param level image level.
569 * \param texImage texture image.
571 * This was basically prompted by the introduction of cube maps.
574 _mesa_set_tex_image(struct gl_texture_object
*tObj
,
575 GLenum target
, GLint level
,
576 struct gl_texture_image
*texImage
)
584 tObj
->Image
[0][level
] = texImage
;
586 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
587 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
588 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
589 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
590 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
591 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
593 GLuint face
= ((GLuint
) target
-
594 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
595 tObj
->Image
[face
][level
] = texImage
;
598 case GL_TEXTURE_RECTANGLE_NV
:
600 tObj
->Image
[0][level
] = texImage
;
603 _mesa_problem(NULL
, "bad target in _mesa_set_tex_image()");
606 /* Set the 'back' pointer */
607 texImage
->TexObject
= tObj
;
612 * Allocate a texture image structure.
614 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
617 * \return a pointer to gl_texture_image struct with all fields initialized to
620 struct gl_texture_image
*
621 _mesa_new_texture_image( GLcontext
*ctx
)
624 return CALLOC_STRUCT(gl_texture_image
);
629 * Free texture image data.
630 * This function is a fallback called via ctx->Driver.FreeTexImageData().
632 * \param teximage texture image.
634 * Free the texture image data if it's not marked as client data.
637 _mesa_free_texture_image_data(GLcontext
*ctx
,
638 struct gl_texture_image
*texImage
)
642 if (texImage
->Data
&& !texImage
->IsClientData
) {
643 /* free the old texture data */
644 _mesa_free_texmemory(texImage
->Data
);
647 texImage
->Data
= NULL
;
652 * Free texture image.
654 * \param teximage texture image.
656 * Free the texture image structure and the associated image data.
659 _mesa_delete_texture_image( GLcontext
*ctx
, struct gl_texture_image
*texImage
)
661 if (texImage
->Data
) {
662 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
664 ASSERT(texImage
->Data
== NULL
);
665 if (texImage
->ImageOffsets
)
666 _mesa_free(texImage
->ImageOffsets
);
667 _mesa_free(texImage
);
672 * Test if a target is a proxy target.
674 * \param target texture target.
676 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
679 _mesa_is_proxy_texture(GLenum target
)
681 return (target
== GL_PROXY_TEXTURE_1D
||
682 target
== GL_PROXY_TEXTURE_2D
||
683 target
== GL_PROXY_TEXTURE_3D
||
684 target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
685 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
);
690 * Get the texture object that corresponds to the target of the given texture unit.
692 * \param ctx GL context.
693 * \param texUnit texture unit.
694 * \param target texture target.
696 * \return pointer to the texture object on success, or NULL on failure.
698 * \sa gl_texture_unit.
700 struct gl_texture_object
*
701 _mesa_select_tex_object(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
706 return texUnit
->Current1D
;
707 case GL_PROXY_TEXTURE_1D
:
708 return ctx
->Texture
.Proxy1D
;
710 return texUnit
->Current2D
;
711 case GL_PROXY_TEXTURE_2D
:
712 return ctx
->Texture
.Proxy2D
;
714 return texUnit
->Current3D
;
715 case GL_PROXY_TEXTURE_3D
:
716 return ctx
->Texture
.Proxy3D
;
717 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
718 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
719 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
720 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
721 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
722 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
723 case GL_TEXTURE_CUBE_MAP_ARB
:
724 return ctx
->Extensions
.ARB_texture_cube_map
725 ? texUnit
->CurrentCubeMap
: NULL
;
726 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
727 return ctx
->Extensions
.ARB_texture_cube_map
728 ? ctx
->Texture
.ProxyCubeMap
: NULL
;
729 case GL_TEXTURE_RECTANGLE_NV
:
730 return ctx
->Extensions
.NV_texture_rectangle
731 ? texUnit
->CurrentRect
: NULL
;
732 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
733 return ctx
->Extensions
.NV_texture_rectangle
734 ? ctx
->Texture
.ProxyRect
: NULL
;
736 _mesa_problem(NULL
, "bad target in _mesa_select_tex_object()");
743 * Get the texture image struct which corresponds to target and level
744 * of the given texture unit.
746 * \param ctx GL context.
747 * \param texUnit texture unit.
748 * \param target texture target.
749 * \param level image level.
751 * \return pointer to the texture image structure on success, or NULL on failure.
753 * \sa gl_texture_unit.
755 struct gl_texture_image
*
756 _mesa_select_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
757 GLenum target
, GLint level
)
760 ASSERT(level
< MAX_TEXTURE_LEVELS
);
763 return texUnit
->Current1D
->Image
[0][level
];
764 case GL_PROXY_TEXTURE_1D
:
765 return ctx
->Texture
.Proxy1D
->Image
[0][level
];
767 return texUnit
->Current2D
->Image
[0][level
];
768 case GL_PROXY_TEXTURE_2D
:
769 return ctx
->Texture
.Proxy2D
->Image
[0][level
];
771 return texUnit
->Current3D
->Image
[0][level
];
772 case GL_PROXY_TEXTURE_3D
:
773 return ctx
->Texture
.Proxy3D
->Image
[0][level
];
774 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
775 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
776 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
777 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
778 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
779 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
780 if (ctx
->Extensions
.ARB_texture_cube_map
) {
781 GLuint face
= ((GLuint
) target
-
782 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
783 return texUnit
->CurrentCubeMap
->Image
[face
][level
];
787 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
788 if (ctx
->Extensions
.ARB_texture_cube_map
)
789 return ctx
->Texture
.ProxyCubeMap
->Image
[0][level
];
792 case GL_TEXTURE_RECTANGLE_NV
:
793 if (ctx
->Extensions
.NV_texture_rectangle
) {
795 return texUnit
->CurrentRect
->Image
[0][level
];
800 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
801 if (ctx
->Extensions
.NV_texture_rectangle
) {
803 return ctx
->Texture
.ProxyRect
->Image
[0][level
];
809 _mesa_problem(ctx
, "bad target in _mesa_select_tex_image()");
816 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
817 * it and install it. Only return NULL if passed a bad parameter or run
820 struct gl_texture_image
*
821 _mesa_get_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
822 GLenum target
, GLint level
)
824 struct gl_texture_image
*texImage
;
825 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
827 struct gl_texture_object
*texObj
;
828 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
830 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture image allocation");
833 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
835 _mesa_set_tex_image(texObj
, target
, level
, texImage
);
842 * Return pointer to the specified proxy texture image.
843 * Note that proxy textures are per-context, not per-texture unit.
844 * \return pointer to texture image or NULL if invalid target, invalid
845 * level, or out of memory.
847 struct gl_texture_image
*
848 _mesa_get_proxy_tex_image(GLcontext
*ctx
, GLenum target
, GLint level
)
850 struct gl_texture_image
*texImage
;
856 case GL_PROXY_TEXTURE_1D
:
857 if (level
>= ctx
->Const
.MaxTextureLevels
)
859 texImage
= ctx
->Texture
.Proxy1D
->Image
[0][level
];
861 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
863 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
866 ctx
->Texture
.Proxy1D
->Image
[0][level
] = texImage
;
867 /* Set the 'back' pointer */
868 texImage
->TexObject
= ctx
->Texture
.Proxy1D
;
871 case GL_PROXY_TEXTURE_2D
:
872 if (level
>= ctx
->Const
.MaxTextureLevels
)
874 texImage
= ctx
->Texture
.Proxy2D
->Image
[0][level
];
876 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
878 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
881 ctx
->Texture
.Proxy2D
->Image
[0][level
] = texImage
;
882 /* Set the 'back' pointer */
883 texImage
->TexObject
= ctx
->Texture
.Proxy2D
;
886 case GL_PROXY_TEXTURE_3D
:
887 if (level
>= ctx
->Const
.Max3DTextureLevels
)
889 texImage
= ctx
->Texture
.Proxy3D
->Image
[0][level
];
891 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
893 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
896 ctx
->Texture
.Proxy3D
->Image
[0][level
] = texImage
;
897 /* Set the 'back' pointer */
898 texImage
->TexObject
= ctx
->Texture
.Proxy3D
;
901 case GL_PROXY_TEXTURE_CUBE_MAP
:
902 if (level
>= ctx
->Const
.MaxCubeTextureLevels
)
904 texImage
= ctx
->Texture
.ProxyCubeMap
->Image
[0][level
];
906 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
908 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
911 ctx
->Texture
.ProxyCubeMap
->Image
[0][level
] = texImage
;
912 /* Set the 'back' pointer */
913 texImage
->TexObject
= ctx
->Texture
.ProxyCubeMap
;
916 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
919 texImage
= ctx
->Texture
.ProxyRect
->Image
[0][level
];
921 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
923 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
926 ctx
->Texture
.ProxyRect
->Image
[0][level
] = texImage
;
927 /* Set the 'back' pointer */
928 texImage
->TexObject
= ctx
->Texture
.ProxyRect
;
938 * Get the maximum number of allowed mipmap levels.
940 * \param ctx GL context.
941 * \param target texture target.
943 * \return the maximum number of allowed mipmap levels for the given
944 * texture target, or zero if passed a bad target.
949 _mesa_max_texture_levels(GLcontext
*ctx
, GLenum target
)
953 case GL_PROXY_TEXTURE_1D
:
955 case GL_PROXY_TEXTURE_2D
:
956 return ctx
->Const
.MaxTextureLevels
;
958 case GL_PROXY_TEXTURE_3D
:
959 return ctx
->Const
.Max3DTextureLevels
;
960 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
961 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
962 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
963 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
964 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
965 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
966 case GL_TEXTURE_CUBE_MAP_ARB
:
967 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
968 return ctx
->Const
.MaxCubeTextureLevels
;
969 case GL_TEXTURE_RECTANGLE_NV
:
970 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
973 return 0; /* bad target */
979 #if 000 /* not used anymore */
981 * glTexImage[123]D can accept a NULL image pointer. In this case we
982 * create a texture image with unspecified image contents per the OpenGL
986 make_null_texture(GLint width
, GLint height
, GLint depth
, GLenum format
)
988 const GLint components
= _mesa_components_in_format(format
);
989 const GLint numPixels
= width
* height
* depth
;
990 GLubyte
*data
= (GLubyte
*) MALLOC(numPixels
* components
* sizeof(GLubyte
));
994 * Let's see if anyone finds this. If glTexImage2D() is called with
995 * a NULL image pointer then load the texture image with something
996 * interesting instead of leaving it indeterminate.
999 static const char message
[8][32] = {
1000 " X X XXXXX XXX X ",
1001 " XX XX X X X X X ",
1003 " X X XXXX XXX XXXXX ",
1006 " X X XXXXX XXX X X ",
1010 GLubyte
*imgPtr
= data
;
1012 for (h
= 0; h
< depth
; h
++) {
1013 for (i
= 0; i
< height
; i
++) {
1014 GLint srcRow
= 7 - (i
% 8);
1015 for (j
= 0; j
< width
; j
++) {
1016 GLint srcCol
= j
% 32;
1017 GLubyte texel
= (message
[srcRow
][srcCol
]=='X') ? 255 : 70;
1018 for (k
= 0; k
< components
; k
++) {
1034 * Reset the fields of a gl_texture_image struct to zero.
1036 * \param img texture image structure.
1038 * This is called when a proxy texture test fails, we set all the
1039 * image members (except DriverData) to zero.
1040 * It's also used in glTexImage[123]D as a safeguard to be sure all
1041 * required fields get initialized properly by the Driver.TexImage[123]D
1045 clear_teximage_fields(struct gl_texture_image
*img
)
1048 img
->_BaseFormat
= 0;
1049 img
->InternalFormat
= 0;
1055 if (img
->ImageOffsets
) {
1056 _mesa_free(img
->ImageOffsets
);
1057 img
->ImageOffsets
= NULL
;
1063 img
->HeightLog2
= 0;
1066 img
->TexFormat
= &_mesa_null_texformat
;
1067 img
->FetchTexelc
= NULL
;
1068 img
->FetchTexelf
= NULL
;
1069 img
->IsCompressed
= 0;
1070 img
->CompressedSize
= 0;
1075 * Initialize basic fields of the gl_texture_image struct.
1077 * \param ctx GL context.
1078 * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
1079 * \param img texture image structure to be initialized.
1080 * \param width image width.
1081 * \param height image height.
1082 * \param depth image depth.
1083 * \param border image border.
1084 * \param internalFormat internal format.
1086 * Fills in the fields of \p img with the given information.
1087 * Note: width, height and depth include the border.
1090 _mesa_init_teximage_fields(GLcontext
*ctx
, GLenum target
,
1091 struct gl_texture_image
*img
,
1092 GLsizei width
, GLsizei height
, GLsizei depth
,
1093 GLint border
, GLenum internalFormat
)
1102 img
->_BaseFormat
= _mesa_base_tex_format( ctx
, internalFormat
);
1103 ASSERT(img
->_BaseFormat
> 0);
1104 img
->InternalFormat
= internalFormat
;
1105 img
->Border
= border
;
1107 img
->Height
= height
;
1109 img
->Width2
= width
- 2 * border
; /* == 1 << img->WidthLog2; */
1110 img
->Height2
= height
- 2 * border
; /* == 1 << img->HeightLog2; */
1111 img
->Depth2
= depth
- 2 * border
; /* == 1 << img->DepthLog2; */
1112 img
->WidthLog2
= logbase2(img
->Width2
);
1113 if (height
== 1) /* 1-D texture */
1114 img
->HeightLog2
= 0;
1116 img
->HeightLog2
= logbase2(img
->Height2
);
1117 if (depth
== 1) /* 2-D texture */
1120 img
->DepthLog2
= logbase2(img
->Depth2
);
1121 img
->MaxLog2
= MAX2(img
->WidthLog2
, img
->HeightLog2
);
1122 img
->IsCompressed
= GL_FALSE
;
1123 img
->CompressedSize
= 0;
1125 if ((width
== 1 || _mesa_bitcount(img
->Width2
) == 1) &&
1126 (height
== 1 || _mesa_bitcount(img
->Height2
) == 1) &&
1127 (depth
== 1 || _mesa_bitcount(img
->Depth2
) == 1))
1128 img
->_IsPowerOfTwo
= GL_TRUE
;
1130 img
->_IsPowerOfTwo
= GL_FALSE
;
1132 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
1133 img
->RowStride
= width
;
1134 /* Allocate the ImageOffsets array and initialize to typical values.
1135 * We allocate the array for 1D/2D textures too in order to avoid special-
1136 * case code in the texstore routines.
1138 img
->ImageOffsets
= (GLuint
*) _mesa_malloc(depth
* sizeof(GLuint
));
1139 for (i
= 0; i
< depth
; i
++) {
1140 img
->ImageOffsets
[i
] = i
* width
* height
;
1143 /* Compute Width/Height/DepthScale for mipmap lod computation */
1144 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1145 /* scale = 1.0 since texture coords directly map to texels */
1146 img
->WidthScale
= 1.0;
1147 img
->HeightScale
= 1.0;
1148 img
->DepthScale
= 1.0;
1151 img
->WidthScale
= (GLfloat
) img
->Width
;
1152 img
->HeightScale
= (GLfloat
) img
->Height
;
1153 img
->DepthScale
= (GLfloat
) img
->Depth
;
1159 * This is the fallback for Driver.TestProxyTexImage(). Test the texture
1160 * level, width, height and depth against the ctx->Const limits for textures.
1162 * A hardware driver might override this function if, for example, the
1163 * max 3D texture size is 512x512x64 (i.e. not a cube).
1165 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
1166 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
1167 * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
1168 * \param level as passed to glTexImage
1169 * \param internalFormat as passed to glTexImage
1170 * \param format as passed to glTexImage
1171 * \param type as passed to glTexImage
1172 * \param width as passed to glTexImage
1173 * \param height as passed to glTexImage
1174 * \param depth as passed to glTexImage
1175 * \param border as passed to glTexImage
1176 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1179 _mesa_test_proxy_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
1180 GLint internalFormat
, GLenum format
, GLenum type
,
1181 GLint width
, GLint height
, GLint depth
, GLint border
)
1185 (void) internalFormat
;
1190 case GL_PROXY_TEXTURE_1D
:
1191 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1192 if (width
< 2 * border
|| width
> 2 + maxSize
||
1193 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1194 _mesa_bitcount(width
- 2 * border
) != 1) ||
1195 level
>= ctx
->Const
.MaxTextureLevels
) {
1196 /* bad width or level */
1200 case GL_PROXY_TEXTURE_2D
:
1201 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1202 if (width
< 2 * border
|| width
> 2 + maxSize
||
1203 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1204 _mesa_bitcount(width
- 2 * border
) != 1) ||
1205 height
< 2 * border
|| height
> 2 + maxSize
||
1206 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1207 _mesa_bitcount(height
- 2 * border
) != 1) ||
1208 level
>= ctx
->Const
.MaxTextureLevels
) {
1209 /* bad width or height or level */
1213 case GL_PROXY_TEXTURE_3D
:
1214 maxSize
= 1 << (ctx
->Const
.Max3DTextureLevels
- 1);
1215 if (width
< 2 * border
|| width
> 2 + maxSize
||
1216 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1217 _mesa_bitcount(width
- 2 * border
) != 1) ||
1218 height
< 2 * border
|| height
> 2 + maxSize
||
1219 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1220 _mesa_bitcount(height
- 2 * border
) != 1) ||
1221 depth
< 2 * border
|| depth
> 2 + maxSize
||
1222 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1223 _mesa_bitcount(depth
- 2 * border
) != 1) ||
1224 level
>= ctx
->Const
.Max3DTextureLevels
) {
1225 /* bad width or height or depth or level */
1229 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
1230 if (width
< 1 || width
> ctx
->Const
.MaxTextureRectSize
||
1231 height
< 1 || height
> ctx
->Const
.MaxTextureRectSize
||
1233 /* bad width or height or level */
1237 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
1238 maxSize
= 1 << (ctx
->Const
.MaxCubeTextureLevels
- 1);
1239 if (width
< 2 * border
|| width
> 2 + maxSize
||
1240 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1241 _mesa_bitcount(width
- 2 * border
) != 1) ||
1242 height
< 2 * border
|| height
> 2 + maxSize
||
1243 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1244 _mesa_bitcount(height
- 2 * border
) != 1) ||
1245 level
>= ctx
->Const
.MaxCubeTextureLevels
) {
1246 /* bad width or height */
1251 _mesa_problem(ctx
, "Invalid target in _mesa_test_proxy_teximage");
1258 * Test the glTexImage[123]D() parameters for errors.
1260 * \param ctx GL context.
1261 * \param target texture target given by the user.
1262 * \param level image level given by the user.
1263 * \param internalFormat internal format given by the user.
1264 * \param format pixel data format given by the user.
1265 * \param type pixel data type given by the user.
1266 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1267 * \param width image width given by the user.
1268 * \param height image height given by the user.
1269 * \param depth image depth given by the user.
1270 * \param border image border given by the user.
1272 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1274 * Verifies each of the parameters against the constants specified in
1275 * __GLcontextRec::Const and the supported extensions, and according to the
1276 * OpenGL specification.
1279 texture_error_check( GLcontext
*ctx
, GLenum target
,
1280 GLint level
, GLint internalFormat
,
1281 GLenum format
, GLenum type
,
1283 GLint width
, GLint height
,
1284 GLint depth
, GLint border
)
1286 const GLboolean isProxy
= _mesa_is_proxy_texture(target
);
1288 GLboolean colorFormat
, indexFormat
;
1290 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1291 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1293 _mesa_error(ctx
, GL_INVALID_VALUE
,
1294 "glTexImage%dD(level=%d)", dimensions
, level
);
1300 if (border
< 0 || border
> 1 ||
1301 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1302 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1304 _mesa_error(ctx
, GL_INVALID_VALUE
,
1305 "glTexImage%dD(border=%d)", dimensions
, border
);
1310 if (width
< 0 || height
< 0 || depth
< 0) {
1312 _mesa_error(ctx
, GL_INVALID_VALUE
,
1313 "glTexImage%dD(width, height or depth < 0)", dimensions
);
1318 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1319 * level, width, height and depth.
1321 if (dimensions
== 1) {
1322 if (target
== GL_PROXY_TEXTURE_1D
|| target
== GL_TEXTURE_1D
) {
1323 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1324 level
, internalFormat
,
1326 width
, 1, 1, border
);
1329 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1333 else if (dimensions
== 2) {
1334 if (target
== GL_PROXY_TEXTURE_2D
|| target
== GL_TEXTURE_2D
) {
1335 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1336 level
, internalFormat
,
1338 width
, height
, 1, border
);
1340 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
1341 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1342 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
1343 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1344 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1347 sizeOK
= (width
== height
) &&
1348 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1349 level
, internalFormat
, format
, type
,
1350 width
, height
, 1, border
);
1352 else if (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
||
1353 target
== GL_TEXTURE_RECTANGLE_NV
) {
1354 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1355 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1358 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1359 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1360 level
, internalFormat
,
1362 width
, height
, 1, border
);
1365 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1369 else if (dimensions
== 3) {
1370 if (target
== GL_PROXY_TEXTURE_3D
|| target
== GL_TEXTURE_3D
) {
1371 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_3D
,
1372 level
, internalFormat
,
1374 width
, height
, depth
, border
);
1377 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1382 _mesa_problem( ctx
, "bad dims in texture_error_check" );
1388 _mesa_error(ctx
, GL_INVALID_VALUE
,
1389 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1390 dimensions
, level
, width
, height
, depth
);
1395 /* Check internalFormat */
1396 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1398 _mesa_error(ctx
, GL_INVALID_VALUE
,
1399 "glTexImage%dD(internalFormat=0x%x)",
1400 dimensions
, internalFormat
);
1405 /* Check incoming image format and type */
1406 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
1407 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1408 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1411 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1412 "glTexImage%dD(format or type)", dimensions
);
1417 /* make sure internal format and format basically agree */
1418 colorFormat
= is_color_format(format
);
1419 indexFormat
= is_index_format(format
);
1420 if ((is_color_format(internalFormat
) && !colorFormat
&& !indexFormat
) ||
1421 (is_index_format(internalFormat
) && !indexFormat
) ||
1422 (is_depth_format(internalFormat
) != is_depth_format(format
)) ||
1423 (is_ycbcr_format(internalFormat
) != is_ycbcr_format(format
)) ||
1424 (is_depthstencil_format(internalFormat
) != is_depthstencil_format(format
))) {
1426 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1427 "glTexImage(internalFormat/format)");
1431 /* additional checks for ycbcr textures */
1432 if (internalFormat
== GL_YCBCR_MESA
) {
1433 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1434 if (type
!= GL_UNSIGNED_SHORT_8_8_MESA
&&
1435 type
!= GL_UNSIGNED_SHORT_8_8_REV_MESA
) {
1437 _mesa_sprintf(message
,
1438 "glTexImage%d(format/type YCBCR mismatch", dimensions
);
1439 _mesa_error(ctx
, GL_INVALID_ENUM
, message
);
1440 return GL_TRUE
; /* error */
1442 if (target
!= GL_TEXTURE_2D
&&
1443 target
!= GL_PROXY_TEXTURE_2D
&&
1444 target
!= GL_TEXTURE_RECTANGLE_NV
&&
1445 target
!= GL_PROXY_TEXTURE_RECTANGLE_NV
) {
1447 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage(target)");
1453 _mesa_sprintf(message
,
1454 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1455 dimensions
, border
);
1456 _mesa_error(ctx
, GL_INVALID_VALUE
, message
);
1462 /* additional checks for depth textures */
1463 if (_mesa_base_tex_format(ctx
, internalFormat
) == GL_DEPTH_COMPONENT
) {
1464 /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
1465 if (target
!= GL_TEXTURE_1D
&&
1466 target
!= GL_PROXY_TEXTURE_1D
&&
1467 target
!= GL_TEXTURE_2D
&&
1468 target
!= GL_PROXY_TEXTURE_2D
&&
1469 target
!= GL_TEXTURE_RECTANGLE_ARB
&&
1470 target
!= GL_PROXY_TEXTURE_RECTANGLE_ARB
) {
1472 _mesa_error(ctx
, GL_INVALID_ENUM
,
1473 "glTexImage(target/internalFormat)");
1478 /* additional checks for compressed textures */
1479 if (is_compressed_format(ctx
, internalFormat
)) {
1480 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1483 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1484 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1485 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1486 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1491 _mesa_error(ctx
, GL_INVALID_ENUM
,
1492 "glTexImage%d(target)", dimensions
);
1498 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1499 "glTexImage%D(border!=0)", dimensions
);
1505 /* if we get here, the parameters are OK */
1511 * Test glTexSubImage[123]D() parameters for errors.
1513 * \param ctx GL context.
1514 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1515 * \param target texture target given by the user.
1516 * \param level image level given by the user.
1517 * \param xoffset sub-image x offset given by the user.
1518 * \param yoffset sub-image y offset given by the user.
1519 * \param zoffset sub-image z offset given by the user.
1520 * \param format pixel data format given by the user.
1521 * \param type pixel data type given by the user.
1522 * \param width image width given by the user.
1523 * \param height image height given by the user.
1524 * \param depth image depth given by the user.
1526 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1528 * Verifies each of the parameters against the constants specified in
1529 * __GLcontextRec::Const and the supported extensions, and according to the
1530 * OpenGL specification.
1533 subtexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1534 GLenum target
, GLint level
,
1535 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1536 GLint width
, GLint height
, GLint depth
,
1537 GLenum format
, GLenum type
)
1539 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1540 struct gl_texture_image
*destTex
;
1543 if (dimensions
== 1) {
1544 if (target
!= GL_TEXTURE_1D
) {
1545 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
1549 else if (dimensions
== 2) {
1550 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1551 target
<=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1552 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1553 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1557 else if (ctx
->Extensions
.NV_texture_rectangle
&&
1558 target
== GL_TEXTURE_RECTANGLE_NV
) {
1559 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1560 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1564 else if (target
!= GL_TEXTURE_2D
) {
1565 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1569 else if (dimensions
== 3) {
1570 if (target
!= GL_TEXTURE_3D
) {
1571 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
1576 _mesa_problem( ctx
, "invalid dims in texture_error_check" );
1580 /* Basic level check */
1581 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1582 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level=%d)", level
);
1587 _mesa_error(ctx
, GL_INVALID_VALUE
,
1588 "glTexSubImage%dD(width=%d)", dimensions
, width
);
1591 if (height
< 0 && dimensions
> 1) {
1592 _mesa_error(ctx
, GL_INVALID_VALUE
,
1593 "glTexSubImage%dD(height=%d)", dimensions
, height
);
1596 if (depth
< 0 && dimensions
> 2) {
1597 _mesa_error(ctx
, GL_INVALID_VALUE
,
1598 "glTexSubImage%dD(depth=%d)", dimensions
, depth
);
1602 destTex
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1605 /* undefined image level */
1606 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage%dD", dimensions
);
1610 if (xoffset
< -((GLint
)destTex
->Border
)) {
1611 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset)",
1615 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
1616 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset+width)",
1620 if (dimensions
> 1) {
1621 if (yoffset
< -((GLint
)destTex
->Border
)) {
1622 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset)",
1626 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
1627 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset+height)",
1632 if (dimensions
> 2) {
1633 if (zoffset
< -((GLint
)destTex
->Border
)) {
1634 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
1637 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+ destTex
->Border
)) {
1638 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
1643 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
1644 _mesa_error(ctx
, GL_INVALID_ENUM
,
1645 "glTexSubImage%dD(format or type)", dimensions
);
1649 if (destTex
->IsCompressed
) {
1650 const struct gl_texture_unit
*texUnit
;
1651 const struct gl_texture_image
*texImage
;
1652 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1653 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1655 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1658 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1659 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1660 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1661 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1665 _mesa_error(ctx
, GL_INVALID_ENUM
,
1666 "glTexSubImage%D(target)", dimensions
);
1669 /* offset must be multiple of 4 */
1670 if ((xoffset
& 3) || (yoffset
& 3)) {
1671 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1672 "glTexSubImage%D(xoffset or yoffset)", dimensions
);
1675 /* size must be multiple of 4 or equal to whole texture size */
1676 if ((width
& 3) && (GLuint
) width
!= texImage
->Width
) {
1677 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1678 "glTexSubImage%D(width)", dimensions
);
1681 if ((height
& 3) && (GLuint
) height
!= texImage
->Height
) {
1682 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1683 "glTexSubImage%D(width)", dimensions
);
1693 * Test glCopyTexImage[12]D() parameters for errors.
1695 * \param ctx GL context.
1696 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1697 * \param target texture target given by the user.
1698 * \param level image level given by the user.
1699 * \param internalFormat internal format given by the user.
1700 * \param width image width given by the user.
1701 * \param height image height given by the user.
1702 * \param depth image depth given by the user.
1703 * \param border texture border.
1705 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1707 * Verifies each of the parameters against the constants specified in
1708 * __GLcontextRec::Const and the supported extensions, and according to the
1709 * OpenGL specification.
1712 copytexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1713 GLenum target
, GLint level
, GLint internalFormat
,
1714 GLint width
, GLint height
, GLint border
)
1720 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1721 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1722 /* Check that the source buffer is complete */
1723 if (ctx
->ReadBuffer
->Name
) {
1724 _mesa_test_framebuffer_completeness(ctx
, ctx
->ReadBuffer
);
1725 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
1726 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
1727 "glCopyTexImage%dD(invalid readbuffer)", dimensions
);
1732 _mesa_error(ctx
, GL_INVALID_VALUE
,
1733 "glCopyTexImage%dD(level=%d)", dimensions
, level
);
1738 if (border
< 0 || border
> 1 ||
1739 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1740 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1744 format
= _mesa_base_tex_format(ctx
, internalFormat
);
1746 _mesa_error(ctx
, GL_INVALID_VALUE
,
1747 "glCopyTexImage%dD(internalFormat)", dimensions
);
1751 /* NOTE: the format and type aren't really significant for
1752 * TestProxyTexImage(). Only the internalformat really matters.
1753 if (!_mesa_source_buffer_exists(ctx, format)) {
1754 _mesa_error(ctx, GL_INVALID_OPERATION,
1755 "glCopyTexImage%dD(missing readbuffer)", dimensions);
1762 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1763 * level, width, height and depth.
1765 if (dimensions
== 1) {
1766 if (target
== GL_TEXTURE_1D
) {
1767 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1768 level
, internalFormat
,
1770 width
, 1, 1, border
);
1773 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
1777 else if (dimensions
== 2) {
1778 if (target
== GL_TEXTURE_2D
) {
1779 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1780 level
, internalFormat
,
1782 width
, height
, 1, border
);
1784 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1785 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1786 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1787 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1790 sizeOK
= (width
== height
) &&
1791 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1792 level
, internalFormat
, format
, type
,
1793 width
, height
, 1, border
);
1795 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1796 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1797 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1800 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1801 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1802 level
, internalFormat
,
1804 width
, height
, 1, border
);
1807 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1812 _mesa_problem(ctx
, "invalid dimensions in copytexture_error_check");
1817 if (dimensions
== 1) {
1818 _mesa_error(ctx
, GL_INVALID_VALUE
,
1819 "glCopyTexImage1D(width=%d)", width
);
1822 ASSERT(dimensions
== 2);
1823 _mesa_error(ctx
, GL_INVALID_VALUE
,
1824 "glCopyTexImage2D(width=%d, height=%d)", width
, height
);
1829 if (is_compressed_format(ctx
, internalFormat
)) {
1830 if (target
!= GL_TEXTURE_2D
) {
1831 _mesa_error(ctx
, GL_INVALID_ENUM
,
1832 "glCopyTexImage%d(target)", dimensions
);
1836 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1837 "glCopyTexImage%D(border!=0)", dimensions
);
1841 else if (is_depth_format(internalFormat
)) {
1842 /* make sure we have depth/stencil buffers */
1843 if (!ctx
->ReadBuffer
->_DepthBuffer
) {
1844 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1845 "glCopyTexImage%D(no depth)", dimensions
);
1849 else if (is_depthstencil_format(internalFormat
)) {
1850 /* make sure we have depth/stencil buffers */
1851 if (!ctx
->ReadBuffer
->_DepthBuffer
|| !ctx
->ReadBuffer
->_StencilBuffer
) {
1852 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1853 "glCopyTexImage%D(no depth/stencil buffer)", dimensions
);
1858 /* if we get here, the parameters are OK */
1864 * Test glCopyTexSubImage[12]D() parameters for errors.
1866 * \param ctx GL context.
1867 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1868 * \param target texture target given by the user.
1869 * \param level image level given by the user.
1870 * \param xoffset sub-image x offset given by the user.
1871 * \param yoffset sub-image y offset given by the user.
1872 * \param zoffset sub-image z offset given by the user.
1873 * \param width image width given by the user.
1874 * \param height image height given by the user.
1876 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1878 * Verifies each of the parameters against the constants specified in
1879 * __GLcontextRec::Const and the supported extensions, and according to the
1880 * OpenGL specification.
1883 copytexsubimage_error_check( GLcontext
*ctx
, GLuint dimensions
,
1884 GLenum target
, GLint level
,
1885 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1886 GLsizei width
, GLsizei height
)
1888 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1889 struct gl_texture_image
*teximage
;
1892 /* Check that the source buffer is complete */
1893 if (ctx
->ReadBuffer
->Name
) {
1894 _mesa_test_framebuffer_completeness(ctx
, ctx
->ReadBuffer
);
1895 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
1896 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
1897 "glCopyTexImage%dD(invalid readbuffer)", dimensions
);
1902 if (dimensions
== 1) {
1903 if (target
!= GL_TEXTURE_1D
) {
1904 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
1908 else if (dimensions
== 2) {
1909 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1910 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1911 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1912 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1916 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1917 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1918 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1922 else if (target
!= GL_TEXTURE_2D
) {
1923 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1927 else if (dimensions
== 3) {
1928 if (target
!= GL_TEXTURE_3D
) {
1929 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
1935 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1936 _mesa_error(ctx
, GL_INVALID_VALUE
,
1937 "glCopyTexSubImage%dD(level=%d)", dimensions
, level
);
1943 _mesa_error(ctx
, GL_INVALID_VALUE
,
1944 "glCopyTexSubImage%dD(width=%d)", dimensions
, width
);
1947 if (dimensions
> 1 && height
< 0) {
1948 _mesa_error(ctx
, GL_INVALID_VALUE
,
1949 "glCopyTexSubImage%dD(height=%d)", dimensions
, height
);
1953 teximage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1955 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1956 "glCopyTexSubImage%dD(undefined texture level: %d)",
1961 if (xoffset
< -((GLint
)teximage
->Border
)) {
1962 _mesa_error(ctx
, GL_INVALID_VALUE
,
1963 "glCopyTexSubImage%dD(xoffset=%d)", dimensions
, xoffset
);
1966 if (xoffset
+ width
> (GLint
) (teximage
->Width
+ teximage
->Border
)) {
1967 _mesa_error(ctx
, GL_INVALID_VALUE
,
1968 "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
1971 if (dimensions
> 1) {
1972 if (yoffset
< -((GLint
)teximage
->Border
)) {
1973 _mesa_error(ctx
, GL_INVALID_VALUE
,
1974 "glCopyTexSubImage%dD(yoffset=%d)", dimensions
, yoffset
);
1977 /* NOTE: we're adding the border here, not subtracting! */
1978 if (yoffset
+ height
> (GLint
) (teximage
->Height
+ teximage
->Border
)) {
1979 _mesa_error(ctx
, GL_INVALID_VALUE
,
1980 "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
1985 if (dimensions
> 2) {
1986 if (zoffset
< -((GLint
)teximage
->Border
)) {
1987 _mesa_error(ctx
, GL_INVALID_VALUE
,
1988 "glCopyTexSubImage%dD(zoffset)", dimensions
);
1991 if (zoffset
> (GLint
) (teximage
->Depth
+ teximage
->Border
)) {
1992 _mesa_error(ctx
, GL_INVALID_VALUE
,
1993 "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
1998 if (teximage
->IsCompressed
) {
1999 if (!_mesa_source_buffer_exists(ctx
, teximage
->_BaseFormat
)) {
2000 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2001 "glCopyTexSubImage%dD(missing readbuffer)", dimensions
);
2005 if (target
!= GL_TEXTURE_2D
) {
2006 _mesa_error(ctx
, GL_INVALID_ENUM
,
2007 "glCopyTexSubImage%d(target)", dimensions
);
2010 /* offset must be multiple of 4 */
2011 if ((xoffset
& 3) || (yoffset
& 3)) {
2012 _mesa_error(ctx
, GL_INVALID_VALUE
,
2013 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions
);
2016 /* size must be multiple of 4 */
2017 if ((width
& 3) != 0 && (GLuint
) width
!= teximage
->Width
) {
2018 _mesa_error(ctx
, GL_INVALID_VALUE
,
2019 "glCopyTexSubImage%D(width)", dimensions
);
2022 if ((height
& 3) != 0 && (GLuint
) height
!= teximage
->Height
) {
2023 _mesa_error(ctx
, GL_INVALID_VALUE
,
2024 "glCopyTexSubImage%D(height)", dimensions
);
2029 if (teximage
->InternalFormat
== GL_YCBCR_MESA
) {
2030 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glCopyTexSubImage2D");
2034 if (teximage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
2035 if (!ctx
->ReadBuffer
->_DepthBuffer
) {
2036 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2037 "glCopyTexSubImage%D(no depth buffer)",
2042 else if (teximage
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2043 if (!ctx
->ReadBuffer
->_DepthBuffer
|| !ctx
->ReadBuffer
->_StencilBuffer
) {
2044 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2045 "glCopyTexSubImage%D(no depth/stencil buffer)",
2051 /* if we get here, the parameters are OK */
2057 * Get texture image. Called by glGetTexImage.
2059 * \param target texture target.
2060 * \param level image level.
2061 * \param format pixel data format for returned image.
2062 * \param type pixel data type for returned image.
2063 * \param pixels returned pixel data.
2066 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
2067 GLenum type
, GLvoid
*pixels
)
2069 const struct gl_texture_unit
*texUnit
;
2070 struct gl_texture_object
*texObj
;
2071 struct gl_texture_image
*texImage
;
2072 GLint maxLevels
= 0;
2073 GET_CURRENT_CONTEXT(ctx
);
2074 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2076 texUnit
= &(ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
]);
2077 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2078 if (!texObj
|| _mesa_is_proxy_texture(target
)) {
2079 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)");
2083 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
2084 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
2086 if (level
< 0 || level
>= maxLevels
) {
2087 _mesa_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
2091 if (_mesa_sizeof_packed_type(type
) <= 0) {
2092 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
2096 if (_mesa_components_in_format(format
) <= 0 ||
2097 format
== GL_STENCIL_INDEX
) {
2098 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
2102 if (!ctx
->Extensions
.EXT_paletted_texture
&& is_index_format(format
)) {
2103 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2106 if (!ctx
->Extensions
.SGIX_depth_texture
&&
2107 !ctx
->Extensions
.ARB_depth_texture
&& is_depth_format(format
)) {
2108 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2111 if (!ctx
->Extensions
.MESA_ycbcr_texture
&& is_ycbcr_format(format
)) {
2112 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2115 if (!ctx
->Extensions
.EXT_packed_depth_stencil
2116 && is_depthstencil_format(format
)) {
2117 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2123 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2125 /* invalid mipmap level, not an error */
2129 /* Make sure the requested image format is compatible with the
2130 * texture's format. Note that a color index texture can be converted
2131 * to RGBA so that combo is allowed.
2133 if (is_color_format(format
)
2134 && !is_color_format(texImage
->TexFormat
->BaseFormat
)
2135 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
2136 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2139 else if (is_index_format(format
)
2140 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
2141 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2144 else if (is_depth_format(format
)
2145 && !is_depth_format(texImage
->TexFormat
->BaseFormat
)
2146 && !is_depthstencil_format(texImage
->TexFormat
->BaseFormat
)) {
2147 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2150 else if (is_ycbcr_format(format
)
2151 && !is_ycbcr_format(texImage
->TexFormat
->BaseFormat
)) {
2152 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2155 else if (is_depthstencil_format(format
)
2156 && !is_depthstencil_format(texImage
->TexFormat
->BaseFormat
)) {
2157 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2161 /* typically, this will call _mesa_get_teximage() */
2162 ctx
->Driver
.GetTexImage(ctx
, target
, level
, format
, type
, pixels
,
2169 * Check if the given texture image is bound to any framebuffer objects
2170 * and update/invalidate them.
2171 * XXX We're only checking the currently bound framebuffer object for now.
2172 * In the future, perhaps struct gl_texture_image should have a pointer (or
2173 * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to.
2176 update_fbo_texture(GLcontext
*ctx
, struct gl_texture_object
*texObj
,
2177 GLuint face
, GLuint level
)
2179 if (ctx
->DrawBuffer
->Name
) {
2181 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
2182 struct gl_renderbuffer_attachment
*att
=
2183 ctx
->DrawBuffer
->Attachment
+ i
;
2184 if (att
->Type
== GL_TEXTURE
&&
2185 att
->Texture
== texObj
&&
2186 att
->TextureLevel
== level
&&
2187 att
->CubeMapFace
== face
) {
2188 ASSERT(att
->Texture
->Image
[att
->CubeMapFace
][att
->TextureLevel
]);
2189 /* Tell driver about the new renderbuffer texture */
2190 ctx
->Driver
.RenderTexture(ctx
, ctx
->DrawBuffer
, att
);
2199 * Called from the API. Note that width includes the border.
2202 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalFormat
,
2203 GLsizei width
, GLint border
, GLenum format
,
2204 GLenum type
, const GLvoid
*pixels
)
2206 GLsizei postConvWidth
= width
;
2207 GET_CURRENT_CONTEXT(ctx
);
2208 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2210 if (is_color_format(internalFormat
)) {
2211 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2214 if (target
== GL_TEXTURE_1D
) {
2215 /* non-proxy target */
2216 struct gl_texture_unit
*texUnit
;
2217 struct gl_texture_object
*texObj
;
2218 struct gl_texture_image
*texImage
;
2219 const GLuint face
= texture_face(target
);
2221 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2222 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2223 return; /* error was recorded */
2226 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2227 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2228 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2231 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2234 else if (texImage
->Data
) {
2235 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2237 ASSERT(texImage
->Data
== NULL
);
2238 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2239 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2240 postConvWidth
, 1, 1,
2241 border
, internalFormat
);
2243 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2244 _mesa_update_state(ctx
);
2246 ASSERT(ctx
->Driver
.TexImage1D
);
2248 /* Give the texture to the driver! <pixels> may be null! */
2249 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
2250 width
, border
, format
, type
, pixels
,
2251 &ctx
->Unpack
, texObj
, texImage
);
2253 ASSERT(texImage
->TexFormat
);
2255 update_fbo_texture(ctx
, texObj
, face
, level
);
2258 texObj
->Complete
= GL_FALSE
;
2259 ctx
->NewState
|= _NEW_TEXTURE
;
2261 else if (target
== GL_PROXY_TEXTURE_1D
) {
2262 /* Proxy texture: check for errors and update proxy state */
2263 struct gl_texture_image
*texImage
;
2264 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2265 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2266 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2267 /* when error, clear all proxy texture image parameters */
2269 clear_teximage_fields(texImage
);
2272 /* no error, set the tex image parameters */
2274 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2275 postConvWidth
, 1, 1,
2276 border
, internalFormat
);
2277 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2278 internalFormat
, format
, type
);
2282 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
2289 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalFormat
,
2290 GLsizei width
, GLsizei height
, GLint border
,
2291 GLenum format
, GLenum type
,
2292 const GLvoid
*pixels
)
2294 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2295 GET_CURRENT_CONTEXT(ctx
);
2296 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2298 if (is_color_format(internalFormat
)) {
2299 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2303 if (target
== GL_TEXTURE_2D
||
2304 (ctx
->Extensions
.ARB_texture_cube_map
&&
2305 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2306 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) ||
2307 (ctx
->Extensions
.NV_texture_rectangle
&&
2308 target
== GL_TEXTURE_RECTANGLE_NV
)) {
2309 /* non-proxy target */
2310 struct gl_texture_unit
*texUnit
;
2311 struct gl_texture_object
*texObj
;
2312 struct gl_texture_image
*texImage
;
2313 const GLuint face
= texture_face(target
);
2315 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2316 format
, type
, 2, postConvWidth
, postConvHeight
,
2318 return; /* error was recorded */
2321 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2322 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2323 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2325 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2328 else if (texImage
->Data
) {
2329 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2331 ASSERT(texImage
->Data
== NULL
);
2332 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2333 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2334 postConvWidth
, postConvHeight
, 1,
2335 border
, internalFormat
);
2337 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2338 _mesa_update_state(ctx
);
2340 ASSERT(ctx
->Driver
.TexImage2D
);
2342 /* Give the texture to the driver! <pixels> may be null! */
2343 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
2344 width
, height
, border
, format
, type
, pixels
,
2345 &ctx
->Unpack
, texObj
, texImage
);
2347 ASSERT(texImage
->TexFormat
);
2349 update_fbo_texture(ctx
, texObj
, face
, level
);
2352 texObj
->Complete
= GL_FALSE
;
2353 ctx
->NewState
|= _NEW_TEXTURE
;
2355 else if (target
== GL_PROXY_TEXTURE_2D
||
2356 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2357 ctx
->Extensions
.ARB_texture_cube_map
) ||
2358 (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
&&
2359 ctx
->Extensions
.NV_texture_rectangle
)) {
2360 /* Proxy texture: check for errors and update proxy state */
2361 struct gl_texture_image
*texImage
;
2362 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2363 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2364 format
, type
, 2, postConvWidth
, postConvHeight
,
2366 /* when error, clear all proxy texture image parameters */
2368 clear_teximage_fields(ctx
->Texture
.Proxy2D
->Image
[0][level
]);
2371 /* no error, set the tex image parameters */
2372 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2373 postConvWidth
, postConvHeight
, 1,
2374 border
, internalFormat
);
2375 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2376 internalFormat
, format
, type
);
2380 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
2387 * Called by the API or display list executor.
2388 * Note that width and height include the border.
2391 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalFormat
,
2392 GLsizei width
, GLsizei height
, GLsizei depth
,
2393 GLint border
, GLenum format
, GLenum type
,
2394 const GLvoid
*pixels
)
2396 GET_CURRENT_CONTEXT(ctx
);
2397 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2399 if (target
== GL_TEXTURE_3D
) {
2400 /* non-proxy target */
2401 struct gl_texture_unit
*texUnit
;
2402 struct gl_texture_object
*texObj
;
2403 struct gl_texture_image
*texImage
;
2404 const GLuint face
= texture_face(target
);
2406 if (texture_error_check(ctx
, target
, level
, (GLint
) internalFormat
,
2407 format
, type
, 3, width
, height
, depth
, border
)) {
2408 return; /* error was recorded */
2411 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2412 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2413 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2415 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2418 else if (texImage
->Data
) {
2419 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2421 ASSERT(texImage
->Data
== NULL
);
2422 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2423 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2424 width
, height
, depth
,
2425 border
, internalFormat
);
2427 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2428 _mesa_update_state(ctx
);
2430 ASSERT(ctx
->Driver
.TexImage3D
);
2432 /* Give the texture to the driver! <pixels> may be null! */
2433 (*ctx
->Driver
.TexImage3D
)(ctx
, target
, level
, internalFormat
,
2434 width
, height
, depth
, border
, format
, type
,
2435 pixels
, &ctx
->Unpack
, texObj
, texImage
);
2437 ASSERT(texImage
->TexFormat
);
2439 update_fbo_texture(ctx
, texObj
, face
, level
);
2442 texObj
->Complete
= GL_FALSE
;
2443 ctx
->NewState
|= _NEW_TEXTURE
;
2445 else if (target
== GL_PROXY_TEXTURE_3D
) {
2446 /* Proxy texture: check for errors and update proxy state */
2447 struct gl_texture_image
*texImage
;
2448 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2449 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2450 format
, type
, 3, width
, height
, depth
, border
)) {
2451 /* when error, clear all proxy texture image parameters */
2453 clear_teximage_fields(texImage
);
2456 /* no error, set the tex image parameters */
2457 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2458 border
, internalFormat
);
2459 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2460 internalFormat
, format
, type
);
2464 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
2471 _mesa_TexImage3DEXT( GLenum target
, GLint level
, GLenum internalFormat
,
2472 GLsizei width
, GLsizei height
, GLsizei depth
,
2473 GLint border
, GLenum format
, GLenum type
,
2474 const GLvoid
*pixels
)
2476 _mesa_TexImage3D(target
, level
, (GLint
) internalFormat
, width
, height
,
2477 depth
, border
, format
, type
, pixels
);
2483 _mesa_TexSubImage1D( GLenum target
, GLint level
,
2484 GLint xoffset
, GLsizei width
,
2485 GLenum format
, GLenum type
,
2486 const GLvoid
*pixels
)
2488 GLsizei postConvWidth
= width
;
2489 struct gl_texture_unit
*texUnit
;
2490 struct gl_texture_object
*texObj
;
2491 struct gl_texture_image
*texImage
;
2492 GET_CURRENT_CONTEXT(ctx
);
2493 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2495 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2496 _mesa_update_state(ctx
);
2498 /* XXX should test internal format */
2499 if (is_color_format(format
)) {
2500 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2503 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
2504 postConvWidth
, 1, 1, format
, type
)) {
2505 return; /* error was detected */
2508 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2509 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2510 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2514 return; /* no-op, not an error */
2516 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2517 xoffset
+= texImage
->Border
;
2519 ASSERT(ctx
->Driver
.TexSubImage1D
);
2520 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
2521 format
, type
, pixels
, &ctx
->Unpack
,
2523 ctx
->NewState
|= _NEW_TEXTURE
;
2528 _mesa_TexSubImage2D( GLenum target
, GLint level
,
2529 GLint xoffset
, GLint yoffset
,
2530 GLsizei width
, GLsizei height
,
2531 GLenum format
, GLenum type
,
2532 const GLvoid
*pixels
)
2534 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2535 struct gl_texture_unit
*texUnit
;
2536 struct gl_texture_object
*texObj
;
2537 struct gl_texture_image
*texImage
;
2538 GET_CURRENT_CONTEXT(ctx
);
2539 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2541 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2542 _mesa_update_state(ctx
);
2544 /* XXX should test internal format */
2545 if (is_color_format(format
)) {
2546 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2550 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2551 postConvWidth
, postConvHeight
, 1, format
, type
)) {
2552 return; /* error was detected */
2555 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2556 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2557 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2560 if (width
== 0 || height
== 0)
2561 return; /* no-op, not an error */
2563 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2564 xoffset
+= texImage
->Border
;
2565 yoffset
+= texImage
->Border
;
2567 ASSERT(ctx
->Driver
.TexSubImage2D
);
2568 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
, xoffset
, yoffset
,
2569 width
, height
, format
, type
, pixels
,
2570 &ctx
->Unpack
, texObj
, texImage
);
2571 ctx
->NewState
|= _NEW_TEXTURE
;
2577 _mesa_TexSubImage3D( GLenum target
, GLint level
,
2578 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2579 GLsizei width
, GLsizei height
, GLsizei depth
,
2580 GLenum format
, GLenum type
,
2581 const GLvoid
*pixels
)
2583 struct gl_texture_unit
*texUnit
;
2584 struct gl_texture_object
*texObj
;
2585 struct gl_texture_image
*texImage
;
2586 GET_CURRENT_CONTEXT(ctx
);
2587 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2589 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2590 _mesa_update_state(ctx
);
2592 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2593 width
, height
, depth
, format
, type
)) {
2594 return; /* error was detected */
2597 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2598 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2599 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2602 if (width
== 0 || height
== 0 || height
== 0)
2603 return; /* no-op, not an error */
2605 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2606 xoffset
+= texImage
->Border
;
2607 yoffset
+= texImage
->Border
;
2608 zoffset
+= texImage
->Border
;
2610 ASSERT(ctx
->Driver
.TexSubImage3D
);
2611 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
2612 xoffset
, yoffset
, zoffset
,
2613 width
, height
, depth
,
2614 format
, type
, pixels
,
2615 &ctx
->Unpack
, texObj
, texImage
);
2616 ctx
->NewState
|= _NEW_TEXTURE
;
2622 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
2623 GLenum internalFormat
,
2625 GLsizei width
, GLint border
)
2627 struct gl_texture_unit
*texUnit
;
2628 struct gl_texture_object
*texObj
;
2629 struct gl_texture_image
*texImage
;
2630 GLsizei postConvWidth
= width
;
2631 const GLuint face
= texture_face(target
);
2632 GET_CURRENT_CONTEXT(ctx
);
2633 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2635 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2636 _mesa_update_state(ctx
);
2638 if (is_color_format(internalFormat
)) {
2639 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2642 if (copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
2643 postConvWidth
, 1, border
))
2646 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2647 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2648 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2650 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
2653 else if (texImage
->Data
) {
2654 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2656 ASSERT(texImage
->Data
== NULL
);
2658 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2659 _mesa_init_teximage_fields(ctx
, target
, texImage
, postConvWidth
, 1, 1,
2660 border
, internalFormat
);
2663 ASSERT(ctx
->Driver
.CopyTexImage1D
);
2664 (*ctx
->Driver
.CopyTexImage1D
)(ctx
, target
, level
, internalFormat
,
2665 x
, y
, width
, border
);
2667 ASSERT(texImage
->TexFormat
);
2669 update_fbo_texture(ctx
, texObj
, face
, level
);
2672 texObj
->Complete
= GL_FALSE
;
2673 ctx
->NewState
|= _NEW_TEXTURE
;
2679 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
2680 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2683 struct gl_texture_unit
*texUnit
;
2684 struct gl_texture_object
*texObj
;
2685 struct gl_texture_image
*texImage
;
2686 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2687 const GLuint face
= texture_face(target
);
2688 GET_CURRENT_CONTEXT(ctx
);
2689 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2691 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2692 _mesa_update_state(ctx
);
2694 if (is_color_format(internalFormat
)) {
2695 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2699 if (copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
2700 postConvWidth
, postConvHeight
, border
))
2703 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2704 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2705 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2707 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
2710 else if (texImage
->Data
) {
2711 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2713 ASSERT(texImage
->Data
== NULL
);
2715 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2716 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2717 postConvWidth
, postConvHeight
, 1,
2718 border
, internalFormat
);
2720 ASSERT(ctx
->Driver
.CopyTexImage2D
);
2721 (*ctx
->Driver
.CopyTexImage2D
)(ctx
, target
, level
, internalFormat
,
2722 x
, y
, width
, height
, border
);
2724 ASSERT(texImage
->TexFormat
);
2726 update_fbo_texture(ctx
, texObj
, face
, level
);
2729 texObj
->Complete
= GL_FALSE
;
2730 ctx
->NewState
|= _NEW_TEXTURE
;
2736 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
2737 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
2739 struct gl_texture_unit
*texUnit
;
2740 struct gl_texture_image
*texImage
;
2741 GLsizei postConvWidth
= width
;
2742 GET_CURRENT_CONTEXT(ctx
);
2743 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2745 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2746 _mesa_update_state(ctx
);
2748 /* XXX should test internal format */
2749 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2751 if (copytexsubimage_error_check(ctx
, 1, target
, level
,
2752 xoffset
, 0, 0, postConvWidth
, 1))
2755 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2756 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2759 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2760 xoffset
+= texImage
->Border
;
2762 ASSERT(ctx
->Driver
.CopyTexSubImage1D
);
2763 (*ctx
->Driver
.CopyTexSubImage1D
)(ctx
, target
, level
, xoffset
, x
, y
, width
);
2764 ctx
->NewState
|= _NEW_TEXTURE
;
2770 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
2771 GLint xoffset
, GLint yoffset
,
2772 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2774 struct gl_texture_unit
*texUnit
;
2775 struct gl_texture_image
*texImage
;
2776 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2777 GET_CURRENT_CONTEXT(ctx
);
2778 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2780 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2781 _mesa_update_state(ctx
);
2783 /* XXX should test internal format */
2784 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2786 if (copytexsubimage_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2787 postConvWidth
, postConvHeight
))
2790 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2791 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2794 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2795 xoffset
+= texImage
->Border
;
2796 yoffset
+= texImage
->Border
;
2798 ASSERT(ctx
->Driver
.CopyTexSubImage2D
);
2799 (*ctx
->Driver
.CopyTexSubImage2D
)(ctx
, target
, level
,
2800 xoffset
, yoffset
, x
, y
, width
, height
);
2801 ctx
->NewState
|= _NEW_TEXTURE
;
2807 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
2808 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2809 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2811 struct gl_texture_unit
*texUnit
;
2812 struct gl_texture_image
*texImage
;
2813 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2814 GET_CURRENT_CONTEXT(ctx
);
2815 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2817 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2818 _mesa_update_state(ctx
);
2820 /* XXX should test internal format */
2821 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2823 if (copytexsubimage_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
,
2824 zoffset
, postConvWidth
, postConvHeight
))
2827 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2828 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2831 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2832 xoffset
+= texImage
->Border
;
2833 yoffset
+= texImage
->Border
;
2834 zoffset
+= texImage
->Border
;
2836 ASSERT(ctx
->Driver
.CopyTexSubImage3D
);
2837 (*ctx
->Driver
.CopyTexSubImage3D
)(ctx
, target
, level
,
2838 xoffset
, yoffset
, zoffset
,
2839 x
, y
, width
, height
);
2840 ctx
->NewState
|= _NEW_TEXTURE
;
2846 /**********************************************************************/
2847 /****** Compressed Textures ******/
2848 /**********************************************************************/
2852 * Error checking for glCompressedTexImage[123]D().
2853 * \return error code or GL_NO_ERROR.
2856 compressed_texture_error_check(GLcontext
*ctx
, GLint dimensions
,
2857 GLenum target
, GLint level
,
2858 GLenum internalFormat
, GLsizei width
,
2859 GLsizei height
, GLsizei depth
, GLint border
,
2862 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2864 if (dimensions
== 1) {
2865 /* 1D compressed textures not allowed */
2866 return GL_INVALID_ENUM
;
2868 else if (dimensions
== 2) {
2869 if (target
== GL_PROXY_TEXTURE_2D
) {
2870 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2872 else if (target
== GL_TEXTURE_2D
) {
2873 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2875 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2876 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2877 return GL_INVALID_ENUM
; /*target*/
2878 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2880 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2881 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2882 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2883 return GL_INVALID_ENUM
; /*target*/
2884 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2887 return GL_INVALID_ENUM
; /*target*/
2890 else if (dimensions
== 3) {
2891 /* 3D compressed textures not allowed */
2892 return GL_INVALID_ENUM
;
2895 maxTextureSize
= 1 << (maxLevels
- 1);
2897 /* This will detect any invalid internalFormat value */
2898 if (!is_compressed_format(ctx
, internalFormat
))
2899 return GL_INVALID_ENUM
;
2901 /* This should really never fail */
2902 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0)
2903 return GL_INVALID_ENUM
;
2906 return GL_INVALID_VALUE
;
2909 * XXX We should probably use the proxy texture error check function here.
2911 if (width
< 1 || width
> maxTextureSize
||
2912 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(width
) != 1))
2913 return GL_INVALID_VALUE
;
2915 if ((height
< 1 || height
> maxTextureSize
||
2916 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(height
) != 1))
2918 return GL_INVALID_VALUE
;
2920 if ((depth
< 1 || depth
> maxTextureSize
||
2921 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(depth
) != 1))
2923 return GL_INVALID_VALUE
;
2925 /* For cube map, width must equal height */
2926 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2927 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
&& width
!= height
)
2928 return GL_INVALID_VALUE
;
2930 if (level
< 0 || level
>= maxLevels
)
2931 return GL_INVALID_VALUE
;
2933 expectedSize
= _mesa_compressed_texture_size_glenum(ctx
, width
, height
,
2934 depth
, internalFormat
);
2935 if (expectedSize
!= imageSize
)
2936 return GL_INVALID_VALUE
;
2943 * Error checking for glCompressedTexSubImage[123]D().
2944 * \warning There are some bad assumptions here about the size of compressed
2945 * texture tiles (multiple of 4) used to test the validity of the
2946 * offset and size parameters.
2947 * \return error code or GL_NO_ERROR.
2950 compressed_subtexture_error_check(GLcontext
*ctx
, GLint dimensions
,
2951 GLenum target
, GLint level
,
2952 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2953 GLsizei width
, GLsizei height
, GLsizei depth
,
2954 GLenum format
, GLsizei imageSize
)
2956 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2959 if (dimensions
== 1) {
2960 /* 1D compressed textures not allowed */
2961 return GL_INVALID_ENUM
;
2963 else if (dimensions
== 2) {
2964 if (target
== GL_PROXY_TEXTURE_2D
) {
2965 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2967 else if (target
== GL_TEXTURE_2D
) {
2968 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2970 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2971 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2972 return GL_INVALID_ENUM
; /*target*/
2973 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2975 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2976 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2977 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2978 return GL_INVALID_ENUM
; /*target*/
2979 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2982 return GL_INVALID_ENUM
; /*target*/
2985 else if (dimensions
== 3) {
2986 /* 3D compressed textures not allowed */
2987 return GL_INVALID_ENUM
;
2990 maxTextureSize
= 1 << (maxLevels
- 1);
2992 /* this will catch any invalid compressed format token */
2993 if (!is_compressed_format(ctx
, format
))
2994 return GL_INVALID_ENUM
;
2996 if (width
< 1 || width
> maxTextureSize
)
2997 return GL_INVALID_VALUE
;
2999 if ((height
< 1 || height
> maxTextureSize
)
3001 return GL_INVALID_VALUE
;
3003 if (level
< 0 || level
>= maxLevels
)
3004 return GL_INVALID_VALUE
;
3006 /* XXX these tests are specific to the compressed format.
3007 * this code should be generalized in some way.
3009 if ((xoffset
& 3) != 0 || (yoffset
& 3) != 0)
3010 return GL_INVALID_VALUE
;
3012 if ((width
& 3) != 0 && width
!= 2 && width
!= 1)
3013 return GL_INVALID_VALUE
;
3015 if ((height
& 3) != 0 && height
!= 2 && height
!= 1)
3016 return GL_INVALID_VALUE
;
3018 expectedSize
= _mesa_compressed_texture_size_glenum(ctx
, width
, height
,
3020 if (expectedSize
!= imageSize
)
3021 return GL_INVALID_VALUE
;
3029 _mesa_CompressedTexImage1DARB(GLenum target
, GLint level
,
3030 GLenum internalFormat
, GLsizei width
,
3031 GLint border
, GLsizei imageSize
,
3034 GET_CURRENT_CONTEXT(ctx
);
3035 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3037 if (target
== GL_TEXTURE_1D
) {
3038 /* non-proxy target */
3039 struct gl_texture_unit
*texUnit
;
3040 struct gl_texture_object
*texObj
;
3041 struct gl_texture_image
*texImage
;
3042 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
3043 internalFormat
, width
, 1, 1, border
, imageSize
);
3045 _mesa_error(ctx
, error
, "glCompressedTexImage1D");
3049 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3050 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3051 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
3053 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage1D");
3056 else if (texImage
->Data
) {
3057 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3059 ASSERT(texImage
->Data
== NULL
);
3061 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
3062 border
, internalFormat
);
3064 ASSERT(ctx
->Driver
.CompressedTexImage1D
);
3065 (*ctx
->Driver
.CompressedTexImage1D
)(ctx
, target
, level
,
3066 internalFormat
, width
, border
,
3071 texObj
->Complete
= GL_FALSE
;
3072 ctx
->NewState
|= _NEW_TEXTURE
;
3074 else if (target
== GL_PROXY_TEXTURE_1D
) {
3075 /* Proxy texture: check for errors and update proxy state */
3076 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
3077 internalFormat
, width
, 1, 1, border
, imageSize
);
3079 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3080 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3081 internalFormat
, GL_NONE
, GL_NONE
,
3082 width
, 1, 1, border
);
3085 /* if error, clear all proxy texture image parameters */
3086 struct gl_texture_image
*texImage
;
3087 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3089 clear_teximage_fields(texImage
);
3092 /* store the teximage parameters */
3093 struct gl_texture_unit
*texUnit
;
3094 struct gl_texture_image
*texImage
;
3095 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3096 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3097 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
3098 border
, internalFormat
);
3102 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage1D(target)");
3109 _mesa_CompressedTexImage2DARB(GLenum target
, GLint level
,
3110 GLenum internalFormat
, GLsizei width
,
3111 GLsizei height
, GLint border
, GLsizei imageSize
,
3114 GET_CURRENT_CONTEXT(ctx
);
3115 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3117 if (target
== GL_TEXTURE_2D
||
3118 (ctx
->Extensions
.ARB_texture_cube_map
&&
3119 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3120 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
3121 /* non-proxy target */
3122 struct gl_texture_unit
*texUnit
;
3123 struct gl_texture_object
*texObj
;
3124 struct gl_texture_image
*texImage
;
3125 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
3126 internalFormat
, width
, height
, 1, border
, imageSize
);
3128 _mesa_error(ctx
, error
, "glCompressedTexImage2D");
3132 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3133 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3134 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
3136 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
3139 else if (texImage
->Data
) {
3140 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3142 ASSERT(texImage
->Data
== NULL
);
3144 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
3145 border
, internalFormat
);
3147 ASSERT(ctx
->Driver
.CompressedTexImage2D
);
3148 (*ctx
->Driver
.CompressedTexImage2D
)(ctx
, target
, level
,
3149 internalFormat
, width
, height
,
3150 border
, imageSize
, data
,
3154 texObj
->Complete
= GL_FALSE
;
3155 ctx
->NewState
|= _NEW_TEXTURE
;
3157 else if (target
== GL_PROXY_TEXTURE_2D
||
3158 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
3159 ctx
->Extensions
.ARB_texture_cube_map
)) {
3160 /* Proxy texture: check for errors and update proxy state */
3161 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
3162 internalFormat
, width
, height
, 1, border
, imageSize
);
3164 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3165 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3166 internalFormat
, GL_NONE
, GL_NONE
,
3167 width
, height
, 1, border
);
3170 /* if error, clear all proxy texture image parameters */
3171 struct gl_texture_image
*texImage
;
3172 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3174 clear_teximage_fields(texImage
);
3177 /* store the teximage parameters */
3178 struct gl_texture_unit
*texUnit
;
3179 struct gl_texture_image
*texImage
;
3180 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3181 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3182 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
3183 border
, internalFormat
);
3187 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(target)");
3194 _mesa_CompressedTexImage3DARB(GLenum target
, GLint level
,
3195 GLenum internalFormat
, GLsizei width
,
3196 GLsizei height
, GLsizei depth
, GLint border
,
3197 GLsizei imageSize
, const GLvoid
*data
)
3199 GET_CURRENT_CONTEXT(ctx
);
3200 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3202 if (target
== GL_TEXTURE_3D
) {
3203 /* non-proxy target */
3204 struct gl_texture_unit
*texUnit
;
3205 struct gl_texture_object
*texObj
;
3206 struct gl_texture_image
*texImage
;
3207 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3208 internalFormat
, width
, height
, depth
, border
, imageSize
);
3210 _mesa_error(ctx
, error
, "glCompressedTexImage3D");
3214 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3215 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3216 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
3218 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage3D");
3221 else if (texImage
->Data
) {
3222 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3224 ASSERT(texImage
->Data
== NULL
);
3226 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, depth
,
3227 border
, internalFormat
);
3229 ASSERT(ctx
->Driver
.CompressedTexImage3D
);
3230 (*ctx
->Driver
.CompressedTexImage3D
)(ctx
, target
, level
,
3232 width
, height
, depth
,
3233 border
, imageSize
, data
,
3237 texObj
->Complete
= GL_FALSE
;
3238 ctx
->NewState
|= _NEW_TEXTURE
;
3240 else if (target
== GL_PROXY_TEXTURE_3D
) {
3241 /* Proxy texture: check for errors and update proxy state */
3242 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3243 internalFormat
, width
, height
, depth
, border
, imageSize
);
3245 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3246 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3247 internalFormat
, GL_NONE
, GL_NONE
,
3248 width
, height
, depth
, border
);
3251 /* if error, clear all proxy texture image parameters */
3252 struct gl_texture_image
*texImage
;
3253 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3255 clear_teximage_fields(texImage
);
3258 /* store the teximage parameters */
3259 struct gl_texture_unit
*texUnit
;
3260 struct gl_texture_image
*texImage
;
3261 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3262 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3263 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
,
3264 depth
, border
, internalFormat
);
3268 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage3D(target)");
3275 _mesa_CompressedTexSubImage1DARB(GLenum target
, GLint level
, GLint xoffset
,
3276 GLsizei width
, GLenum format
,
3277 GLsizei imageSize
, const GLvoid
*data
)
3279 struct gl_texture_unit
*texUnit
;
3280 struct gl_texture_object
*texObj
;
3281 struct gl_texture_image
*texImage
;
3283 GET_CURRENT_CONTEXT(ctx
);
3284 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3286 error
= compressed_subtexture_error_check(ctx
, 1, target
, level
,
3287 xoffset
, 0, 0, /* pos */
3288 width
, 1, 1, /* size */
3291 _mesa_error(ctx
, error
, "glCompressedTexSubImage1D");
3295 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3296 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3297 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3300 if ((GLint
) format
!= texImage
->InternalFormat
) {
3301 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3302 "glCompressedTexSubImage1D(format)");
3306 if ((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) {
3307 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage1D(width)");
3312 return; /* no-op, not an error */
3314 if (ctx
->Driver
.CompressedTexSubImage1D
) {
3315 (*ctx
->Driver
.CompressedTexSubImage1D
)(ctx
, target
, level
,
3317 format
, imageSize
, data
,
3320 ctx
->NewState
|= _NEW_TEXTURE
;
3325 _mesa_CompressedTexSubImage2DARB(GLenum target
, GLint level
, GLint xoffset
,
3326 GLint yoffset
, GLsizei width
, GLsizei height
,
3327 GLenum format
, GLsizei imageSize
,
3330 struct gl_texture_unit
*texUnit
;
3331 struct gl_texture_object
*texObj
;
3332 struct gl_texture_image
*texImage
;
3334 GET_CURRENT_CONTEXT(ctx
);
3335 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3337 error
= compressed_subtexture_error_check(ctx
, 2, target
, level
,
3338 xoffset
, yoffset
, 0, /* pos */
3339 width
, height
, 1, /* size */
3342 /* XXX proxy target? */
3343 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3347 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3348 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3349 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3352 if ((GLint
) format
!= texImage
->InternalFormat
) {
3353 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3354 "glCompressedTexSubImage2D(format)");
3358 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3359 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
)) {
3360 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage2D(size)");
3364 if (width
== 0 || height
== 0)
3365 return; /* no-op, not an error */
3367 if (ctx
->Driver
.CompressedTexSubImage2D
) {
3368 (*ctx
->Driver
.CompressedTexSubImage2D
)(ctx
, target
, level
,
3369 xoffset
, yoffset
, width
, height
,
3370 format
, imageSize
, data
,
3373 ctx
->NewState
|= _NEW_TEXTURE
;
3378 _mesa_CompressedTexSubImage3DARB(GLenum target
, GLint level
, GLint xoffset
,
3379 GLint yoffset
, GLint zoffset
, GLsizei width
,
3380 GLsizei height
, GLsizei depth
, GLenum format
,
3381 GLsizei imageSize
, const GLvoid
*data
)
3383 struct gl_texture_unit
*texUnit
;
3384 struct gl_texture_object
*texObj
;
3385 struct gl_texture_image
*texImage
;
3387 GET_CURRENT_CONTEXT(ctx
);
3388 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3390 error
= compressed_subtexture_error_check(ctx
, 3, target
, level
,
3391 xoffset
, yoffset
, zoffset
,/*pos*/
3392 width
, height
, depth
, /*size*/
3395 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3399 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3400 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3401 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3404 if ((GLint
) format
!= texImage
->InternalFormat
) {
3405 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3406 "glCompressedTexSubImage3D(format)");
3410 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3411 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
) ||
3412 ((depth
== 1 || depth
== 2) && (GLuint
) depth
!= texImage
->Depth
)) {
3413 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage3D(size)");
3417 if (width
== 0 || height
== 0 || depth
== 0)
3418 return; /* no-op, not an error */
3420 if (ctx
->Driver
.CompressedTexSubImage3D
) {
3421 (*ctx
->Driver
.CompressedTexSubImage3D
)(ctx
, target
, level
,
3422 xoffset
, yoffset
, zoffset
,
3423 width
, height
, depth
,
3424 format
, imageSize
, data
,
3427 ctx
->NewState
|= _NEW_TEXTURE
;
3432 _mesa_GetCompressedTexImageARB(GLenum target
, GLint level
, GLvoid
*img
)
3434 const struct gl_texture_unit
*texUnit
;
3435 const struct gl_texture_object
*texObj
;
3436 struct gl_texture_image
*texImage
;
3438 GET_CURRENT_CONTEXT(ctx
);
3439 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3441 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3442 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3444 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB");
3448 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
3449 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
3451 if (level
< 0 || level
>= maxLevels
) {
3452 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3456 if (_mesa_is_proxy_texture(target
)) {
3457 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
3461 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3463 /* probably invalid mipmap level */
3464 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3468 if (!texImage
->IsCompressed
) {
3469 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetCompressedTexImageARB");
3473 /* this typically calls _mesa_get_compressed_teximage() */
3474 ctx
->Driver
.GetCompressedTexImage(ctx
, target
, level
, img
, texObj
,texImage
);