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
)
1099 ASSERT(height
>= 0);
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)");
2107 if (!ctx
->Extensions
.SGIX_depth_texture
&&
2108 !ctx
->Extensions
.ARB_depth_texture
&& is_depth_format(format
)) {
2109 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2113 if (!ctx
->Extensions
.MESA_ycbcr_texture
&& is_ycbcr_format(format
)) {
2114 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2118 if (!ctx
->Extensions
.EXT_packed_depth_stencil
2119 && is_depthstencil_format(format
)) {
2120 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2127 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2129 /* invalid mipmap level, not an error */
2133 /* Make sure the requested image format is compatible with the
2134 * texture's format. Note that a color index texture can be converted
2135 * to RGBA so that combo is allowed.
2137 if (is_color_format(format
)
2138 && !is_color_format(texImage
->TexFormat
->BaseFormat
)
2139 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
2140 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2143 else if (is_index_format(format
)
2144 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
2145 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2148 else if (is_depth_format(format
)
2149 && !is_depth_format(texImage
->TexFormat
->BaseFormat
)
2150 && !is_depthstencil_format(texImage
->TexFormat
->BaseFormat
)) {
2151 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2154 else if (is_ycbcr_format(format
)
2155 && !is_ycbcr_format(texImage
->TexFormat
->BaseFormat
)) {
2156 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2159 else if (is_depthstencil_format(format
)
2160 && !is_depthstencil_format(texImage
->TexFormat
->BaseFormat
)) {
2161 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2165 /* typically, this will call _mesa_get_teximage() */
2166 ctx
->Driver
.GetTexImage(ctx
, target
, level
, format
, type
, pixels
,
2173 * Check if the given texture image is bound to any framebuffer objects
2174 * and update/invalidate them.
2175 * XXX We're only checking the currently bound framebuffer object for now.
2176 * In the future, perhaps struct gl_texture_image should have a pointer (or
2177 * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to.
2180 update_fbo_texture(GLcontext
*ctx
, struct gl_texture_object
*texObj
,
2181 GLuint face
, GLuint level
)
2183 if (ctx
->DrawBuffer
->Name
) {
2185 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
2186 struct gl_renderbuffer_attachment
*att
=
2187 ctx
->DrawBuffer
->Attachment
+ i
;
2188 if (att
->Type
== GL_TEXTURE
&&
2189 att
->Texture
== texObj
&&
2190 att
->TextureLevel
== level
&&
2191 att
->CubeMapFace
== face
) {
2192 ASSERT(att
->Texture
->Image
[att
->CubeMapFace
][att
->TextureLevel
]);
2193 /* Tell driver about the new renderbuffer texture */
2194 ctx
->Driver
.RenderTexture(ctx
, ctx
->DrawBuffer
, att
);
2203 * Called from the API. Note that width includes the border.
2206 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalFormat
,
2207 GLsizei width
, GLint border
, GLenum format
,
2208 GLenum type
, const GLvoid
*pixels
)
2210 GLsizei postConvWidth
= width
;
2211 GET_CURRENT_CONTEXT(ctx
);
2212 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2214 if (is_color_format(internalFormat
)) {
2215 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2218 if (target
== GL_TEXTURE_1D
) {
2219 /* non-proxy target */
2220 struct gl_texture_unit
*texUnit
;
2221 struct gl_texture_object
*texObj
;
2222 struct gl_texture_image
*texImage
;
2223 const GLuint face
= texture_face(target
);
2225 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2226 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2227 return; /* error was recorded */
2230 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2231 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2232 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2235 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2238 else if (texImage
->Data
) {
2239 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2241 ASSERT(texImage
->Data
== NULL
);
2242 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2243 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2244 postConvWidth
, 1, 1,
2245 border
, internalFormat
);
2247 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2248 _mesa_update_state(ctx
);
2250 ASSERT(ctx
->Driver
.TexImage1D
);
2252 /* Give the texture to the driver! <pixels> may be null! */
2253 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
2254 width
, border
, format
, type
, pixels
,
2255 &ctx
->Unpack
, texObj
, texImage
);
2257 ASSERT(texImage
->TexFormat
);
2259 update_fbo_texture(ctx
, texObj
, face
, level
);
2262 texObj
->Complete
= GL_FALSE
;
2263 ctx
->NewState
|= _NEW_TEXTURE
;
2265 else if (target
== GL_PROXY_TEXTURE_1D
) {
2266 /* Proxy texture: check for errors and update proxy state */
2267 struct gl_texture_image
*texImage
;
2268 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2269 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2270 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2271 /* when error, clear all proxy texture image parameters */
2273 clear_teximage_fields(texImage
);
2276 /* no error, set the tex image parameters */
2278 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2279 postConvWidth
, 1, 1,
2280 border
, internalFormat
);
2281 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2282 internalFormat
, format
, type
);
2286 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
2293 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalFormat
,
2294 GLsizei width
, GLsizei height
, GLint border
,
2295 GLenum format
, GLenum type
,
2296 const GLvoid
*pixels
)
2298 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2299 GET_CURRENT_CONTEXT(ctx
);
2300 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2302 if (is_color_format(internalFormat
)) {
2303 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2307 if (target
== GL_TEXTURE_2D
||
2308 (ctx
->Extensions
.ARB_texture_cube_map
&&
2309 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2310 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) ||
2311 (ctx
->Extensions
.NV_texture_rectangle
&&
2312 target
== GL_TEXTURE_RECTANGLE_NV
)) {
2313 /* non-proxy target */
2314 struct gl_texture_unit
*texUnit
;
2315 struct gl_texture_object
*texObj
;
2316 struct gl_texture_image
*texImage
;
2317 const GLuint face
= texture_face(target
);
2319 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2320 format
, type
, 2, postConvWidth
, postConvHeight
,
2322 return; /* error was recorded */
2325 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2326 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2327 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2329 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2332 else if (texImage
->Data
) {
2333 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2335 ASSERT(texImage
->Data
== NULL
);
2336 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2337 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2338 postConvWidth
, postConvHeight
, 1,
2339 border
, internalFormat
);
2341 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2342 _mesa_update_state(ctx
);
2344 ASSERT(ctx
->Driver
.TexImage2D
);
2346 /* Give the texture to the driver! <pixels> may be null! */
2347 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
2348 width
, height
, border
, format
, type
, pixels
,
2349 &ctx
->Unpack
, texObj
, texImage
);
2351 ASSERT(texImage
->TexFormat
);
2353 update_fbo_texture(ctx
, texObj
, face
, level
);
2356 texObj
->Complete
= GL_FALSE
;
2357 ctx
->NewState
|= _NEW_TEXTURE
;
2359 else if (target
== GL_PROXY_TEXTURE_2D
||
2360 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2361 ctx
->Extensions
.ARB_texture_cube_map
) ||
2362 (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
&&
2363 ctx
->Extensions
.NV_texture_rectangle
)) {
2364 /* Proxy texture: check for errors and update proxy state */
2365 struct gl_texture_image
*texImage
;
2366 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2367 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2368 format
, type
, 2, postConvWidth
, postConvHeight
,
2370 /* when error, clear all proxy texture image parameters */
2372 clear_teximage_fields(ctx
->Texture
.Proxy2D
->Image
[0][level
]);
2375 /* no error, set the tex image parameters */
2376 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2377 postConvWidth
, postConvHeight
, 1,
2378 border
, internalFormat
);
2379 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2380 internalFormat
, format
, type
);
2384 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
2391 * Called by the API or display list executor.
2392 * Note that width and height include the border.
2395 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalFormat
,
2396 GLsizei width
, GLsizei height
, GLsizei depth
,
2397 GLint border
, GLenum format
, GLenum type
,
2398 const GLvoid
*pixels
)
2400 GET_CURRENT_CONTEXT(ctx
);
2401 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2403 if (target
== GL_TEXTURE_3D
) {
2404 /* non-proxy target */
2405 struct gl_texture_unit
*texUnit
;
2406 struct gl_texture_object
*texObj
;
2407 struct gl_texture_image
*texImage
;
2408 const GLuint face
= texture_face(target
);
2410 if (texture_error_check(ctx
, target
, level
, (GLint
) internalFormat
,
2411 format
, type
, 3, width
, height
, depth
, border
)) {
2412 return; /* error was recorded */
2415 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2416 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2417 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2419 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2422 else if (texImage
->Data
) {
2423 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2425 ASSERT(texImage
->Data
== NULL
);
2426 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2427 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2428 width
, height
, depth
,
2429 border
, internalFormat
);
2431 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2432 _mesa_update_state(ctx
);
2434 ASSERT(ctx
->Driver
.TexImage3D
);
2436 /* Give the texture to the driver! <pixels> may be null! */
2437 (*ctx
->Driver
.TexImage3D
)(ctx
, target
, level
, internalFormat
,
2438 width
, height
, depth
, border
, format
, type
,
2439 pixels
, &ctx
->Unpack
, texObj
, texImage
);
2441 ASSERT(texImage
->TexFormat
);
2443 update_fbo_texture(ctx
, texObj
, face
, level
);
2446 texObj
->Complete
= GL_FALSE
;
2447 ctx
->NewState
|= _NEW_TEXTURE
;
2449 else if (target
== GL_PROXY_TEXTURE_3D
) {
2450 /* Proxy texture: check for errors and update proxy state */
2451 struct gl_texture_image
*texImage
;
2452 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2453 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2454 format
, type
, 3, width
, height
, depth
, border
)) {
2455 /* when error, clear all proxy texture image parameters */
2457 clear_teximage_fields(texImage
);
2460 /* no error, set the tex image parameters */
2461 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2462 border
, internalFormat
);
2463 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2464 internalFormat
, format
, type
);
2468 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
2475 _mesa_TexImage3DEXT( GLenum target
, GLint level
, GLenum internalFormat
,
2476 GLsizei width
, GLsizei height
, GLsizei depth
,
2477 GLint border
, GLenum format
, GLenum type
,
2478 const GLvoid
*pixels
)
2480 _mesa_TexImage3D(target
, level
, (GLint
) internalFormat
, width
, height
,
2481 depth
, border
, format
, type
, pixels
);
2487 _mesa_TexSubImage1D( GLenum target
, GLint level
,
2488 GLint xoffset
, GLsizei width
,
2489 GLenum format
, GLenum type
,
2490 const GLvoid
*pixels
)
2492 GLsizei postConvWidth
= width
;
2493 struct gl_texture_unit
*texUnit
;
2494 struct gl_texture_object
*texObj
;
2495 struct gl_texture_image
*texImage
;
2496 GET_CURRENT_CONTEXT(ctx
);
2497 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2499 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2500 _mesa_update_state(ctx
);
2502 /* XXX should test internal format */
2503 if (is_color_format(format
)) {
2504 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2507 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
2508 postConvWidth
, 1, 1, format
, type
)) {
2509 return; /* error was detected */
2512 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2513 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2514 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2518 return; /* no-op, not an error */
2520 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2521 xoffset
+= texImage
->Border
;
2523 ASSERT(ctx
->Driver
.TexSubImage1D
);
2524 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
2525 format
, type
, pixels
, &ctx
->Unpack
,
2527 ctx
->NewState
|= _NEW_TEXTURE
;
2532 _mesa_TexSubImage2D( GLenum target
, GLint level
,
2533 GLint xoffset
, GLint yoffset
,
2534 GLsizei width
, GLsizei height
,
2535 GLenum format
, GLenum type
,
2536 const GLvoid
*pixels
)
2538 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2539 struct gl_texture_unit
*texUnit
;
2540 struct gl_texture_object
*texObj
;
2541 struct gl_texture_image
*texImage
;
2542 GET_CURRENT_CONTEXT(ctx
);
2543 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2545 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2546 _mesa_update_state(ctx
);
2548 /* XXX should test internal format */
2549 if (is_color_format(format
)) {
2550 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2554 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2555 postConvWidth
, postConvHeight
, 1, format
, type
)) {
2556 return; /* error was detected */
2559 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2560 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2561 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2564 if (width
== 0 || height
== 0)
2565 return; /* no-op, not an error */
2567 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2568 xoffset
+= texImage
->Border
;
2569 yoffset
+= texImage
->Border
;
2571 ASSERT(ctx
->Driver
.TexSubImage2D
);
2572 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
, xoffset
, yoffset
,
2573 width
, height
, format
, type
, pixels
,
2574 &ctx
->Unpack
, texObj
, texImage
);
2575 ctx
->NewState
|= _NEW_TEXTURE
;
2581 _mesa_TexSubImage3D( GLenum target
, GLint level
,
2582 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2583 GLsizei width
, GLsizei height
, GLsizei depth
,
2584 GLenum format
, GLenum type
,
2585 const GLvoid
*pixels
)
2587 struct gl_texture_unit
*texUnit
;
2588 struct gl_texture_object
*texObj
;
2589 struct gl_texture_image
*texImage
;
2590 GET_CURRENT_CONTEXT(ctx
);
2591 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2593 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2594 _mesa_update_state(ctx
);
2596 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2597 width
, height
, depth
, format
, type
)) {
2598 return; /* error was detected */
2601 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2602 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2603 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2606 if (width
== 0 || height
== 0 || height
== 0)
2607 return; /* no-op, not an error */
2609 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2610 xoffset
+= texImage
->Border
;
2611 yoffset
+= texImage
->Border
;
2612 zoffset
+= texImage
->Border
;
2614 ASSERT(ctx
->Driver
.TexSubImage3D
);
2615 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
2616 xoffset
, yoffset
, zoffset
,
2617 width
, height
, depth
,
2618 format
, type
, pixels
,
2619 &ctx
->Unpack
, texObj
, texImage
);
2620 ctx
->NewState
|= _NEW_TEXTURE
;
2626 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
2627 GLenum internalFormat
,
2629 GLsizei width
, GLint border
)
2631 struct gl_texture_unit
*texUnit
;
2632 struct gl_texture_object
*texObj
;
2633 struct gl_texture_image
*texImage
;
2634 GLsizei postConvWidth
= width
;
2635 const GLuint face
= texture_face(target
);
2636 GET_CURRENT_CONTEXT(ctx
);
2637 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2639 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2640 _mesa_update_state(ctx
);
2642 if (is_color_format(internalFormat
)) {
2643 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2646 if (copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
2647 postConvWidth
, 1, border
))
2650 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2651 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2652 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2654 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
2657 else if (texImage
->Data
) {
2658 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2660 ASSERT(texImage
->Data
== NULL
);
2662 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2663 _mesa_init_teximage_fields(ctx
, target
, texImage
, postConvWidth
, 1, 1,
2664 border
, internalFormat
);
2667 ASSERT(ctx
->Driver
.CopyTexImage1D
);
2668 (*ctx
->Driver
.CopyTexImage1D
)(ctx
, target
, level
, internalFormat
,
2669 x
, y
, width
, border
);
2671 ASSERT(texImage
->TexFormat
);
2673 update_fbo_texture(ctx
, texObj
, face
, level
);
2676 texObj
->Complete
= GL_FALSE
;
2677 ctx
->NewState
|= _NEW_TEXTURE
;
2683 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
2684 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2687 struct gl_texture_unit
*texUnit
;
2688 struct gl_texture_object
*texObj
;
2689 struct gl_texture_image
*texImage
;
2690 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2691 const GLuint face
= texture_face(target
);
2692 GET_CURRENT_CONTEXT(ctx
);
2693 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2695 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2696 _mesa_update_state(ctx
);
2698 if (is_color_format(internalFormat
)) {
2699 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2703 if (copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
2704 postConvWidth
, postConvHeight
, border
))
2707 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2708 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2709 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2711 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
2714 else if (texImage
->Data
) {
2715 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2717 ASSERT(texImage
->Data
== NULL
);
2719 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2720 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2721 postConvWidth
, postConvHeight
, 1,
2722 border
, internalFormat
);
2724 ASSERT(ctx
->Driver
.CopyTexImage2D
);
2725 (*ctx
->Driver
.CopyTexImage2D
)(ctx
, target
, level
, internalFormat
,
2726 x
, y
, width
, height
, border
);
2728 ASSERT(texImage
->TexFormat
);
2730 update_fbo_texture(ctx
, texObj
, face
, level
);
2733 texObj
->Complete
= GL_FALSE
;
2734 ctx
->NewState
|= _NEW_TEXTURE
;
2740 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
2741 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
2743 struct gl_texture_unit
*texUnit
;
2744 struct gl_texture_image
*texImage
;
2745 GLsizei postConvWidth
= width
;
2746 GET_CURRENT_CONTEXT(ctx
);
2747 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2749 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2750 _mesa_update_state(ctx
);
2752 /* XXX should test internal format */
2753 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2755 if (copytexsubimage_error_check(ctx
, 1, target
, level
,
2756 xoffset
, 0, 0, postConvWidth
, 1))
2759 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2760 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2763 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2764 xoffset
+= texImage
->Border
;
2766 ASSERT(ctx
->Driver
.CopyTexSubImage1D
);
2767 (*ctx
->Driver
.CopyTexSubImage1D
)(ctx
, target
, level
, xoffset
, x
, y
, width
);
2768 ctx
->NewState
|= _NEW_TEXTURE
;
2774 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
2775 GLint xoffset
, GLint yoffset
,
2776 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2778 struct gl_texture_unit
*texUnit
;
2779 struct gl_texture_image
*texImage
;
2780 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2781 GET_CURRENT_CONTEXT(ctx
);
2782 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2784 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2785 _mesa_update_state(ctx
);
2787 /* XXX should test internal format */
2788 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2790 if (copytexsubimage_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2791 postConvWidth
, postConvHeight
))
2794 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2795 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2798 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2799 xoffset
+= texImage
->Border
;
2800 yoffset
+= texImage
->Border
;
2802 ASSERT(ctx
->Driver
.CopyTexSubImage2D
);
2803 (*ctx
->Driver
.CopyTexSubImage2D
)(ctx
, target
, level
,
2804 xoffset
, yoffset
, x
, y
, width
, height
);
2805 ctx
->NewState
|= _NEW_TEXTURE
;
2811 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
2812 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2813 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2815 struct gl_texture_unit
*texUnit
;
2816 struct gl_texture_image
*texImage
;
2817 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2818 GET_CURRENT_CONTEXT(ctx
);
2819 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2821 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2822 _mesa_update_state(ctx
);
2824 /* XXX should test internal format */
2825 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2827 if (copytexsubimage_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
,
2828 zoffset
, postConvWidth
, postConvHeight
))
2831 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2832 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2835 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2836 xoffset
+= texImage
->Border
;
2837 yoffset
+= texImage
->Border
;
2838 zoffset
+= texImage
->Border
;
2840 ASSERT(ctx
->Driver
.CopyTexSubImage3D
);
2841 (*ctx
->Driver
.CopyTexSubImage3D
)(ctx
, target
, level
,
2842 xoffset
, yoffset
, zoffset
,
2843 x
, y
, width
, height
);
2844 ctx
->NewState
|= _NEW_TEXTURE
;
2850 /**********************************************************************/
2851 /****** Compressed Textures ******/
2852 /**********************************************************************/
2856 * Error checking for glCompressedTexImage[123]D().
2857 * \return error code or GL_NO_ERROR.
2860 compressed_texture_error_check(GLcontext
*ctx
, GLint dimensions
,
2861 GLenum target
, GLint level
,
2862 GLenum internalFormat
, GLsizei width
,
2863 GLsizei height
, GLsizei depth
, GLint border
,
2866 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2868 if (dimensions
== 1) {
2869 /* 1D compressed textures not allowed */
2870 return GL_INVALID_ENUM
;
2872 else if (dimensions
== 2) {
2873 if (target
== GL_PROXY_TEXTURE_2D
) {
2874 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2876 else if (target
== GL_TEXTURE_2D
) {
2877 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2879 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2880 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2881 return GL_INVALID_ENUM
; /*target*/
2882 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2884 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2885 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2886 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2887 return GL_INVALID_ENUM
; /*target*/
2888 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2891 return GL_INVALID_ENUM
; /*target*/
2894 else if (dimensions
== 3) {
2895 /* 3D compressed textures not allowed */
2896 return GL_INVALID_ENUM
;
2899 maxTextureSize
= 1 << (maxLevels
- 1);
2901 /* This will detect any invalid internalFormat value */
2902 if (!is_compressed_format(ctx
, internalFormat
))
2903 return GL_INVALID_ENUM
;
2905 /* This should really never fail */
2906 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0)
2907 return GL_INVALID_ENUM
;
2910 return GL_INVALID_VALUE
;
2913 * XXX We should probably use the proxy texture error check function here.
2915 if (width
< 1 || width
> maxTextureSize
||
2916 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(width
) != 1))
2917 return GL_INVALID_VALUE
;
2919 if ((height
< 1 || height
> maxTextureSize
||
2920 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(height
) != 1))
2922 return GL_INVALID_VALUE
;
2924 if ((depth
< 1 || depth
> maxTextureSize
||
2925 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(depth
) != 1))
2927 return GL_INVALID_VALUE
;
2929 /* For cube map, width must equal height */
2930 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2931 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
&& width
!= height
)
2932 return GL_INVALID_VALUE
;
2934 if (level
< 0 || level
>= maxLevels
)
2935 return GL_INVALID_VALUE
;
2937 expectedSize
= _mesa_compressed_texture_size_glenum(ctx
, width
, height
,
2938 depth
, internalFormat
);
2939 if (expectedSize
!= imageSize
)
2940 return GL_INVALID_VALUE
;
2947 * Error checking for glCompressedTexSubImage[123]D().
2948 * \warning There are some bad assumptions here about the size of compressed
2949 * texture tiles (multiple of 4) used to test the validity of the
2950 * offset and size parameters.
2951 * \return error code or GL_NO_ERROR.
2954 compressed_subtexture_error_check(GLcontext
*ctx
, GLint dimensions
,
2955 GLenum target
, GLint level
,
2956 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2957 GLsizei width
, GLsizei height
, GLsizei depth
,
2958 GLenum format
, GLsizei imageSize
)
2960 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2963 if (dimensions
== 1) {
2964 /* 1D compressed textures not allowed */
2965 return GL_INVALID_ENUM
;
2967 else if (dimensions
== 2) {
2968 if (target
== GL_PROXY_TEXTURE_2D
) {
2969 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2971 else if (target
== GL_TEXTURE_2D
) {
2972 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2974 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2975 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2976 return GL_INVALID_ENUM
; /*target*/
2977 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2979 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2980 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2981 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2982 return GL_INVALID_ENUM
; /*target*/
2983 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2986 return GL_INVALID_ENUM
; /*target*/
2989 else if (dimensions
== 3) {
2990 /* 3D compressed textures not allowed */
2991 return GL_INVALID_ENUM
;
2994 maxTextureSize
= 1 << (maxLevels
- 1);
2996 /* this will catch any invalid compressed format token */
2997 if (!is_compressed_format(ctx
, format
))
2998 return GL_INVALID_ENUM
;
3000 if (width
< 1 || width
> maxTextureSize
)
3001 return GL_INVALID_VALUE
;
3003 if ((height
< 1 || height
> maxTextureSize
)
3005 return GL_INVALID_VALUE
;
3007 if (level
< 0 || level
>= maxLevels
)
3008 return GL_INVALID_VALUE
;
3010 /* XXX these tests are specific to the compressed format.
3011 * this code should be generalized in some way.
3013 if ((xoffset
& 3) != 0 || (yoffset
& 3) != 0)
3014 return GL_INVALID_VALUE
;
3016 if ((width
& 3) != 0 && width
!= 2 && width
!= 1)
3017 return GL_INVALID_VALUE
;
3019 if ((height
& 3) != 0 && height
!= 2 && height
!= 1)
3020 return GL_INVALID_VALUE
;
3022 expectedSize
= _mesa_compressed_texture_size_glenum(ctx
, width
, height
,
3024 if (expectedSize
!= imageSize
)
3025 return GL_INVALID_VALUE
;
3033 _mesa_CompressedTexImage1DARB(GLenum target
, GLint level
,
3034 GLenum internalFormat
, GLsizei width
,
3035 GLint border
, GLsizei imageSize
,
3038 GET_CURRENT_CONTEXT(ctx
);
3039 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3041 if (target
== GL_TEXTURE_1D
) {
3042 /* non-proxy target */
3043 struct gl_texture_unit
*texUnit
;
3044 struct gl_texture_object
*texObj
;
3045 struct gl_texture_image
*texImage
;
3046 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
3047 internalFormat
, width
, 1, 1, border
, imageSize
);
3049 _mesa_error(ctx
, error
, "glCompressedTexImage1D");
3053 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3054 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3055 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
3057 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage1D");
3060 else if (texImage
->Data
) {
3061 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3063 ASSERT(texImage
->Data
== NULL
);
3065 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
3066 border
, internalFormat
);
3068 ASSERT(ctx
->Driver
.CompressedTexImage1D
);
3069 (*ctx
->Driver
.CompressedTexImage1D
)(ctx
, target
, level
,
3070 internalFormat
, width
, border
,
3075 texObj
->Complete
= GL_FALSE
;
3076 ctx
->NewState
|= _NEW_TEXTURE
;
3078 else if (target
== GL_PROXY_TEXTURE_1D
) {
3079 /* Proxy texture: check for errors and update proxy state */
3080 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
3081 internalFormat
, width
, 1, 1, border
, imageSize
);
3083 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3084 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3085 internalFormat
, GL_NONE
, GL_NONE
,
3086 width
, 1, 1, border
);
3089 /* if error, clear all proxy texture image parameters */
3090 struct gl_texture_image
*texImage
;
3091 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3093 clear_teximage_fields(texImage
);
3096 /* store the teximage parameters */
3097 struct gl_texture_unit
*texUnit
;
3098 struct gl_texture_image
*texImage
;
3099 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3100 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3101 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
3102 border
, internalFormat
);
3106 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage1D(target)");
3113 _mesa_CompressedTexImage2DARB(GLenum target
, GLint level
,
3114 GLenum internalFormat
, GLsizei width
,
3115 GLsizei height
, GLint border
, GLsizei imageSize
,
3118 GET_CURRENT_CONTEXT(ctx
);
3119 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3121 if (target
== GL_TEXTURE_2D
||
3122 (ctx
->Extensions
.ARB_texture_cube_map
&&
3123 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3124 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
3125 /* non-proxy target */
3126 struct gl_texture_unit
*texUnit
;
3127 struct gl_texture_object
*texObj
;
3128 struct gl_texture_image
*texImage
;
3129 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
3130 internalFormat
, width
, height
, 1, border
, imageSize
);
3132 _mesa_error(ctx
, error
, "glCompressedTexImage2D");
3136 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3137 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3138 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
3140 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
3143 else if (texImage
->Data
) {
3144 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3146 ASSERT(texImage
->Data
== NULL
);
3148 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
3149 border
, internalFormat
);
3151 ASSERT(ctx
->Driver
.CompressedTexImage2D
);
3152 (*ctx
->Driver
.CompressedTexImage2D
)(ctx
, target
, level
,
3153 internalFormat
, width
, height
,
3154 border
, imageSize
, data
,
3158 texObj
->Complete
= GL_FALSE
;
3159 ctx
->NewState
|= _NEW_TEXTURE
;
3161 else if (target
== GL_PROXY_TEXTURE_2D
||
3162 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
3163 ctx
->Extensions
.ARB_texture_cube_map
)) {
3164 /* Proxy texture: check for errors and update proxy state */
3165 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
3166 internalFormat
, width
, height
, 1, border
, imageSize
);
3168 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3169 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3170 internalFormat
, GL_NONE
, GL_NONE
,
3171 width
, height
, 1, border
);
3174 /* if error, clear all proxy texture image parameters */
3175 struct gl_texture_image
*texImage
;
3176 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3178 clear_teximage_fields(texImage
);
3181 /* store the teximage parameters */
3182 struct gl_texture_unit
*texUnit
;
3183 struct gl_texture_image
*texImage
;
3184 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3185 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3186 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
3187 border
, internalFormat
);
3191 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(target)");
3198 _mesa_CompressedTexImage3DARB(GLenum target
, GLint level
,
3199 GLenum internalFormat
, GLsizei width
,
3200 GLsizei height
, GLsizei depth
, GLint border
,
3201 GLsizei imageSize
, const GLvoid
*data
)
3203 GET_CURRENT_CONTEXT(ctx
);
3204 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3206 if (target
== GL_TEXTURE_3D
) {
3207 /* non-proxy target */
3208 struct gl_texture_unit
*texUnit
;
3209 struct gl_texture_object
*texObj
;
3210 struct gl_texture_image
*texImage
;
3211 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3212 internalFormat
, width
, height
, depth
, border
, imageSize
);
3214 _mesa_error(ctx
, error
, "glCompressedTexImage3D");
3218 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3219 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3220 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
3222 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage3D");
3225 else if (texImage
->Data
) {
3226 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3228 ASSERT(texImage
->Data
== NULL
);
3230 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, depth
,
3231 border
, internalFormat
);
3233 ASSERT(ctx
->Driver
.CompressedTexImage3D
);
3234 (*ctx
->Driver
.CompressedTexImage3D
)(ctx
, target
, level
,
3236 width
, height
, depth
,
3237 border
, imageSize
, data
,
3241 texObj
->Complete
= GL_FALSE
;
3242 ctx
->NewState
|= _NEW_TEXTURE
;
3244 else if (target
== GL_PROXY_TEXTURE_3D
) {
3245 /* Proxy texture: check for errors and update proxy state */
3246 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3247 internalFormat
, width
, height
, depth
, border
, imageSize
);
3249 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3250 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3251 internalFormat
, GL_NONE
, GL_NONE
,
3252 width
, height
, depth
, border
);
3255 /* if error, clear all proxy texture image parameters */
3256 struct gl_texture_image
*texImage
;
3257 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3259 clear_teximage_fields(texImage
);
3262 /* store the teximage parameters */
3263 struct gl_texture_unit
*texUnit
;
3264 struct gl_texture_image
*texImage
;
3265 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3266 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3267 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
,
3268 depth
, border
, internalFormat
);
3272 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage3D(target)");
3279 _mesa_CompressedTexSubImage1DARB(GLenum target
, GLint level
, GLint xoffset
,
3280 GLsizei width
, GLenum format
,
3281 GLsizei imageSize
, const GLvoid
*data
)
3283 struct gl_texture_unit
*texUnit
;
3284 struct gl_texture_object
*texObj
;
3285 struct gl_texture_image
*texImage
;
3287 GET_CURRENT_CONTEXT(ctx
);
3288 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3290 error
= compressed_subtexture_error_check(ctx
, 1, target
, level
,
3291 xoffset
, 0, 0, /* pos */
3292 width
, 1, 1, /* size */
3295 _mesa_error(ctx
, error
, "glCompressedTexSubImage1D");
3299 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3300 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3301 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3304 if ((GLint
) format
!= texImage
->InternalFormat
) {
3305 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3306 "glCompressedTexSubImage1D(format)");
3310 if ((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) {
3311 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage1D(width)");
3316 return; /* no-op, not an error */
3318 if (ctx
->Driver
.CompressedTexSubImage1D
) {
3319 (*ctx
->Driver
.CompressedTexSubImage1D
)(ctx
, target
, level
,
3321 format
, imageSize
, data
,
3324 ctx
->NewState
|= _NEW_TEXTURE
;
3329 _mesa_CompressedTexSubImage2DARB(GLenum target
, GLint level
, GLint xoffset
,
3330 GLint yoffset
, GLsizei width
, GLsizei height
,
3331 GLenum format
, GLsizei imageSize
,
3334 struct gl_texture_unit
*texUnit
;
3335 struct gl_texture_object
*texObj
;
3336 struct gl_texture_image
*texImage
;
3338 GET_CURRENT_CONTEXT(ctx
);
3339 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3341 error
= compressed_subtexture_error_check(ctx
, 2, target
, level
,
3342 xoffset
, yoffset
, 0, /* pos */
3343 width
, height
, 1, /* size */
3346 /* XXX proxy target? */
3347 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3351 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3352 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3353 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3356 if ((GLint
) format
!= texImage
->InternalFormat
) {
3357 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3358 "glCompressedTexSubImage2D(format)");
3362 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3363 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
)) {
3364 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage2D(size)");
3368 if (width
== 0 || height
== 0)
3369 return; /* no-op, not an error */
3371 if (ctx
->Driver
.CompressedTexSubImage2D
) {
3372 (*ctx
->Driver
.CompressedTexSubImage2D
)(ctx
, target
, level
,
3373 xoffset
, yoffset
, width
, height
,
3374 format
, imageSize
, data
,
3377 ctx
->NewState
|= _NEW_TEXTURE
;
3382 _mesa_CompressedTexSubImage3DARB(GLenum target
, GLint level
, GLint xoffset
,
3383 GLint yoffset
, GLint zoffset
, GLsizei width
,
3384 GLsizei height
, GLsizei depth
, GLenum format
,
3385 GLsizei imageSize
, const GLvoid
*data
)
3387 struct gl_texture_unit
*texUnit
;
3388 struct gl_texture_object
*texObj
;
3389 struct gl_texture_image
*texImage
;
3391 GET_CURRENT_CONTEXT(ctx
);
3392 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3394 error
= compressed_subtexture_error_check(ctx
, 3, target
, level
,
3395 xoffset
, yoffset
, zoffset
,/*pos*/
3396 width
, height
, depth
, /*size*/
3399 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3403 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3404 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3405 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3408 if ((GLint
) format
!= texImage
->InternalFormat
) {
3409 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3410 "glCompressedTexSubImage3D(format)");
3414 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3415 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
) ||
3416 ((depth
== 1 || depth
== 2) && (GLuint
) depth
!= texImage
->Depth
)) {
3417 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage3D(size)");
3421 if (width
== 0 || height
== 0 || depth
== 0)
3422 return; /* no-op, not an error */
3424 if (ctx
->Driver
.CompressedTexSubImage3D
) {
3425 (*ctx
->Driver
.CompressedTexSubImage3D
)(ctx
, target
, level
,
3426 xoffset
, yoffset
, zoffset
,
3427 width
, height
, depth
,
3428 format
, imageSize
, data
,
3431 ctx
->NewState
|= _NEW_TEXTURE
;
3436 _mesa_GetCompressedTexImageARB(GLenum target
, GLint level
, GLvoid
*img
)
3438 const struct gl_texture_unit
*texUnit
;
3439 const struct gl_texture_object
*texObj
;
3440 struct gl_texture_image
*texImage
;
3442 GET_CURRENT_CONTEXT(ctx
);
3443 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3445 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3446 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3448 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB");
3452 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
3453 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
3455 if (level
< 0 || level
>= maxLevels
) {
3456 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3460 if (_mesa_is_proxy_texture(target
)) {
3461 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
3465 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3467 /* probably invalid mipmap level */
3468 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3472 if (!texImage
->IsCompressed
) {
3473 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetCompressedTexImageARB");
3477 /* this typically calls _mesa_get_compressed_teximage() */
3478 ctx
->Driver
.GetCompressedTexImage(ctx
, target
, level
, img
, texObj
,texImage
);