2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * Texture images manipulation functions.
30 * \note Mesa's native texture data type is GLchan. Native formats are
31 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA, and
34 * \note Device drivers are free to implement any internal format they want.
39 #include "bufferobj.h"
46 #include "texcompress.h"
47 #include "texformat.h"
55 * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
59 _mesa_alloc_texmemory(GLsizei bytes
)
61 return _mesa_align_malloc(bytes
, 512);
66 * Free texture memory allocated with _mesa_alloc_texmemory()
69 _mesa_free_texmemory(void *m
)
78 static void PrintTexture(GLcontext
*ctx
, const struct gl_texture_image
*img
)
80 #if CHAN_TYPE == GL_FLOAT
81 _mesa_problem(NULL
, "PrintTexture doesn't support float channels");
84 const GLchan
*data
= (const GLchan
*) img
->Data
;
87 _mesa_printf("No texture data\n");
91 switch (img
->Format
) {
98 case GL_LUMINANCE_ALPHA
:
108 _mesa_problem(NULL
, "error in PrintTexture\n");
112 for (i
= 0; i
< img
->Height
; i
++) {
113 for (j
= 0; j
< img
->Width
; j
++) {
115 _mesa_printf("%02x ", data
[0]);
117 _mesa_printf("%02x%02x ", data
[0], data
[1]);
119 _mesa_printf("%02x%02x%02x ", data
[0], data
[1], data
[2]);
121 _mesa_printf("%02x%02x%02x%02x ", data
[0], data
[1], data
[2], data
[3]);
122 data
+= (img
->RowStride
- img
->Width
) * c
;
132 * Compute floor(log_base_2(n)).
133 * If n < 0 return -1.
162 * Return the simple base format for a given internal texture format.
163 * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
165 * \param ctx GL context.
166 * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
168 * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
169 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
171 * This is the format which is used during texture application (i.e. the
172 * texture format and env mode determine the arithmetic used.
175 _mesa_base_tex_format( GLcontext
*ctx
, GLint internalFormat
)
177 switch (internalFormat
) {
192 case GL_LUMINANCE_ALPHA
:
193 case GL_LUMINANCE4_ALPHA4
:
194 case GL_LUMINANCE6_ALPHA2
:
195 case GL_LUMINANCE8_ALPHA8
:
196 case GL_LUMINANCE12_ALPHA4
:
197 case GL_LUMINANCE12_ALPHA12
:
198 case GL_LUMINANCE16_ALPHA16
:
199 return GL_LUMINANCE_ALPHA
;
230 if (ctx
->Extensions
.EXT_paletted_texture
) {
231 switch (internalFormat
) {
233 case GL_COLOR_INDEX1_EXT
:
234 case GL_COLOR_INDEX2_EXT
:
235 case GL_COLOR_INDEX4_EXT
:
236 case GL_COLOR_INDEX8_EXT
:
237 case GL_COLOR_INDEX12_EXT
:
238 case GL_COLOR_INDEX16_EXT
:
239 return GL_COLOR_INDEX
;
245 if (ctx
->Extensions
.SGIX_depth_texture
||
246 ctx
->Extensions
.ARB_depth_texture
) {
247 switch (internalFormat
) {
248 case GL_DEPTH_COMPONENT
:
249 case GL_DEPTH_COMPONENT16_SGIX
:
250 case GL_DEPTH_COMPONENT24_SGIX
:
251 case GL_DEPTH_COMPONENT32_SGIX
:
252 return GL_DEPTH_COMPONENT
;
258 if (ctx
->Extensions
.ARB_texture_compression
) {
259 switch (internalFormat
) {
260 case GL_COMPRESSED_ALPHA
:
262 case GL_COMPRESSED_LUMINANCE
:
264 case GL_COMPRESSED_LUMINANCE_ALPHA
:
265 return GL_LUMINANCE_ALPHA
;
266 case GL_COMPRESSED_INTENSITY
:
268 case GL_COMPRESSED_RGB
:
270 case GL_COMPRESSED_RGBA
:
277 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
) {
278 switch (internalFormat
) {
279 case GL_COMPRESSED_RGB_FXT1_3DFX
:
281 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
288 if (ctx
->Extensions
.EXT_texture_compression_s3tc
) {
289 switch (internalFormat
) {
290 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
292 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
293 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
294 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
301 if (ctx
->Extensions
.S3_s3tc
) {
302 switch (internalFormat
) {
314 if (ctx
->Extensions
.MESA_ycbcr_texture
) {
315 if (internalFormat
== GL_YCBCR_MESA
)
316 return GL_YCBCR_MESA
;
319 if (ctx
->Extensions
.ARB_texture_float
) {
320 switch (internalFormat
) {
321 case GL_ALPHA16F_ARB
:
322 case GL_ALPHA32F_ARB
:
330 case GL_INTENSITY16F_ARB
:
331 case GL_INTENSITY32F_ARB
:
333 case GL_LUMINANCE16F_ARB
:
334 case GL_LUMINANCE32F_ARB
:
336 case GL_LUMINANCE_ALPHA16F_ARB
:
337 case GL_LUMINANCE_ALPHA32F_ARB
:
338 return GL_LUMINANCE_ALPHA
;
344 if (ctx
->Extensions
.EXT_packed_depth_stencil
) {
345 switch (internalFormat
) {
346 case GL_DEPTH_STENCIL_EXT
:
347 case GL_DEPTH24_STENCIL8_EXT
:
348 return GL_DEPTH_STENCIL_EXT
;
354 return -1; /* error */
359 * Test if the given image format is a color/RGBA format (i.e., not color
360 * index, depth, stencil, etc).
361 * \param format the image format value (may by an internal texture format)
362 * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
365 is_color_format(GLenum format
)
383 case GL_LUMINANCE_ALPHA
:
384 case GL_LUMINANCE4_ALPHA4
:
385 case GL_LUMINANCE6_ALPHA2
:
386 case GL_LUMINANCE8_ALPHA8
:
387 case GL_LUMINANCE12_ALPHA4
:
388 case GL_LUMINANCE12_ALPHA12
:
389 case GL_LUMINANCE16_ALPHA16
:
416 /* float texture formats */
417 case GL_ALPHA16F_ARB
:
418 case GL_ALPHA32F_ARB
:
419 case GL_LUMINANCE16F_ARB
:
420 case GL_LUMINANCE32F_ARB
:
421 case GL_LUMINANCE_ALPHA16F_ARB
:
422 case GL_LUMINANCE_ALPHA32F_ARB
:
423 case GL_INTENSITY16F_ARB
:
424 case GL_INTENSITY32F_ARB
:
429 /* compressed formats */
430 case GL_COMPRESSED_ALPHA
:
431 case GL_COMPRESSED_LUMINANCE
:
432 case GL_COMPRESSED_LUMINANCE_ALPHA
:
433 case GL_COMPRESSED_INTENSITY
:
434 case GL_COMPRESSED_RGB
:
435 case GL_COMPRESSED_RGBA
:
440 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
441 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
442 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
443 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
444 case GL_COMPRESSED_RGB_FXT1_3DFX
:
445 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
447 case GL_YCBCR_MESA
: /* not considered to be RGB */
455 * Test if the given image format is a color index format.
458 is_index_format(GLenum format
)
462 case GL_COLOR_INDEX1_EXT
:
463 case GL_COLOR_INDEX2_EXT
:
464 case GL_COLOR_INDEX4_EXT
:
465 case GL_COLOR_INDEX8_EXT
:
466 case GL_COLOR_INDEX12_EXT
:
467 case GL_COLOR_INDEX16_EXT
:
476 * Test if the given image format is a depth component format.
479 is_depth_format(GLenum format
)
482 case GL_DEPTH_COMPONENT16_ARB
:
483 case GL_DEPTH_COMPONENT24_ARB
:
484 case GL_DEPTH_COMPONENT32_ARB
:
485 case GL_DEPTH_COMPONENT
:
494 * Test if the given image format is a YCbCr format.
497 is_ycbcr_format(GLenum format
)
509 * Test if the given image format is a Depth/Stencil format.
512 is_depthstencil_format(GLenum format
)
515 case GL_DEPTH24_STENCIL8_EXT
:
516 case GL_DEPTH_STENCIL_EXT
:
526 * Test if it is a supported compressed format.
528 * \param internalFormat the internal format token provided by the user.
530 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
531 * GL_FALSE otherwise.
533 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
537 is_compressed_format(GLcontext
*ctx
, GLenum internalFormat
)
540 switch (internalFormat
) {
541 case GL_COMPRESSED_RGB_FXT1_3DFX
:
542 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
543 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
544 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
545 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
546 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
559 * Store a gl_texture_image pointer in a gl_texture_object structure
560 * according to the target and level parameters.
562 * \param tObj texture object.
563 * \param target texture target.
564 * \param level image level.
565 * \param texImage texture image.
567 * This was basically prompted by the introduction of cube maps.
570 _mesa_set_tex_image(struct gl_texture_object
*tObj
,
571 GLenum target
, GLint level
,
572 struct gl_texture_image
*texImage
)
580 tObj
->Image
[0][level
] = texImage
;
582 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
583 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
584 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
585 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
586 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
587 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
589 GLuint face
= ((GLuint
) target
-
590 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
591 tObj
->Image
[face
][level
] = texImage
;
594 case GL_TEXTURE_RECTANGLE_NV
:
596 tObj
->Image
[0][level
] = texImage
;
599 _mesa_problem(NULL
, "bad target in _mesa_set_tex_image()");
602 /* Set the 'back' pointer */
603 texImage
->TexObject
= tObj
;
608 * Allocate a texture image structure.
610 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
613 * \return a pointer to gl_texture_image struct with all fields initialized to
616 struct gl_texture_image
*
617 _mesa_new_texture_image( GLcontext
*ctx
)
620 return CALLOC_STRUCT(gl_texture_image
);
625 * Free texture image data.
626 * This function is a fallback called via ctx->Driver.FreeTexImageData().
628 * \param teximage texture image.
630 * Free the texture image data if it's not marked as client data.
633 _mesa_free_texture_image_data(GLcontext
*ctx
,
634 struct gl_texture_image
*texImage
)
636 if (texImage
->Data
&& !texImage
->IsClientData
) {
637 /* free the old texture data */
638 _mesa_free_texmemory(texImage
->Data
);
641 texImage
->Data
= NULL
;
646 * Free texture image.
648 * \param teximage texture image.
650 * Free the texture image structure and the associated image data.
653 _mesa_delete_texture_image( GLcontext
*ctx
, struct gl_texture_image
*texImage
)
655 if (texImage
->Data
) {
656 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
658 ASSERT(texImage
->Data
== NULL
);
664 * Test if a target is a proxy target.
666 * \param target texture target.
668 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
671 is_proxy_target(GLenum target
)
673 return (target
== GL_PROXY_TEXTURE_1D
||
674 target
== GL_PROXY_TEXTURE_2D
||
675 target
== GL_PROXY_TEXTURE_3D
||
676 target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
677 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
);
682 * Get the texture object that corresponds to the target of the given texture unit.
684 * \param ctx GL context.
685 * \param texUnit texture unit.
686 * \param target texture target.
688 * \return pointer to the texture object on success, or NULL on failure.
690 * \sa gl_texture_unit.
692 struct gl_texture_object
*
693 _mesa_select_tex_object(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
698 return texUnit
->Current1D
;
699 case GL_PROXY_TEXTURE_1D
:
700 return ctx
->Texture
.Proxy1D
;
702 return texUnit
->Current2D
;
703 case GL_PROXY_TEXTURE_2D
:
704 return ctx
->Texture
.Proxy2D
;
706 return texUnit
->Current3D
;
707 case GL_PROXY_TEXTURE_3D
:
708 return ctx
->Texture
.Proxy3D
;
709 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
710 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
711 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
712 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
713 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
714 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
715 case GL_TEXTURE_CUBE_MAP_ARB
:
716 return ctx
->Extensions
.ARB_texture_cube_map
717 ? texUnit
->CurrentCubeMap
: NULL
;
718 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
719 return ctx
->Extensions
.ARB_texture_cube_map
720 ? ctx
->Texture
.ProxyCubeMap
: NULL
;
721 case GL_TEXTURE_RECTANGLE_NV
:
722 return ctx
->Extensions
.NV_texture_rectangle
723 ? texUnit
->CurrentRect
: NULL
;
724 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
725 return ctx
->Extensions
.NV_texture_rectangle
726 ? ctx
->Texture
.ProxyRect
: NULL
;
728 _mesa_problem(NULL
, "bad target in _mesa_select_tex_object()");
735 * Get the texture image struct which corresponds to target and level
736 * of the given texture unit.
738 * \param ctx GL context.
739 * \param texUnit texture unit.
740 * \param target texture target.
741 * \param level image level.
743 * \return pointer to the texture image structure on success, or NULL on failure.
745 * \sa gl_texture_unit.
747 struct gl_texture_image
*
748 _mesa_select_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
749 GLenum target
, GLint level
)
752 ASSERT(level
< MAX_TEXTURE_LEVELS
);
755 return texUnit
->Current1D
->Image
[0][level
];
756 case GL_PROXY_TEXTURE_1D
:
757 return ctx
->Texture
.Proxy1D
->Image
[0][level
];
759 return texUnit
->Current2D
->Image
[0][level
];
760 case GL_PROXY_TEXTURE_2D
:
761 return ctx
->Texture
.Proxy2D
->Image
[0][level
];
763 return texUnit
->Current3D
->Image
[0][level
];
764 case GL_PROXY_TEXTURE_3D
:
765 return ctx
->Texture
.Proxy3D
->Image
[0][level
];
766 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
767 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
768 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
769 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
770 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
771 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
772 if (ctx
->Extensions
.ARB_texture_cube_map
) {
773 GLuint face
= ((GLuint
) target
-
774 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
775 return texUnit
->CurrentCubeMap
->Image
[face
][level
];
779 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
780 if (ctx
->Extensions
.ARB_texture_cube_map
)
781 return ctx
->Texture
.ProxyCubeMap
->Image
[0][level
];
784 case GL_TEXTURE_RECTANGLE_NV
:
785 if (ctx
->Extensions
.NV_texture_rectangle
) {
787 return texUnit
->CurrentRect
->Image
[0][level
];
792 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
793 if (ctx
->Extensions
.NV_texture_rectangle
) {
795 return ctx
->Texture
.ProxyRect
->Image
[0][level
];
801 _mesa_problem(ctx
, "bad target in _mesa_select_tex_image()");
808 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
809 * it and install it. Only return NULL if passed a bad parameter or run
812 struct gl_texture_image
*
813 _mesa_get_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
814 GLenum target
, GLint level
)
816 struct gl_texture_image
*texImage
;
817 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
819 struct gl_texture_object
*texObj
;
820 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
822 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture image allocation");
825 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
827 _mesa_set_tex_image(texObj
, target
, level
, texImage
);
834 * Return pointer to the specified proxy texture image.
835 * Note that proxy textures are per-context, not per-texture unit.
836 * \return pointer to texture image or NULL if invalid target, invalid
837 * level, or out of memory.
839 struct gl_texture_image
*
840 _mesa_get_proxy_tex_image(GLcontext
*ctx
, GLenum target
, GLint level
)
842 struct gl_texture_image
*texImage
;
848 case GL_PROXY_TEXTURE_1D
:
849 if (level
>= ctx
->Const
.MaxTextureLevels
)
851 texImage
= ctx
->Texture
.Proxy1D
->Image
[0][level
];
853 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
855 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
858 ctx
->Texture
.Proxy1D
->Image
[0][level
] = texImage
;
859 /* Set the 'back' pointer */
860 texImage
->TexObject
= ctx
->Texture
.Proxy1D
;
863 case GL_PROXY_TEXTURE_2D
:
864 if (level
>= ctx
->Const
.MaxTextureLevels
)
866 texImage
= ctx
->Texture
.Proxy2D
->Image
[0][level
];
868 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
870 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
873 ctx
->Texture
.Proxy2D
->Image
[0][level
] = texImage
;
874 /* Set the 'back' pointer */
875 texImage
->TexObject
= ctx
->Texture
.Proxy2D
;
878 case GL_PROXY_TEXTURE_3D
:
879 if (level
>= ctx
->Const
.Max3DTextureLevels
)
881 texImage
= ctx
->Texture
.Proxy3D
->Image
[0][level
];
883 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
885 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
888 ctx
->Texture
.Proxy3D
->Image
[0][level
] = texImage
;
889 /* Set the 'back' pointer */
890 texImage
->TexObject
= ctx
->Texture
.Proxy3D
;
893 case GL_PROXY_TEXTURE_CUBE_MAP
:
894 if (level
>= ctx
->Const
.MaxCubeTextureLevels
)
896 texImage
= ctx
->Texture
.ProxyCubeMap
->Image
[0][level
];
898 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
900 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
903 ctx
->Texture
.ProxyCubeMap
->Image
[0][level
] = texImage
;
904 /* Set the 'back' pointer */
905 texImage
->TexObject
= ctx
->Texture
.ProxyCubeMap
;
908 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
911 texImage
= ctx
->Texture
.ProxyRect
->Image
[0][level
];
913 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
915 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
918 ctx
->Texture
.ProxyRect
->Image
[0][level
] = texImage
;
919 /* Set the 'back' pointer */
920 texImage
->TexObject
= ctx
->Texture
.ProxyRect
;
930 * Get the maximum number of allowed mipmap levels.
932 * \param ctx GL context.
933 * \param target texture target.
935 * \return the maximum number of allowed mipmap levels for the given
936 * texture target, or zero if passed a bad target.
941 _mesa_max_texture_levels(GLcontext
*ctx
, GLenum target
)
945 case GL_PROXY_TEXTURE_1D
:
947 case GL_PROXY_TEXTURE_2D
:
948 return ctx
->Const
.MaxTextureLevels
;
950 case GL_PROXY_TEXTURE_3D
:
951 return ctx
->Const
.Max3DTextureLevels
;
952 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
953 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
954 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
955 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
956 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
957 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
958 case GL_TEXTURE_CUBE_MAP_ARB
:
959 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
960 return ctx
->Const
.MaxCubeTextureLevels
;
961 case GL_TEXTURE_RECTANGLE_NV
:
962 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
965 return 0; /* bad target */
971 #if 000 /* not used anymore */
973 * glTexImage[123]D can accept a NULL image pointer. In this case we
974 * create a texture image with unspecified image contents per the OpenGL
978 make_null_texture(GLint width
, GLint height
, GLint depth
, GLenum format
)
980 const GLint components
= _mesa_components_in_format(format
);
981 const GLint numPixels
= width
* height
* depth
;
982 GLubyte
*data
= (GLubyte
*) MALLOC(numPixels
* components
* sizeof(GLubyte
));
986 * Let's see if anyone finds this. If glTexImage2D() is called with
987 * a NULL image pointer then load the texture image with something
988 * interesting instead of leaving it indeterminate.
991 static const char message
[8][32] = {
995 " X X XXXX XXX XXXXX ",
998 " X X XXXXX XXX X X ",
1002 GLubyte
*imgPtr
= data
;
1004 for (h
= 0; h
< depth
; h
++) {
1005 for (i
= 0; i
< height
; i
++) {
1006 GLint srcRow
= 7 - (i
% 8);
1007 for (j
= 0; j
< width
; j
++) {
1008 GLint srcCol
= j
% 32;
1009 GLubyte texel
= (message
[srcRow
][srcCol
]=='X') ? 255 : 70;
1010 for (k
= 0; k
< components
; k
++) {
1026 * Reset the fields of a gl_texture_image struct to zero.
1028 * \param img texture image structure.
1030 * This is called when a proxy texture test fails, we set all the
1031 * image members (except DriverData) to zero.
1032 * It's also used in glTexImage[123]D as a safeguard to be sure all
1033 * required fields get initialized properly by the Driver.TexImage[123]D
1037 clear_teximage_fields(struct gl_texture_image
*img
)
1051 img
->HeightLog2
= 0;
1054 img
->TexFormat
= &_mesa_null_texformat
;
1055 img
->FetchTexelc
= NULL
;
1056 img
->FetchTexelf
= NULL
;
1057 img
->IsCompressed
= 0;
1058 img
->CompressedSize
= 0;
1063 * Initialize basic fields of the gl_texture_image struct.
1065 * \param ctx GL context.
1066 * \param target texture target.
1067 * \param img texture image structure to be initialized.
1068 * \param width image width.
1069 * \param height image height.
1070 * \param depth image depth.
1071 * \param border image border.
1072 * \param internalFormat internal format.
1074 * Fills in the fields of \p img with the given information.
1075 * Note: width, height and depth include the border.
1078 _mesa_init_teximage_fields(GLcontext
*ctx
, GLenum target
,
1079 struct gl_texture_image
*img
,
1080 GLsizei width
, GLsizei height
, GLsizei depth
,
1081 GLint border
, GLenum internalFormat
)
1084 img
->Format
= _mesa_base_tex_format( ctx
, internalFormat
);
1085 ASSERT(img
->Format
> 0);
1086 img
->IntFormat
= internalFormat
;
1087 img
->Border
= border
;
1089 img
->Height
= height
;
1091 img
->RowStride
= width
;
1092 img
->WidthLog2
= logbase2(width
- 2 * border
);
1093 if (height
== 1) /* 1-D texture */
1094 img
->HeightLog2
= 0;
1096 img
->HeightLog2
= logbase2(height
- 2 * border
);
1097 if (depth
== 1) /* 2-D texture */
1100 img
->DepthLog2
= logbase2(depth
- 2 * border
);
1101 img
->Width2
= width
- 2 * border
; /*1 << img->WidthLog2;*/
1102 img
->Height2
= height
- 2 * border
; /*1 << img->HeightLog2;*/
1103 img
->Depth2
= depth
- 2 * border
; /*1 << img->DepthLog2;*/
1104 img
->MaxLog2
= MAX2(img
->WidthLog2
, img
->HeightLog2
);
1105 img
->IsCompressed
= is_compressed_format(ctx
, internalFormat
);
1106 if (img
->IsCompressed
)
1107 img
->CompressedSize
= ctx
->Driver
.CompressedTextureSize(ctx
, width
,
1108 height
, depth
, internalFormat
);
1110 img
->CompressedSize
= 0;
1112 if ((width
== 1 || _mesa_bitcount(width
- 2 * border
) == 1) &&
1113 (height
== 1 || _mesa_bitcount(height
- 2 * border
) == 1) &&
1114 (depth
== 1 || _mesa_bitcount(depth
- 2 * border
) == 1))
1115 img
->_IsPowerOfTwo
= GL_TRUE
;
1117 img
->_IsPowerOfTwo
= GL_FALSE
;
1119 /* Compute Width/Height/DepthScale for mipmap lod computation */
1120 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1121 /* scale = 1.0 since texture coords directly map to texels */
1122 img
->WidthScale
= 1.0;
1123 img
->HeightScale
= 1.0;
1124 img
->DepthScale
= 1.0;
1127 img
->WidthScale
= (GLfloat
) img
->Width
;
1128 img
->HeightScale
= (GLfloat
) img
->Height
;
1129 img
->DepthScale
= (GLfloat
) img
->Depth
;
1135 * This is the fallback for Driver.TestProxyTexImage(). Test the texture
1136 * level, width, height and depth against the ctx->Const limits for textures.
1138 * A hardware driver might override this function if, for example, the
1139 * max 3D texture size is 512x512x64 (i.e. not a cube).
1141 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
1142 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
1143 * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
1144 * \param level as passed to glTexImage
1145 * \param internalFormat as passed to glTexImage
1146 * \param format as passed to glTexImage
1147 * \param type as passed to glTexImage
1148 * \param width as passed to glTexImage
1149 * \param height as passed to glTexImage
1150 * \param depth as passed to glTexImage
1151 * \param border as passed to glTexImage
1152 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1155 _mesa_test_proxy_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
1156 GLint internalFormat
, GLenum format
, GLenum type
,
1157 GLint width
, GLint height
, GLint depth
, GLint border
)
1161 (void) internalFormat
;
1166 case GL_PROXY_TEXTURE_1D
:
1167 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1168 if (width
< 2 * border
|| width
> 2 + maxSize
||
1169 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1170 _mesa_bitcount(width
- 2 * border
) != 1) ||
1171 level
>= ctx
->Const
.MaxTextureLevels
) {
1172 /* bad width or level */
1176 case GL_PROXY_TEXTURE_2D
:
1177 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1178 if (width
< 2 * border
|| width
> 2 + maxSize
||
1179 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1180 _mesa_bitcount(width
- 2 * border
) != 1) ||
1181 height
< 2 * border
|| height
> 2 + maxSize
||
1182 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1183 _mesa_bitcount(height
- 2 * border
) != 1) ||
1184 level
>= ctx
->Const
.MaxTextureLevels
) {
1185 /* bad width or height or level */
1189 case GL_PROXY_TEXTURE_3D
:
1190 maxSize
= 1 << (ctx
->Const
.Max3DTextureLevels
- 1);
1191 if (width
< 2 * border
|| width
> 2 + maxSize
||
1192 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1193 _mesa_bitcount(width
- 2 * border
) != 1) ||
1194 height
< 2 * border
|| height
> 2 + maxSize
||
1195 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1196 _mesa_bitcount(height
- 2 * border
) != 1) ||
1197 depth
< 2 * border
|| depth
> 2 + maxSize
||
1198 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1199 _mesa_bitcount(depth
- 2 * border
) != 1) ||
1200 level
>= ctx
->Const
.Max3DTextureLevels
) {
1201 /* bad width or height or depth or level */
1205 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
1206 if (width
< 1 || width
> ctx
->Const
.MaxTextureRectSize
||
1207 height
< 1 || height
> ctx
->Const
.MaxTextureRectSize
||
1209 /* bad width or height or level */
1213 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
1214 maxSize
= 1 << (ctx
->Const
.MaxCubeTextureLevels
- 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 level
>= ctx
->Const
.MaxCubeTextureLevels
) {
1222 /* bad width or height */
1227 _mesa_problem(ctx
, "Invalid target in _mesa_test_proxy_teximage");
1234 * Test the glTexImage[123]D() parameters for errors.
1236 * \param ctx GL context.
1237 * \param target texture target given by the user.
1238 * \param level image level given by the user.
1239 * \param internalFormat internal format given by the user.
1240 * \param format pixel data format given by the user.
1241 * \param type pixel data type given by the user.
1242 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1243 * \param width image width given by the user.
1244 * \param height image height given by the user.
1245 * \param depth image depth given by the user.
1246 * \param border image border given by the user.
1248 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1250 * Verifies each of the parameters against the constants specified in
1251 * __GLcontextRec::Const and the supported extensions, and according to the
1252 * OpenGL specification.
1255 texture_error_check( GLcontext
*ctx
, GLenum target
,
1256 GLint level
, GLint internalFormat
,
1257 GLenum format
, GLenum type
,
1259 GLint width
, GLint height
,
1260 GLint depth
, GLint border
)
1262 const GLboolean isProxy
= is_proxy_target(target
);
1264 GLboolean colorFormat
, indexFormat
;
1266 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1267 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1269 _mesa_error(ctx
, GL_INVALID_VALUE
,
1270 "glTexImage%dD(level=%d)", dimensions
, level
);
1276 if (border
< 0 || border
> 1 ||
1277 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1278 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1280 _mesa_error(ctx
, GL_INVALID_VALUE
,
1281 "glTexImage%dD(border=%d)", dimensions
, border
);
1286 if (width
< 0 || height
< 0 || depth
< 0) {
1288 _mesa_error(ctx
, GL_INVALID_VALUE
,
1289 "glTexImage%dD(width, height or depth < 0)", dimensions
);
1294 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1295 * level, width, height and depth.
1297 if (dimensions
== 1) {
1298 if (target
== GL_PROXY_TEXTURE_1D
|| target
== GL_TEXTURE_1D
) {
1299 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1300 level
, internalFormat
,
1302 width
, 1, 1, border
);
1305 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1309 else if (dimensions
== 2) {
1310 if (target
== GL_PROXY_TEXTURE_2D
|| target
== GL_TEXTURE_2D
) {
1311 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1312 level
, internalFormat
,
1314 width
, height
, 1, border
);
1316 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
1317 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1318 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
1319 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1320 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1323 sizeOK
= (width
== height
) &&
1324 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1325 level
, internalFormat
, format
, type
,
1326 width
, height
, 1, border
);
1328 else if (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
||
1329 target
== GL_TEXTURE_RECTANGLE_NV
) {
1330 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1331 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1334 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1335 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1336 level
, internalFormat
,
1338 width
, height
, 1, border
);
1341 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1345 else if (dimensions
== 3) {
1346 if (target
== GL_PROXY_TEXTURE_3D
|| target
== GL_TEXTURE_3D
) {
1347 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_3D
,
1348 level
, internalFormat
,
1350 width
, height
, depth
, border
);
1353 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1358 _mesa_problem( ctx
, "bad dims in texture_error_check" );
1364 _mesa_error(ctx
, GL_INVALID_VALUE
,
1365 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1366 dimensions
, level
, width
, height
, depth
);
1371 /* Check internalFormat */
1372 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1374 _mesa_error(ctx
, GL_INVALID_VALUE
,
1375 "glTexImage%dD(internalFormat=0x%x)",
1376 dimensions
, internalFormat
);
1381 /* Check incoming image format and type */
1382 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
1383 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1384 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1387 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1388 "glTexImage%dD(format or type)", dimensions
);
1393 /* make sure internal format and format basically agree */
1394 colorFormat
= is_color_format(format
);
1395 indexFormat
= is_index_format(format
);
1396 if ((is_color_format(internalFormat
) && !colorFormat
&& !indexFormat
) ||
1397 (is_index_format(internalFormat
) && !indexFormat
) ||
1398 (is_depth_format(internalFormat
) != is_depth_format(format
)) ||
1399 (is_ycbcr_format(internalFormat
) != is_ycbcr_format(format
)) ||
1400 (is_depthstencil_format(internalFormat
) != is_depthstencil_format(format
))) {
1402 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1403 "glTexImage(internalFormat/format)");
1407 /* additional checks for ycbcr textures */
1408 if (internalFormat
== GL_YCBCR_MESA
) {
1409 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1410 if (type
!= GL_UNSIGNED_SHORT_8_8_MESA
&&
1411 type
!= GL_UNSIGNED_SHORT_8_8_REV_MESA
) {
1413 _mesa_sprintf(message
,
1414 "glTexImage%d(format/type YCBCR mismatch", dimensions
);
1415 _mesa_error(ctx
, GL_INVALID_ENUM
, message
);
1416 return GL_TRUE
; /* error */
1418 if (target
!= GL_TEXTURE_2D
&&
1419 target
!= GL_PROXY_TEXTURE_2D
&&
1420 target
!= GL_TEXTURE_RECTANGLE_NV
&&
1421 target
!= GL_PROXY_TEXTURE_RECTANGLE_NV
) {
1423 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage(target)");
1429 _mesa_sprintf(message
,
1430 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1431 dimensions
, border
);
1432 _mesa_error(ctx
, GL_INVALID_VALUE
, message
);
1438 /* additional checks for depth textures */
1439 if (_mesa_base_tex_format(ctx
, internalFormat
) == GL_DEPTH_COMPONENT
) {
1440 /* Only 1D and 2D textures supported */
1441 if (target
!= GL_TEXTURE_1D
&&
1442 target
!= GL_PROXY_TEXTURE_1D
&&
1443 target
!= GL_TEXTURE_2D
&&
1444 target
!= GL_PROXY_TEXTURE_2D
) {
1446 _mesa_error(ctx
, GL_INVALID_ENUM
,
1447 "glTexImage(target/internalFormat)");
1452 /* additional checks for compressed textures */
1453 if (is_compressed_format(ctx
, internalFormat
)) {
1454 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1457 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1458 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1459 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1460 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1465 _mesa_error(ctx
, GL_INVALID_ENUM
,
1466 "glTexImage%d(target)", dimensions
);
1472 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1473 "glTexImage%D(border!=0)", dimensions
);
1479 /* if we get here, the parameters are OK */
1485 * Test glTexSubImage[123]D() parameters for errors.
1487 * \param ctx GL context.
1488 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1489 * \param target texture target given by the user.
1490 * \param level image level given by the user.
1491 * \param xoffset sub-image x offset given by the user.
1492 * \param yoffset sub-image y offset given by the user.
1493 * \param zoffset sub-image z offset given by the user.
1494 * \param format pixel data format given by the user.
1495 * \param type pixel data type given by the user.
1496 * \param width image width given by the user.
1497 * \param height image height given by the user.
1498 * \param depth image depth given by the user.
1500 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1502 * Verifies each of the parameters against the constants specified in
1503 * __GLcontextRec::Const and the supported extensions, and according to the
1504 * OpenGL specification.
1507 subtexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1508 GLenum target
, GLint level
,
1509 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1510 GLint width
, GLint height
, GLint depth
,
1511 GLenum format
, GLenum type
)
1513 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1514 struct gl_texture_image
*destTex
;
1517 if (dimensions
== 1) {
1518 if (target
!= GL_TEXTURE_1D
) {
1519 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
1523 else if (dimensions
== 2) {
1524 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1525 target
<=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1526 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1527 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1531 else if (ctx
->Extensions
.NV_texture_rectangle
&&
1532 target
== GL_TEXTURE_RECTANGLE_NV
) {
1533 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1534 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1538 else if (target
!= GL_TEXTURE_2D
) {
1539 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1543 else if (dimensions
== 3) {
1544 if (target
!= GL_TEXTURE_3D
) {
1545 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
1550 _mesa_problem( ctx
, "invalid dims in texture_error_check" );
1554 /* Basic level check */
1555 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1556 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level=%d)", level
);
1561 _mesa_error(ctx
, GL_INVALID_VALUE
,
1562 "glTexSubImage%dD(width=%d)", dimensions
, width
);
1565 if (height
< 0 && dimensions
> 1) {
1566 _mesa_error(ctx
, GL_INVALID_VALUE
,
1567 "glTexSubImage%dD(height=%d)", dimensions
, height
);
1570 if (depth
< 0 && dimensions
> 2) {
1571 _mesa_error(ctx
, GL_INVALID_VALUE
,
1572 "glTexSubImage%dD(depth=%d)", dimensions
, depth
);
1576 destTex
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1579 /* undefined image level */
1580 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage%dD", dimensions
);
1584 if (xoffset
< -((GLint
)destTex
->Border
)) {
1585 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset)",
1589 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
1590 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset+width)",
1594 if (dimensions
> 1) {
1595 if (yoffset
< -((GLint
)destTex
->Border
)) {
1596 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset)",
1600 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
1601 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset+height)",
1606 if (dimensions
> 2) {
1607 if (zoffset
< -((GLint
)destTex
->Border
)) {
1608 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
1611 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+ destTex
->Border
)) {
1612 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
1617 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
1618 _mesa_error(ctx
, GL_INVALID_ENUM
,
1619 "glTexSubImage%dD(format or type)", dimensions
);
1623 if (destTex
->IsCompressed
) {
1624 const struct gl_texture_unit
*texUnit
;
1625 const struct gl_texture_image
*texImage
;
1626 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1627 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1629 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1632 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1633 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1634 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1635 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1639 _mesa_error(ctx
, GL_INVALID_ENUM
,
1640 "glTexSubImage%D(target)", dimensions
);
1643 /* offset must be multiple of 4 */
1644 if ((xoffset
& 3) || (yoffset
& 3)) {
1645 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1646 "glTexSubImage%D(xoffset or yoffset)", dimensions
);
1649 /* size must be multiple of 4 or equal to whole texture size */
1650 if ((width
& 3) && (GLuint
) width
!= texImage
->Width
) {
1651 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1652 "glTexSubImage%D(width)", dimensions
);
1655 if ((height
& 3) && (GLuint
) height
!= texImage
->Height
) {
1656 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1657 "glTexSubImage%D(width)", dimensions
);
1667 * Test glCopyTexImage[12]D() parameters for errors.
1669 * \param ctx GL context.
1670 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1671 * \param target texture target given by the user.
1672 * \param level image level given by the user.
1673 * \param internalFormat internal format given by the user.
1674 * \param width image width given by the user.
1675 * \param height image height given by the user.
1676 * \param depth image depth given by the user.
1677 * \param border texture border.
1679 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1681 * Verifies each of the parameters against the constants specified in
1682 * __GLcontextRec::Const and the supported extensions, and according to the
1683 * OpenGL specification.
1686 copytexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1687 GLenum target
, GLint level
, GLint internalFormat
,
1688 GLint width
, GLint height
, GLint border
)
1690 GLenum format
, type
;
1693 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1694 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1695 _mesa_error(ctx
, GL_INVALID_VALUE
,
1696 "glCopyTexImage%dD(level=%d)", dimensions
, level
);
1701 if (border
< 0 || border
> 1 ||
1702 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1703 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1707 /* The format and type aren't really significant here, but we need to pass
1708 * something to TestProxyTexImage().
1710 format
= _mesa_base_tex_format(ctx
, internalFormat
);
1713 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1714 * level, width, height and depth.
1716 if (dimensions
== 1) {
1717 if (target
== GL_TEXTURE_1D
) {
1718 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1719 level
, internalFormat
,
1721 width
, 1, 1, border
);
1724 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
1728 else if (dimensions
== 2) {
1729 if (target
== GL_TEXTURE_2D
) {
1730 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1731 level
, internalFormat
,
1733 width
, height
, 1, border
);
1735 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1736 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1737 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1738 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1741 sizeOK
= (width
== height
) &&
1742 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1743 level
, internalFormat
, format
, type
,
1744 width
, height
, 1, border
);
1746 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1747 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1748 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1751 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1752 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1753 level
, internalFormat
,
1755 width
, height
, 1, border
);
1758 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1763 _mesa_problem(ctx
, "invalid dimensions in copytexture_error_check");
1768 if (dimensions
== 1) {
1769 _mesa_error(ctx
, GL_INVALID_VALUE
,
1770 "glCopyTexImage1D(width=%d)", width
);
1773 ASSERT(dimensions
== 2);
1774 _mesa_error(ctx
, GL_INVALID_VALUE
,
1775 "glCopyTexImage2D(width=%d, height=%d)", width
, height
);
1780 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1781 _mesa_error(ctx
, GL_INVALID_VALUE
,
1782 "glCopyTexImage%dD(internalFormat)", dimensions
);
1786 if (is_compressed_format(ctx
, internalFormat
)) {
1787 if (target
!= GL_TEXTURE_2D
) {
1788 _mesa_error(ctx
, GL_INVALID_ENUM
,
1789 "glCopyTexImage%d(target)", dimensions
);
1793 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1794 "glCopyTexImage%D(border!=0)", dimensions
);
1799 /* if we get here, the parameters are OK */
1805 * Test glCopyTexImage[12]D() parameters for errors.
1807 * \param ctx GL context.
1808 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1809 * \param target texture target given by the user.
1810 * \param level image level given by the user.
1811 * \param xoffset sub-image x offset given by the user.
1812 * \param yoffset sub-image y offset given by the user.
1813 * \param zoffset sub-image z offset given by the user.
1814 * \param width image width given by the user.
1815 * \param height image height given by the user.
1817 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1819 * Verifies each of the parameters against the constants specified in
1820 * __GLcontextRec::Const and the supported extensions, and according to the
1821 * OpenGL specification.
1824 copytexsubimage_error_check( GLcontext
*ctx
, GLuint dimensions
,
1825 GLenum target
, GLint level
,
1826 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1827 GLsizei width
, GLsizei height
)
1829 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1830 struct gl_texture_image
*teximage
;
1833 if (dimensions
== 1) {
1834 if (target
!= GL_TEXTURE_1D
) {
1835 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
1839 else if (dimensions
== 2) {
1840 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1841 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1842 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1843 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1847 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1848 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1849 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1853 else if (target
!= GL_TEXTURE_2D
) {
1854 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1858 else if (dimensions
== 3) {
1859 if (target
!= GL_TEXTURE_3D
) {
1860 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
1866 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1867 _mesa_error(ctx
, GL_INVALID_VALUE
,
1868 "glCopyTexSubImage%dD(level=%d)", dimensions
, level
);
1874 _mesa_error(ctx
, GL_INVALID_VALUE
,
1875 "glCopyTexSubImage%dD(width=%d)", dimensions
, width
);
1878 if (dimensions
> 1 && height
< 0) {
1879 _mesa_error(ctx
, GL_INVALID_VALUE
,
1880 "glCopyTexSubImage%dD(height=%d)", dimensions
, height
);
1884 teximage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1886 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1887 "glCopyTexSubImage%dD(undefined texture level: %d)",
1892 if (xoffset
< -((GLint
)teximage
->Border
)) {
1893 _mesa_error(ctx
, GL_INVALID_VALUE
,
1894 "glCopyTexSubImage%dD(xoffset=%d)", dimensions
, xoffset
);
1897 if (xoffset
+ width
> (GLint
) (teximage
->Width
+ teximage
->Border
)) {
1898 _mesa_error(ctx
, GL_INVALID_VALUE
,
1899 "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
1902 if (dimensions
> 1) {
1903 if (yoffset
< -((GLint
)teximage
->Border
)) {
1904 _mesa_error(ctx
, GL_INVALID_VALUE
,
1905 "glCopyTexSubImage%dD(yoffset=%d)", dimensions
, yoffset
);
1908 /* NOTE: we're adding the border here, not subtracting! */
1909 if (yoffset
+ height
> (GLint
) (teximage
->Height
+ teximage
->Border
)) {
1910 _mesa_error(ctx
, GL_INVALID_VALUE
,
1911 "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
1916 if (dimensions
> 2) {
1917 if (zoffset
< -((GLint
)teximage
->Border
)) {
1918 _mesa_error(ctx
, GL_INVALID_VALUE
,
1919 "glCopyTexSubImage%dD(zoffset)", dimensions
);
1922 if (zoffset
> (GLint
) (teximage
->Depth
+ teximage
->Border
)) {
1923 _mesa_error(ctx
, GL_INVALID_VALUE
,
1924 "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
1929 if (teximage
->IsCompressed
) {
1930 if (target
!= GL_TEXTURE_2D
) {
1931 _mesa_error(ctx
, GL_INVALID_ENUM
,
1932 "glCopyTexSubImage%d(target)", dimensions
);
1935 /* offset must be multiple of 4 */
1936 if ((xoffset
& 3) || (yoffset
& 3)) {
1937 _mesa_error(ctx
, GL_INVALID_VALUE
,
1938 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions
);
1941 /* size must be multiple of 4 */
1942 if ((width
& 3) != 0 && (GLuint
) width
!= teximage
->Width
) {
1943 _mesa_error(ctx
, GL_INVALID_VALUE
,
1944 "glCopyTexSubImage%D(width)", dimensions
);
1947 if ((height
& 3) != 0 && (GLuint
) height
!= teximage
->Height
) {
1948 _mesa_error(ctx
, GL_INVALID_VALUE
,
1949 "glCopyTexSubImage%D(height)", dimensions
);
1954 if (teximage
->IntFormat
== GL_YCBCR_MESA
) {
1955 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glCopyTexSubImage2D");
1959 /* if we get here, the parameters are OK */
1965 * Get texture image. Called by glGetTexImage.
1967 * \param target texture target.
1968 * \param level image level.
1969 * \param format pixel data format for returned image.
1970 * \param type pixel data type for returned image.
1971 * \param pixels returned pixel data.
1974 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
1975 GLenum type
, GLvoid
*pixels
)
1977 const struct gl_texture_unit
*texUnit
;
1978 const struct gl_texture_object
*texObj
;
1979 const struct gl_texture_image
*texImage
;
1980 GLint maxLevels
= 0;
1981 GET_CURRENT_CONTEXT(ctx
);
1982 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
1984 texUnit
= &(ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
]);
1985 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
1986 if (!texObj
|| is_proxy_target(target
)) {
1987 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)");
1991 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
1992 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
1994 if (level
< 0 || level
>= maxLevels
) {
1995 _mesa_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
1999 if (_mesa_sizeof_packed_type(type
) <= 0) {
2000 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
2004 if (_mesa_components_in_format(format
) <= 0 ||
2005 format
== GL_STENCIL_INDEX
) {
2006 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
2010 if (!ctx
->Extensions
.EXT_paletted_texture
&& is_index_format(format
)) {
2011 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2014 if (!ctx
->Extensions
.SGIX_depth_texture
&&
2015 !ctx
->Extensions
.ARB_depth_texture
&& is_depth_format(format
)) {
2016 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2019 if (!ctx
->Extensions
.MESA_ycbcr_texture
&& is_ycbcr_format(format
)) {
2020 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2023 if (!ctx
->Extensions
.EXT_packed_depth_stencil
2024 && is_depthstencil_format(format
)) {
2025 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2031 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2033 /* invalid mipmap level, not an error */
2037 /* Make sure the requested image format is compatible with the
2038 * texture's format. We let the colorformat-indexformat go through,
2039 * because the texelfetcher will dequantize to full rgba.
2041 if (is_color_format(format
)
2042 && !is_color_format(texImage
->TexFormat
->BaseFormat
)
2043 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
2044 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2047 else if (is_index_format(format
)
2048 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
2049 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2052 else if (is_depth_format(format
)
2053 && !is_depth_format(texImage
->TexFormat
->BaseFormat
)) {
2054 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2057 else if (is_ycbcr_format(format
)
2058 && !is_ycbcr_format(texImage
->TexFormat
->BaseFormat
)) {
2059 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2062 else if (is_depthstencil_format(format
)
2063 && !is_depthstencil_format(texImage
->TexFormat
->BaseFormat
)) {
2064 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2068 /* typically, this will call _mesa_get_teximage() */
2069 ctx
->Driver
.GetTexImage(ctx
, target
, level
, format
, type
, pixels
,
2076 * Called from the API. Note that width includes the border.
2079 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalFormat
,
2080 GLsizei width
, GLint border
, GLenum format
,
2081 GLenum type
, const GLvoid
*pixels
)
2083 GLsizei postConvWidth
= width
;
2084 GET_CURRENT_CONTEXT(ctx
);
2085 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2087 if (is_color_format(internalFormat
)) {
2088 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2091 if (target
== GL_TEXTURE_1D
) {
2092 /* non-proxy target */
2093 struct gl_texture_unit
*texUnit
;
2094 struct gl_texture_object
*texObj
;
2095 struct gl_texture_image
*texImage
;
2097 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2098 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2099 return; /* error was recorded */
2102 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2103 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2104 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2107 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2110 else if (texImage
->Data
) {
2111 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2113 ASSERT(texImage
->Data
== NULL
);
2114 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2115 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2116 postConvWidth
, 1, 1,
2117 border
, internalFormat
);
2119 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2120 _mesa_update_state(ctx
);
2122 ASSERT(ctx
->Driver
.TexImage1D
);
2124 /* Give the texture to the driver! <pixels> may be null! */
2125 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
2126 width
, border
, format
, type
, pixels
,
2127 &ctx
->Unpack
, texObj
, texImage
);
2129 ASSERT(texImage
->TexFormat
);
2132 texObj
->Complete
= GL_FALSE
;
2133 ctx
->NewState
|= _NEW_TEXTURE
;
2135 else if (target
== GL_PROXY_TEXTURE_1D
) {
2136 /* Proxy texture: check for errors and update proxy state */
2137 struct gl_texture_image
*texImage
;
2138 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2139 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2140 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2141 /* when error, clear all proxy texture image parameters */
2143 clear_teximage_fields(texImage
);
2146 /* no error, set the tex image parameters */
2148 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2149 postConvWidth
, 1, 1,
2150 border
, internalFormat
);
2151 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2152 internalFormat
, format
, type
);
2156 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
2163 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalFormat
,
2164 GLsizei width
, GLsizei height
, GLint border
,
2165 GLenum format
, GLenum type
,
2166 const GLvoid
*pixels
)
2168 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2169 GET_CURRENT_CONTEXT(ctx
);
2170 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2172 if (is_color_format(internalFormat
)) {
2173 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2177 if (target
== GL_TEXTURE_2D
||
2178 (ctx
->Extensions
.ARB_texture_cube_map
&&
2179 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2180 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) ||
2181 (ctx
->Extensions
.NV_texture_rectangle
&&
2182 target
== GL_TEXTURE_RECTANGLE_NV
)) {
2183 /* non-proxy target */
2184 struct gl_texture_unit
*texUnit
;
2185 struct gl_texture_object
*texObj
;
2186 struct gl_texture_image
*texImage
;
2188 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2189 format
, type
, 2, postConvWidth
, postConvHeight
,
2191 return; /* error was recorded */
2194 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2195 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2196 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2198 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2201 else if (texImage
->Data
) {
2202 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2204 ASSERT(texImage
->Data
== NULL
);
2205 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2206 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2207 postConvWidth
, postConvHeight
, 1,
2208 border
, internalFormat
);
2210 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2211 _mesa_update_state(ctx
);
2213 ASSERT(ctx
->Driver
.TexImage2D
);
2215 /* Give the texture to the driver! <pixels> may be null! */
2216 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
2217 width
, height
, border
, format
, type
, pixels
,
2218 &ctx
->Unpack
, texObj
, texImage
);
2220 ASSERT(texImage
->TexFormat
);
2223 texObj
->Complete
= GL_FALSE
;
2224 ctx
->NewState
|= _NEW_TEXTURE
;
2226 else if (target
== GL_PROXY_TEXTURE_2D
||
2227 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2228 ctx
->Extensions
.ARB_texture_cube_map
) ||
2229 (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
&&
2230 ctx
->Extensions
.NV_texture_rectangle
)) {
2231 /* Proxy texture: check for errors and update proxy state */
2232 struct gl_texture_image
*texImage
;
2233 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2234 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2235 format
, type
, 2, postConvWidth
, postConvHeight
,
2237 /* when error, clear all proxy texture image parameters */
2239 clear_teximage_fields(ctx
->Texture
.Proxy2D
->Image
[0][level
]);
2242 /* no error, set the tex image parameters */
2243 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2244 postConvWidth
, postConvHeight
, 1,
2245 border
, internalFormat
);
2246 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2247 internalFormat
, format
, type
);
2251 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
2258 * Called by the API or display list executor.
2259 * Note that width and height include the border.
2262 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalFormat
,
2263 GLsizei width
, GLsizei height
, GLsizei depth
,
2264 GLint border
, GLenum format
, GLenum type
,
2265 const GLvoid
*pixels
)
2267 GET_CURRENT_CONTEXT(ctx
);
2268 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2270 if (target
== GL_TEXTURE_3D
) {
2271 struct gl_texture_unit
*texUnit
;
2272 struct gl_texture_object
*texObj
;
2273 struct gl_texture_image
*texImage
;
2274 /* non-proxy target */
2276 if (texture_error_check(ctx
, target
, level
, (GLint
) internalFormat
,
2277 format
, type
, 3, width
, height
, depth
, border
)) {
2278 return; /* error was recorded */
2281 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2282 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2283 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2285 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2288 else if (texImage
->Data
) {
2289 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2291 ASSERT(texImage
->Data
== NULL
);
2292 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2293 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2294 width
, height
, depth
,
2295 border
, internalFormat
);
2297 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2298 _mesa_update_state(ctx
);
2300 ASSERT(ctx
->Driver
.TexImage3D
);
2302 /* Give the texture to the driver! <pixels> may be null! */
2303 (*ctx
->Driver
.TexImage3D
)(ctx
, target
, level
, internalFormat
,
2304 width
, height
, depth
, border
, format
, type
,
2305 pixels
, &ctx
->Unpack
, texObj
, texImage
);
2307 ASSERT(texImage
->TexFormat
);
2310 texObj
->Complete
= GL_FALSE
;
2311 ctx
->NewState
|= _NEW_TEXTURE
;
2313 else if (target
== GL_PROXY_TEXTURE_3D
) {
2314 /* Proxy texture: check for errors and update proxy state */
2315 struct gl_texture_image
*texImage
;
2316 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2317 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2318 format
, type
, 3, width
, height
, depth
, border
)) {
2319 /* when error, clear all proxy texture image parameters */
2321 clear_teximage_fields(texImage
);
2324 /* no error, set the tex image parameters */
2325 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2326 border
, internalFormat
);
2327 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2328 internalFormat
, format
, type
);
2332 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
2339 _mesa_TexImage3DEXT( GLenum target
, GLint level
, GLenum internalFormat
,
2340 GLsizei width
, GLsizei height
, GLsizei depth
,
2341 GLint border
, GLenum format
, GLenum type
,
2342 const GLvoid
*pixels
)
2344 _mesa_TexImage3D(target
, level
, (GLint
) internalFormat
, width
, height
,
2345 depth
, border
, format
, type
, pixels
);
2351 _mesa_TexSubImage1D( GLenum target
, GLint level
,
2352 GLint xoffset
, GLsizei width
,
2353 GLenum format
, GLenum type
,
2354 const GLvoid
*pixels
)
2356 GLsizei postConvWidth
= width
;
2357 struct gl_texture_unit
*texUnit
;
2358 struct gl_texture_object
*texObj
;
2359 struct gl_texture_image
*texImage
;
2360 GET_CURRENT_CONTEXT(ctx
);
2361 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2363 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2364 _mesa_update_state(ctx
);
2366 /* XXX should test internal format */
2367 if (is_color_format(format
)) {
2368 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2371 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
2372 postConvWidth
, 1, 1, format
, type
)) {
2373 return; /* error was detected */
2376 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2377 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2378 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2382 return; /* no-op, not an error */
2384 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2385 xoffset
+= texImage
->Border
;
2387 ASSERT(ctx
->Driver
.TexSubImage1D
);
2388 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
2389 format
, type
, pixels
, &ctx
->Unpack
,
2391 ctx
->NewState
|= _NEW_TEXTURE
;
2396 _mesa_TexSubImage2D( GLenum target
, GLint level
,
2397 GLint xoffset
, GLint yoffset
,
2398 GLsizei width
, GLsizei height
,
2399 GLenum format
, GLenum type
,
2400 const GLvoid
*pixels
)
2402 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2403 struct gl_texture_unit
*texUnit
;
2404 struct gl_texture_object
*texObj
;
2405 struct gl_texture_image
*texImage
;
2406 GET_CURRENT_CONTEXT(ctx
);
2407 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2409 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2410 _mesa_update_state(ctx
);
2412 /* XXX should test internal format */
2413 if (is_color_format(format
)) {
2414 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2418 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2419 postConvWidth
, postConvHeight
, 1, format
, type
)) {
2420 return; /* error was detected */
2423 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2424 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2425 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2428 if (width
== 0 || height
== 0)
2429 return; /* no-op, not an error */
2431 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2432 xoffset
+= texImage
->Border
;
2433 yoffset
+= texImage
->Border
;
2435 ASSERT(ctx
->Driver
.TexSubImage2D
);
2436 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
, xoffset
, yoffset
,
2437 width
, height
, format
, type
, pixels
,
2438 &ctx
->Unpack
, texObj
, texImage
);
2439 ctx
->NewState
|= _NEW_TEXTURE
;
2445 _mesa_TexSubImage3D( GLenum target
, GLint level
,
2446 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2447 GLsizei width
, GLsizei height
, GLsizei depth
,
2448 GLenum format
, GLenum type
,
2449 const GLvoid
*pixels
)
2451 struct gl_texture_unit
*texUnit
;
2452 struct gl_texture_object
*texObj
;
2453 struct gl_texture_image
*texImage
;
2454 GET_CURRENT_CONTEXT(ctx
);
2455 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2457 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2458 _mesa_update_state(ctx
);
2460 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2461 width
, height
, depth
, format
, type
)) {
2462 return; /* error was detected */
2465 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2466 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2467 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2470 if (width
== 0 || height
== 0 || height
== 0)
2471 return; /* no-op, not an error */
2473 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2474 xoffset
+= texImage
->Border
;
2475 yoffset
+= texImage
->Border
;
2476 zoffset
+= texImage
->Border
;
2478 ASSERT(ctx
->Driver
.TexSubImage3D
);
2479 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
2480 xoffset
, yoffset
, zoffset
,
2481 width
, height
, depth
,
2482 format
, type
, pixels
,
2483 &ctx
->Unpack
, texObj
, texImage
);
2484 ctx
->NewState
|= _NEW_TEXTURE
;
2490 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
2491 GLenum internalFormat
,
2493 GLsizei width
, GLint border
)
2495 struct gl_texture_unit
*texUnit
;
2496 struct gl_texture_object
*texObj
;
2497 struct gl_texture_image
*texImage
;
2498 GLsizei postConvWidth
= width
;
2499 GET_CURRENT_CONTEXT(ctx
);
2500 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2502 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2503 _mesa_update_state(ctx
);
2505 if (is_color_format(internalFormat
)) {
2506 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2509 if (copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
2510 postConvWidth
, 1, border
))
2513 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2514 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2515 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2517 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
2520 else if (texImage
->Data
) {
2521 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2523 ASSERT(texImage
->Data
== NULL
);
2525 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2526 _mesa_init_teximage_fields(ctx
, target
, texImage
, postConvWidth
, 1, 1,
2527 border
, internalFormat
);
2530 ASSERT(ctx
->Driver
.CopyTexImage1D
);
2531 (*ctx
->Driver
.CopyTexImage1D
)(ctx
, target
, level
, internalFormat
,
2532 x
, y
, width
, border
);
2534 ASSERT(texImage
->TexFormat
);
2537 texObj
->Complete
= GL_FALSE
;
2538 ctx
->NewState
|= _NEW_TEXTURE
;
2544 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
2545 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2548 struct gl_texture_unit
*texUnit
;
2549 struct gl_texture_object
*texObj
;
2550 struct gl_texture_image
*texImage
;
2551 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2552 GET_CURRENT_CONTEXT(ctx
);
2553 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2555 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2556 _mesa_update_state(ctx
);
2558 if (is_color_format(internalFormat
)) {
2559 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2563 if (copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
2564 postConvWidth
, postConvHeight
, border
))
2567 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2568 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2569 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2571 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
2574 else if (texImage
->Data
) {
2575 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2577 ASSERT(texImage
->Data
== NULL
);
2579 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2580 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2581 postConvWidth
, postConvHeight
, 1,
2582 border
, internalFormat
);
2584 ASSERT(ctx
->Driver
.CopyTexImage2D
);
2585 (*ctx
->Driver
.CopyTexImage2D
)(ctx
, target
, level
, internalFormat
,
2586 x
, y
, width
, height
, border
);
2588 ASSERT(texImage
->TexFormat
);
2591 texObj
->Complete
= GL_FALSE
;
2592 ctx
->NewState
|= _NEW_TEXTURE
;
2598 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
2599 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
2601 struct gl_texture_unit
*texUnit
;
2602 struct gl_texture_image
*texImage
;
2603 GLsizei postConvWidth
= width
;
2604 GET_CURRENT_CONTEXT(ctx
);
2605 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2607 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2608 _mesa_update_state(ctx
);
2610 /* XXX should test internal format */
2611 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2613 if (copytexsubimage_error_check(ctx
, 1, target
, level
,
2614 xoffset
, 0, 0, postConvWidth
, 1))
2617 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2618 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2621 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2622 xoffset
+= texImage
->Border
;
2624 ASSERT(ctx
->Driver
.CopyTexSubImage1D
);
2625 (*ctx
->Driver
.CopyTexSubImage1D
)(ctx
, target
, level
, xoffset
, x
, y
, width
);
2626 ctx
->NewState
|= _NEW_TEXTURE
;
2632 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
2633 GLint xoffset
, GLint yoffset
,
2634 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2636 struct gl_texture_unit
*texUnit
;
2637 struct gl_texture_image
*texImage
;
2638 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2639 GET_CURRENT_CONTEXT(ctx
);
2640 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2642 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2643 _mesa_update_state(ctx
);
2645 /* XXX should test internal format */
2646 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2648 if (copytexsubimage_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2649 postConvWidth
, postConvHeight
))
2652 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2653 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2656 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2657 xoffset
+= texImage
->Border
;
2658 yoffset
+= texImage
->Border
;
2660 ASSERT(ctx
->Driver
.CopyTexSubImage2D
);
2661 (*ctx
->Driver
.CopyTexSubImage2D
)(ctx
, target
, level
,
2662 xoffset
, yoffset
, x
, y
, width
, height
);
2663 ctx
->NewState
|= _NEW_TEXTURE
;
2669 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
2670 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2671 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2673 struct gl_texture_unit
*texUnit
;
2674 struct gl_texture_image
*texImage
;
2675 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2676 GET_CURRENT_CONTEXT(ctx
);
2677 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2679 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2680 _mesa_update_state(ctx
);
2682 /* XXX should test internal format */
2683 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2685 if (copytexsubimage_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
,
2686 zoffset
, postConvWidth
, postConvHeight
))
2689 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2690 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2693 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2694 xoffset
+= texImage
->Border
;
2695 yoffset
+= texImage
->Border
;
2696 zoffset
+= texImage
->Border
;
2698 ASSERT(ctx
->Driver
.CopyTexSubImage3D
);
2699 (*ctx
->Driver
.CopyTexSubImage3D
)(ctx
, target
, level
,
2700 xoffset
, yoffset
, zoffset
,
2701 x
, y
, width
, height
);
2702 ctx
->NewState
|= _NEW_TEXTURE
;
2708 /**********************************************************************/
2709 /****** Compressed Textures ******/
2710 /**********************************************************************/
2714 * Error checking for glCompressedTexImage[123]D().
2715 * \return error code or GL_NO_ERROR.
2718 compressed_texture_error_check(GLcontext
*ctx
, GLint dimensions
,
2719 GLenum target
, GLint level
,
2720 GLenum internalFormat
, GLsizei width
,
2721 GLsizei height
, GLsizei depth
, GLint border
,
2724 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2726 if (dimensions
== 1) {
2727 /* 1D compressed textures not allowed */
2728 return GL_INVALID_ENUM
;
2730 else if (dimensions
== 2) {
2731 if (target
== GL_PROXY_TEXTURE_2D
) {
2732 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2734 else if (target
== GL_TEXTURE_2D
) {
2735 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2737 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2738 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2739 return GL_INVALID_ENUM
; /*target*/
2740 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2742 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2743 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2744 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2745 return GL_INVALID_ENUM
; /*target*/
2746 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2749 return GL_INVALID_ENUM
; /*target*/
2752 else if (dimensions
== 3) {
2753 /* 3D compressed textures not allowed */
2754 return GL_INVALID_ENUM
;
2757 maxTextureSize
= 1 << (maxLevels
- 1);
2759 if (!is_compressed_format(ctx
, internalFormat
))
2760 return GL_INVALID_ENUM
;
2762 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0)
2763 return GL_INVALID_ENUM
;
2766 return GL_INVALID_VALUE
;
2769 * XXX We should probably use the proxy texture error check function here.
2771 if (width
< 1 || width
> maxTextureSize
||
2772 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(width
) != 1))
2773 return GL_INVALID_VALUE
;
2775 if ((height
< 1 || height
> maxTextureSize
||
2776 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(height
) != 1))
2778 return GL_INVALID_VALUE
;
2780 if ((depth
< 1 || depth
> maxTextureSize
||
2781 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(depth
) != 1))
2783 return GL_INVALID_VALUE
;
2785 /* For cube map, width must equal height */
2786 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2787 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
&& width
!= height
)
2788 return GL_INVALID_VALUE
;
2790 if (level
< 0 || level
>= maxLevels
)
2791 return GL_INVALID_VALUE
;
2793 expectedSize
= ctx
->Driver
.CompressedTextureSize(ctx
, width
, height
, depth
,
2795 if (expectedSize
!= imageSize
)
2796 return GL_INVALID_VALUE
;
2803 * Error checking for glCompressedTexSubImage[123]D().
2804 * \warning There are some bad assumptions here about the size of compressed
2805 * texture tiles (multiple of 4) used to test the validity of the
2806 * offset and size parameters.
2807 * \return error code or GL_NO_ERROR.
2810 compressed_subtexture_error_check(GLcontext
*ctx
, GLint dimensions
,
2811 GLenum target
, GLint level
,
2812 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2813 GLsizei width
, GLsizei height
, GLsizei depth
,
2814 GLenum format
, GLsizei imageSize
)
2816 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2819 if (dimensions
== 1) {
2820 /* 1D compressed textures not allowed */
2821 return GL_INVALID_ENUM
;
2823 else if (dimensions
== 2) {
2824 if (target
== GL_PROXY_TEXTURE_2D
) {
2825 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2827 else if (target
== GL_TEXTURE_2D
) {
2828 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2830 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2831 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2832 return GL_INVALID_ENUM
; /*target*/
2833 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2835 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2836 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2837 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2838 return GL_INVALID_ENUM
; /*target*/
2839 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2842 return GL_INVALID_ENUM
; /*target*/
2845 else if (dimensions
== 3) {
2846 /* 3D compressed textures not allowed */
2847 return GL_INVALID_ENUM
;
2850 maxTextureSize
= 1 << (maxLevels
- 1);
2852 if (!is_compressed_format(ctx
, format
))
2853 return GL_INVALID_ENUM
;
2855 if (width
< 1 || width
> maxTextureSize
)
2856 return GL_INVALID_VALUE
;
2858 if ((height
< 1 || height
> maxTextureSize
)
2860 return GL_INVALID_VALUE
;
2862 if (level
< 0 || level
>= maxLevels
)
2863 return GL_INVALID_VALUE
;
2865 /* XXX these tests are specific to the compressed format.
2866 * this code should be generalized in some way.
2868 if ((xoffset
& 3) != 0 || (yoffset
& 3) != 0)
2869 return GL_INVALID_VALUE
;
2871 if ((width
& 3) != 0 && width
!= 2 && width
!= 1)
2872 return GL_INVALID_VALUE
;
2874 if ((height
& 3) != 0 && height
!= 2 && height
!= 1)
2875 return GL_INVALID_VALUE
;
2877 expectedSize
= ctx
->Driver
.CompressedTextureSize(ctx
, width
, height
, depth
,
2879 if (expectedSize
!= imageSize
)
2880 return GL_INVALID_VALUE
;
2888 _mesa_CompressedTexImage1DARB(GLenum target
, GLint level
,
2889 GLenum internalFormat
, GLsizei width
,
2890 GLint border
, GLsizei imageSize
,
2893 GET_CURRENT_CONTEXT(ctx
);
2894 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2896 if (target
== GL_TEXTURE_1D
) {
2897 /* non-proxy target */
2898 struct gl_texture_unit
*texUnit
;
2899 struct gl_texture_object
*texObj
;
2900 struct gl_texture_image
*texImage
;
2901 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
2902 internalFormat
, width
, 1, 1, border
, imageSize
);
2904 _mesa_error(ctx
, error
, "glCompressedTexImage1D");
2908 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2909 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2910 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2912 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage1D");
2915 else if (texImage
->Data
) {
2916 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2918 ASSERT(texImage
->Data
== NULL
);
2920 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
2921 border
, internalFormat
);
2923 ASSERT(ctx
->Driver
.CompressedTexImage1D
);
2924 (*ctx
->Driver
.CompressedTexImage1D
)(ctx
, target
, level
,
2925 internalFormat
, width
, border
,
2930 texObj
->Complete
= GL_FALSE
;
2931 ctx
->NewState
|= _NEW_TEXTURE
;
2933 else if (target
== GL_PROXY_TEXTURE_1D
) {
2934 /* Proxy texture: check for errors and update proxy state */
2935 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
2936 internalFormat
, width
, 1, 1, border
, imageSize
);
2938 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2939 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2940 internalFormat
, GL_NONE
, GL_NONE
,
2941 width
, 1, 1, border
);
2944 /* if error, clear all proxy texture image parameters */
2945 struct gl_texture_image
*texImage
;
2946 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2948 clear_teximage_fields(texImage
);
2951 /* store the teximage parameters */
2952 struct gl_texture_unit
*texUnit
;
2953 struct gl_texture_image
*texImage
;
2954 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2955 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2956 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
2957 border
, internalFormat
);
2961 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage1D(target)");
2968 _mesa_CompressedTexImage2DARB(GLenum target
, GLint level
,
2969 GLenum internalFormat
, GLsizei width
,
2970 GLsizei height
, GLint border
, GLsizei imageSize
,
2973 GET_CURRENT_CONTEXT(ctx
);
2974 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2976 if (target
== GL_TEXTURE_2D
||
2977 (ctx
->Extensions
.ARB_texture_cube_map
&&
2978 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2979 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
2980 /* non-proxy target */
2981 struct gl_texture_unit
*texUnit
;
2982 struct gl_texture_object
*texObj
;
2983 struct gl_texture_image
*texImage
;
2984 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
2985 internalFormat
, width
, height
, 1, border
, imageSize
);
2987 _mesa_error(ctx
, error
, "glCompressedTexImage2D");
2991 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2992 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2993 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2995 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
2998 else if (texImage
->Data
) {
2999 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3001 ASSERT(texImage
->Data
== NULL
);
3003 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
3004 border
, internalFormat
);
3006 ASSERT(ctx
->Driver
.CompressedTexImage2D
);
3007 (*ctx
->Driver
.CompressedTexImage2D
)(ctx
, target
, level
,
3008 internalFormat
, width
, height
,
3009 border
, imageSize
, data
,
3013 texObj
->Complete
= GL_FALSE
;
3014 ctx
->NewState
|= _NEW_TEXTURE
;
3016 else if (target
== GL_PROXY_TEXTURE_2D
||
3017 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
3018 ctx
->Extensions
.ARB_texture_cube_map
)) {
3019 /* Proxy texture: check for errors and update proxy state */
3020 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
3021 internalFormat
, width
, height
, 1, border
, imageSize
);
3023 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3024 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3025 internalFormat
, GL_NONE
, GL_NONE
,
3026 width
, height
, 1, border
);
3029 /* if error, clear all proxy texture image parameters */
3030 struct gl_texture_image
*texImage
;
3031 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3033 clear_teximage_fields(texImage
);
3036 /* store the teximage parameters */
3037 struct gl_texture_unit
*texUnit
;
3038 struct gl_texture_image
*texImage
;
3039 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3040 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3041 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
3042 border
, internalFormat
);
3046 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(target)");
3053 _mesa_CompressedTexImage3DARB(GLenum target
, GLint level
,
3054 GLenum internalFormat
, GLsizei width
,
3055 GLsizei height
, GLsizei depth
, GLint border
,
3056 GLsizei imageSize
, const GLvoid
*data
)
3058 GET_CURRENT_CONTEXT(ctx
);
3059 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3061 if (target
== GL_TEXTURE_3D
) {
3062 /* non-proxy target */
3063 struct gl_texture_unit
*texUnit
;
3064 struct gl_texture_object
*texObj
;
3065 struct gl_texture_image
*texImage
;
3066 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3067 internalFormat
, width
, height
, depth
, border
, imageSize
);
3069 _mesa_error(ctx
, error
, "glCompressedTexImage3D");
3073 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3074 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3075 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
3077 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage3D");
3080 else if (texImage
->Data
) {
3081 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3083 ASSERT(texImage
->Data
== NULL
);
3085 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, depth
,
3086 border
, internalFormat
);
3088 ASSERT(ctx
->Driver
.CompressedTexImage3D
);
3089 (*ctx
->Driver
.CompressedTexImage3D
)(ctx
, target
, level
,
3091 width
, height
, depth
,
3092 border
, imageSize
, data
,
3096 texObj
->Complete
= GL_FALSE
;
3097 ctx
->NewState
|= _NEW_TEXTURE
;
3099 else if (target
== GL_PROXY_TEXTURE_3D
) {
3100 /* Proxy texture: check for errors and update proxy state */
3101 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3102 internalFormat
, width
, height
, depth
, border
, imageSize
);
3104 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3105 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3106 internalFormat
, GL_NONE
, GL_NONE
,
3107 width
, height
, depth
, border
);
3110 /* if error, clear all proxy texture image parameters */
3111 struct gl_texture_image
*texImage
;
3112 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3114 clear_teximage_fields(texImage
);
3117 /* store the teximage parameters */
3118 struct gl_texture_unit
*texUnit
;
3119 struct gl_texture_image
*texImage
;
3120 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3121 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3122 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
,
3123 depth
, border
, internalFormat
);
3127 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage3D(target)");
3134 _mesa_CompressedTexSubImage1DARB(GLenum target
, GLint level
, GLint xoffset
,
3135 GLsizei width
, GLenum format
,
3136 GLsizei imageSize
, const GLvoid
*data
)
3138 struct gl_texture_unit
*texUnit
;
3139 struct gl_texture_object
*texObj
;
3140 struct gl_texture_image
*texImage
;
3142 GET_CURRENT_CONTEXT(ctx
);
3143 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3145 error
= compressed_subtexture_error_check(ctx
, 1, target
, level
,
3146 xoffset
, 0, 0, width
, 1, 1, format
, imageSize
);
3148 _mesa_error(ctx
, error
, "glCompressedTexSubImage1D");
3152 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3153 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3154 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3157 if ((GLint
) format
!= texImage
->IntFormat
) {
3158 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3159 "glCompressedTexSubImage1D(format)");
3163 if ((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) {
3164 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage1D(width)");
3169 return; /* no-op, not an error */
3171 if (ctx
->Driver
.CompressedTexSubImage1D
) {
3172 (*ctx
->Driver
.CompressedTexSubImage1D
)(ctx
, target
, level
,
3174 format
, imageSize
, data
,
3177 ctx
->NewState
|= _NEW_TEXTURE
;
3182 _mesa_CompressedTexSubImage2DARB(GLenum target
, GLint level
, GLint xoffset
,
3183 GLint yoffset
, GLsizei width
, GLsizei height
,
3184 GLenum format
, GLsizei imageSize
,
3187 struct gl_texture_unit
*texUnit
;
3188 struct gl_texture_object
*texObj
;
3189 struct gl_texture_image
*texImage
;
3191 GET_CURRENT_CONTEXT(ctx
);
3192 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3194 error
= compressed_subtexture_error_check(ctx
, 2, target
, level
,
3195 xoffset
, yoffset
, 0, width
, height
, 1, format
, imageSize
);
3197 /* XXX proxy target? */
3198 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3202 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3203 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3204 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3207 if ((GLint
) format
!= texImage
->IntFormat
) {
3208 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3209 "glCompressedTexSubImage2D(format)");
3213 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3214 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
)) {
3215 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage2D(size)");
3219 if (width
== 0 || height
== 0)
3220 return; /* no-op, not an error */
3222 if (ctx
->Driver
.CompressedTexSubImage2D
) {
3223 (*ctx
->Driver
.CompressedTexSubImage2D
)(ctx
, target
, level
,
3224 xoffset
, yoffset
, width
, height
,
3225 format
, imageSize
, data
,
3228 ctx
->NewState
|= _NEW_TEXTURE
;
3233 _mesa_CompressedTexSubImage3DARB(GLenum target
, GLint level
, GLint xoffset
,
3234 GLint yoffset
, GLint zoffset
, GLsizei width
,
3235 GLsizei height
, GLsizei depth
, GLenum format
,
3236 GLsizei imageSize
, const GLvoid
*data
)
3238 struct gl_texture_unit
*texUnit
;
3239 struct gl_texture_object
*texObj
;
3240 struct gl_texture_image
*texImage
;
3242 GET_CURRENT_CONTEXT(ctx
);
3243 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3245 error
= compressed_subtexture_error_check(ctx
, 3, target
, level
,
3246 xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
, imageSize
);
3248 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3252 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3253 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3254 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3257 if ((GLint
) format
!= texImage
->IntFormat
) {
3258 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3259 "glCompressedTexSubImage3D(format)");
3263 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3264 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
) ||
3265 ((depth
== 1 || depth
== 2) && (GLuint
) depth
!= texImage
->Depth
)) {
3266 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage3D(size)");
3270 if (width
== 0 || height
== 0 || depth
== 0)
3271 return; /* no-op, not an error */
3273 if (ctx
->Driver
.CompressedTexSubImage3D
) {
3274 (*ctx
->Driver
.CompressedTexSubImage3D
)(ctx
, target
, level
,
3275 xoffset
, yoffset
, zoffset
,
3276 width
, height
, depth
,
3277 format
, imageSize
, data
,
3280 ctx
->NewState
|= _NEW_TEXTURE
;
3285 _mesa_GetCompressedTexImageARB(GLenum target
, GLint level
, GLvoid
*img
)
3287 const struct gl_texture_unit
*texUnit
;
3288 const struct gl_texture_object
*texObj
;
3289 struct gl_texture_image
*texImage
;
3291 GET_CURRENT_CONTEXT(ctx
);
3292 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3294 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3295 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3297 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB");
3301 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
3302 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
3304 if (level
< 0 || level
>= maxLevels
) {
3305 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3309 if (is_proxy_target(target
)) {
3310 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
3314 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3316 /* probably invalid mipmap level */
3317 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3321 if (!texImage
->IsCompressed
) {
3322 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetCompressedTexImageARB");
3326 /* this typically calls _mesa_get_compressed_teximage() */
3327 ctx
->Driver
.GetCompressedTexImage(ctx
, target
, level
, img
, texObj
,texImage
);