2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 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"
39 #include "framebuffer.h"
44 #include "texcompress.h"
45 #include "texformat.h"
53 * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
57 _mesa_alloc_texmemory(GLsizei bytes
)
59 return _mesa_align_malloc(bytes
, 512);
64 * Free texture memory allocated with _mesa_alloc_texmemory()
67 _mesa_free_texmemory(void *m
)
76 static void PrintTexture(GLcontext
*ctx
, const struct gl_texture_image
*img
)
78 #if CHAN_TYPE != GL_UNSIGNED_BYTE
79 _mesa_problem(NULL
, "PrintTexture not supported");
82 const GLubyte
*data
= (const GLubyte
*) img
->Data
;
85 _mesa_printf("No texture data\n");
89 switch (img
->Format
) {
96 case GL_LUMINANCE_ALPHA
:
106 _mesa_problem(NULL
, "error in PrintTexture\n");
110 for (i
= 0; i
< img
->Height
; i
++) {
111 for (j
= 0; j
< img
->Width
; j
++) {
113 _mesa_printf("%02x ", data
[0]);
115 _mesa_printf("%02x%02x ", data
[0], data
[1]);
117 _mesa_printf("%02x%02x%02x ", data
[0], data
[1], data
[2]);
119 _mesa_printf("%02x%02x%02x%02x ", data
[0], data
[1], data
[2], data
[3]);
120 data
+= (img
->RowStride
- img
->Width
) * c
;
122 /* XXX use img->ImageStride here */
131 * Compute floor(log_base_2(n)).
132 * If n < 0 return -1.
161 * Return the simple base format for a given internal texture format.
162 * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
164 * \param ctx GL context.
165 * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
167 * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
168 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
170 * This is the format which is used during texture application (i.e. the
171 * texture format and env mode determine the arithmetic used.
174 _mesa_base_tex_format( GLcontext
*ctx
, GLint internalFormat
)
176 switch (internalFormat
) {
191 case GL_LUMINANCE_ALPHA
:
192 case GL_LUMINANCE4_ALPHA4
:
193 case GL_LUMINANCE6_ALPHA2
:
194 case GL_LUMINANCE8_ALPHA8
:
195 case GL_LUMINANCE12_ALPHA4
:
196 case GL_LUMINANCE12_ALPHA12
:
197 case GL_LUMINANCE16_ALPHA16
:
198 return GL_LUMINANCE_ALPHA
;
229 if (ctx
->Extensions
.EXT_paletted_texture
) {
230 switch (internalFormat
) {
232 case GL_COLOR_INDEX1_EXT
:
233 case GL_COLOR_INDEX2_EXT
:
234 case GL_COLOR_INDEX4_EXT
:
235 case GL_COLOR_INDEX8_EXT
:
236 case GL_COLOR_INDEX12_EXT
:
237 case GL_COLOR_INDEX16_EXT
:
238 return GL_COLOR_INDEX
;
244 if (ctx
->Extensions
.ARB_depth_texture
) {
245 switch (internalFormat
) {
246 case GL_DEPTH_COMPONENT
:
247 case GL_DEPTH_COMPONENT16
:
248 case GL_DEPTH_COMPONENT24
:
249 case GL_DEPTH_COMPONENT32
:
250 return GL_DEPTH_COMPONENT
;
256 if (ctx
->Extensions
.ARB_texture_compression
) {
257 switch (internalFormat
) {
258 case GL_COMPRESSED_ALPHA
:
260 case GL_COMPRESSED_LUMINANCE
:
262 case GL_COMPRESSED_LUMINANCE_ALPHA
:
263 return GL_LUMINANCE_ALPHA
;
264 case GL_COMPRESSED_INTENSITY
:
266 case GL_COMPRESSED_RGB
:
268 case GL_COMPRESSED_RGBA
:
275 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
) {
276 switch (internalFormat
) {
277 case GL_COMPRESSED_RGB_FXT1_3DFX
:
279 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
286 if (ctx
->Extensions
.EXT_texture_compression_s3tc
) {
287 switch (internalFormat
) {
288 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
290 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
291 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
292 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
299 if (ctx
->Extensions
.S3_s3tc
) {
300 switch (internalFormat
) {
312 if (ctx
->Extensions
.MESA_ycbcr_texture
) {
313 if (internalFormat
== GL_YCBCR_MESA
)
314 return GL_YCBCR_MESA
;
317 if (ctx
->Extensions
.ARB_texture_float
) {
318 switch (internalFormat
) {
319 case GL_ALPHA16F_ARB
:
320 case GL_ALPHA32F_ARB
:
328 case GL_INTENSITY16F_ARB
:
329 case GL_INTENSITY32F_ARB
:
331 case GL_LUMINANCE16F_ARB
:
332 case GL_LUMINANCE32F_ARB
:
334 case GL_LUMINANCE_ALPHA16F_ARB
:
335 case GL_LUMINANCE_ALPHA32F_ARB
:
336 return GL_LUMINANCE_ALPHA
;
342 if (ctx
->Extensions
.EXT_packed_depth_stencil
) {
343 switch (internalFormat
) {
344 case GL_DEPTH_STENCIL_EXT
:
345 case GL_DEPTH24_STENCIL8_EXT
:
346 return GL_DEPTH_STENCIL_EXT
;
352 #if FEATURE_EXT_texture_sRGB
353 if (ctx
->Extensions
.EXT_texture_sRGB
) {
354 switch (internalFormat
) {
357 case GL_COMPRESSED_SRGB_EXT
:
358 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
:
360 case GL_SRGB_ALPHA_EXT
:
361 case GL_SRGB8_ALPHA8_EXT
:
362 case GL_COMPRESSED_SRGB_ALPHA_EXT
:
363 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
:
364 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
:
365 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
:
367 case GL_SLUMINANCE_ALPHA_EXT
:
368 case GL_SLUMINANCE8_ALPHA8_EXT
:
369 case GL_COMPRESSED_SLUMINANCE_EXT
:
370 case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT
:
371 return GL_LUMINANCE_ALPHA
;
372 case GL_SLUMINANCE_EXT
:
373 case GL_SLUMINANCE8_EXT
:
380 #endif /* FEATURE_EXT_texture_sRGB */
382 return -1; /* error */
387 * Test if the given image format is a color/RGBA format (i.e., not color
388 * index, depth, stencil, etc).
389 * \param format the image format value (may by an internal texture format)
390 * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
393 is_color_format(GLenum format
)
411 case GL_LUMINANCE_ALPHA
:
412 case GL_LUMINANCE4_ALPHA4
:
413 case GL_LUMINANCE6_ALPHA2
:
414 case GL_LUMINANCE8_ALPHA8
:
415 case GL_LUMINANCE12_ALPHA4
:
416 case GL_LUMINANCE12_ALPHA12
:
417 case GL_LUMINANCE16_ALPHA16
:
444 /* float texture formats */
445 case GL_ALPHA16F_ARB
:
446 case GL_ALPHA32F_ARB
:
447 case GL_LUMINANCE16F_ARB
:
448 case GL_LUMINANCE32F_ARB
:
449 case GL_LUMINANCE_ALPHA16F_ARB
:
450 case GL_LUMINANCE_ALPHA32F_ARB
:
451 case GL_INTENSITY16F_ARB
:
452 case GL_INTENSITY32F_ARB
:
457 /* compressed formats */
458 case GL_COMPRESSED_ALPHA
:
459 case GL_COMPRESSED_LUMINANCE
:
460 case GL_COMPRESSED_LUMINANCE_ALPHA
:
461 case GL_COMPRESSED_INTENSITY
:
462 case GL_COMPRESSED_RGB
:
463 case GL_COMPRESSED_RGBA
:
468 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
469 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
470 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
471 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
472 case GL_COMPRESSED_RGB_FXT1_3DFX
:
473 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
474 #if FEATURE_EXT_texture_sRGB
477 case GL_SRGB_ALPHA_EXT
:
478 case GL_SRGB8_ALPHA8_EXT
:
479 case GL_SLUMINANCE_ALPHA_EXT
:
480 case GL_SLUMINANCE8_ALPHA8_EXT
:
481 case GL_SLUMINANCE_EXT
:
482 case GL_SLUMINANCE8_EXT
:
483 case GL_COMPRESSED_SRGB_EXT
:
484 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
:
485 case GL_COMPRESSED_SRGB_ALPHA_EXT
:
486 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
:
487 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
:
488 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
:
489 case GL_COMPRESSED_SLUMINANCE_EXT
:
490 case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT
:
491 #endif /* FEATURE_EXT_texture_sRGB */
493 case GL_YCBCR_MESA
: /* not considered to be RGB */
501 * Test if the given image format is a color index format.
504 is_index_format(GLenum format
)
508 case GL_COLOR_INDEX1_EXT
:
509 case GL_COLOR_INDEX2_EXT
:
510 case GL_COLOR_INDEX4_EXT
:
511 case GL_COLOR_INDEX8_EXT
:
512 case GL_COLOR_INDEX12_EXT
:
513 case GL_COLOR_INDEX16_EXT
:
522 * Test if the given image format is a depth component format.
525 is_depth_format(GLenum format
)
528 case GL_DEPTH_COMPONENT16
:
529 case GL_DEPTH_COMPONENT24
:
530 case GL_DEPTH_COMPONENT32
:
531 case GL_DEPTH_COMPONENT
:
540 * Test if the given image format is a YCbCr format.
543 is_ycbcr_format(GLenum format
)
555 * Test if the given image format is a Depth/Stencil format.
558 is_depthstencil_format(GLenum format
)
561 case GL_DEPTH24_STENCIL8_EXT
:
562 case GL_DEPTH_STENCIL_EXT
:
572 * Test if it is a supported compressed format.
574 * \param internalFormat the internal format token provided by the user.
576 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
577 * GL_FALSE otherwise.
579 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
583 is_compressed_format(GLcontext
*ctx
, GLenum internalFormat
)
585 GLint supported
[100]; /* 100 should be plenty */
588 n
= _mesa_get_compressed_formats(ctx
, supported
, GL_TRUE
);
590 for (i
= 0; i
< n
; i
++) {
591 if ((GLint
) internalFormat
== supported
[i
]) {
600 * For cube map faces, return a face index in [0,5].
601 * For other targets return 0;
604 _mesa_tex_target_to_face(GLenum target
)
606 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
607 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)
608 return (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
616 * Store a gl_texture_image pointer in a gl_texture_object structure
617 * according to the target and level parameters.
619 * \param tObj texture object.
620 * \param target texture target.
621 * \param level image level.
622 * \param texImage texture image.
624 * This was basically prompted by the introduction of cube maps.
627 _mesa_set_tex_image(struct gl_texture_object
*tObj
,
628 GLenum target
, GLint level
,
629 struct gl_texture_image
*texImage
)
633 /* XXX simplify this with _mesa_tex_target_to_face() */
638 case GL_TEXTURE_1D_ARRAY_EXT
:
639 case GL_TEXTURE_2D_ARRAY_EXT
:
640 tObj
->Image
[0][level
] = texImage
;
642 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
643 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
644 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
645 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
646 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
647 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
649 GLuint face
= ((GLuint
) target
-
650 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
651 tObj
->Image
[face
][level
] = texImage
;
654 case GL_TEXTURE_RECTANGLE_NV
:
656 tObj
->Image
[0][level
] = texImage
;
659 _mesa_problem(NULL
, "bad target in _mesa_set_tex_image()");
662 /* Set the 'back' pointer */
663 texImage
->TexObject
= tObj
;
668 * Allocate a texture image structure.
670 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
673 * \return a pointer to gl_texture_image struct with all fields initialized to
676 struct gl_texture_image
*
677 _mesa_new_texture_image( GLcontext
*ctx
)
680 return CALLOC_STRUCT(gl_texture_image
);
685 * Free texture image data.
686 * This function is a fallback called via ctx->Driver.FreeTexImageData().
688 * \param teximage texture image.
690 * Free the texture image data if it's not marked as client data.
693 _mesa_free_texture_image_data(GLcontext
*ctx
,
694 struct gl_texture_image
*texImage
)
698 if (texImage
->Data
&& !texImage
->IsClientData
) {
699 /* free the old texture data */
700 _mesa_free_texmemory(texImage
->Data
);
703 texImage
->Data
= NULL
;
708 * Free texture image.
710 * \param teximage texture image.
712 * Free the texture image structure and the associated image data.
715 _mesa_delete_texture_image( GLcontext
*ctx
, struct gl_texture_image
*texImage
)
717 /* Free texImage->Data and/or any other driver-specific texture
720 ASSERT(ctx
->Driver
.FreeTexImageData
);
721 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
723 ASSERT(texImage
->Data
== NULL
);
724 if (texImage
->ImageOffsets
)
725 _mesa_free(texImage
->ImageOffsets
);
726 _mesa_free(texImage
);
731 * Test if a target is a proxy target.
733 * \param target texture target.
735 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
738 _mesa_is_proxy_texture(GLenum target
)
740 return (target
== GL_PROXY_TEXTURE_1D
||
741 target
== GL_PROXY_TEXTURE_2D
||
742 target
== GL_PROXY_TEXTURE_3D
||
743 target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
744 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
||
745 target
== GL_PROXY_TEXTURE_1D_ARRAY_EXT
||
746 target
== GL_PROXY_TEXTURE_2D_ARRAY_EXT
);
751 * Get the texture object that corresponds to the target of the given texture unit.
753 * \param ctx GL context.
754 * \param texUnit texture unit.
755 * \param target texture target.
757 * \return pointer to the texture object on success, or NULL on failure.
759 * \sa gl_texture_unit.
761 struct gl_texture_object
*
762 _mesa_select_tex_object(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
767 return texUnit
->Current1D
;
768 case GL_PROXY_TEXTURE_1D
:
769 return ctx
->Texture
.ProxyTex
[TEXTURE_1D_INDEX
];
771 return texUnit
->Current2D
;
772 case GL_PROXY_TEXTURE_2D
:
773 return ctx
->Texture
.ProxyTex
[TEXTURE_2D_INDEX
];
775 return texUnit
->Current3D
;
776 case GL_PROXY_TEXTURE_3D
:
777 return ctx
->Texture
.ProxyTex
[TEXTURE_3D_INDEX
];
778 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
779 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
780 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
781 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
782 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
783 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
784 case GL_TEXTURE_CUBE_MAP_ARB
:
785 return ctx
->Extensions
.ARB_texture_cube_map
786 ? texUnit
->CurrentCubeMap
: NULL
;
787 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
788 return ctx
->Extensions
.ARB_texture_cube_map
789 ? ctx
->Texture
.ProxyTex
[TEXTURE_CUBE_INDEX
] : NULL
;
790 case GL_TEXTURE_RECTANGLE_NV
:
791 return ctx
->Extensions
.NV_texture_rectangle
792 ? texUnit
->CurrentRect
: NULL
;
793 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
794 return ctx
->Extensions
.NV_texture_rectangle
795 ? ctx
->Texture
.ProxyTex
[TEXTURE_RECT_INDEX
] : NULL
;
796 case GL_TEXTURE_1D_ARRAY_EXT
:
797 return ctx
->Extensions
.MESA_texture_array
798 ? texUnit
->Current1DArray
: NULL
;
799 case GL_PROXY_TEXTURE_1D_ARRAY_EXT
:
800 return ctx
->Extensions
.MESA_texture_array
801 ? ctx
->Texture
.ProxyTex
[TEXTURE_1D_ARRAY_INDEX
] : NULL
;
802 case GL_TEXTURE_2D_ARRAY_EXT
:
803 return ctx
->Extensions
.MESA_texture_array
804 ? texUnit
->Current2DArray
: NULL
;
805 case GL_PROXY_TEXTURE_2D_ARRAY_EXT
:
806 return ctx
->Extensions
.MESA_texture_array
807 ? ctx
->Texture
.ProxyTex
[TEXTURE_2D_ARRAY_INDEX
] : NULL
;
809 _mesa_problem(NULL
, "bad target in _mesa_select_tex_object()");
816 * Get the texture image struct which corresponds to target and level
817 * of the given texture unit.
819 * \param ctx GL context.
820 * \param texUnit texture unit.
821 * \param target texture target.
822 * \param level image level.
824 * \return pointer to the texture image structure on success, or NULL on failure.
826 * \sa gl_texture_unit.
828 struct gl_texture_image
*
829 _mesa_select_tex_image(GLcontext
*ctx
, const struct gl_texture_object
*texObj
,
830 GLenum target
, GLint level
)
834 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
)
837 /* XXX simplify this with _mesa_tex_target_to_face() */
840 case GL_PROXY_TEXTURE_1D
:
842 case GL_PROXY_TEXTURE_2D
:
844 case GL_PROXY_TEXTURE_3D
:
845 return texObj
->Image
[0][level
];
847 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
848 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
849 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
850 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
851 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
852 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
853 if (ctx
->Extensions
.ARB_texture_cube_map
) {
854 GLuint face
= ((GLuint
) target
-
855 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
856 return texObj
->Image
[face
][level
];
861 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
862 if (ctx
->Extensions
.ARB_texture_cube_map
)
863 return texObj
->Image
[0][level
];
867 case GL_TEXTURE_RECTANGLE_NV
:
868 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
869 if (ctx
->Extensions
.NV_texture_rectangle
&& level
== 0)
870 return texObj
->Image
[0][level
];
874 case GL_TEXTURE_1D_ARRAY_EXT
:
875 case GL_PROXY_TEXTURE_1D_ARRAY_EXT
:
876 case GL_TEXTURE_2D_ARRAY_EXT
:
877 case GL_PROXY_TEXTURE_2D_ARRAY_EXT
:
878 return (ctx
->Extensions
.MESA_texture_array
)
879 ? texObj
->Image
[0][level
] : NULL
;
888 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
889 * it and install it. Only return NULL if passed a bad parameter or run
892 struct gl_texture_image
*
893 _mesa_get_tex_image(GLcontext
*ctx
, struct gl_texture_object
*texObj
,
894 GLenum target
, GLint level
)
896 struct gl_texture_image
*texImage
;
901 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
903 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
905 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture image allocation");
909 _mesa_set_tex_image(texObj
, target
, level
, texImage
);
917 * Return pointer to the specified proxy texture image.
918 * Note that proxy textures are per-context, not per-texture unit.
919 * \return pointer to texture image or NULL if invalid target, invalid
920 * level, or out of memory.
922 struct gl_texture_image
*
923 _mesa_get_proxy_tex_image(GLcontext
*ctx
, GLenum target
, GLint level
)
925 struct gl_texture_image
*texImage
;
931 case GL_PROXY_TEXTURE_1D
:
932 if (level
>= ctx
->Const
.MaxTextureLevels
)
934 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_1D_INDEX
]->Image
[0][level
];
936 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
938 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
941 ctx
->Texture
.ProxyTex
[TEXTURE_1D_INDEX
]->Image
[0][level
] = texImage
;
942 /* Set the 'back' pointer */
943 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_1D_INDEX
];
946 case GL_PROXY_TEXTURE_2D
:
947 if (level
>= ctx
->Const
.MaxTextureLevels
)
949 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_2D_INDEX
]->Image
[0][level
];
951 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
953 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
956 ctx
->Texture
.ProxyTex
[TEXTURE_2D_INDEX
]->Image
[0][level
] = texImage
;
957 /* Set the 'back' pointer */
958 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_2D_INDEX
];
961 case GL_PROXY_TEXTURE_3D
:
962 if (level
>= ctx
->Const
.Max3DTextureLevels
)
964 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_3D_INDEX
]->Image
[0][level
];
966 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
968 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
971 ctx
->Texture
.ProxyTex
[TEXTURE_3D_INDEX
]->Image
[0][level
] = texImage
;
972 /* Set the 'back' pointer */
973 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_3D_INDEX
];
976 case GL_PROXY_TEXTURE_CUBE_MAP
:
977 if (level
>= ctx
->Const
.MaxCubeTextureLevels
)
979 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_CUBE_INDEX
]->Image
[0][level
];
981 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
983 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
986 ctx
->Texture
.ProxyTex
[TEXTURE_CUBE_INDEX
]->Image
[0][level
] = texImage
;
987 /* Set the 'back' pointer */
988 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_CUBE_INDEX
];
991 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
994 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_RECT_INDEX
]->Image
[0][level
];
996 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
998 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
1001 ctx
->Texture
.ProxyTex
[TEXTURE_RECT_INDEX
]->Image
[0][level
] = texImage
;
1002 /* Set the 'back' pointer */
1003 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_RECT_INDEX
];
1006 case GL_PROXY_TEXTURE_1D_ARRAY_EXT
:
1007 if (level
>= ctx
->Const
.MaxTextureLevels
)
1009 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_1D_ARRAY_INDEX
]->Image
[0][level
];
1011 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
1013 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
1016 ctx
->Texture
.ProxyTex
[TEXTURE_1D_ARRAY_INDEX
]->Image
[0][level
] = texImage
;
1017 /* Set the 'back' pointer */
1018 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_1D_ARRAY_INDEX
];
1021 case GL_PROXY_TEXTURE_2D_ARRAY_EXT
:
1022 if (level
>= ctx
->Const
.MaxTextureLevels
)
1024 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_2D_ARRAY_INDEX
]->Image
[0][level
];
1026 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
1028 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
1031 ctx
->Texture
.ProxyTex
[TEXTURE_2D_ARRAY_INDEX
]->Image
[0][level
] = texImage
;
1032 /* Set the 'back' pointer */
1033 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_2D_ARRAY_INDEX
];
1043 * Get the maximum number of allowed mipmap levels.
1045 * \param ctx GL context.
1046 * \param target texture target.
1048 * \return the maximum number of allowed mipmap levels for the given
1049 * texture target, or zero if passed a bad target.
1054 _mesa_max_texture_levels(GLcontext
*ctx
, GLenum target
)
1058 case GL_PROXY_TEXTURE_1D
:
1060 case GL_PROXY_TEXTURE_2D
:
1061 case GL_TEXTURE_1D_ARRAY_EXT
:
1062 case GL_PROXY_TEXTURE_1D_ARRAY_EXT
:
1063 case GL_TEXTURE_2D_ARRAY_EXT
:
1064 case GL_PROXY_TEXTURE_2D_ARRAY_EXT
:
1065 return ctx
->Const
.MaxTextureLevels
;
1067 case GL_PROXY_TEXTURE_3D
:
1068 return ctx
->Const
.Max3DTextureLevels
;
1069 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
1070 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
1071 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
1072 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
1073 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
1074 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
1075 case GL_TEXTURE_CUBE_MAP_ARB
:
1076 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
1077 return ctx
->Const
.MaxCubeTextureLevels
;
1078 case GL_TEXTURE_RECTANGLE_NV
:
1079 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
1082 return 0; /* bad target */
1088 #if 000 /* not used anymore */
1090 * glTexImage[123]D can accept a NULL image pointer. In this case we
1091 * create a texture image with unspecified image contents per the OpenGL
1095 make_null_texture(GLint width
, GLint height
, GLint depth
, GLenum format
)
1097 const GLint components
= _mesa_components_in_format(format
);
1098 const GLint numPixels
= width
* height
* depth
;
1099 GLubyte
*data
= (GLubyte
*) MALLOC(numPixels
* components
* sizeof(GLubyte
));
1103 * Let's see if anyone finds this. If glTexImage2D() is called with
1104 * a NULL image pointer then load the texture image with something
1105 * interesting instead of leaving it indeterminate.
1108 static const char message
[8][32] = {
1109 " X X XXXXX XXX X ",
1110 " XX XX X X X X X ",
1112 " X X XXXX XXX XXXXX ",
1115 " X X XXXXX XXX X X ",
1119 GLubyte
*imgPtr
= data
;
1121 for (h
= 0; h
< depth
; h
++) {
1122 for (i
= 0; i
< height
; i
++) {
1123 GLint srcRow
= 7 - (i
% 8);
1124 for (j
= 0; j
< width
; j
++) {
1125 GLint srcCol
= j
% 32;
1126 GLubyte texel
= (message
[srcRow
][srcCol
]=='X') ? 255 : 70;
1127 for (k
= 0; k
< components
; k
++) {
1143 * Reset the fields of a gl_texture_image struct to zero.
1145 * \param img texture image structure.
1147 * This is called when a proxy texture test fails, we set all the
1148 * image members (except DriverData) to zero.
1149 * It's also used in glTexImage[123]D as a safeguard to be sure all
1150 * required fields get initialized properly by the Driver.TexImage[123]D
1154 clear_teximage_fields(struct gl_texture_image
*img
)
1157 img
->_BaseFormat
= 0;
1158 img
->InternalFormat
= 0;
1164 if (img
->ImageOffsets
) {
1165 _mesa_free(img
->ImageOffsets
);
1166 img
->ImageOffsets
= NULL
;
1172 img
->HeightLog2
= 0;
1175 img
->TexFormat
= &_mesa_null_texformat
;
1176 img
->FetchTexelc
= NULL
;
1177 img
->FetchTexelf
= NULL
;
1178 img
->IsCompressed
= 0;
1179 img
->CompressedSize
= 0;
1184 * Initialize basic fields of the gl_texture_image struct.
1186 * \param ctx GL context.
1187 * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
1188 * \param img texture image structure to be initialized.
1189 * \param width image width.
1190 * \param height image height.
1191 * \param depth image depth.
1192 * \param border image border.
1193 * \param internalFormat internal format.
1195 * Fills in the fields of \p img with the given information.
1196 * Note: width, height and depth include the border.
1199 _mesa_init_teximage_fields(GLcontext
*ctx
, GLenum target
,
1200 struct gl_texture_image
*img
,
1201 GLsizei width
, GLsizei height
, GLsizei depth
,
1202 GLint border
, GLenum internalFormat
)
1208 ASSERT(height
>= 0);
1211 img
->_BaseFormat
= _mesa_base_tex_format( ctx
, internalFormat
);
1212 ASSERT(img
->_BaseFormat
> 0);
1213 img
->InternalFormat
= internalFormat
;
1214 img
->Border
= border
;
1216 img
->Height
= height
;
1218 img
->Width2
= width
- 2 * border
; /* == 1 << img->WidthLog2; */
1219 img
->Height2
= height
- 2 * border
; /* == 1 << img->HeightLog2; */
1220 img
->Depth2
= depth
- 2 * border
; /* == 1 << img->DepthLog2; */
1221 img
->WidthLog2
= logbase2(img
->Width2
);
1222 if (height
== 1) /* 1-D texture */
1223 img
->HeightLog2
= 0;
1225 img
->HeightLog2
= logbase2(img
->Height2
);
1226 if (depth
== 1) /* 2-D texture */
1229 img
->DepthLog2
= logbase2(img
->Depth2
);
1230 img
->MaxLog2
= MAX2(img
->WidthLog2
, img
->HeightLog2
);
1231 img
->IsCompressed
= GL_FALSE
;
1232 img
->CompressedSize
= 0;
1234 if ((width
== 1 || _mesa_bitcount(img
->Width2
) == 1) &&
1235 (height
== 1 || _mesa_bitcount(img
->Height2
) == 1) &&
1236 (depth
== 1 || _mesa_bitcount(img
->Depth2
) == 1))
1237 img
->_IsPowerOfTwo
= GL_TRUE
;
1239 img
->_IsPowerOfTwo
= GL_FALSE
;
1241 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
1242 img
->RowStride
= width
;
1243 /* Allocate the ImageOffsets array and initialize to typical values.
1244 * We allocate the array for 1D/2D textures too in order to avoid special-
1245 * case code in the texstore routines.
1247 img
->ImageOffsets
= (GLuint
*) _mesa_malloc(depth
* sizeof(GLuint
));
1248 for (i
= 0; i
< depth
; i
++) {
1249 img
->ImageOffsets
[i
] = i
* width
* height
;
1252 /* Compute Width/Height/DepthScale for mipmap lod computation */
1253 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1254 /* scale = 1.0 since texture coords directly map to texels */
1255 img
->WidthScale
= 1.0;
1256 img
->HeightScale
= 1.0;
1257 img
->DepthScale
= 1.0;
1260 img
->WidthScale
= (GLfloat
) img
->Width
;
1261 img
->HeightScale
= (GLfloat
) img
->Height
;
1262 img
->DepthScale
= (GLfloat
) img
->Depth
;
1268 * This is the fallback for Driver.TestProxyTexImage(). Test the texture
1269 * level, width, height and depth against the ctx->Const limits for textures.
1271 * A hardware driver might override this function if, for example, the
1272 * max 3D texture size is 512x512x64 (i.e. not a cube).
1274 * Note that width, height, depth == 0 is not an error. However, a
1275 * texture with zero width/height/depth will be considered "incomplete"
1276 * and texturing will effectively be disabled.
1278 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
1279 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
1280 * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
1281 * \param level as passed to glTexImage
1282 * \param internalFormat as passed to glTexImage
1283 * \param format as passed to glTexImage
1284 * \param type as passed to glTexImage
1285 * \param width as passed to glTexImage
1286 * \param height as passed to glTexImage
1287 * \param depth as passed to glTexImage
1288 * \param border as passed to glTexImage
1289 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1292 _mesa_test_proxy_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
1293 GLint internalFormat
, GLenum format
, GLenum type
,
1294 GLint width
, GLint height
, GLint depth
, GLint border
)
1298 (void) internalFormat
;
1303 case GL_PROXY_TEXTURE_1D
:
1304 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1305 if (width
< 2 * border
|| width
> 2 + maxSize
||
1306 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1307 width
>0 && _mesa_bitcount(width
- 2 * border
) != 1) ||
1308 level
>= ctx
->Const
.MaxTextureLevels
) {
1309 /* bad width or level */
1313 case GL_PROXY_TEXTURE_2D
:
1314 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1315 if (width
< 2 * border
|| width
> 2 + maxSize
||
1316 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1317 width
> 0 && _mesa_bitcount(width
- 2 * border
) != 1) ||
1318 height
< 2 * border
|| height
> 2 + maxSize
||
1319 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1320 height
> 0 && _mesa_bitcount(height
- 2 * border
) != 1) ||
1321 level
>= ctx
->Const
.MaxTextureLevels
) {
1322 /* bad width or height or level */
1326 case GL_PROXY_TEXTURE_3D
:
1327 maxSize
= 1 << (ctx
->Const
.Max3DTextureLevels
- 1);
1328 if (width
< 2 * border
|| width
> 2 + maxSize
||
1329 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1330 width
> 0 && _mesa_bitcount(width
- 2 * border
) != 1) ||
1331 height
< 2 * border
|| height
> 2 + maxSize
||
1332 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1333 height
> 0 && _mesa_bitcount(height
- 2 * border
) != 1) ||
1334 depth
< 2 * border
|| depth
> 2 + maxSize
||
1335 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1336 depth
> 0 && _mesa_bitcount(depth
- 2 * border
) != 1) ||
1337 level
>= ctx
->Const
.Max3DTextureLevels
) {
1338 /* bad width or height or depth or level */
1342 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
1343 if (width
< 0 || width
> ctx
->Const
.MaxTextureRectSize
||
1344 height
< 0 || height
> ctx
->Const
.MaxTextureRectSize
||
1346 /* bad width or height or level */
1350 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
1351 maxSize
= 1 << (ctx
->Const
.MaxCubeTextureLevels
- 1);
1352 if (width
< 2 * border
|| width
> 2 + maxSize
||
1353 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1354 width
> 0 && _mesa_bitcount(width
- 2 * border
) != 1) ||
1355 height
< 2 * border
|| height
> 2 + maxSize
||
1356 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1357 height
> 0 && _mesa_bitcount(height
- 2 * border
) != 1) ||
1358 level
>= ctx
->Const
.MaxCubeTextureLevels
) {
1359 /* bad width or height */
1363 case GL_PROXY_TEXTURE_1D_ARRAY_EXT
:
1364 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1365 if (width
< 2 * border
|| width
> 2 + maxSize
||
1366 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1367 width
> 0 && _mesa_bitcount(width
- 2 * border
) != 1) ||
1368 level
>= ctx
->Const
.MaxTextureLevels
) {
1369 /* bad width or level */
1373 if (height
< 1 || height
> ctx
->Const
.MaxArrayTextureLayers
) {
1377 case GL_PROXY_TEXTURE_2D_ARRAY_EXT
:
1378 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1379 if (width
< 2 * border
|| width
> 2 + maxSize
||
1380 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1381 width
> 0 && _mesa_bitcount(width
- 2 * border
) != 1) ||
1382 height
< 2 * border
|| height
> 2 + maxSize
||
1383 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1384 height
> 0 && _mesa_bitcount(height
- 2 * border
) != 1) ||
1385 level
>= ctx
->Const
.MaxTextureLevels
) {
1386 /* bad width or height or level */
1389 if (depth
< 1 || depth
> ctx
->Const
.MaxArrayTextureLayers
) {
1394 _mesa_problem(ctx
, "Invalid target in _mesa_test_proxy_teximage");
1401 * Helper function to determine whether a target supports compressed textures
1404 target_can_be_compressed(GLcontext
*ctx
, GLenum target
)
1406 return (((target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
))
1407 || ((ctx
->Extensions
.ARB_texture_cube_map
&&
1408 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1409 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1410 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))))
1411 || ((ctx
->Extensions
.MESA_texture_array
&&
1412 ((target
== GL_PROXY_TEXTURE_2D_ARRAY_EXT
) ||
1413 (target
== GL_TEXTURE_2D_ARRAY_EXT
)))));
1418 * Test the glTexImage[123]D() parameters for errors.
1420 * \param ctx GL context.
1421 * \param target texture target given by the user.
1422 * \param level image level given by the user.
1423 * \param internalFormat internal format given by the user.
1424 * \param format pixel data format given by the user.
1425 * \param type pixel data type given by the user.
1426 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1427 * \param width image width given by the user.
1428 * \param height image height given by the user.
1429 * \param depth image depth given by the user.
1430 * \param border image border given by the user.
1432 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1434 * Verifies each of the parameters against the constants specified in
1435 * __GLcontextRec::Const and the supported extensions, and according to the
1436 * OpenGL specification.
1439 texture_error_check( GLcontext
*ctx
, GLenum target
,
1440 GLint level
, GLint internalFormat
,
1441 GLenum format
, GLenum type
,
1443 GLint width
, GLint height
,
1444 GLint depth
, GLint border
)
1446 const GLboolean isProxy
= _mesa_is_proxy_texture(target
);
1447 GLboolean sizeOK
= GL_TRUE
;
1448 GLboolean colorFormat
, indexFormat
;
1449 GLenum proxy_target
;
1451 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1452 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1454 _mesa_error(ctx
, GL_INVALID_VALUE
,
1455 "glTexImage%dD(level=%d)", dimensions
, level
);
1461 if (border
< 0 || border
> 1 ||
1462 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1463 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1465 _mesa_error(ctx
, GL_INVALID_VALUE
,
1466 "glTexImage%dD(border=%d)", dimensions
, border
);
1471 if (width
< 0 || height
< 0 || depth
< 0) {
1473 _mesa_error(ctx
, GL_INVALID_VALUE
,
1474 "glTexImage%dD(width, height or depth < 0)", dimensions
);
1479 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1480 * level, width, height and depth.
1482 if (dimensions
== 1) {
1483 if (target
== GL_PROXY_TEXTURE_1D
|| target
== GL_TEXTURE_1D
) {
1484 proxy_target
= GL_PROXY_TEXTURE_1D
;
1489 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1493 else if (dimensions
== 2) {
1495 if (target
== GL_PROXY_TEXTURE_2D
|| target
== GL_TEXTURE_2D
) {
1496 proxy_target
= GL_PROXY_TEXTURE_2D
;
1498 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
1499 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1500 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
1501 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1502 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1505 proxy_target
= GL_PROXY_TEXTURE_CUBE_MAP_ARB
;
1506 sizeOK
= (width
== height
);
1508 else if (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
||
1509 target
== GL_TEXTURE_RECTANGLE_NV
) {
1510 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1511 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1514 proxy_target
= GL_PROXY_TEXTURE_RECTANGLE_NV
;
1516 else if (target
== GL_PROXY_TEXTURE_1D_ARRAY_EXT
||
1517 target
== GL_TEXTURE_1D_ARRAY_EXT
) {
1518 proxy_target
= GL_PROXY_TEXTURE_1D_ARRAY_EXT
;
1521 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1525 else if (dimensions
== 3) {
1526 if (target
== GL_PROXY_TEXTURE_3D
|| target
== GL_TEXTURE_3D
) {
1527 proxy_target
= GL_PROXY_TEXTURE_3D
;
1529 else if (target
== GL_PROXY_TEXTURE_2D_ARRAY_EXT
||
1530 target
== GL_TEXTURE_2D_ARRAY_EXT
) {
1531 proxy_target
= GL_PROXY_TEXTURE_2D_ARRAY_EXT
;
1534 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1539 _mesa_problem( ctx
, "bad dims in texture_error_check" );
1543 sizeOK
= sizeOK
&& ctx
->Driver
.TestProxyTexImage(ctx
, proxy_target
, level
,
1544 internalFormat
, format
,
1545 type
, width
, height
,
1549 _mesa_error(ctx
, GL_INVALID_VALUE
,
1550 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1551 dimensions
, level
, width
, height
, depth
);
1556 /* Check internalFormat */
1557 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1559 _mesa_error(ctx
, GL_INVALID_VALUE
,
1560 "glTexImage%dD(internalFormat=0x%x)",
1561 dimensions
, internalFormat
);
1566 /* Check incoming image format and type */
1567 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
1568 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1569 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1572 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1573 "glTexImage%dD(format or type)", dimensions
);
1578 /* make sure internal format and format basically agree */
1579 colorFormat
= is_color_format(format
);
1580 indexFormat
= is_index_format(format
);
1581 if ((is_color_format(internalFormat
) && !colorFormat
&& !indexFormat
) ||
1582 (is_index_format(internalFormat
) && !indexFormat
) ||
1583 (is_depth_format(internalFormat
) != is_depth_format(format
)) ||
1584 (is_ycbcr_format(internalFormat
) != is_ycbcr_format(format
)) ||
1585 (is_depthstencil_format(internalFormat
) != is_depthstencil_format(format
))) {
1587 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1588 "glTexImage(internalFormat/format)");
1592 /* additional checks for ycbcr textures */
1593 if (internalFormat
== GL_YCBCR_MESA
) {
1594 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1595 if (type
!= GL_UNSIGNED_SHORT_8_8_MESA
&&
1596 type
!= GL_UNSIGNED_SHORT_8_8_REV_MESA
) {
1598 _mesa_sprintf(message
,
1599 "glTexImage%d(format/type YCBCR mismatch", dimensions
);
1600 _mesa_error(ctx
, GL_INVALID_ENUM
, message
);
1601 return GL_TRUE
; /* error */
1603 if (target
!= GL_TEXTURE_2D
&&
1604 target
!= GL_PROXY_TEXTURE_2D
&&
1605 target
!= GL_TEXTURE_RECTANGLE_NV
&&
1606 target
!= GL_PROXY_TEXTURE_RECTANGLE_NV
) {
1608 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage(target)");
1614 _mesa_sprintf(message
,
1615 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1616 dimensions
, border
);
1617 _mesa_error(ctx
, GL_INVALID_VALUE
, message
);
1623 /* additional checks for depth textures */
1624 if (_mesa_base_tex_format(ctx
, internalFormat
) == GL_DEPTH_COMPONENT
) {
1625 /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
1626 if (target
!= GL_TEXTURE_1D
&&
1627 target
!= GL_PROXY_TEXTURE_1D
&&
1628 target
!= GL_TEXTURE_2D
&&
1629 target
!= GL_PROXY_TEXTURE_2D
&&
1630 target
!= GL_TEXTURE_RECTANGLE_ARB
&&
1631 target
!= GL_PROXY_TEXTURE_RECTANGLE_ARB
) {
1633 _mesa_error(ctx
, GL_INVALID_ENUM
,
1634 "glTexImage(target/internalFormat)");
1639 /* additional checks for compressed textures */
1640 if (is_compressed_format(ctx
, internalFormat
)) {
1641 if (!target_can_be_compressed(ctx
, target
) && !isProxy
) {
1642 _mesa_error(ctx
, GL_INVALID_ENUM
,
1643 "glTexImage%d(target)", dimensions
);
1648 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1649 "glTexImage%D(border!=0)", dimensions
);
1655 /* if we get here, the parameters are OK */
1661 * Test glTexSubImage[123]D() parameters for errors.
1663 * \param ctx GL context.
1664 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1665 * \param target texture target given by the user.
1666 * \param level image level given by the user.
1667 * \param xoffset sub-image x offset given by the user.
1668 * \param yoffset sub-image y offset given by the user.
1669 * \param zoffset sub-image z offset given by the user.
1670 * \param format pixel data format given by the user.
1671 * \param type pixel data type given by the user.
1672 * \param width image width given by the user.
1673 * \param height image height given by the user.
1674 * \param depth image depth given by the user.
1676 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1678 * Verifies each of the parameters against the constants specified in
1679 * __GLcontextRec::Const and the supported extensions, and according to the
1680 * OpenGL specification.
1683 subtexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1684 GLenum target
, GLint level
,
1685 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1686 GLint width
, GLint height
, GLint depth
,
1687 GLenum format
, GLenum type
)
1690 if (dimensions
== 1) {
1691 if (target
!= GL_TEXTURE_1D
) {
1692 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
1696 else if (dimensions
== 2) {
1697 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1698 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1699 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1700 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1704 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1705 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1706 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1710 else if (target
== GL_TEXTURE_1D_ARRAY_EXT
) {
1711 if (!ctx
->Extensions
.MESA_texture_array
) {
1712 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1716 else if (target
!= GL_TEXTURE_2D
) {
1717 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1721 else if (dimensions
== 3) {
1722 if (target
== GL_TEXTURE_2D_ARRAY_EXT
) {
1723 if (!ctx
->Extensions
.MESA_texture_array
) {
1724 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
1728 else if (target
!= GL_TEXTURE_3D
) {
1729 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
1734 _mesa_problem( ctx
, "invalid dims in texture_error_check" );
1738 /* Basic level check */
1739 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1740 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level=%d)", level
);
1745 _mesa_error(ctx
, GL_INVALID_VALUE
,
1746 "glTexSubImage%dD(width=%d)", dimensions
, width
);
1749 if (height
< 0 && dimensions
> 1) {
1750 _mesa_error(ctx
, GL_INVALID_VALUE
,
1751 "glTexSubImage%dD(height=%d)", dimensions
, height
);
1754 if (depth
< 0 && dimensions
> 2) {
1755 _mesa_error(ctx
, GL_INVALID_VALUE
,
1756 "glTexSubImage%dD(depth=%d)", dimensions
, depth
);
1760 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
1761 _mesa_error(ctx
, GL_INVALID_ENUM
,
1762 "glTexSubImage%dD(format or type)", dimensions
);
1770 subtexture_error_check2( GLcontext
*ctx
, GLuint dimensions
,
1771 GLenum target
, GLint level
,
1772 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1773 GLint width
, GLint height
, GLint depth
,
1774 GLenum format
, GLenum type
,
1775 const struct gl_texture_image
*destTex
)
1778 /* undefined image level */
1779 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage%dD", dimensions
);
1783 if (xoffset
< -((GLint
)destTex
->Border
)) {
1784 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset)",
1788 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
1789 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset+width)",
1793 if (dimensions
> 1) {
1794 if (yoffset
< -((GLint
)destTex
->Border
)) {
1795 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset)",
1799 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
1800 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset+height)",
1805 if (dimensions
> 2) {
1806 if (zoffset
< -((GLint
)destTex
->Border
)) {
1807 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
1810 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+ destTex
->Border
)) {
1811 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
1816 #if FEATURE_EXT_texture_sRGB
1817 if (destTex
->InternalFormat
== GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
||
1818 destTex
->InternalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
||
1819 destTex
->InternalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
||
1820 destTex
->InternalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
) {
1821 if ((width
& 0x3) || (height
& 0x3) ||
1822 (xoffset
& 0x3) || (yoffset
& 0x3))
1823 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1824 "glTexSubImage%dD(size or offset not multiple of 4)",
1830 if (destTex
->IsCompressed
) {
1831 if (!target_can_be_compressed(ctx
, target
)) {
1832 _mesa_error(ctx
, GL_INVALID_ENUM
,
1833 "glTexSubImage%D(target)", dimensions
);
1836 /* offset must be multiple of 4 */
1837 if ((xoffset
& 3) || (yoffset
& 3)) {
1838 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1839 "glTexSubImage%D(xoffset or yoffset)", dimensions
);
1842 /* size must be multiple of 4 or equal to whole texture size */
1843 if ((width
& 3) && (GLuint
) width
!= destTex
->Width
) {
1844 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1845 "glTexSubImage%D(width)", dimensions
);
1848 if ((height
& 3) && (GLuint
) height
!= destTex
->Height
) {
1849 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1850 "glTexSubImage%D(width)", dimensions
);
1860 * Test glCopyTexImage[12]D() parameters for errors.
1862 * \param ctx GL context.
1863 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1864 * \param target texture target given by the user.
1865 * \param level image level given by the user.
1866 * \param internalFormat internal format given by the user.
1867 * \param width image width given by the user.
1868 * \param height image height given by the user.
1869 * \param depth image depth given by the user.
1870 * \param border texture border.
1872 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1874 * Verifies each of the parameters against the constants specified in
1875 * __GLcontextRec::Const and the supported extensions, and according to the
1876 * OpenGL specification.
1879 copytexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1880 GLenum target
, GLint level
, GLint internalFormat
,
1881 GLint width
, GLint height
, GLint border
)
1887 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1888 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1889 _mesa_error(ctx
, GL_INVALID_VALUE
,
1890 "glCopyTexImage%dD(level=%d)", dimensions
, level
);
1894 /* Check that the source buffer is complete */
1895 if (ctx
->ReadBuffer
->Name
) {
1896 _mesa_test_framebuffer_completeness(ctx
, ctx
->ReadBuffer
);
1897 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
1898 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
1899 "glCopyTexImage%dD(invalid readbuffer)", dimensions
);
1905 if (border
< 0 || border
> 1 ||
1906 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1907 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1911 format
= _mesa_base_tex_format(ctx
, internalFormat
);
1913 _mesa_error(ctx
, GL_INVALID_VALUE
,
1914 "glCopyTexImage%dD(internalFormat)", dimensions
);
1918 /* NOTE: the format and type aren't really significant for
1919 * TestProxyTexImage(). Only the internalformat really matters.
1920 if (!_mesa_source_buffer_exists(ctx, format)) {
1921 _mesa_error(ctx, GL_INVALID_OPERATION,
1922 "glCopyTexImage%dD(missing readbuffer)", dimensions);
1929 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1930 * level, width, height and depth.
1932 if (dimensions
== 1) {
1933 if (target
== GL_TEXTURE_1D
) {
1934 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1935 level
, internalFormat
,
1937 width
, 1, 1, border
);
1940 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
1944 else if (dimensions
== 2) {
1945 if (target
== GL_TEXTURE_2D
) {
1946 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1947 level
, internalFormat
,
1949 width
, height
, 1, border
);
1951 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1952 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1953 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1954 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1957 sizeOK
= (width
== height
) &&
1958 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1959 level
, internalFormat
, format
, type
,
1960 width
, height
, 1, border
);
1962 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1963 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1964 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1967 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1968 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1969 level
, internalFormat
,
1971 width
, height
, 1, border
);
1973 else if (target
== GL_TEXTURE_1D_ARRAY_EXT
) {
1974 if (!ctx
->Extensions
.MESA_texture_array
) {
1975 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)");
1978 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1979 GL_PROXY_TEXTURE_1D_ARRAY_EXT
,
1980 level
, internalFormat
,
1982 width
, height
, 1, border
);
1985 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1990 _mesa_problem(ctx
, "invalid dimensions in copytexture_error_check");
1995 if (dimensions
== 1) {
1996 _mesa_error(ctx
, GL_INVALID_VALUE
,
1997 "glCopyTexImage1D(width=%d)", width
);
2000 ASSERT(dimensions
== 2);
2001 _mesa_error(ctx
, GL_INVALID_VALUE
,
2002 "glCopyTexImage2D(width=%d, height=%d)", width
, height
);
2007 if (is_compressed_format(ctx
, internalFormat
)) {
2008 if (!target_can_be_compressed(ctx
, target
)) {
2009 _mesa_error(ctx
, GL_INVALID_ENUM
,
2010 "glCopyTexImage%d(target)", dimensions
);
2014 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2015 "glCopyTexImage%D(border!=0)", dimensions
);
2019 else if (is_depth_format(internalFormat
)) {
2020 /* make sure we have depth/stencil buffers */
2021 if (!ctx
->ReadBuffer
->_DepthBuffer
) {
2022 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2023 "glCopyTexImage%D(no depth)", dimensions
);
2027 else if (is_depthstencil_format(internalFormat
)) {
2028 /* make sure we have depth/stencil buffers */
2029 if (!ctx
->ReadBuffer
->_DepthBuffer
|| !ctx
->ReadBuffer
->_StencilBuffer
) {
2030 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2031 "glCopyTexImage%D(no depth/stencil buffer)", dimensions
);
2036 /* if we get here, the parameters are OK */
2042 * Test glCopyTexSubImage[12]D() parameters for errors.
2044 * \param ctx GL context.
2045 * \param dimensions texture image dimensions (must be 1, 2 or 3).
2046 * \param target texture target given by the user.
2047 * \param level image level given by the user.
2048 * \param xoffset sub-image x offset given by the user.
2049 * \param yoffset sub-image y offset given by the user.
2050 * \param zoffset sub-image z offset given by the user.
2051 * \param width image width given by the user.
2052 * \param height image height given by the user.
2054 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
2056 * Verifies each of the parameters against the constants specified in
2057 * __GLcontextRec::Const and the supported extensions, and according to the
2058 * OpenGL specification.
2061 copytexsubimage_error_check( GLcontext
*ctx
, GLuint dimensions
,
2062 GLenum target
, GLint level
,
2063 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2064 GLsizei width
, GLsizei height
)
2067 /* Check that the source buffer is complete */
2068 if (ctx
->ReadBuffer
->Name
) {
2069 _mesa_test_framebuffer_completeness(ctx
, ctx
->ReadBuffer
);
2070 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
2071 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
2072 "glCopyTexImage%dD(invalid readbuffer)", dimensions
);
2077 if (dimensions
== 1) {
2078 if (target
!= GL_TEXTURE_1D
) {
2079 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
2083 else if (dimensions
== 2) {
2084 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2085 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2086 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
2087 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
2091 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
2092 if (!ctx
->Extensions
.NV_texture_rectangle
) {
2093 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
2097 else if (target
== GL_TEXTURE_1D_ARRAY_EXT
) {
2098 if (!ctx
->Extensions
.MESA_texture_array
) {
2099 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
2103 else if (target
!= GL_TEXTURE_2D
) {
2104 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
2108 else if (dimensions
== 3) {
2109 if (((target
!= GL_TEXTURE_2D_ARRAY_EXT
) ||
2110 (!ctx
->Extensions
.MESA_texture_array
))
2111 && (target
!= GL_TEXTURE_3D
)) {
2112 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
2118 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
2119 _mesa_error(ctx
, GL_INVALID_VALUE
,
2120 "glCopyTexSubImage%dD(level=%d)", dimensions
, level
);
2126 _mesa_error(ctx
, GL_INVALID_VALUE
,
2127 "glCopyTexSubImage%dD(width=%d)", dimensions
, width
);
2130 if (dimensions
> 1 && height
< 0) {
2131 _mesa_error(ctx
, GL_INVALID_VALUE
,
2132 "glCopyTexSubImage%dD(height=%d)", dimensions
, height
);
2140 copytexsubimage_error_check2( GLcontext
*ctx
, GLuint dimensions
,
2141 GLenum target
, GLint level
,
2142 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2143 GLsizei width
, GLsizei height
,
2144 const struct gl_texture_image
*teximage
)
2147 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2148 "glCopyTexSubImage%dD(undefined texture level: %d)",
2153 if (xoffset
< -((GLint
)teximage
->Border
)) {
2154 _mesa_error(ctx
, GL_INVALID_VALUE
,
2155 "glCopyTexSubImage%dD(xoffset=%d)", dimensions
, xoffset
);
2158 if (xoffset
+ width
> (GLint
) (teximage
->Width
+ teximage
->Border
)) {
2159 _mesa_error(ctx
, GL_INVALID_VALUE
,
2160 "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
2163 if (dimensions
> 1) {
2164 if (yoffset
< -((GLint
)teximage
->Border
)) {
2165 _mesa_error(ctx
, GL_INVALID_VALUE
,
2166 "glCopyTexSubImage%dD(yoffset=%d)", dimensions
, yoffset
);
2169 /* NOTE: we're adding the border here, not subtracting! */
2170 if (yoffset
+ height
> (GLint
) (teximage
->Height
+ teximage
->Border
)) {
2171 _mesa_error(ctx
, GL_INVALID_VALUE
,
2172 "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
2177 if (dimensions
> 2) {
2178 if (zoffset
< -((GLint
)teximage
->Border
)) {
2179 _mesa_error(ctx
, GL_INVALID_VALUE
,
2180 "glCopyTexSubImage%dD(zoffset)", dimensions
);
2183 if (zoffset
> (GLint
) (teximage
->Depth
+ teximage
->Border
)) {
2184 _mesa_error(ctx
, GL_INVALID_VALUE
,
2185 "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
2190 if (teximage
->IsCompressed
) {
2191 if (!target_can_be_compressed(ctx
, target
)) {
2192 _mesa_error(ctx
, GL_INVALID_ENUM
,
2193 "glCopyTexSubImage%d(target)", dimensions
);
2196 /* offset must be multiple of 4 */
2197 if ((xoffset
& 3) || (yoffset
& 3)) {
2198 _mesa_error(ctx
, GL_INVALID_VALUE
,
2199 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions
);
2202 /* size must be multiple of 4 */
2203 if ((width
& 3) != 0 && (GLuint
) width
!= teximage
->Width
) {
2204 _mesa_error(ctx
, GL_INVALID_VALUE
,
2205 "glCopyTexSubImage%D(width)", dimensions
);
2208 if ((height
& 3) != 0 && (GLuint
) height
!= teximage
->Height
) {
2209 _mesa_error(ctx
, GL_INVALID_VALUE
,
2210 "glCopyTexSubImage%D(height)", dimensions
);
2215 if (teximage
->InternalFormat
== GL_YCBCR_MESA
) {
2216 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glCopyTexSubImage2D");
2220 if (!_mesa_source_buffer_exists(ctx
, teximage
->_BaseFormat
)) {
2221 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2222 "glCopyTexSubImage%dD(missing readbuffer)", dimensions
);
2226 if (teximage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
2227 if (!ctx
->ReadBuffer
->_DepthBuffer
) {
2228 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2229 "glCopyTexSubImage%D(no depth buffer)",
2234 else if (teximage
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2235 if (!ctx
->ReadBuffer
->_DepthBuffer
|| !ctx
->ReadBuffer
->_StencilBuffer
) {
2236 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2237 "glCopyTexSubImage%D(no depth/stencil buffer)",
2243 /* if we get here, the parameters are OK */
2249 * Get texture image. Called by glGetTexImage.
2251 * \param target texture target.
2252 * \param level image level.
2253 * \param format pixel data format for returned image.
2254 * \param type pixel data type for returned image.
2255 * \param pixels returned pixel data.
2258 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
2259 GLenum type
, GLvoid
*pixels
)
2261 const struct gl_texture_unit
*texUnit
;
2262 struct gl_texture_object
*texObj
;
2263 struct gl_texture_image
*texImage
;
2264 GLint maxLevels
= 0;
2265 GET_CURRENT_CONTEXT(ctx
);
2266 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2268 texUnit
= &(ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
]);
2269 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2270 if (!texObj
|| _mesa_is_proxy_texture(target
)) {
2271 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)");
2275 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
2276 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
2278 if (level
< 0 || level
>= maxLevels
) {
2279 _mesa_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
2283 if (_mesa_sizeof_packed_type(type
) <= 0) {
2284 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
2288 if (_mesa_components_in_format(format
) <= 0 ||
2289 format
== GL_STENCIL_INDEX
) {
2290 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
2294 if (!ctx
->Extensions
.EXT_paletted_texture
&& is_index_format(format
)) {
2295 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2299 if (!ctx
->Extensions
.ARB_depth_texture
&& is_depth_format(format
)) {
2300 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2304 if (!ctx
->Extensions
.MESA_ycbcr_texture
&& is_ycbcr_format(format
)) {
2305 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2309 if (!ctx
->Extensions
.EXT_packed_depth_stencil
2310 && is_depthstencil_format(format
)) {
2311 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2315 _mesa_lock_texture(ctx
, texObj
);
2317 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2319 /* invalid mipmap level, not an error */
2324 /* Make sure the requested image format is compatible with the
2325 * texture's format. Note that a color index texture can be converted
2326 * to RGBA so that combo is allowed.
2328 if (is_color_format(format
)
2329 && !is_color_format(texImage
->TexFormat
->BaseFormat
)
2330 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
2331 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2334 else if (is_index_format(format
)
2335 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
2336 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2339 else if (is_depth_format(format
)
2340 && !is_depth_format(texImage
->TexFormat
->BaseFormat
)
2341 && !is_depthstencil_format(texImage
->TexFormat
->BaseFormat
)) {
2342 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2345 else if (is_ycbcr_format(format
)
2346 && !is_ycbcr_format(texImage
->TexFormat
->BaseFormat
)) {
2347 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2350 else if (is_depthstencil_format(format
)
2351 && !is_depthstencil_format(texImage
->TexFormat
->BaseFormat
)) {
2352 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2356 if (ctx
->Pack
.BufferObj
->Name
) {
2357 /* packing texture image into a PBO */
2358 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
2359 if (!_mesa_validate_pbo_access(dimensions
, &ctx
->Pack
, texImage
->Width
,
2360 texImage
->Height
, texImage
->Depth
,
2361 format
, type
, pixels
)) {
2362 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2363 "glGetTexImage(invalid PBO access)");
2368 /* typically, this will call _mesa_get_teximage() */
2369 ctx
->Driver
.GetTexImage(ctx
, target
, level
, format
, type
, pixels
,
2374 _mesa_unlock_texture(ctx
, texObj
);
2380 * Check if the given texture image is bound to any framebuffer objects
2381 * and update/invalidate them.
2382 * XXX We're only checking the currently bound framebuffer object for now.
2383 * In the future, perhaps struct gl_texture_image should have a pointer (or
2384 * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to.
2387 update_fbo_texture(GLcontext
*ctx
, struct gl_texture_object
*texObj
,
2388 GLuint face
, GLuint level
)
2390 if (ctx
->DrawBuffer
->Name
) {
2392 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
2393 struct gl_renderbuffer_attachment
*att
=
2394 ctx
->DrawBuffer
->Attachment
+ i
;
2395 if (att
->Type
== GL_TEXTURE
&&
2396 att
->Texture
== texObj
&&
2397 att
->TextureLevel
== level
&&
2398 att
->CubeMapFace
== face
) {
2399 ASSERT(att
->Texture
->Image
[att
->CubeMapFace
][att
->TextureLevel
]);
2400 /* Tell driver about the new renderbuffer texture */
2401 ctx
->Driver
.RenderTexture(ctx
, ctx
->DrawBuffer
, att
);
2410 * Called from the API. Note that width includes the border.
2413 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalFormat
,
2414 GLsizei width
, GLint border
, GLenum format
,
2415 GLenum type
, const GLvoid
*pixels
)
2417 GLsizei postConvWidth
= width
;
2418 GET_CURRENT_CONTEXT(ctx
);
2419 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2421 #if FEATURE_convolve
2422 if (is_color_format(internalFormat
)) {
2423 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2427 if (target
== GL_TEXTURE_1D
) {
2428 /* non-proxy target */
2429 struct gl_texture_unit
*texUnit
;
2430 struct gl_texture_object
*texObj
;
2431 struct gl_texture_image
*texImage
;
2432 const GLuint face
= _mesa_tex_target_to_face(target
);
2434 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2435 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2436 return; /* error was recorded */
2439 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2440 _mesa_update_state(ctx
);
2442 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2443 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2444 _mesa_lock_texture(ctx
, texObj
);
2446 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
2448 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2452 if (texImage
->Data
) {
2453 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2456 ASSERT(texImage
->Data
== NULL
);
2458 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2459 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2460 postConvWidth
, 1, 1,
2461 border
, internalFormat
);
2463 ASSERT(ctx
->Driver
.TexImage1D
);
2465 /* Give the texture to the driver! <pixels> may be null! */
2466 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
2467 width
, border
, format
, type
, pixels
,
2468 &ctx
->Unpack
, texObj
, texImage
);
2470 ASSERT(texImage
->TexFormat
);
2472 update_fbo_texture(ctx
, texObj
, face
, level
);
2475 texObj
->_Complete
= GL_FALSE
;
2476 ctx
->NewState
|= _NEW_TEXTURE
;
2479 _mesa_unlock_texture(ctx
, texObj
);
2481 else if (target
== GL_PROXY_TEXTURE_1D
) {
2482 /* Proxy texture: check for errors and update proxy state */
2483 struct gl_texture_image
*texImage
;
2484 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2485 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2486 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2487 /* when error, clear all proxy texture image parameters */
2489 clear_teximage_fields(texImage
);
2492 /* no error, set the tex image parameters */
2494 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2495 postConvWidth
, 1, 1,
2496 border
, internalFormat
);
2497 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2498 internalFormat
, format
, type
);
2502 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
2509 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalFormat
,
2510 GLsizei width
, GLsizei height
, GLint border
,
2511 GLenum format
, GLenum type
,
2512 const GLvoid
*pixels
)
2514 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2515 GET_CURRENT_CONTEXT(ctx
);
2516 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2518 #if FEATURE_convolve
2519 if (is_color_format(internalFormat
)) {
2520 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2525 if (target
== GL_TEXTURE_2D
||
2526 (ctx
->Extensions
.ARB_texture_cube_map
&&
2527 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2528 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) ||
2529 (ctx
->Extensions
.NV_texture_rectangle
&&
2530 target
== GL_TEXTURE_RECTANGLE_NV
) ||
2531 (ctx
->Extensions
.MESA_texture_array
&&
2532 target
== GL_TEXTURE_1D_ARRAY_EXT
)) {
2533 /* non-proxy target */
2534 struct gl_texture_unit
*texUnit
;
2535 struct gl_texture_object
*texObj
;
2536 struct gl_texture_image
*texImage
;
2537 const GLuint face
= _mesa_tex_target_to_face(target
);
2539 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2540 format
, type
, 2, postConvWidth
, postConvHeight
,
2542 return; /* error was recorded */
2545 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2546 _mesa_update_state(ctx
);
2548 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2549 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2550 _mesa_lock_texture(ctx
, texObj
);
2552 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
2554 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2558 if (texImage
->Data
) {
2559 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2562 ASSERT(texImage
->Data
== NULL
);
2563 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2564 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2565 postConvWidth
, postConvHeight
, 1,
2566 border
, internalFormat
);
2568 ASSERT(ctx
->Driver
.TexImage2D
);
2570 /* Give the texture to the driver! <pixels> may be null! */
2571 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
2572 width
, height
, border
, format
, type
, pixels
,
2573 &ctx
->Unpack
, texObj
, texImage
);
2575 ASSERT(texImage
->TexFormat
);
2577 update_fbo_texture(ctx
, texObj
, face
, level
);
2580 texObj
->_Complete
= GL_FALSE
;
2581 ctx
->NewState
|= _NEW_TEXTURE
;
2584 _mesa_unlock_texture(ctx
, texObj
);
2586 else if (target
== GL_PROXY_TEXTURE_2D
||
2587 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2588 ctx
->Extensions
.ARB_texture_cube_map
) ||
2589 (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
&&
2590 ctx
->Extensions
.NV_texture_rectangle
) ||
2591 (ctx
->Extensions
.MESA_texture_array
&&
2592 target
== GL_PROXY_TEXTURE_1D_ARRAY_EXT
)) {
2593 /* Proxy texture: check for errors and update proxy state */
2594 struct gl_texture_image
*texImage
;
2595 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2596 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2597 format
, type
, 2, postConvWidth
, postConvHeight
,
2599 /* when error, clear all proxy texture image parameters */
2601 clear_teximage_fields(ctx
->Texture
.ProxyTex
[TEXTURE_2D_INDEX
]->Image
[0][level
]);
2604 /* no error, set the tex image parameters */
2605 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2606 postConvWidth
, postConvHeight
, 1,
2607 border
, internalFormat
);
2608 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2609 internalFormat
, format
, type
);
2613 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
2620 * Called by the API or display list executor.
2621 * Note that width and height include the border.
2624 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalFormat
,
2625 GLsizei width
, GLsizei height
, GLsizei depth
,
2626 GLint border
, GLenum format
, GLenum type
,
2627 const GLvoid
*pixels
)
2629 GET_CURRENT_CONTEXT(ctx
);
2630 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2632 if (target
== GL_TEXTURE_3D
||
2633 (ctx
->Extensions
.MESA_texture_array
&&
2634 target
== GL_TEXTURE_2D_ARRAY_EXT
)) {
2635 /* non-proxy target */
2636 struct gl_texture_unit
*texUnit
;
2637 struct gl_texture_object
*texObj
;
2638 struct gl_texture_image
*texImage
;
2639 const GLuint face
= _mesa_tex_target_to_face(target
);
2641 if (texture_error_check(ctx
, target
, level
, (GLint
) internalFormat
,
2642 format
, type
, 3, width
, height
, depth
, border
)) {
2643 return; /* error was recorded */
2646 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2647 _mesa_update_state(ctx
);
2649 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2650 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2651 _mesa_lock_texture(ctx
, texObj
);
2653 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
2655 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2659 if (texImage
->Data
) {
2660 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2663 ASSERT(texImage
->Data
== NULL
);
2664 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2665 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2666 width
, height
, depth
,
2667 border
, internalFormat
);
2669 ASSERT(ctx
->Driver
.TexImage3D
);
2671 /* Give the texture to the driver! <pixels> may be null! */
2672 (*ctx
->Driver
.TexImage3D
)(ctx
, target
, level
, internalFormat
,
2673 width
, height
, depth
, border
, format
, type
,
2674 pixels
, &ctx
->Unpack
, texObj
, texImage
);
2676 ASSERT(texImage
->TexFormat
);
2678 update_fbo_texture(ctx
, texObj
, face
, level
);
2681 texObj
->_Complete
= GL_FALSE
;
2682 ctx
->NewState
|= _NEW_TEXTURE
;
2685 _mesa_unlock_texture(ctx
, texObj
);
2687 else if (target
== GL_PROXY_TEXTURE_3D
||
2688 (ctx
->Extensions
.MESA_texture_array
&&
2689 target
== GL_PROXY_TEXTURE_2D_ARRAY_EXT
)) {
2690 /* Proxy texture: check for errors and update proxy state */
2691 struct gl_texture_image
*texImage
;
2692 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2693 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2694 format
, type
, 3, width
, height
, depth
, border
)) {
2695 /* when error, clear all proxy texture image parameters */
2697 clear_teximage_fields(texImage
);
2700 /* no error, set the tex image parameters */
2701 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
,
2702 depth
, border
, internalFormat
);
2703 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2704 internalFormat
, format
, type
);
2708 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
2715 _mesa_TexImage3DEXT( GLenum target
, GLint level
, GLenum internalFormat
,
2716 GLsizei width
, GLsizei height
, GLsizei depth
,
2717 GLint border
, GLenum format
, GLenum type
,
2718 const GLvoid
*pixels
)
2720 _mesa_TexImage3D(target
, level
, (GLint
) internalFormat
, width
, height
,
2721 depth
, border
, format
, type
, pixels
);
2727 _mesa_TexSubImage1D( GLenum target
, GLint level
,
2728 GLint xoffset
, GLsizei width
,
2729 GLenum format
, GLenum type
,
2730 const GLvoid
*pixels
)
2732 GLsizei postConvWidth
= width
;
2733 struct gl_texture_unit
*texUnit
;
2734 struct gl_texture_object
*texObj
;
2735 struct gl_texture_image
*texImage
= NULL
;
2736 GET_CURRENT_CONTEXT(ctx
);
2737 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2739 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2740 _mesa_update_state(ctx
);
2742 #if FEATURE_convolve
2743 /* XXX should test internal format */
2744 if (is_color_format(format
)) {
2745 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2749 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
2750 postConvWidth
, 1, 1, format
, type
)) {
2751 return; /* error was detected */
2755 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2756 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2759 _mesa_lock_texture(ctx
, texObj
);
2761 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2763 if (subtexture_error_check2(ctx
, 1, target
, level
, xoffset
, 0, 0,
2764 postConvWidth
, 1, 1, format
, type
, texImage
)) {
2765 goto out
; /* error was detected */
2769 goto out
; /* no-op, not an error */
2771 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2772 xoffset
+= texImage
->Border
;
2774 ASSERT(ctx
->Driver
.TexSubImage1D
);
2775 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
2776 format
, type
, pixels
, &ctx
->Unpack
,
2778 ctx
->NewState
|= _NEW_TEXTURE
;
2781 _mesa_unlock_texture(ctx
, texObj
);
2786 _mesa_TexSubImage2D( GLenum target
, GLint level
,
2787 GLint xoffset
, GLint yoffset
,
2788 GLsizei width
, GLsizei height
,
2789 GLenum format
, GLenum type
,
2790 const GLvoid
*pixels
)
2792 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2793 struct gl_texture_unit
*texUnit
;
2794 struct gl_texture_object
*texObj
;
2795 struct gl_texture_image
*texImage
;
2796 GET_CURRENT_CONTEXT(ctx
);
2797 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2799 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2800 _mesa_update_state(ctx
);
2802 #if FEATURE_convolve
2803 /* XXX should test internal format */
2804 if (is_color_format(format
)) {
2805 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2810 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2811 postConvWidth
, postConvHeight
, 1, format
, type
)) {
2812 return; /* error was detected */
2815 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2816 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2817 _mesa_lock_texture(ctx
, texObj
);
2819 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2821 if (subtexture_error_check2(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2822 postConvWidth
, postConvHeight
, 1, format
, type
,
2824 goto out
; /* error was detected */
2827 if (width
== 0 || height
== 0)
2828 goto out
; /* no-op, not an error */
2830 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2831 xoffset
+= texImage
->Border
;
2832 yoffset
+= texImage
->Border
;
2834 ASSERT(ctx
->Driver
.TexSubImage2D
);
2835 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
, xoffset
, yoffset
,
2836 width
, height
, format
, type
, pixels
,
2837 &ctx
->Unpack
, texObj
, texImage
);
2838 ctx
->NewState
|= _NEW_TEXTURE
;
2841 _mesa_unlock_texture(ctx
, texObj
);
2847 _mesa_TexSubImage3D( GLenum target
, GLint level
,
2848 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2849 GLsizei width
, GLsizei height
, GLsizei depth
,
2850 GLenum format
, GLenum type
,
2851 const GLvoid
*pixels
)
2853 struct gl_texture_unit
*texUnit
;
2854 struct gl_texture_object
*texObj
;
2855 struct gl_texture_image
*texImage
;
2856 GET_CURRENT_CONTEXT(ctx
);
2857 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2859 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2860 _mesa_update_state(ctx
);
2862 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2863 width
, height
, depth
, format
, type
)) {
2864 return; /* error was detected */
2867 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2868 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2870 _mesa_lock_texture(ctx
, texObj
);
2872 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2874 if (subtexture_error_check2(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2875 width
, height
, depth
, format
, type
, texImage
)) {
2876 goto out
; /* error was detected */
2879 if (width
== 0 || height
== 0 || height
== 0)
2880 goto out
; /* no-op, not an error */
2882 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2883 xoffset
+= texImage
->Border
;
2884 yoffset
+= texImage
->Border
;
2885 zoffset
+= texImage
->Border
;
2887 ASSERT(ctx
->Driver
.TexSubImage3D
);
2888 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
2889 xoffset
, yoffset
, zoffset
,
2890 width
, height
, depth
,
2891 format
, type
, pixels
,
2892 &ctx
->Unpack
, texObj
, texImage
);
2893 ctx
->NewState
|= _NEW_TEXTURE
;
2896 _mesa_unlock_texture(ctx
, texObj
);
2902 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
2903 GLenum internalFormat
,
2905 GLsizei width
, GLint border
)
2907 struct gl_texture_unit
*texUnit
;
2908 struct gl_texture_object
*texObj
;
2909 struct gl_texture_image
*texImage
;
2910 GLsizei postConvWidth
= width
;
2911 const GLuint face
= _mesa_tex_target_to_face(target
);
2912 GET_CURRENT_CONTEXT(ctx
);
2913 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2915 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2916 _mesa_update_state(ctx
);
2918 #if FEATURE_convolve
2919 if (is_color_format(internalFormat
)) {
2920 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2924 if (copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
2925 postConvWidth
, 1, border
))
2928 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2929 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2930 _mesa_lock_texture(ctx
, texObj
);
2932 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
2934 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
2938 if (texImage
->Data
) {
2939 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2942 ASSERT(texImage
->Data
== NULL
);
2944 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2945 _mesa_init_teximage_fields(ctx
, target
, texImage
, postConvWidth
, 1, 1,
2946 border
, internalFormat
);
2949 ASSERT(ctx
->Driver
.CopyTexImage1D
);
2950 (*ctx
->Driver
.CopyTexImage1D
)(ctx
, target
, level
, internalFormat
,
2951 x
, y
, width
, border
);
2953 ASSERT(texImage
->TexFormat
);
2955 update_fbo_texture(ctx
, texObj
, face
, level
);
2958 texObj
->_Complete
= GL_FALSE
;
2959 ctx
->NewState
|= _NEW_TEXTURE
;
2962 _mesa_unlock_texture(ctx
, texObj
);
2968 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
2969 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2972 struct gl_texture_unit
*texUnit
;
2973 struct gl_texture_object
*texObj
;
2974 struct gl_texture_image
*texImage
;
2975 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2976 const GLuint face
= _mesa_tex_target_to_face(target
);
2977 GET_CURRENT_CONTEXT(ctx
);
2978 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2980 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2981 _mesa_update_state(ctx
);
2983 #if FEATURE_convolve
2984 if (is_color_format(internalFormat
)) {
2985 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2989 if (copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
2990 postConvWidth
, postConvHeight
, border
))
2993 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2994 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2996 _mesa_lock_texture(ctx
, texObj
);
2998 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
3001 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
3005 if (texImage
->Data
) {
3006 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3009 ASSERT(texImage
->Data
== NULL
);
3011 clear_teximage_fields(texImage
); /* not really needed, but helpful */
3012 _mesa_init_teximage_fields(ctx
, target
, texImage
,
3013 postConvWidth
, postConvHeight
, 1,
3014 border
, internalFormat
);
3016 ASSERT(ctx
->Driver
.CopyTexImage2D
);
3017 (*ctx
->Driver
.CopyTexImage2D
)(ctx
, target
, level
, internalFormat
,
3018 x
, y
, width
, height
, border
);
3020 ASSERT(texImage
->TexFormat
);
3022 update_fbo_texture(ctx
, texObj
, face
, level
);
3025 texObj
->_Complete
= GL_FALSE
;
3026 ctx
->NewState
|= _NEW_TEXTURE
;
3029 _mesa_unlock_texture(ctx
, texObj
);
3034 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
3035 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
3037 struct gl_texture_unit
*texUnit
;
3038 struct gl_texture_object
*texObj
;
3039 struct gl_texture_image
*texImage
;
3040 GLsizei postConvWidth
= width
;
3044 GET_CURRENT_CONTEXT(ctx
);
3045 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3047 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
3048 _mesa_update_state(ctx
);
3050 #if FEATURE_convolve
3051 /* XXX should test internal format */
3052 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
3055 if (copytexsubimage_error_check(ctx
, 1, target
, level
,
3056 xoffset
, 0, 0, postConvWidth
, 1))
3059 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3060 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3062 _mesa_lock_texture(ctx
, texObj
);
3064 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3066 if (copytexsubimage_error_check2(ctx
, 1, target
, level
,
3067 xoffset
, 0, 0, postConvWidth
, 1,
3072 /* If we have a border, xoffset=-1 is legal. Bias by border width */
3073 xoffset
+= texImage
->Border
;
3075 if (_mesa_clip_copytexsubimage(ctx
, &xoffset
, &yoffset
, &x
, &y
,
3077 ASSERT(ctx
->Driver
.CopyTexSubImage1D
);
3078 ctx
->Driver
.CopyTexSubImage1D(ctx
, target
, level
,
3079 xoffset
, x
, y
, width
);
3082 ctx
->NewState
|= _NEW_TEXTURE
;
3085 _mesa_unlock_texture(ctx
, texObj
);
3091 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
3092 GLint xoffset
, GLint yoffset
,
3093 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
3095 struct gl_texture_unit
*texUnit
;
3096 struct gl_texture_object
*texObj
;
3097 struct gl_texture_image
*texImage
;
3098 GLsizei postConvWidth
= width
, postConvHeight
= height
;
3099 GET_CURRENT_CONTEXT(ctx
);
3100 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3102 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
3103 _mesa_update_state(ctx
);
3105 #if FEATURE_convolve
3106 /* XXX should test internal format */
3107 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
3110 if (copytexsubimage_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
3111 postConvWidth
, postConvHeight
))
3114 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3115 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3117 _mesa_lock_texture(ctx
, texObj
);
3119 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3121 if (copytexsubimage_error_check2(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
3122 postConvWidth
, postConvHeight
, texImage
))
3125 /* If we have a border, xoffset=-1 is legal. Bias by border width */
3126 xoffset
+= texImage
->Border
;
3127 yoffset
+= texImage
->Border
;
3129 if (_mesa_clip_copytexsubimage(ctx
, &xoffset
, &yoffset
, &x
, &y
,
3131 ASSERT(ctx
->Driver
.CopyTexSubImage2D
);
3132 ctx
->Driver
.CopyTexSubImage2D(ctx
, target
, level
,
3133 xoffset
, yoffset
, x
, y
, width
, height
);
3136 ctx
->NewState
|= _NEW_TEXTURE
;
3139 _mesa_unlock_texture(ctx
, texObj
);
3145 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
3146 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3147 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
3149 struct gl_texture_unit
*texUnit
;
3150 struct gl_texture_object
*texObj
;
3151 struct gl_texture_image
*texImage
;
3152 GLsizei postConvWidth
= width
, postConvHeight
= height
;
3153 GET_CURRENT_CONTEXT(ctx
);
3154 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3156 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
3157 _mesa_update_state(ctx
);
3159 #if FEATURE_convolve
3160 /* XXX should test internal format */
3161 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
3164 if (copytexsubimage_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
,
3165 zoffset
, postConvWidth
, postConvHeight
))
3168 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3169 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3171 _mesa_lock_texture(ctx
, texObj
);
3173 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3175 if (copytexsubimage_error_check2(ctx
, 3, target
, level
, xoffset
, yoffset
,
3176 zoffset
, postConvWidth
, postConvHeight
,
3180 /* If we have a border, xoffset=-1 is legal. Bias by border width */
3181 xoffset
+= texImage
->Border
;
3182 yoffset
+= texImage
->Border
;
3183 zoffset
+= texImage
->Border
;
3185 if (_mesa_clip_copytexsubimage(ctx
, &xoffset
, &yoffset
, &x
, &y
,
3187 ASSERT(ctx
->Driver
.CopyTexSubImage3D
);
3188 ctx
->Driver
.CopyTexSubImage3D(ctx
, target
, level
,
3189 xoffset
, yoffset
, zoffset
,
3190 x
, y
, width
, height
);
3193 ctx
->NewState
|= _NEW_TEXTURE
;
3196 _mesa_unlock_texture(ctx
, texObj
);
3202 /**********************************************************************/
3203 /****** Compressed Textures ******/
3204 /**********************************************************************/
3208 * Error checking for glCompressedTexImage[123]D().
3209 * \return error code or GL_NO_ERROR.
3212 compressed_texture_error_check(GLcontext
*ctx
, GLint dimensions
,
3213 GLenum target
, GLint level
,
3214 GLenum internalFormat
, GLsizei width
,
3215 GLsizei height
, GLsizei depth
, GLint border
,
3218 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
3220 if (dimensions
== 1) {
3221 /* 1D compressed textures not allowed */
3222 return GL_INVALID_ENUM
;
3224 else if (dimensions
== 2) {
3225 if (target
== GL_PROXY_TEXTURE_2D
) {
3226 maxLevels
= ctx
->Const
.MaxTextureLevels
;
3228 else if (target
== GL_TEXTURE_2D
) {
3229 maxLevels
= ctx
->Const
.MaxTextureLevels
;
3231 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
3232 if (!ctx
->Extensions
.ARB_texture_cube_map
)
3233 return GL_INVALID_ENUM
; /*target*/
3234 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
3236 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3237 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
3238 if (!ctx
->Extensions
.ARB_texture_cube_map
)
3239 return GL_INVALID_ENUM
; /*target*/
3240 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
3243 return GL_INVALID_ENUM
; /*target*/
3246 else if (dimensions
== 3) {
3247 /* 3D compressed textures not allowed */
3248 return GL_INVALID_ENUM
;
3251 maxTextureSize
= 1 << (maxLevels
- 1);
3253 /* This will detect any invalid internalFormat value */
3254 if (!is_compressed_format(ctx
, internalFormat
))
3255 return GL_INVALID_ENUM
;
3257 /* This should really never fail */
3258 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0)
3259 return GL_INVALID_ENUM
;
3262 return GL_INVALID_VALUE
;
3265 * XXX We should probably use the proxy texture error check function here.
3267 if (width
< 1 || width
> maxTextureSize
||
3268 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(width
) != 1))
3269 return GL_INVALID_VALUE
;
3271 if ((height
< 1 || height
> maxTextureSize
||
3272 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(height
) != 1))
3274 return GL_INVALID_VALUE
;
3276 if ((depth
< 1 || depth
> maxTextureSize
||
3277 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(depth
) != 1))
3279 return GL_INVALID_VALUE
;
3281 /* For cube map, width must equal height */
3282 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3283 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
&& width
!= height
)
3284 return GL_INVALID_VALUE
;
3286 if (level
< 0 || level
>= maxLevels
)
3287 return GL_INVALID_VALUE
;
3289 expectedSize
= _mesa_compressed_texture_size_glenum(ctx
, width
, height
,
3290 depth
, internalFormat
);
3291 if (expectedSize
!= imageSize
)
3292 return GL_INVALID_VALUE
;
3294 #if FEATURE_EXT_texture_sRGB
3295 if ((internalFormat
== GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
||
3296 internalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
||
3297 internalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
||
3298 internalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
)
3300 return GL_INVALID_OPERATION
;
3309 * Error checking for glCompressedTexSubImage[123]D().
3310 * \warning There are some bad assumptions here about the size of compressed
3311 * texture tiles (multiple of 4) used to test the validity of the
3312 * offset and size parameters.
3313 * \return error code or GL_NO_ERROR.
3316 compressed_subtexture_error_check(GLcontext
*ctx
, GLint dimensions
,
3317 GLenum target
, GLint level
,
3318 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3319 GLsizei width
, GLsizei height
, GLsizei depth
,
3320 GLenum format
, GLsizei imageSize
)
3322 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
3325 if (dimensions
== 1) {
3326 /* 1D compressed textures not allowed */
3327 return GL_INVALID_ENUM
;
3329 else if (dimensions
== 2) {
3330 if (target
== GL_PROXY_TEXTURE_2D
) {
3331 maxLevels
= ctx
->Const
.MaxTextureLevels
;
3333 else if (target
== GL_TEXTURE_2D
) {
3334 maxLevels
= ctx
->Const
.MaxTextureLevels
;
3336 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
3337 if (!ctx
->Extensions
.ARB_texture_cube_map
)
3338 return GL_INVALID_ENUM
; /*target*/
3339 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
3341 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3342 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
3343 if (!ctx
->Extensions
.ARB_texture_cube_map
)
3344 return GL_INVALID_ENUM
; /*target*/
3345 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
3348 return GL_INVALID_ENUM
; /*target*/
3351 else if (dimensions
== 3) {
3352 /* 3D compressed textures not allowed */
3353 return GL_INVALID_ENUM
;
3356 maxTextureSize
= 1 << (maxLevels
- 1);
3358 /* this will catch any invalid compressed format token */
3359 if (!is_compressed_format(ctx
, format
))
3360 return GL_INVALID_ENUM
;
3362 if (width
< 1 || width
> maxTextureSize
)
3363 return GL_INVALID_VALUE
;
3365 if ((height
< 1 || height
> maxTextureSize
)
3367 return GL_INVALID_VALUE
;
3369 if (level
< 0 || level
>= maxLevels
)
3370 return GL_INVALID_VALUE
;
3372 /* XXX these tests are specific to the compressed format.
3373 * this code should be generalized in some way.
3375 if ((xoffset
& 3) != 0 || (yoffset
& 3) != 0)
3376 return GL_INVALID_VALUE
;
3378 if ((width
& 3) != 0 && width
!= 2 && width
!= 1)
3379 return GL_INVALID_VALUE
;
3381 if ((height
& 3) != 0 && height
!= 2 && height
!= 1)
3382 return GL_INVALID_VALUE
;
3384 expectedSize
= _mesa_compressed_texture_size_glenum(ctx
, width
, height
,
3386 if (expectedSize
!= imageSize
)
3387 return GL_INVALID_VALUE
;
3395 _mesa_CompressedTexImage1DARB(GLenum target
, GLint level
,
3396 GLenum internalFormat
, GLsizei width
,
3397 GLint border
, GLsizei imageSize
,
3400 GET_CURRENT_CONTEXT(ctx
);
3401 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3403 if (target
== GL_TEXTURE_1D
) {
3404 /* non-proxy target */
3405 struct gl_texture_unit
*texUnit
;
3406 struct gl_texture_object
*texObj
;
3407 struct gl_texture_image
*texImage
;
3408 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
3409 internalFormat
, width
, 1, 1, border
, imageSize
);
3411 _mesa_error(ctx
, error
, "glCompressedTexImage1D");
3415 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3416 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3418 _mesa_lock_texture(ctx
, texObj
);
3420 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
3422 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage1D");
3426 if (texImage
->Data
) {
3427 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3429 ASSERT(texImage
->Data
== NULL
);
3431 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
3432 border
, internalFormat
);
3434 ASSERT(ctx
->Driver
.CompressedTexImage1D
);
3435 (*ctx
->Driver
.CompressedTexImage1D
)(ctx
, target
, level
,
3436 internalFormat
, width
, border
,
3441 texObj
->_Complete
= GL_FALSE
;
3442 ctx
->NewState
|= _NEW_TEXTURE
;
3445 _mesa_unlock_texture(ctx
, texObj
);
3447 else if (target
== GL_PROXY_TEXTURE_1D
) {
3448 /* Proxy texture: check for errors and update proxy state */
3449 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
3450 internalFormat
, width
, 1, 1, border
, imageSize
);
3452 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3453 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3454 internalFormat
, GL_NONE
, GL_NONE
,
3455 width
, 1, 1, border
);
3458 /* if error, clear all proxy texture image parameters */
3459 struct gl_texture_image
*texImage
;
3460 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3462 clear_teximage_fields(texImage
);
3465 /* store the teximage parameters */
3466 struct gl_texture_unit
*texUnit
;
3467 struct gl_texture_object
*texObj
;
3468 struct gl_texture_image
*texImage
;
3469 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3470 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3472 _mesa_lock_texture(ctx
, texObj
);
3474 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3475 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
3476 border
, internalFormat
);
3478 _mesa_unlock_texture(ctx
, texObj
);
3482 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage1D(target)");
3489 _mesa_CompressedTexImage2DARB(GLenum target
, GLint level
,
3490 GLenum internalFormat
, GLsizei width
,
3491 GLsizei height
, GLint border
, GLsizei imageSize
,
3494 GET_CURRENT_CONTEXT(ctx
);
3495 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3497 if (target
== GL_TEXTURE_2D
||
3498 (ctx
->Extensions
.ARB_texture_cube_map
&&
3499 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3500 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
3501 /* non-proxy target */
3502 struct gl_texture_unit
*texUnit
;
3503 struct gl_texture_object
*texObj
;
3504 struct gl_texture_image
*texImage
;
3505 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
3506 internalFormat
, width
, height
, 1, border
, imageSize
);
3508 _mesa_error(ctx
, error
, "glCompressedTexImage2D");
3512 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3513 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3515 _mesa_lock_texture(ctx
, texObj
);
3517 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
3519 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
3523 if (texImage
->Data
) {
3524 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3526 ASSERT(texImage
->Data
== NULL
);
3528 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
3529 border
, internalFormat
);
3531 ASSERT(ctx
->Driver
.CompressedTexImage2D
);
3532 (*ctx
->Driver
.CompressedTexImage2D
)(ctx
, target
, level
,
3533 internalFormat
, width
, height
,
3534 border
, imageSize
, data
,
3538 texObj
->_Complete
= GL_FALSE
;
3539 ctx
->NewState
|= _NEW_TEXTURE
;
3542 _mesa_unlock_texture(ctx
, texObj
);
3544 else if (target
== GL_PROXY_TEXTURE_2D
||
3545 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
3546 ctx
->Extensions
.ARB_texture_cube_map
)) {
3547 /* Proxy texture: check for errors and update proxy state */
3548 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
3549 internalFormat
, width
, height
, 1, border
, imageSize
);
3551 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3552 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3553 internalFormat
, GL_NONE
, GL_NONE
,
3554 width
, height
, 1, border
);
3557 /* if error, clear all proxy texture image parameters */
3558 struct gl_texture_image
*texImage
;
3559 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3561 clear_teximage_fields(texImage
);
3564 /* store the teximage parameters */
3565 struct gl_texture_unit
*texUnit
;
3566 struct gl_texture_object
*texObj
;
3567 struct gl_texture_image
*texImage
;
3568 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3569 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3571 _mesa_lock_texture(ctx
, texObj
);
3573 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3574 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
3575 border
, internalFormat
);
3577 _mesa_unlock_texture(ctx
, texObj
);
3581 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(target)");
3588 _mesa_CompressedTexImage3DARB(GLenum target
, GLint level
,
3589 GLenum internalFormat
, GLsizei width
,
3590 GLsizei height
, GLsizei depth
, GLint border
,
3591 GLsizei imageSize
, const GLvoid
*data
)
3593 GET_CURRENT_CONTEXT(ctx
);
3594 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3596 if (target
== GL_TEXTURE_3D
) {
3597 /* non-proxy target */
3598 struct gl_texture_unit
*texUnit
;
3599 struct gl_texture_object
*texObj
;
3600 struct gl_texture_image
*texImage
;
3601 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3602 internalFormat
, width
, height
, depth
, border
, imageSize
);
3604 _mesa_error(ctx
, error
, "glCompressedTexImage3D");
3608 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3609 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3610 _mesa_lock_texture(ctx
, texObj
);
3612 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
3614 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage3D");
3618 if (texImage
->Data
) {
3619 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3621 ASSERT(texImage
->Data
== NULL
);
3623 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, depth
,
3624 border
, internalFormat
);
3626 ASSERT(ctx
->Driver
.CompressedTexImage3D
);
3627 (*ctx
->Driver
.CompressedTexImage3D
)(ctx
, target
, level
,
3629 width
, height
, depth
,
3630 border
, imageSize
, data
,
3634 texObj
->_Complete
= GL_FALSE
;
3635 ctx
->NewState
|= _NEW_TEXTURE
;
3638 _mesa_unlock_texture(ctx
, texObj
);
3640 else if (target
== GL_PROXY_TEXTURE_3D
) {
3641 /* Proxy texture: check for errors and update proxy state */
3642 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3643 internalFormat
, width
, height
, depth
, border
, imageSize
);
3645 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3646 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3647 internalFormat
, GL_NONE
, GL_NONE
,
3648 width
, height
, depth
, border
);
3651 /* if error, clear all proxy texture image parameters */
3652 struct gl_texture_image
*texImage
;
3653 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3655 clear_teximage_fields(texImage
);
3658 /* store the teximage parameters */
3659 struct gl_texture_unit
*texUnit
;
3660 struct gl_texture_object
*texObj
;
3661 struct gl_texture_image
*texImage
;
3662 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3663 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3664 _mesa_lock_texture(ctx
, texObj
);
3666 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3667 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
,
3668 depth
, border
, internalFormat
);
3670 _mesa_unlock_texture(ctx
, texObj
);
3674 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage3D(target)");
3681 _mesa_CompressedTexSubImage1DARB(GLenum target
, GLint level
, GLint xoffset
,
3682 GLsizei width
, GLenum format
,
3683 GLsizei imageSize
, const GLvoid
*data
)
3685 struct gl_texture_unit
*texUnit
;
3686 struct gl_texture_object
*texObj
;
3687 struct gl_texture_image
*texImage
;
3689 GET_CURRENT_CONTEXT(ctx
);
3690 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3692 error
= compressed_subtexture_error_check(ctx
, 1, target
, level
,
3693 xoffset
, 0, 0, /* pos */
3694 width
, 1, 1, /* size */
3697 _mesa_error(ctx
, error
, "glCompressedTexSubImage1D");
3701 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3702 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3703 _mesa_lock_texture(ctx
, texObj
);
3705 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3708 if ((GLint
) format
!= texImage
->InternalFormat
) {
3709 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3710 "glCompressedTexSubImage1D(format)");
3714 if ((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) {
3715 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage1D(width)");
3720 goto out
; /* no-op, not an error */
3722 if (ctx
->Driver
.CompressedTexSubImage1D
) {
3723 (*ctx
->Driver
.CompressedTexSubImage1D
)(ctx
, target
, level
,
3725 format
, imageSize
, data
,
3728 ctx
->NewState
|= _NEW_TEXTURE
;
3731 _mesa_unlock_texture(ctx
, texObj
);
3736 _mesa_CompressedTexSubImage2DARB(GLenum target
, GLint level
, GLint xoffset
,
3737 GLint yoffset
, GLsizei width
, GLsizei height
,
3738 GLenum format
, GLsizei imageSize
,
3741 struct gl_texture_unit
*texUnit
;
3742 struct gl_texture_object
*texObj
;
3743 struct gl_texture_image
*texImage
;
3745 GET_CURRENT_CONTEXT(ctx
);
3746 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3748 error
= compressed_subtexture_error_check(ctx
, 2, target
, level
,
3749 xoffset
, yoffset
, 0, /* pos */
3750 width
, height
, 1, /* size */
3753 /* XXX proxy target? */
3754 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3758 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3759 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3760 _mesa_lock_texture(ctx
, texObj
);
3762 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3765 if ((GLint
) format
!= texImage
->InternalFormat
) {
3766 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3767 "glCompressedTexSubImage2D(format)");
3771 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3772 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
)) {
3773 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage2D(size)");
3777 if (width
== 0 || height
== 0)
3778 goto out
; /* no-op, not an error */
3780 if (ctx
->Driver
.CompressedTexSubImage2D
) {
3781 (*ctx
->Driver
.CompressedTexSubImage2D
)(ctx
, target
, level
,
3782 xoffset
, yoffset
, width
, height
,
3783 format
, imageSize
, data
,
3786 ctx
->NewState
|= _NEW_TEXTURE
;
3789 _mesa_unlock_texture(ctx
, texObj
);
3794 _mesa_CompressedTexSubImage3DARB(GLenum target
, GLint level
, GLint xoffset
,
3795 GLint yoffset
, GLint zoffset
, GLsizei width
,
3796 GLsizei height
, GLsizei depth
, GLenum format
,
3797 GLsizei imageSize
, const GLvoid
*data
)
3799 struct gl_texture_unit
*texUnit
;
3800 struct gl_texture_object
*texObj
;
3801 struct gl_texture_image
*texImage
;
3803 GET_CURRENT_CONTEXT(ctx
);
3804 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3806 error
= compressed_subtexture_error_check(ctx
, 3, target
, level
,
3807 xoffset
, yoffset
, zoffset
,/*pos*/
3808 width
, height
, depth
, /*size*/
3811 _mesa_error(ctx
, error
, "glCompressedTexSubImage3D");
3815 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3816 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3817 _mesa_lock_texture(ctx
, texObj
);
3819 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3822 if ((GLint
) format
!= texImage
->InternalFormat
) {
3823 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3824 "glCompressedTexSubImage3D(format)");
3828 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3829 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
) ||
3830 ((depth
== 1 || depth
== 2) && (GLuint
) depth
!= texImage
->Depth
)) {
3831 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage3D(size)");
3835 if (width
== 0 || height
== 0 || depth
== 0)
3836 goto out
; /* no-op, not an error */
3838 if (ctx
->Driver
.CompressedTexSubImage3D
) {
3839 (*ctx
->Driver
.CompressedTexSubImage3D
)(ctx
, target
, level
,
3840 xoffset
, yoffset
, zoffset
,
3841 width
, height
, depth
,
3842 format
, imageSize
, data
,
3845 ctx
->NewState
|= _NEW_TEXTURE
;
3848 _mesa_unlock_texture(ctx
, texObj
);
3853 _mesa_GetCompressedTexImageARB(GLenum target
, GLint level
, GLvoid
*img
)
3855 const struct gl_texture_unit
*texUnit
;
3856 struct gl_texture_object
*texObj
;
3857 struct gl_texture_image
*texImage
;
3859 GET_CURRENT_CONTEXT(ctx
);
3860 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3862 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3863 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3865 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB");
3869 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
3870 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
3872 if (level
< 0 || level
>= maxLevels
) {
3873 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3877 if (_mesa_is_proxy_texture(target
)) {
3878 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
3882 _mesa_lock_texture(ctx
, texObj
);
3884 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3886 if (texImage
->IsCompressed
) {
3887 /* this typically calls _mesa_get_compressed_teximage() */
3888 ctx
->Driver
.GetCompressedTexImage(ctx
, target
, level
, img
,
3892 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3893 "glGetCompressedTexImageARB");
3897 /* probably invalid mipmap level */
3898 _mesa_error(ctx
, GL_INVALID_VALUE
,
3899 "glGetCompressedTexImageARB(level)");
3902 _mesa_unlock_texture(ctx
, texObj
);