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"
45 #include "texcompress.h"
46 #include "texformat.h"
54 * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
58 _mesa_alloc_texmemory(GLsizei bytes
)
60 return _mesa_align_malloc(bytes
, 512);
65 * Free texture memory allocated with _mesa_alloc_texmemory()
68 _mesa_free_texmemory(void *m
)
77 static void PrintTexture(GLcontext
*ctx
, const struct gl_texture_image
*img
)
79 #if CHAN_TYPE != GL_UNSIGNED_BYTE
80 _mesa_problem(NULL
, "PrintTexture not supported");
83 const GLubyte
*data
= (const GLubyte
*) img
->Data
;
86 _mesa_printf("No texture data\n");
90 switch (img
->Format
) {
97 case GL_LUMINANCE_ALPHA
:
107 _mesa_problem(NULL
, "error in PrintTexture\n");
111 for (i
= 0; i
< img
->Height
; i
++) {
112 for (j
= 0; j
< img
->Width
; j
++) {
114 _mesa_printf("%02x ", data
[0]);
116 _mesa_printf("%02x%02x ", data
[0], data
[1]);
118 _mesa_printf("%02x%02x%02x ", data
[0], data
[1], data
[2]);
120 _mesa_printf("%02x%02x%02x%02x ", data
[0], data
[1], data
[2], data
[3]);
121 data
+= (img
->RowStride
- img
->Width
) * c
;
123 /* XXX use img->ImageStride here */
132 * Compute floor(log_base_2(n)).
133 * If n < 0 return -1.
162 * Return the simple base format for a given internal texture format.
163 * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
165 * \param ctx GL context.
166 * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
168 * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
169 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
171 * This is the format which is used during texture application (i.e. the
172 * texture format and env mode determine the arithmetic used.
175 _mesa_base_tex_format( GLcontext
*ctx
, GLint internalFormat
)
177 switch (internalFormat
) {
192 case GL_LUMINANCE_ALPHA
:
193 case GL_LUMINANCE4_ALPHA4
:
194 case GL_LUMINANCE6_ALPHA2
:
195 case GL_LUMINANCE8_ALPHA8
:
196 case GL_LUMINANCE12_ALPHA4
:
197 case GL_LUMINANCE12_ALPHA12
:
198 case GL_LUMINANCE16_ALPHA16
:
199 return GL_LUMINANCE_ALPHA
;
230 if (ctx
->Extensions
.EXT_paletted_texture
) {
231 switch (internalFormat
) {
233 case GL_COLOR_INDEX1_EXT
:
234 case GL_COLOR_INDEX2_EXT
:
235 case GL_COLOR_INDEX4_EXT
:
236 case GL_COLOR_INDEX8_EXT
:
237 case GL_COLOR_INDEX12_EXT
:
238 case GL_COLOR_INDEX16_EXT
:
239 return GL_COLOR_INDEX
;
245 if (ctx
->Extensions
.ARB_depth_texture
) {
246 switch (internalFormat
) {
247 case GL_DEPTH_COMPONENT
:
248 case GL_DEPTH_COMPONENT16
:
249 case GL_DEPTH_COMPONENT24
:
250 case GL_DEPTH_COMPONENT32
:
251 return GL_DEPTH_COMPONENT
;
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
:
274 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
) {
275 switch (internalFormat
) {
276 case GL_COMPRESSED_RGB_FXT1_3DFX
:
278 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
285 if (ctx
->Extensions
.EXT_texture_compression_s3tc
) {
286 switch (internalFormat
) {
287 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
289 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
290 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
291 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
298 if (ctx
->Extensions
.S3_s3tc
) {
299 switch (internalFormat
) {
311 if (ctx
->Extensions
.MESA_ycbcr_texture
) {
312 if (internalFormat
== GL_YCBCR_MESA
)
313 return GL_YCBCR_MESA
;
316 if (ctx
->Extensions
.ARB_texture_float
) {
317 switch (internalFormat
) {
318 case GL_ALPHA16F_ARB
:
319 case GL_ALPHA32F_ARB
:
327 case GL_INTENSITY16F_ARB
:
328 case GL_INTENSITY32F_ARB
:
330 case GL_LUMINANCE16F_ARB
:
331 case GL_LUMINANCE32F_ARB
:
333 case GL_LUMINANCE_ALPHA16F_ARB
:
334 case GL_LUMINANCE_ALPHA32F_ARB
:
335 return GL_LUMINANCE_ALPHA
;
341 if (ctx
->Extensions
.EXT_packed_depth_stencil
) {
342 switch (internalFormat
) {
343 case GL_DEPTH_STENCIL_EXT
:
344 case GL_DEPTH24_STENCIL8_EXT
:
345 return GL_DEPTH_STENCIL_EXT
;
351 #if FEATURE_EXT_texture_sRGB
352 if (ctx
->Extensions
.EXT_texture_sRGB
) {
353 switch (internalFormat
) {
356 case GL_COMPRESSED_SRGB_EXT
:
357 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
:
359 case GL_SRGB_ALPHA_EXT
:
360 case GL_SRGB8_ALPHA8_EXT
:
361 case GL_COMPRESSED_SRGB_ALPHA_EXT
:
362 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
:
363 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
:
364 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
:
366 case GL_SLUMINANCE_ALPHA_EXT
:
367 case GL_SLUMINANCE8_ALPHA8_EXT
:
368 case GL_COMPRESSED_SLUMINANCE_EXT
:
369 case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT
:
370 return GL_LUMINANCE_ALPHA
;
371 case GL_SLUMINANCE_EXT
:
372 case GL_SLUMINANCE8_EXT
:
379 #endif /* FEATURE_EXT_texture_sRGB */
381 return -1; /* error */
386 * Test if the given image format is a color/RGBA format (i.e., not color
387 * index, depth, stencil, etc).
388 * \param format the image format value (may by an internal texture format)
389 * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
390 * XXX maybe move this func to image.c
393 _mesa_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 */
502 * Test if the given image format is a color index format.
505 is_index_format(GLenum format
)
509 case GL_COLOR_INDEX1_EXT
:
510 case GL_COLOR_INDEX2_EXT
:
511 case GL_COLOR_INDEX4_EXT
:
512 case GL_COLOR_INDEX8_EXT
:
513 case GL_COLOR_INDEX12_EXT
:
514 case GL_COLOR_INDEX16_EXT
:
523 * Test if the given image format is a depth component format.
526 is_depth_format(GLenum format
)
529 case GL_DEPTH_COMPONENT16
:
530 case GL_DEPTH_COMPONENT24
:
531 case GL_DEPTH_COMPONENT32
:
532 case GL_DEPTH_COMPONENT
:
541 * Test if the given image format is a YCbCr format.
544 is_ycbcr_format(GLenum format
)
556 * Test if the given image format is a Depth/Stencil format.
559 is_depthstencil_format(GLenum format
)
562 case GL_DEPTH24_STENCIL8_EXT
:
563 case GL_DEPTH_STENCIL_EXT
:
573 * Test if it is a supported compressed format.
575 * \param internalFormat the internal format token provided by the user.
577 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
578 * GL_FALSE otherwise.
580 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
584 is_compressed_format(GLcontext
*ctx
, GLenum internalFormat
)
586 GLint supported
[100]; /* 100 should be plenty */
589 n
= _mesa_get_compressed_formats(ctx
, supported
, GL_TRUE
);
591 for (i
= 0; i
< n
; i
++) {
592 if ((GLint
) internalFormat
== supported
[i
]) {
601 * For cube map faces, return a face index in [0,5].
602 * For other targets return 0;
605 _mesa_tex_target_to_face(GLenum target
)
607 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
608 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)
609 return (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
617 * Store a gl_texture_image pointer in a gl_texture_object structure
618 * according to the target and level parameters.
620 * \param tObj texture object.
621 * \param target texture target.
622 * \param level image level.
623 * \param texImage texture image.
625 * This was basically prompted by the introduction of cube maps.
628 _mesa_set_tex_image(struct gl_texture_object
*tObj
,
629 GLenum target
, GLint level
,
630 struct gl_texture_image
*texImage
)
634 /* XXX simplify this with _mesa_tex_target_to_face() */
639 case GL_TEXTURE_1D_ARRAY_EXT
:
640 case GL_TEXTURE_2D_ARRAY_EXT
:
641 tObj
->Image
[0][level
] = texImage
;
643 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
644 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
645 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
646 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
647 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
648 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
650 GLuint face
= ((GLuint
) target
-
651 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
652 tObj
->Image
[face
][level
] = texImage
;
655 case GL_TEXTURE_RECTANGLE_NV
:
657 tObj
->Image
[0][level
] = texImage
;
660 _mesa_problem(NULL
, "bad target in _mesa_set_tex_image()");
663 /* Set the 'back' pointer */
664 texImage
->TexObject
= tObj
;
669 * Allocate a texture image structure.
671 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
674 * \return a pointer to gl_texture_image struct with all fields initialized to
677 struct gl_texture_image
*
678 _mesa_new_texture_image( GLcontext
*ctx
)
681 return CALLOC_STRUCT(gl_texture_image
);
686 * Free texture image data.
687 * This function is a fallback called via ctx->Driver.FreeTexImageData().
689 * \param teximage texture image.
691 * Free the texture image data if it's not marked as client data.
694 _mesa_free_texture_image_data(GLcontext
*ctx
,
695 struct gl_texture_image
*texImage
)
699 if (texImage
->Data
&& !texImage
->IsClientData
) {
700 /* free the old texture data */
701 _mesa_free_texmemory(texImage
->Data
);
704 texImage
->Data
= NULL
;
709 * Free texture image.
711 * \param teximage texture image.
713 * Free the texture image structure and the associated image data.
716 _mesa_delete_texture_image( GLcontext
*ctx
, struct gl_texture_image
*texImage
)
718 /* Free texImage->Data and/or any other driver-specific texture
721 ASSERT(ctx
->Driver
.FreeTexImageData
);
722 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
724 ASSERT(texImage
->Data
== NULL
);
725 if (texImage
->ImageOffsets
)
726 _mesa_free(texImage
->ImageOffsets
);
727 _mesa_free(texImage
);
732 * Test if a target is a proxy target.
734 * \param target texture target.
736 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
739 _mesa_is_proxy_texture(GLenum target
)
741 return (target
== GL_PROXY_TEXTURE_1D
||
742 target
== GL_PROXY_TEXTURE_2D
||
743 target
== GL_PROXY_TEXTURE_3D
||
744 target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
745 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
||
746 target
== GL_PROXY_TEXTURE_1D_ARRAY_EXT
||
747 target
== GL_PROXY_TEXTURE_2D_ARRAY_EXT
);
752 * Get the texture object that corresponds to the target of the given texture unit.
754 * \param ctx GL context.
755 * \param texUnit texture unit.
756 * \param target texture target.
758 * \return pointer to the texture object on success, or NULL on failure.
760 * \sa gl_texture_unit.
762 struct gl_texture_object
*
763 _mesa_select_tex_object(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
768 return texUnit
->Current1D
;
769 case GL_PROXY_TEXTURE_1D
:
770 return ctx
->Texture
.ProxyTex
[TEXTURE_1D_INDEX
];
772 return texUnit
->Current2D
;
773 case GL_PROXY_TEXTURE_2D
:
774 return ctx
->Texture
.ProxyTex
[TEXTURE_2D_INDEX
];
776 return texUnit
->Current3D
;
777 case GL_PROXY_TEXTURE_3D
:
778 return ctx
->Texture
.ProxyTex
[TEXTURE_3D_INDEX
];
779 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
780 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
781 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
782 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
783 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
784 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
785 case GL_TEXTURE_CUBE_MAP_ARB
:
786 return ctx
->Extensions
.ARB_texture_cube_map
787 ? texUnit
->CurrentCubeMap
: NULL
;
788 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
789 return ctx
->Extensions
.ARB_texture_cube_map
790 ? ctx
->Texture
.ProxyTex
[TEXTURE_CUBE_INDEX
] : NULL
;
791 case GL_TEXTURE_RECTANGLE_NV
:
792 return ctx
->Extensions
.NV_texture_rectangle
793 ? texUnit
->CurrentRect
: NULL
;
794 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
795 return ctx
->Extensions
.NV_texture_rectangle
796 ? ctx
->Texture
.ProxyTex
[TEXTURE_RECT_INDEX
] : NULL
;
797 case GL_TEXTURE_1D_ARRAY_EXT
:
798 return ctx
->Extensions
.MESA_texture_array
799 ? texUnit
->Current1DArray
: NULL
;
800 case GL_PROXY_TEXTURE_1D_ARRAY_EXT
:
801 return ctx
->Extensions
.MESA_texture_array
802 ? ctx
->Texture
.ProxyTex
[TEXTURE_1D_ARRAY_INDEX
] : NULL
;
803 case GL_TEXTURE_2D_ARRAY_EXT
:
804 return ctx
->Extensions
.MESA_texture_array
805 ? texUnit
->Current2DArray
: NULL
;
806 case GL_PROXY_TEXTURE_2D_ARRAY_EXT
:
807 return ctx
->Extensions
.MESA_texture_array
808 ? ctx
->Texture
.ProxyTex
[TEXTURE_2D_ARRAY_INDEX
] : NULL
;
810 _mesa_problem(NULL
, "bad target in _mesa_select_tex_object()");
817 * Get the texture image struct which corresponds to target and level
818 * of the given texture unit.
820 * \param ctx GL context.
821 * \param texUnit texture unit.
822 * \param target texture target.
823 * \param level image level.
825 * \return pointer to the texture image structure on success, or NULL on failure.
827 * \sa gl_texture_unit.
829 struct gl_texture_image
*
830 _mesa_select_tex_image(GLcontext
*ctx
, const struct gl_texture_object
*texObj
,
831 GLenum target
, GLint level
)
835 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
)
838 /* XXX simplify this with _mesa_tex_target_to_face() */
841 case GL_PROXY_TEXTURE_1D
:
843 case GL_PROXY_TEXTURE_2D
:
845 case GL_PROXY_TEXTURE_3D
:
846 return texObj
->Image
[0][level
];
848 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
849 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
850 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
851 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
852 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
853 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
854 if (ctx
->Extensions
.ARB_texture_cube_map
) {
855 GLuint face
= ((GLuint
) target
-
856 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
857 return texObj
->Image
[face
][level
];
862 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
863 if (ctx
->Extensions
.ARB_texture_cube_map
)
864 return texObj
->Image
[0][level
];
868 case GL_TEXTURE_RECTANGLE_NV
:
869 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
870 if (ctx
->Extensions
.NV_texture_rectangle
&& level
== 0)
871 return texObj
->Image
[0][level
];
875 case GL_TEXTURE_1D_ARRAY_EXT
:
876 case GL_PROXY_TEXTURE_1D_ARRAY_EXT
:
877 case GL_TEXTURE_2D_ARRAY_EXT
:
878 case GL_PROXY_TEXTURE_2D_ARRAY_EXT
:
879 return (ctx
->Extensions
.MESA_texture_array
)
880 ? texObj
->Image
[0][level
] : NULL
;
889 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
890 * it and install it. Only return NULL if passed a bad parameter or run
893 struct gl_texture_image
*
894 _mesa_get_tex_image(GLcontext
*ctx
, struct gl_texture_object
*texObj
,
895 GLenum target
, GLint level
)
897 struct gl_texture_image
*texImage
;
902 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
904 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
906 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture image allocation");
910 _mesa_set_tex_image(texObj
, target
, level
, texImage
);
918 * Return pointer to the specified proxy texture image.
919 * Note that proxy textures are per-context, not per-texture unit.
920 * \return pointer to texture image or NULL if invalid target, invalid
921 * level, or out of memory.
923 struct gl_texture_image
*
924 _mesa_get_proxy_tex_image(GLcontext
*ctx
, GLenum target
, GLint level
)
926 struct gl_texture_image
*texImage
;
932 case GL_PROXY_TEXTURE_1D
:
933 if (level
>= ctx
->Const
.MaxTextureLevels
)
935 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_1D_INDEX
]->Image
[0][level
];
937 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
939 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
942 ctx
->Texture
.ProxyTex
[TEXTURE_1D_INDEX
]->Image
[0][level
] = texImage
;
943 /* Set the 'back' pointer */
944 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_1D_INDEX
];
947 case GL_PROXY_TEXTURE_2D
:
948 if (level
>= ctx
->Const
.MaxTextureLevels
)
950 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_2D_INDEX
]->Image
[0][level
];
952 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
954 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
957 ctx
->Texture
.ProxyTex
[TEXTURE_2D_INDEX
]->Image
[0][level
] = texImage
;
958 /* Set the 'back' pointer */
959 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_2D_INDEX
];
962 case GL_PROXY_TEXTURE_3D
:
963 if (level
>= ctx
->Const
.Max3DTextureLevels
)
965 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_3D_INDEX
]->Image
[0][level
];
967 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
969 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
972 ctx
->Texture
.ProxyTex
[TEXTURE_3D_INDEX
]->Image
[0][level
] = texImage
;
973 /* Set the 'back' pointer */
974 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_3D_INDEX
];
977 case GL_PROXY_TEXTURE_CUBE_MAP
:
978 if (level
>= ctx
->Const
.MaxCubeTextureLevels
)
980 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_CUBE_INDEX
]->Image
[0][level
];
982 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
984 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
987 ctx
->Texture
.ProxyTex
[TEXTURE_CUBE_INDEX
]->Image
[0][level
] = texImage
;
988 /* Set the 'back' pointer */
989 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_CUBE_INDEX
];
992 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
995 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_RECT_INDEX
]->Image
[0][level
];
997 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
999 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
1002 ctx
->Texture
.ProxyTex
[TEXTURE_RECT_INDEX
]->Image
[0][level
] = texImage
;
1003 /* Set the 'back' pointer */
1004 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_RECT_INDEX
];
1007 case GL_PROXY_TEXTURE_1D_ARRAY_EXT
:
1008 if (level
>= ctx
->Const
.MaxTextureLevels
)
1010 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_1D_ARRAY_INDEX
]->Image
[0][level
];
1012 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
1014 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
1017 ctx
->Texture
.ProxyTex
[TEXTURE_1D_ARRAY_INDEX
]->Image
[0][level
] = texImage
;
1018 /* Set the 'back' pointer */
1019 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_1D_ARRAY_INDEX
];
1022 case GL_PROXY_TEXTURE_2D_ARRAY_EXT
:
1023 if (level
>= ctx
->Const
.MaxTextureLevels
)
1025 texImage
= ctx
->Texture
.ProxyTex
[TEXTURE_2D_ARRAY_INDEX
]->Image
[0][level
];
1027 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
1029 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
1032 ctx
->Texture
.ProxyTex
[TEXTURE_2D_ARRAY_INDEX
]->Image
[0][level
] = texImage
;
1033 /* Set the 'back' pointer */
1034 texImage
->TexObject
= ctx
->Texture
.ProxyTex
[TEXTURE_2D_ARRAY_INDEX
];
1044 * Get the maximum number of allowed mipmap levels.
1046 * \param ctx GL context.
1047 * \param target texture target.
1049 * \return the maximum number of allowed mipmap levels for the given
1050 * texture target, or zero if passed a bad target.
1055 _mesa_max_texture_levels(GLcontext
*ctx
, GLenum target
)
1059 case GL_PROXY_TEXTURE_1D
:
1061 case GL_PROXY_TEXTURE_2D
:
1062 case GL_TEXTURE_1D_ARRAY_EXT
:
1063 case GL_PROXY_TEXTURE_1D_ARRAY_EXT
:
1064 case GL_TEXTURE_2D_ARRAY_EXT
:
1065 case GL_PROXY_TEXTURE_2D_ARRAY_EXT
:
1066 return ctx
->Const
.MaxTextureLevels
;
1068 case GL_PROXY_TEXTURE_3D
:
1069 return ctx
->Const
.Max3DTextureLevels
;
1070 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
1071 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
1072 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
1073 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
1074 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
1075 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
1076 case GL_TEXTURE_CUBE_MAP_ARB
:
1077 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
1078 return ctx
->Const
.MaxCubeTextureLevels
;
1079 case GL_TEXTURE_RECTANGLE_NV
:
1080 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
1083 return 0; /* bad target */
1089 #if 000 /* not used anymore */
1091 * glTexImage[123]D can accept a NULL image pointer. In this case we
1092 * create a texture image with unspecified image contents per the OpenGL
1096 make_null_texture(GLint width
, GLint height
, GLint depth
, GLenum format
)
1098 const GLint components
= _mesa_components_in_format(format
);
1099 const GLint numPixels
= width
* height
* depth
;
1100 GLubyte
*data
= (GLubyte
*) MALLOC(numPixels
* components
* sizeof(GLubyte
));
1104 * Let's see if anyone finds this. If glTexImage2D() is called with
1105 * a NULL image pointer then load the texture image with something
1106 * interesting instead of leaving it indeterminate.
1109 static const char message
[8][32] = {
1110 " X X XXXXX XXX X ",
1111 " XX XX X X X X X ",
1113 " X X XXXX XXX XXXXX ",
1116 " X X XXXXX XXX X X ",
1120 GLubyte
*imgPtr
= data
;
1122 for (h
= 0; h
< depth
; h
++) {
1123 for (i
= 0; i
< height
; i
++) {
1124 GLint srcRow
= 7 - (i
% 8);
1125 for (j
= 0; j
< width
; j
++) {
1126 GLint srcCol
= j
% 32;
1127 GLubyte texel
= (message
[srcRow
][srcCol
]=='X') ? 255 : 70;
1128 for (k
= 0; k
< components
; k
++) {
1144 * Reset the fields of a gl_texture_image struct to zero.
1146 * \param img texture image structure.
1148 * This is called when a proxy texture test fails, we set all the
1149 * image members (except DriverData) to zero.
1150 * It's also used in glTexImage[123]D as a safeguard to be sure all
1151 * required fields get initialized properly by the Driver.TexImage[123]D
1155 clear_teximage_fields(struct gl_texture_image
*img
)
1158 img
->_BaseFormat
= 0;
1159 img
->InternalFormat
= 0;
1165 if (img
->ImageOffsets
) {
1166 _mesa_free(img
->ImageOffsets
);
1167 img
->ImageOffsets
= NULL
;
1173 img
->HeightLog2
= 0;
1176 img
->TexFormat
= &_mesa_null_texformat
;
1177 img
->FetchTexelc
= NULL
;
1178 img
->FetchTexelf
= NULL
;
1179 img
->IsCompressed
= 0;
1180 img
->CompressedSize
= 0;
1185 * Initialize basic fields of the gl_texture_image struct.
1187 * \param ctx GL context.
1188 * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
1189 * \param img texture image structure to be initialized.
1190 * \param width image width.
1191 * \param height image height.
1192 * \param depth image depth.
1193 * \param border image border.
1194 * \param internalFormat internal format.
1196 * Fills in the fields of \p img with the given information.
1197 * Note: width, height and depth include the border.
1200 _mesa_init_teximage_fields(GLcontext
*ctx
, GLenum target
,
1201 struct gl_texture_image
*img
,
1202 GLsizei width
, GLsizei height
, GLsizei depth
,
1203 GLint border
, GLenum internalFormat
)
1209 ASSERT(height
>= 0);
1212 img
->_BaseFormat
= _mesa_base_tex_format( ctx
, internalFormat
);
1213 ASSERT(img
->_BaseFormat
> 0);
1214 img
->InternalFormat
= internalFormat
;
1215 img
->Border
= border
;
1217 img
->Height
= height
;
1219 img
->Width2
= width
- 2 * border
; /* == 1 << img->WidthLog2; */
1220 img
->Height2
= height
- 2 * border
; /* == 1 << img->HeightLog2; */
1221 img
->Depth2
= depth
- 2 * border
; /* == 1 << img->DepthLog2; */
1222 img
->WidthLog2
= logbase2(img
->Width2
);
1223 if (height
== 1) /* 1-D texture */
1224 img
->HeightLog2
= 0;
1226 img
->HeightLog2
= logbase2(img
->Height2
);
1227 if (depth
== 1) /* 2-D texture */
1230 img
->DepthLog2
= logbase2(img
->Depth2
);
1231 img
->MaxLog2
= MAX2(img
->WidthLog2
, img
->HeightLog2
);
1232 img
->IsCompressed
= GL_FALSE
;
1233 img
->CompressedSize
= 0;
1235 if ((width
== 1 || _mesa_is_pow_two(img
->Width2
)) &&
1236 (height
== 1 || _mesa_is_pow_two(img
->Height2
)) &&
1237 (depth
== 1 || _mesa_is_pow_two(img
->Depth2
)))
1238 img
->_IsPowerOfTwo
= GL_TRUE
;
1240 img
->_IsPowerOfTwo
= GL_FALSE
;
1242 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
1243 img
->RowStride
= width
;
1244 /* Allocate the ImageOffsets array and initialize to typical values.
1245 * We allocate the array for 1D/2D textures too in order to avoid special-
1246 * case code in the texstore routines.
1248 img
->ImageOffsets
= (GLuint
*) _mesa_malloc(depth
* sizeof(GLuint
));
1249 for (i
= 0; i
< depth
; i
++) {
1250 img
->ImageOffsets
[i
] = i
* width
* height
;
1253 /* Compute Width/Height/DepthScale for mipmap lod computation */
1254 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1255 /* scale = 1.0 since texture coords directly map to texels */
1256 img
->WidthScale
= 1.0;
1257 img
->HeightScale
= 1.0;
1258 img
->DepthScale
= 1.0;
1261 img
->WidthScale
= (GLfloat
) img
->Width
;
1262 img
->HeightScale
= (GLfloat
) img
->Height
;
1263 img
->DepthScale
= (GLfloat
) img
->Depth
;
1269 * This is the fallback for Driver.TestProxyTexImage(). Test the texture
1270 * level, width, height and depth against the ctx->Const limits for textures.
1272 * A hardware driver might override this function if, for example, the
1273 * max 3D texture size is 512x512x64 (i.e. not a cube).
1275 * Note that width, height, depth == 0 is not an error. However, a
1276 * texture with zero width/height/depth will be considered "incomplete"
1277 * and texturing will effectively be disabled.
1279 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
1280 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
1281 * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
1282 * \param level as passed to glTexImage
1283 * \param internalFormat as passed to glTexImage
1284 * \param format as passed to glTexImage
1285 * \param type as passed to glTexImage
1286 * \param width as passed to glTexImage
1287 * \param height as passed to glTexImage
1288 * \param depth as passed to glTexImage
1289 * \param border as passed to glTexImage
1290 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1293 _mesa_test_proxy_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
1294 GLint internalFormat
, GLenum format
, GLenum type
,
1295 GLint width
, GLint height
, GLint depth
, GLint border
)
1299 (void) internalFormat
;
1304 case GL_PROXY_TEXTURE_1D
:
1305 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1306 if (width
< 2 * border
|| width
> 2 + maxSize
||
1307 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1308 width
>0 && !_mesa_is_pow_two(width
- 2 * border
)) ||
1309 level
>= ctx
->Const
.MaxTextureLevels
) {
1310 /* bad width or level */
1314 case GL_PROXY_TEXTURE_2D
:
1315 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1316 if (width
< 2 * border
|| width
> 2 + maxSize
||
1317 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1318 width
> 0 && !_mesa_is_pow_two(width
- 2 * border
)) ||
1319 height
< 2 * border
|| height
> 2 + maxSize
||
1320 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1321 height
> 0 && !_mesa_is_pow_two(height
- 2 * border
)) ||
1322 level
>= ctx
->Const
.MaxTextureLevels
) {
1323 /* bad width or height or level */
1327 case GL_PROXY_TEXTURE_3D
:
1328 maxSize
= 1 << (ctx
->Const
.Max3DTextureLevels
- 1);
1329 if (width
< 2 * border
|| width
> 2 + maxSize
||
1330 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1331 width
> 0 && !_mesa_is_pow_two(width
- 2 * border
)) ||
1332 height
< 2 * border
|| height
> 2 + maxSize
||
1333 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1334 height
> 0 && !_mesa_is_pow_two(height
- 2 * border
)) ||
1335 depth
< 2 * border
|| depth
> 2 + maxSize
||
1336 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1337 depth
> 0 && !_mesa_is_pow_two(depth
- 2 * border
)) ||
1338 level
>= ctx
->Const
.Max3DTextureLevels
) {
1339 /* bad width or height or depth or level */
1343 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
1344 if (width
< 0 || width
> ctx
->Const
.MaxTextureRectSize
||
1345 height
< 0 || height
> ctx
->Const
.MaxTextureRectSize
||
1347 /* bad width or height or level */
1351 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
1352 maxSize
= 1 << (ctx
->Const
.MaxCubeTextureLevels
- 1);
1353 if (width
< 2 * border
|| width
> 2 + maxSize
||
1354 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1355 width
> 0 && !_mesa_is_pow_two(width
- 2 * border
)) ||
1356 height
< 2 * border
|| height
> 2 + maxSize
||
1357 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1358 height
> 0 && !_mesa_is_pow_two(height
- 2 * border
)) ||
1359 level
>= ctx
->Const
.MaxCubeTextureLevels
) {
1360 /* bad width or height */
1364 case GL_PROXY_TEXTURE_1D_ARRAY_EXT
:
1365 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1366 if (width
< 2 * border
|| width
> 2 + maxSize
||
1367 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1368 width
> 0 && !_mesa_is_pow_two(width
- 2 * border
)) ||
1369 level
>= ctx
->Const
.MaxTextureLevels
) {
1370 /* bad width or level */
1374 if (height
< 1 || height
> ctx
->Const
.MaxArrayTextureLayers
) {
1378 case GL_PROXY_TEXTURE_2D_ARRAY_EXT
:
1379 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1380 if (width
< 2 * border
|| width
> 2 + maxSize
||
1381 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1382 width
> 0 && !_mesa_is_pow_two(width
- 2 * border
)) ||
1383 height
< 2 * border
|| height
> 2 + maxSize
||
1384 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1385 height
> 0 && !_mesa_is_pow_two(height
- 2 * border
)) ||
1386 level
>= ctx
->Const
.MaxTextureLevels
) {
1387 /* bad width or height or level */
1390 if (depth
< 1 || depth
> ctx
->Const
.MaxArrayTextureLayers
) {
1395 _mesa_problem(ctx
, "Invalid target in _mesa_test_proxy_teximage");
1402 * Helper function to determine whether a target supports compressed textures
1405 target_can_be_compressed(GLcontext
*ctx
, GLenum target
)
1407 return (((target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
))
1408 || ((ctx
->Extensions
.ARB_texture_cube_map
&&
1409 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1410 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1411 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))))
1412 || ((ctx
->Extensions
.MESA_texture_array
&&
1413 ((target
== GL_PROXY_TEXTURE_2D_ARRAY_EXT
) ||
1414 (target
== GL_TEXTURE_2D_ARRAY_EXT
)))));
1419 * Test the glTexImage[123]D() parameters for errors.
1421 * \param ctx GL context.
1422 * \param target texture target given by the user.
1423 * \param level image level given by the user.
1424 * \param internalFormat internal format given by the user.
1425 * \param format pixel data format given by the user.
1426 * \param type pixel data type given by the user.
1427 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1428 * \param width image width given by the user.
1429 * \param height image height given by the user.
1430 * \param depth image depth given by the user.
1431 * \param border image border given by the user.
1433 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1435 * Verifies each of the parameters against the constants specified in
1436 * __GLcontextRec::Const and the supported extensions, and according to the
1437 * OpenGL specification.
1440 texture_error_check( GLcontext
*ctx
, GLenum target
,
1441 GLint level
, GLint internalFormat
,
1442 GLenum format
, GLenum type
,
1444 GLint width
, GLint height
,
1445 GLint depth
, GLint border
)
1447 const GLboolean isProxy
= _mesa_is_proxy_texture(target
);
1448 GLboolean sizeOK
= GL_TRUE
;
1449 GLboolean colorFormat
, indexFormat
;
1450 GLenum proxy_target
;
1452 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1453 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1455 _mesa_error(ctx
, GL_INVALID_VALUE
,
1456 "glTexImage%dD(level=%d)", dimensions
, level
);
1462 if (border
< 0 || border
> 1 ||
1463 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1464 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1466 _mesa_error(ctx
, GL_INVALID_VALUE
,
1467 "glTexImage%dD(border=%d)", dimensions
, border
);
1472 if (width
< 0 || height
< 0 || depth
< 0) {
1474 _mesa_error(ctx
, GL_INVALID_VALUE
,
1475 "glTexImage%dD(width, height or depth < 0)", dimensions
);
1480 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1481 * level, width, height and depth.
1483 if (dimensions
== 1) {
1484 if (target
== GL_PROXY_TEXTURE_1D
|| target
== GL_TEXTURE_1D
) {
1485 proxy_target
= GL_PROXY_TEXTURE_1D
;
1490 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1494 else if (dimensions
== 2) {
1496 if (target
== GL_PROXY_TEXTURE_2D
|| target
== GL_TEXTURE_2D
) {
1497 proxy_target
= GL_PROXY_TEXTURE_2D
;
1499 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
1500 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1501 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
1502 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1503 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1506 proxy_target
= GL_PROXY_TEXTURE_CUBE_MAP_ARB
;
1507 sizeOK
= (width
== height
);
1509 else if (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
||
1510 target
== GL_TEXTURE_RECTANGLE_NV
) {
1511 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1512 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1515 proxy_target
= GL_PROXY_TEXTURE_RECTANGLE_NV
;
1517 else if (target
== GL_PROXY_TEXTURE_1D_ARRAY_EXT
||
1518 target
== GL_TEXTURE_1D_ARRAY_EXT
) {
1519 proxy_target
= GL_PROXY_TEXTURE_1D_ARRAY_EXT
;
1522 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1526 else if (dimensions
== 3) {
1527 if (target
== GL_PROXY_TEXTURE_3D
|| target
== GL_TEXTURE_3D
) {
1528 proxy_target
= GL_PROXY_TEXTURE_3D
;
1530 else if (target
== GL_PROXY_TEXTURE_2D_ARRAY_EXT
||
1531 target
== GL_TEXTURE_2D_ARRAY_EXT
) {
1532 proxy_target
= GL_PROXY_TEXTURE_2D_ARRAY_EXT
;
1535 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1540 _mesa_problem( ctx
, "bad dims in texture_error_check" );
1544 sizeOK
= sizeOK
&& ctx
->Driver
.TestProxyTexImage(ctx
, proxy_target
, level
,
1545 internalFormat
, format
,
1546 type
, width
, height
,
1550 _mesa_error(ctx
, GL_INVALID_VALUE
,
1551 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1552 dimensions
, level
, width
, height
, depth
);
1557 /* Check internalFormat */
1558 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1560 _mesa_error(ctx
, GL_INVALID_VALUE
,
1561 "glTexImage%dD(internalFormat=0x%x)",
1562 dimensions
, internalFormat
);
1567 /* Check incoming image format and type */
1568 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
1569 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1570 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1573 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1574 "glTexImage%dD(format or type)", dimensions
);
1579 /* make sure internal format and format basically agree */
1580 colorFormat
= _mesa_is_color_format(format
);
1581 indexFormat
= is_index_format(format
);
1582 if ((_mesa_is_color_format(internalFormat
) && !colorFormat
&& !indexFormat
) ||
1583 (is_index_format(internalFormat
) && !indexFormat
) ||
1584 (is_depth_format(internalFormat
) != is_depth_format(format
)) ||
1585 (is_ycbcr_format(internalFormat
) != is_ycbcr_format(format
)) ||
1586 (is_depthstencil_format(internalFormat
) != is_depthstencil_format(format
))) {
1588 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1589 "glTexImage(internalFormat/format)");
1593 /* additional checks for ycbcr textures */
1594 if (internalFormat
== GL_YCBCR_MESA
) {
1595 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1596 if (type
!= GL_UNSIGNED_SHORT_8_8_MESA
&&
1597 type
!= GL_UNSIGNED_SHORT_8_8_REV_MESA
) {
1599 _mesa_sprintf(message
,
1600 "glTexImage%d(format/type YCBCR mismatch", dimensions
);
1601 _mesa_error(ctx
, GL_INVALID_ENUM
, message
);
1602 return GL_TRUE
; /* error */
1604 if (target
!= GL_TEXTURE_2D
&&
1605 target
!= GL_PROXY_TEXTURE_2D
&&
1606 target
!= GL_TEXTURE_RECTANGLE_NV
&&
1607 target
!= GL_PROXY_TEXTURE_RECTANGLE_NV
) {
1609 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage(target)");
1615 _mesa_sprintf(message
,
1616 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1617 dimensions
, border
);
1618 _mesa_error(ctx
, GL_INVALID_VALUE
, message
);
1624 /* additional checks for depth textures */
1625 if (_mesa_base_tex_format(ctx
, internalFormat
) == GL_DEPTH_COMPONENT
) {
1626 /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
1627 if (target
!= GL_TEXTURE_1D
&&
1628 target
!= GL_PROXY_TEXTURE_1D
&&
1629 target
!= GL_TEXTURE_2D
&&
1630 target
!= GL_PROXY_TEXTURE_2D
&&
1631 target
!= GL_TEXTURE_RECTANGLE_ARB
&&
1632 target
!= GL_PROXY_TEXTURE_RECTANGLE_ARB
) {
1634 _mesa_error(ctx
, GL_INVALID_ENUM
,
1635 "glTexImage(target/internalFormat)");
1640 /* additional checks for compressed textures */
1641 if (is_compressed_format(ctx
, internalFormat
)) {
1642 if (!target_can_be_compressed(ctx
, target
) && !isProxy
) {
1643 _mesa_error(ctx
, GL_INVALID_ENUM
,
1644 "glTexImage%d(target)", dimensions
);
1649 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1650 "glTexImage%D(border!=0)", dimensions
);
1656 /* if we get here, the parameters are OK */
1662 * Test glTexSubImage[123]D() parameters for errors.
1664 * \param ctx GL context.
1665 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1666 * \param target texture target given by the user.
1667 * \param level image level given by the user.
1668 * \param xoffset sub-image x offset given by the user.
1669 * \param yoffset sub-image y offset given by the user.
1670 * \param zoffset sub-image z offset given by the user.
1671 * \param format pixel data format given by the user.
1672 * \param type pixel data type given by the user.
1673 * \param width image width given by the user.
1674 * \param height image height given by the user.
1675 * \param depth image depth given by the user.
1677 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1679 * Verifies each of the parameters against the constants specified in
1680 * __GLcontextRec::Const and the supported extensions, and according to the
1681 * OpenGL specification.
1684 subtexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1685 GLenum target
, GLint level
,
1686 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1687 GLint width
, GLint height
, GLint depth
,
1688 GLenum format
, GLenum type
)
1691 if (dimensions
== 1) {
1692 if (target
!= GL_TEXTURE_1D
) {
1693 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
1697 else if (dimensions
== 2) {
1698 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1699 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1700 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1701 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1705 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1706 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1707 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1711 else if (target
== GL_TEXTURE_1D_ARRAY_EXT
) {
1712 if (!ctx
->Extensions
.MESA_texture_array
) {
1713 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1717 else if (target
!= GL_TEXTURE_2D
) {
1718 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1722 else if (dimensions
== 3) {
1723 if (target
== GL_TEXTURE_2D_ARRAY_EXT
) {
1724 if (!ctx
->Extensions
.MESA_texture_array
) {
1725 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
1729 else if (target
!= GL_TEXTURE_3D
) {
1730 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
1735 _mesa_problem( ctx
, "invalid dims in texture_error_check" );
1739 /* Basic level check */
1740 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1741 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level=%d)", level
);
1746 _mesa_error(ctx
, GL_INVALID_VALUE
,
1747 "glTexSubImage%dD(width=%d)", dimensions
, width
);
1750 if (height
< 0 && dimensions
> 1) {
1751 _mesa_error(ctx
, GL_INVALID_VALUE
,
1752 "glTexSubImage%dD(height=%d)", dimensions
, height
);
1755 if (depth
< 0 && dimensions
> 2) {
1756 _mesa_error(ctx
, GL_INVALID_VALUE
,
1757 "glTexSubImage%dD(depth=%d)", dimensions
, depth
);
1761 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
1762 _mesa_error(ctx
, GL_INVALID_ENUM
,
1763 "glTexSubImage%dD(format or type)", dimensions
);
1771 subtexture_error_check2( GLcontext
*ctx
, GLuint dimensions
,
1772 GLenum target
, GLint level
,
1773 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1774 GLint width
, GLint height
, GLint depth
,
1775 GLenum format
, GLenum type
,
1776 const struct gl_texture_image
*destTex
)
1779 /* undefined image level */
1780 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage%dD", dimensions
);
1784 if (xoffset
< -((GLint
)destTex
->Border
)) {
1785 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset)",
1789 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
1790 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset+width)",
1794 if (dimensions
> 1) {
1795 if (yoffset
< -((GLint
)destTex
->Border
)) {
1796 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset)",
1800 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
1801 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset+height)",
1806 if (dimensions
> 2) {
1807 if (zoffset
< -((GLint
)destTex
->Border
)) {
1808 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
1811 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+ destTex
->Border
)) {
1812 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
1817 #if FEATURE_EXT_texture_sRGB
1818 if (destTex
->InternalFormat
== GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
||
1819 destTex
->InternalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
||
1820 destTex
->InternalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
||
1821 destTex
->InternalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
) {
1822 if ((width
& 0x3) || (height
& 0x3) ||
1823 (xoffset
& 0x3) || (yoffset
& 0x3))
1824 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1825 "glTexSubImage%dD(size or offset not multiple of 4)",
1831 if (destTex
->IsCompressed
) {
1832 if (!target_can_be_compressed(ctx
, target
)) {
1833 _mesa_error(ctx
, GL_INVALID_ENUM
,
1834 "glTexSubImage%D(target)", dimensions
);
1837 /* offset must be multiple of 4 */
1838 if ((xoffset
& 3) || (yoffset
& 3)) {
1839 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1840 "glTexSubImage%D(xoffset or yoffset)", dimensions
);
1843 /* size must be multiple of 4 or equal to whole texture size */
1844 if ((width
& 3) && (GLuint
) width
!= destTex
->Width
) {
1845 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1846 "glTexSubImage%D(width)", dimensions
);
1849 if ((height
& 3) && (GLuint
) height
!= destTex
->Height
) {
1850 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1851 "glTexSubImage%D(width)", dimensions
);
1861 * Test glCopyTexImage[12]D() parameters for errors.
1863 * \param ctx GL context.
1864 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1865 * \param target texture target given by the user.
1866 * \param level image level given by the user.
1867 * \param internalFormat internal format given by the user.
1868 * \param width image width given by the user.
1869 * \param height image height given by the user.
1870 * \param depth image depth given by the user.
1871 * \param border texture border.
1873 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1875 * Verifies each of the parameters against the constants specified in
1876 * __GLcontextRec::Const and the supported extensions, and according to the
1877 * OpenGL specification.
1880 copytexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1881 GLenum target
, GLint level
, GLint internalFormat
,
1882 GLint width
, GLint height
, GLint border
)
1888 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1889 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1890 _mesa_error(ctx
, GL_INVALID_VALUE
,
1891 "glCopyTexImage%dD(level=%d)", dimensions
, level
);
1895 /* Check that the source buffer is complete */
1896 if (ctx
->ReadBuffer
->Name
) {
1897 _mesa_test_framebuffer_completeness(ctx
, ctx
->ReadBuffer
);
1898 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
1899 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
1900 "glCopyTexImage%dD(invalid readbuffer)", dimensions
);
1906 if (border
< 0 || border
> 1 ||
1907 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1908 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1912 format
= _mesa_base_tex_format(ctx
, internalFormat
);
1914 _mesa_error(ctx
, GL_INVALID_VALUE
,
1915 "glCopyTexImage%dD(internalFormat)", dimensions
);
1919 /* NOTE: the format and type aren't really significant for
1920 * TestProxyTexImage(). Only the internalformat really matters.
1921 if (!_mesa_source_buffer_exists(ctx, format)) {
1922 _mesa_error(ctx, GL_INVALID_OPERATION,
1923 "glCopyTexImage%dD(missing readbuffer)", dimensions);
1930 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1931 * level, width, height and depth.
1933 if (dimensions
== 1) {
1934 if (target
== GL_TEXTURE_1D
) {
1935 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1936 level
, internalFormat
,
1938 width
, 1, 1, border
);
1941 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
1945 else if (dimensions
== 2) {
1946 if (target
== GL_TEXTURE_2D
) {
1947 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1948 level
, internalFormat
,
1950 width
, height
, 1, border
);
1952 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1953 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1954 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1955 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1958 sizeOK
= (width
== height
) &&
1959 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1960 level
, internalFormat
, format
, type
,
1961 width
, height
, 1, border
);
1963 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1964 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1965 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1968 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1969 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1970 level
, internalFormat
,
1972 width
, height
, 1, border
);
1974 else if (target
== GL_TEXTURE_1D_ARRAY_EXT
) {
1975 if (!ctx
->Extensions
.MESA_texture_array
) {
1976 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)");
1979 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1980 GL_PROXY_TEXTURE_1D_ARRAY_EXT
,
1981 level
, internalFormat
,
1983 width
, height
, 1, border
);
1986 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1991 _mesa_problem(ctx
, "invalid dimensions in copytexture_error_check");
1996 if (dimensions
== 1) {
1997 _mesa_error(ctx
, GL_INVALID_VALUE
,
1998 "glCopyTexImage1D(width=%d)", width
);
2001 ASSERT(dimensions
== 2);
2002 _mesa_error(ctx
, GL_INVALID_VALUE
,
2003 "glCopyTexImage2D(width=%d, height=%d)", width
, height
);
2008 if (is_compressed_format(ctx
, internalFormat
)) {
2009 if (!target_can_be_compressed(ctx
, target
)) {
2010 _mesa_error(ctx
, GL_INVALID_ENUM
,
2011 "glCopyTexImage%d(target)", dimensions
);
2015 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2016 "glCopyTexImage%D(border!=0)", dimensions
);
2020 else if (is_depth_format(internalFormat
)) {
2021 /* make sure we have depth/stencil buffers */
2022 if (!ctx
->ReadBuffer
->_DepthBuffer
) {
2023 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2024 "glCopyTexImage%D(no depth)", dimensions
);
2028 else if (is_depthstencil_format(internalFormat
)) {
2029 /* make sure we have depth/stencil buffers */
2030 if (!ctx
->ReadBuffer
->_DepthBuffer
|| !ctx
->ReadBuffer
->_StencilBuffer
) {
2031 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2032 "glCopyTexImage%D(no depth/stencil buffer)", dimensions
);
2037 /* if we get here, the parameters are OK */
2043 * Test glCopyTexSubImage[12]D() parameters for errors.
2044 * Note that this is the first part of error checking.
2045 * See also copytexsubimage_error_check2() below for the second part.
2047 * \param ctx GL context.
2048 * \param dimensions texture image dimensions (must be 1, 2 or 3).
2049 * \param target texture target given by the user.
2050 * \param level image level given by the user.
2052 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
2055 copytexsubimage_error_check1( GLcontext
*ctx
, GLuint dimensions
,
2056 GLenum target
, GLint level
)
2058 /* Check that the source buffer is complete */
2059 if (ctx
->ReadBuffer
->Name
) {
2060 _mesa_test_framebuffer_completeness(ctx
, ctx
->ReadBuffer
);
2061 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
2062 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
2063 "glCopyTexImage%dD(invalid readbuffer)", dimensions
);
2069 if (dimensions
== 1) {
2070 if (target
!= GL_TEXTURE_1D
) {
2071 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
2075 else if (dimensions
== 2) {
2076 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2077 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2078 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
2079 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
2083 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
2084 if (!ctx
->Extensions
.NV_texture_rectangle
) {
2085 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
2089 else if (target
== GL_TEXTURE_1D_ARRAY_EXT
) {
2090 if (!ctx
->Extensions
.MESA_texture_array
) {
2091 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
2095 else if (target
!= GL_TEXTURE_2D
) {
2096 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
2100 else if (dimensions
== 3) {
2101 if (((target
!= GL_TEXTURE_2D_ARRAY_EXT
) ||
2102 (!ctx
->Extensions
.MESA_texture_array
))
2103 && (target
!= GL_TEXTURE_3D
)) {
2104 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
2110 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
2111 _mesa_error(ctx
, GL_INVALID_VALUE
,
2112 "glCopyTexSubImage%dD(level=%d)", dimensions
, level
);
2121 * Second part of error checking for glCopyTexSubImage[12]D().
2122 * \param xoffset sub-image x offset given by the user.
2123 * \param yoffset sub-image y offset given by the user.
2124 * \param zoffset sub-image z offset given by the user.
2125 * \param width image width given by the user.
2126 * \param height image height given by the user.
2129 copytexsubimage_error_check2( GLcontext
*ctx
, GLuint dimensions
,
2130 GLenum target
, GLint level
,
2131 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2132 GLsizei width
, GLsizei height
,
2133 const struct gl_texture_image
*teximage
)
2135 /* check that dest tex image exists */
2137 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2138 "glCopyTexSubImage%dD(undefined texture level: %d)",
2145 _mesa_error(ctx
, GL_INVALID_VALUE
,
2146 "glCopyTexSubImage%dD(width=%d)", dimensions
, width
);
2149 if (dimensions
> 1 && height
< 0) {
2150 _mesa_error(ctx
, GL_INVALID_VALUE
,
2151 "glCopyTexSubImage%dD(height=%d)", dimensions
, height
);
2155 /* check x/y offsets */
2156 if (xoffset
< -((GLint
)teximage
->Border
)) {
2157 _mesa_error(ctx
, GL_INVALID_VALUE
,
2158 "glCopyTexSubImage%dD(xoffset=%d)", dimensions
, xoffset
);
2161 if (xoffset
+ width
> (GLint
) (teximage
->Width
+ teximage
->Border
)) {
2162 _mesa_error(ctx
, GL_INVALID_VALUE
,
2163 "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
2166 if (dimensions
> 1) {
2167 if (yoffset
< -((GLint
)teximage
->Border
)) {
2168 _mesa_error(ctx
, GL_INVALID_VALUE
,
2169 "glCopyTexSubImage%dD(yoffset=%d)", dimensions
, yoffset
);
2172 /* NOTE: we're adding the border here, not subtracting! */
2173 if (yoffset
+ height
> (GLint
) (teximage
->Height
+ teximage
->Border
)) {
2174 _mesa_error(ctx
, GL_INVALID_VALUE
,
2175 "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
2180 /* check z offset */
2181 if (dimensions
> 2) {
2182 if (zoffset
< -((GLint
)teximage
->Border
)) {
2183 _mesa_error(ctx
, GL_INVALID_VALUE
,
2184 "glCopyTexSubImage%dD(zoffset)", dimensions
);
2187 if (zoffset
> (GLint
) (teximage
->Depth
+ teximage
->Border
)) {
2188 _mesa_error(ctx
, GL_INVALID_VALUE
,
2189 "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
2194 if (teximage
->IsCompressed
) {
2195 if (!target_can_be_compressed(ctx
, target
)) {
2196 _mesa_error(ctx
, GL_INVALID_ENUM
,
2197 "glCopyTexSubImage%d(target)", dimensions
);
2200 /* offset must be multiple of 4 */
2201 if ((xoffset
& 3) || (yoffset
& 3)) {
2202 _mesa_error(ctx
, GL_INVALID_VALUE
,
2203 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions
);
2206 /* size must be multiple of 4 */
2207 if ((width
& 3) != 0 && (GLuint
) width
!= teximage
->Width
) {
2208 _mesa_error(ctx
, GL_INVALID_VALUE
,
2209 "glCopyTexSubImage%D(width)", dimensions
);
2212 if ((height
& 3) != 0 && (GLuint
) height
!= teximage
->Height
) {
2213 _mesa_error(ctx
, GL_INVALID_VALUE
,
2214 "glCopyTexSubImage%D(height)", dimensions
);
2219 if (teximage
->InternalFormat
== GL_YCBCR_MESA
) {
2220 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glCopyTexSubImage2D");
2224 if (!_mesa_source_buffer_exists(ctx
, teximage
->_BaseFormat
)) {
2225 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2226 "glCopyTexSubImage%dD(missing readbuffer)", dimensions
);
2230 if (teximage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
2231 if (!ctx
->ReadBuffer
->_DepthBuffer
) {
2232 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2233 "glCopyTexSubImage%D(no depth buffer)",
2238 else if (teximage
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2239 if (!ctx
->ReadBuffer
->_DepthBuffer
|| !ctx
->ReadBuffer
->_StencilBuffer
) {
2240 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2241 "glCopyTexSubImage%D(no depth/stencil buffer)",
2247 /* if we get here, the parameters are OK */
2253 * Get texture image. Called by glGetTexImage.
2255 * \param target texture target.
2256 * \param level image level.
2257 * \param format pixel data format for returned image.
2258 * \param type pixel data type for returned image.
2259 * \param pixels returned pixel data.
2262 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
2263 GLenum type
, GLvoid
*pixels
)
2265 const struct gl_texture_unit
*texUnit
;
2266 struct gl_texture_object
*texObj
;
2267 struct gl_texture_image
*texImage
;
2268 GLint maxLevels
= 0;
2269 GET_CURRENT_CONTEXT(ctx
);
2270 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2272 texUnit
= &(ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
]);
2273 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2274 if (!texObj
|| _mesa_is_proxy_texture(target
)) {
2275 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)");
2279 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
2280 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
2282 if (level
< 0 || level
>= maxLevels
) {
2283 _mesa_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
2287 if (_mesa_sizeof_packed_type(type
) <= 0) {
2288 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
2292 if (_mesa_components_in_format(format
) <= 0 ||
2293 format
== GL_STENCIL_INDEX
) {
2294 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
2298 if (!ctx
->Extensions
.EXT_paletted_texture
&& is_index_format(format
)) {
2299 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2303 if (!ctx
->Extensions
.ARB_depth_texture
&& is_depth_format(format
)) {
2304 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2308 if (!ctx
->Extensions
.MESA_ycbcr_texture
&& is_ycbcr_format(format
)) {
2309 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2313 if (!ctx
->Extensions
.EXT_packed_depth_stencil
2314 && is_depthstencil_format(format
)) {
2315 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2319 _mesa_lock_texture(ctx
, texObj
);
2321 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2323 /* invalid mipmap level, not an error */
2328 /* Make sure the requested image format is compatible with the
2329 * texture's format. Note that a color index texture can be converted
2330 * to RGBA so that combo is allowed.
2332 if (_mesa_is_color_format(format
)
2333 && !_mesa_is_color_format(texImage
->TexFormat
->BaseFormat
)
2334 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
2335 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2338 else if (is_index_format(format
)
2339 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
2340 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2343 else if (is_depth_format(format
)
2344 && !is_depth_format(texImage
->TexFormat
->BaseFormat
)
2345 && !is_depthstencil_format(texImage
->TexFormat
->BaseFormat
)) {
2346 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2349 else if (is_ycbcr_format(format
)
2350 && !is_ycbcr_format(texImage
->TexFormat
->BaseFormat
)) {
2351 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2354 else if (is_depthstencil_format(format
)
2355 && !is_depthstencil_format(texImage
->TexFormat
->BaseFormat
)) {
2356 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2360 if (ctx
->Pack
.BufferObj
->Name
) {
2361 /* packing texture image into a PBO */
2362 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
2363 if (!_mesa_validate_pbo_access(dimensions
, &ctx
->Pack
, texImage
->Width
,
2364 texImage
->Height
, texImage
->Depth
,
2365 format
, type
, pixels
)) {
2366 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2367 "glGetTexImage(invalid PBO access)");
2372 /* typically, this will call _mesa_get_teximage() */
2373 ctx
->Driver
.GetTexImage(ctx
, target
, level
, format
, type
, pixels
,
2378 _mesa_unlock_texture(ctx
, texObj
);
2382 /** Callback info for walking over FBO hash table */
2386 struct gl_texture_object
*texObj
;
2392 * Check render to texture callback. Called from _mesa_HashWalk().
2395 check_rtt_cb(GLuint key
, void *data
, void *userData
)
2397 struct gl_framebuffer
*fb
= (struct gl_framebuffer
*) data
;
2398 const struct cb_info
*info
= (struct cb_info
*) userData
;
2399 GLcontext
*ctx
= info
->ctx
;
2400 const struct gl_texture_object
*texObj
= info
->texObj
;
2401 const GLuint level
= info
->level
, face
= info
->face
;
2403 /* If this is a user-created FBO */
2406 /* check if any of the FBO's attachments point to 'texObj' */
2407 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
2408 struct gl_renderbuffer_attachment
*att
= fb
->Attachment
+ i
;
2409 if (att
->Type
== GL_TEXTURE
&&
2410 att
->Texture
== texObj
&&
2411 att
->TextureLevel
== level
&&
2412 att
->CubeMapFace
== face
) {
2413 ASSERT(att
->Texture
->Image
[att
->CubeMapFace
][att
->TextureLevel
]);
2414 /* Tell driver about the new renderbuffer texture */
2415 ctx
->Driver
.RenderTexture(ctx
, ctx
->DrawBuffer
, att
);
2416 /* Mark fb status as indeterminate to force re-validation */
2425 * When a texture image is specified we have to check if it's bound to
2426 * any framebuffer objects (render to texture) in order to detect changes
2427 * in size or format since that effects FBO completeness.
2428 * Any FBOs rendering into the texture must be re-validated.
2431 update_fbo_texture(GLcontext
*ctx
, struct gl_texture_object
*texObj
,
2432 GLuint face
, GLuint level
)
2434 /* Only check this texture if it's been marked as RenderToTexture */
2435 if (texObj
->_RenderToTexture
) {
2436 struct cb_info info
;
2438 info
.texObj
= texObj
;
2441 _mesa_HashWalk(ctx
->Shared
->FrameBuffers
, check_rtt_cb
, &info
);
2448 * Called from the API. Note that width includes the border.
2451 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalFormat
,
2452 GLsizei width
, GLint border
, GLenum format
,
2453 GLenum type
, const GLvoid
*pixels
)
2455 GLsizei postConvWidth
= width
;
2456 GET_CURRENT_CONTEXT(ctx
);
2457 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2459 #if FEATURE_convolve
2460 if (_mesa_is_color_format(internalFormat
)) {
2461 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2465 if (target
== GL_TEXTURE_1D
) {
2466 /* non-proxy target */
2467 struct gl_texture_unit
*texUnit
;
2468 struct gl_texture_object
*texObj
;
2469 struct gl_texture_image
*texImage
;
2470 const GLuint face
= _mesa_tex_target_to_face(target
);
2472 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2473 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2474 return; /* error was recorded */
2477 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2478 _mesa_update_state(ctx
);
2480 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2481 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2482 _mesa_lock_texture(ctx
, texObj
);
2484 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
2486 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2490 if (texImage
->Data
) {
2491 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2494 ASSERT(texImage
->Data
== NULL
);
2496 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2497 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2498 postConvWidth
, 1, 1,
2499 border
, internalFormat
);
2501 ASSERT(ctx
->Driver
.TexImage1D
);
2503 /* Give the texture to the driver! <pixels> may be null! */
2504 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
2505 width
, border
, format
, type
, pixels
,
2506 &ctx
->Unpack
, texObj
, texImage
);
2508 ASSERT(texImage
->TexFormat
);
2510 update_fbo_texture(ctx
, texObj
, face
, level
);
2513 texObj
->_Complete
= GL_FALSE
;
2514 ctx
->NewState
|= _NEW_TEXTURE
;
2517 _mesa_unlock_texture(ctx
, texObj
);
2519 else if (target
== GL_PROXY_TEXTURE_1D
) {
2520 /* Proxy texture: check for errors and update proxy state */
2521 struct gl_texture_image
*texImage
;
2522 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2523 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2524 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2525 /* when error, clear all proxy texture image parameters */
2527 clear_teximage_fields(texImage
);
2530 /* no error, set the tex image parameters */
2532 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2533 postConvWidth
, 1, 1,
2534 border
, internalFormat
);
2535 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2536 internalFormat
, format
, type
);
2540 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
2547 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalFormat
,
2548 GLsizei width
, GLsizei height
, GLint border
,
2549 GLenum format
, GLenum type
,
2550 const GLvoid
*pixels
)
2552 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2553 GET_CURRENT_CONTEXT(ctx
);
2554 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2556 #if FEATURE_convolve
2557 if (_mesa_is_color_format(internalFormat
)) {
2558 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2563 if (target
== GL_TEXTURE_2D
||
2564 (ctx
->Extensions
.ARB_texture_cube_map
&&
2565 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2566 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) ||
2567 (ctx
->Extensions
.NV_texture_rectangle
&&
2568 target
== GL_TEXTURE_RECTANGLE_NV
) ||
2569 (ctx
->Extensions
.MESA_texture_array
&&
2570 target
== GL_TEXTURE_1D_ARRAY_EXT
)) {
2571 /* non-proxy target */
2572 struct gl_texture_unit
*texUnit
;
2573 struct gl_texture_object
*texObj
;
2574 struct gl_texture_image
*texImage
;
2575 const GLuint face
= _mesa_tex_target_to_face(target
);
2577 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2578 format
, type
, 2, postConvWidth
, postConvHeight
,
2580 return; /* error was recorded */
2583 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2584 _mesa_update_state(ctx
);
2586 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2587 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2588 _mesa_lock_texture(ctx
, texObj
);
2590 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
2592 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2596 if (texImage
->Data
) {
2597 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2600 ASSERT(texImage
->Data
== NULL
);
2601 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2602 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2603 postConvWidth
, postConvHeight
, 1,
2604 border
, internalFormat
);
2606 ASSERT(ctx
->Driver
.TexImage2D
);
2608 /* Give the texture to the driver! <pixels> may be null! */
2609 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
2610 width
, height
, border
, format
, type
, pixels
,
2611 &ctx
->Unpack
, texObj
, texImage
);
2613 ASSERT(texImage
->TexFormat
);
2615 update_fbo_texture(ctx
, texObj
, face
, level
);
2618 texObj
->_Complete
= GL_FALSE
;
2619 ctx
->NewState
|= _NEW_TEXTURE
;
2622 _mesa_unlock_texture(ctx
, texObj
);
2624 else if (target
== GL_PROXY_TEXTURE_2D
||
2625 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2626 ctx
->Extensions
.ARB_texture_cube_map
) ||
2627 (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
&&
2628 ctx
->Extensions
.NV_texture_rectangle
) ||
2629 (ctx
->Extensions
.MESA_texture_array
&&
2630 target
== GL_PROXY_TEXTURE_1D_ARRAY_EXT
)) {
2631 /* Proxy texture: check for errors and update proxy state */
2632 struct gl_texture_image
*texImage
;
2633 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2634 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2635 format
, type
, 2, postConvWidth
, postConvHeight
,
2637 /* when error, clear all proxy texture image parameters */
2639 clear_teximage_fields(ctx
->Texture
.ProxyTex
[TEXTURE_2D_INDEX
]->Image
[0][level
]);
2642 /* no error, set the tex image parameters */
2643 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2644 postConvWidth
, postConvHeight
, 1,
2645 border
, internalFormat
);
2646 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2647 internalFormat
, format
, type
);
2651 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
2658 * Called by the API or display list executor.
2659 * Note that width and height include the border.
2662 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalFormat
,
2663 GLsizei width
, GLsizei height
, GLsizei depth
,
2664 GLint border
, GLenum format
, GLenum type
,
2665 const GLvoid
*pixels
)
2667 GET_CURRENT_CONTEXT(ctx
);
2668 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2670 if (target
== GL_TEXTURE_3D
||
2671 (ctx
->Extensions
.MESA_texture_array
&&
2672 target
== GL_TEXTURE_2D_ARRAY_EXT
)) {
2673 /* non-proxy target */
2674 struct gl_texture_unit
*texUnit
;
2675 struct gl_texture_object
*texObj
;
2676 struct gl_texture_image
*texImage
;
2677 const GLuint face
= _mesa_tex_target_to_face(target
);
2679 if (texture_error_check(ctx
, target
, level
, (GLint
) internalFormat
,
2680 format
, type
, 3, width
, height
, depth
, border
)) {
2681 return; /* error was recorded */
2684 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2685 _mesa_update_state(ctx
);
2687 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2688 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2689 _mesa_lock_texture(ctx
, texObj
);
2691 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
2693 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2697 if (texImage
->Data
) {
2698 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2701 ASSERT(texImage
->Data
== NULL
);
2702 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2703 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2704 width
, height
, depth
,
2705 border
, internalFormat
);
2707 ASSERT(ctx
->Driver
.TexImage3D
);
2709 /* Give the texture to the driver! <pixels> may be null! */
2710 (*ctx
->Driver
.TexImage3D
)(ctx
, target
, level
, internalFormat
,
2711 width
, height
, depth
, border
, format
, type
,
2712 pixels
, &ctx
->Unpack
, texObj
, texImage
);
2714 ASSERT(texImage
->TexFormat
);
2716 update_fbo_texture(ctx
, texObj
, face
, level
);
2719 texObj
->_Complete
= GL_FALSE
;
2720 ctx
->NewState
|= _NEW_TEXTURE
;
2723 _mesa_unlock_texture(ctx
, texObj
);
2725 else if (target
== GL_PROXY_TEXTURE_3D
||
2726 (ctx
->Extensions
.MESA_texture_array
&&
2727 target
== GL_PROXY_TEXTURE_2D_ARRAY_EXT
)) {
2728 /* Proxy texture: check for errors and update proxy state */
2729 struct gl_texture_image
*texImage
;
2730 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2731 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2732 format
, type
, 3, width
, height
, depth
, border
)) {
2733 /* when error, clear all proxy texture image parameters */
2735 clear_teximage_fields(texImage
);
2738 /* no error, set the tex image parameters */
2739 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
,
2740 depth
, border
, internalFormat
);
2741 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2742 internalFormat
, format
, type
);
2746 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
2753 _mesa_TexImage3DEXT( GLenum target
, GLint level
, GLenum internalFormat
,
2754 GLsizei width
, GLsizei height
, GLsizei depth
,
2755 GLint border
, GLenum format
, GLenum type
,
2756 const GLvoid
*pixels
)
2758 _mesa_TexImage3D(target
, level
, (GLint
) internalFormat
, width
, height
,
2759 depth
, border
, format
, type
, pixels
);
2765 _mesa_TexSubImage1D( GLenum target
, GLint level
,
2766 GLint xoffset
, GLsizei width
,
2767 GLenum format
, GLenum type
,
2768 const GLvoid
*pixels
)
2770 GLsizei postConvWidth
= width
;
2771 struct gl_texture_unit
*texUnit
;
2772 struct gl_texture_object
*texObj
;
2773 struct gl_texture_image
*texImage
= NULL
;
2774 GET_CURRENT_CONTEXT(ctx
);
2775 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2777 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2778 _mesa_update_state(ctx
);
2780 #if FEATURE_convolve
2781 /* XXX should test internal format */
2782 if (_mesa_is_color_format(format
)) {
2783 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2787 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
2788 postConvWidth
, 1, 1, format
, type
)) {
2789 return; /* error was detected */
2793 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2794 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2797 _mesa_lock_texture(ctx
, texObj
);
2799 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2801 if (subtexture_error_check2(ctx
, 1, target
, level
, xoffset
, 0, 0,
2802 postConvWidth
, 1, 1, format
, type
, texImage
)) {
2803 goto out
; /* error was detected */
2807 goto out
; /* no-op, not an error */
2809 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2810 xoffset
+= texImage
->Border
;
2812 ASSERT(ctx
->Driver
.TexSubImage1D
);
2813 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
2814 format
, type
, pixels
, &ctx
->Unpack
,
2816 ctx
->NewState
|= _NEW_TEXTURE
;
2819 _mesa_unlock_texture(ctx
, texObj
);
2824 _mesa_TexSubImage2D( GLenum target
, GLint level
,
2825 GLint xoffset
, GLint yoffset
,
2826 GLsizei width
, GLsizei height
,
2827 GLenum format
, GLenum type
,
2828 const GLvoid
*pixels
)
2830 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2831 struct gl_texture_unit
*texUnit
;
2832 struct gl_texture_object
*texObj
;
2833 struct gl_texture_image
*texImage
;
2834 GET_CURRENT_CONTEXT(ctx
);
2835 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2837 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2838 _mesa_update_state(ctx
);
2840 #if FEATURE_convolve
2841 /* XXX should test internal format */
2842 if (_mesa_is_color_format(format
)) {
2843 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2848 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2849 postConvWidth
, postConvHeight
, 1, format
, type
)) {
2850 return; /* error was detected */
2853 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2854 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2855 _mesa_lock_texture(ctx
, texObj
);
2857 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2859 if (subtexture_error_check2(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2860 postConvWidth
, postConvHeight
, 1, format
, type
,
2862 goto out
; /* error was detected */
2865 if (width
== 0 || height
== 0)
2866 goto out
; /* no-op, not an error */
2868 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2869 xoffset
+= texImage
->Border
;
2870 yoffset
+= texImage
->Border
;
2872 ASSERT(ctx
->Driver
.TexSubImage2D
);
2873 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
, xoffset
, yoffset
,
2874 width
, height
, format
, type
, pixels
,
2875 &ctx
->Unpack
, texObj
, texImage
);
2876 ctx
->NewState
|= _NEW_TEXTURE
;
2879 _mesa_unlock_texture(ctx
, texObj
);
2885 _mesa_TexSubImage3D( GLenum target
, GLint level
,
2886 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2887 GLsizei width
, GLsizei height
, GLsizei depth
,
2888 GLenum format
, GLenum type
,
2889 const GLvoid
*pixels
)
2891 struct gl_texture_unit
*texUnit
;
2892 struct gl_texture_object
*texObj
;
2893 struct gl_texture_image
*texImage
;
2894 GET_CURRENT_CONTEXT(ctx
);
2895 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2897 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2898 _mesa_update_state(ctx
);
2900 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2901 width
, height
, depth
, format
, type
)) {
2902 return; /* error was detected */
2905 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2906 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2908 _mesa_lock_texture(ctx
, texObj
);
2910 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2912 if (subtexture_error_check2(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2913 width
, height
, depth
, format
, type
, texImage
)) {
2914 goto out
; /* error was detected */
2917 if (width
== 0 || height
== 0 || height
== 0)
2918 goto out
; /* no-op, not an error */
2920 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2921 xoffset
+= texImage
->Border
;
2922 yoffset
+= texImage
->Border
;
2923 zoffset
+= texImage
->Border
;
2925 ASSERT(ctx
->Driver
.TexSubImage3D
);
2926 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
2927 xoffset
, yoffset
, zoffset
,
2928 width
, height
, depth
,
2929 format
, type
, pixels
,
2930 &ctx
->Unpack
, texObj
, texImage
);
2931 ctx
->NewState
|= _NEW_TEXTURE
;
2934 _mesa_unlock_texture(ctx
, texObj
);
2940 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
2941 GLenum internalFormat
,
2943 GLsizei width
, GLint border
)
2945 struct gl_texture_unit
*texUnit
;
2946 struct gl_texture_object
*texObj
;
2947 struct gl_texture_image
*texImage
;
2948 GLsizei postConvWidth
= width
;
2949 const GLuint face
= _mesa_tex_target_to_face(target
);
2950 GET_CURRENT_CONTEXT(ctx
);
2951 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2953 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2954 _mesa_update_state(ctx
);
2956 #if FEATURE_convolve
2957 if (_mesa_is_color_format(internalFormat
)) {
2958 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2962 if (copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
2963 postConvWidth
, 1, border
))
2966 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2967 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2968 _mesa_lock_texture(ctx
, texObj
);
2970 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
2972 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
2976 if (texImage
->Data
) {
2977 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2980 ASSERT(texImage
->Data
== NULL
);
2982 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2983 _mesa_init_teximage_fields(ctx
, target
, texImage
, postConvWidth
, 1, 1,
2984 border
, internalFormat
);
2987 ASSERT(ctx
->Driver
.CopyTexImage1D
);
2988 (*ctx
->Driver
.CopyTexImage1D
)(ctx
, target
, level
, internalFormat
,
2989 x
, y
, width
, border
);
2991 ASSERT(texImage
->TexFormat
);
2993 update_fbo_texture(ctx
, texObj
, face
, level
);
2996 texObj
->_Complete
= GL_FALSE
;
2997 ctx
->NewState
|= _NEW_TEXTURE
;
3000 _mesa_unlock_texture(ctx
, texObj
);
3006 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
3007 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
3010 struct gl_texture_unit
*texUnit
;
3011 struct gl_texture_object
*texObj
;
3012 struct gl_texture_image
*texImage
;
3013 GLsizei postConvWidth
= width
, postConvHeight
= height
;
3014 const GLuint face
= _mesa_tex_target_to_face(target
);
3015 GET_CURRENT_CONTEXT(ctx
);
3016 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3018 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
3019 _mesa_update_state(ctx
);
3021 #if FEATURE_convolve
3022 if (_mesa_is_color_format(internalFormat
)) {
3023 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
3028 if (copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
3029 postConvWidth
, postConvHeight
, border
))
3032 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3033 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3035 _mesa_lock_texture(ctx
, texObj
);
3037 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
3040 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
3044 if (texImage
->Data
) {
3045 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3048 ASSERT(texImage
->Data
== NULL
);
3050 clear_teximage_fields(texImage
); /* not really needed, but helpful */
3051 _mesa_init_teximage_fields(ctx
, target
, texImage
,
3052 postConvWidth
, postConvHeight
, 1,
3053 border
, internalFormat
);
3055 ASSERT(ctx
->Driver
.CopyTexImage2D
);
3056 (*ctx
->Driver
.CopyTexImage2D
)(ctx
, target
, level
, internalFormat
,
3057 x
, y
, width
, height
, border
);
3059 ASSERT(texImage
->TexFormat
);
3061 update_fbo_texture(ctx
, texObj
, face
, level
);
3064 texObj
->_Complete
= GL_FALSE
;
3065 ctx
->NewState
|= _NEW_TEXTURE
;
3068 _mesa_unlock_texture(ctx
, texObj
);
3073 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
3074 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
3076 struct gl_texture_unit
*texUnit
;
3077 struct gl_texture_object
*texObj
;
3078 struct gl_texture_image
*texImage
;
3079 GLsizei postConvWidth
= width
;
3083 GET_CURRENT_CONTEXT(ctx
);
3084 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3086 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
3087 _mesa_update_state(ctx
);
3089 if (copytexsubimage_error_check1(ctx
, 1, target
, level
))
3092 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3093 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3095 _mesa_lock_texture(ctx
, texObj
);
3097 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3099 #if FEATURE_convolve
3100 if (texImage
&& _mesa_is_color_format(texImage
->InternalFormat
)) {
3101 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
3105 if (copytexsubimage_error_check2(ctx
, 1, target
, level
,
3106 xoffset
, 0, 0, postConvWidth
, 1,
3111 /* If we have a border, xoffset=-1 is legal. Bias by border width */
3112 xoffset
+= texImage
->Border
;
3114 if (_mesa_clip_copytexsubimage(ctx
, &xoffset
, &yoffset
, &x
, &y
,
3116 ASSERT(ctx
->Driver
.CopyTexSubImage1D
);
3117 ctx
->Driver
.CopyTexSubImage1D(ctx
, target
, level
,
3118 xoffset
, x
, y
, width
);
3121 ctx
->NewState
|= _NEW_TEXTURE
;
3124 _mesa_unlock_texture(ctx
, texObj
);
3130 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
3131 GLint xoffset
, GLint yoffset
,
3132 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
3134 struct gl_texture_unit
*texUnit
;
3135 struct gl_texture_object
*texObj
;
3136 struct gl_texture_image
*texImage
;
3137 GLsizei postConvWidth
= width
, postConvHeight
= height
;
3138 GET_CURRENT_CONTEXT(ctx
);
3139 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3141 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
3142 _mesa_update_state(ctx
);
3144 if (copytexsubimage_error_check1(ctx
, 2, target
, level
))
3147 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3148 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3150 _mesa_lock_texture(ctx
, texObj
);
3152 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3154 #if FEATURE_convolve
3155 if (texImage
&& _mesa_is_color_format(texImage
->InternalFormat
)) {
3156 _mesa_adjust_image_for_convolution(ctx
, 2,
3157 &postConvWidth
, &postConvHeight
);
3161 if (copytexsubimage_error_check2(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
3162 postConvWidth
, postConvHeight
, texImage
))
3165 /* If we have a border, xoffset=-1 is legal. Bias by border width */
3166 xoffset
+= texImage
->Border
;
3167 yoffset
+= texImage
->Border
;
3169 if (_mesa_clip_copytexsubimage(ctx
, &xoffset
, &yoffset
, &x
, &y
,
3171 ASSERT(ctx
->Driver
.CopyTexSubImage2D
);
3172 ctx
->Driver
.CopyTexSubImage2D(ctx
, target
, level
,
3173 xoffset
, yoffset
, x
, y
, width
, height
);
3176 ctx
->NewState
|= _NEW_TEXTURE
;
3179 _mesa_unlock_texture(ctx
, texObj
);
3185 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
3186 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3187 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
3189 struct gl_texture_unit
*texUnit
;
3190 struct gl_texture_object
*texObj
;
3191 struct gl_texture_image
*texImage
;
3192 GLsizei postConvWidth
= width
, postConvHeight
= height
;
3193 GET_CURRENT_CONTEXT(ctx
);
3194 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3196 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
3197 _mesa_update_state(ctx
);
3199 if (copytexsubimage_error_check1(ctx
, 3, target
, level
))
3202 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3203 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3205 _mesa_lock_texture(ctx
, texObj
);
3207 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3209 #if FEATURE_convolve
3210 if (texImage
&& _mesa_is_color_format(texImage
->InternalFormat
)) {
3211 _mesa_adjust_image_for_convolution(ctx
, 2,
3212 &postConvWidth
, &postConvHeight
);
3216 if (copytexsubimage_error_check2(ctx
, 3, target
, level
, xoffset
, yoffset
,
3217 zoffset
, postConvWidth
, postConvHeight
,
3221 /* If we have a border, xoffset=-1 is legal. Bias by border width */
3222 xoffset
+= texImage
->Border
;
3223 yoffset
+= texImage
->Border
;
3224 zoffset
+= texImage
->Border
;
3226 if (_mesa_clip_copytexsubimage(ctx
, &xoffset
, &yoffset
, &x
, &y
,
3228 ASSERT(ctx
->Driver
.CopyTexSubImage3D
);
3229 ctx
->Driver
.CopyTexSubImage3D(ctx
, target
, level
,
3230 xoffset
, yoffset
, zoffset
,
3231 x
, y
, width
, height
);
3234 ctx
->NewState
|= _NEW_TEXTURE
;
3237 _mesa_unlock_texture(ctx
, texObj
);
3243 /**********************************************************************/
3244 /****** Compressed Textures ******/
3245 /**********************************************************************/
3249 * Error checking for glCompressedTexImage[123]D().
3250 * \return error code or GL_NO_ERROR.
3253 compressed_texture_error_check(GLcontext
*ctx
, GLint dimensions
,
3254 GLenum target
, GLint level
,
3255 GLenum internalFormat
, GLsizei width
,
3256 GLsizei height
, GLsizei depth
, GLint border
,
3259 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
3261 if (dimensions
== 1) {
3262 /* 1D compressed textures not allowed */
3263 return GL_INVALID_ENUM
;
3265 else if (dimensions
== 2) {
3266 if (target
== GL_PROXY_TEXTURE_2D
) {
3267 maxLevels
= ctx
->Const
.MaxTextureLevels
;
3269 else if (target
== GL_TEXTURE_2D
) {
3270 maxLevels
= ctx
->Const
.MaxTextureLevels
;
3272 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
3273 if (!ctx
->Extensions
.ARB_texture_cube_map
)
3274 return GL_INVALID_ENUM
; /*target*/
3275 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
3277 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3278 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
3279 if (!ctx
->Extensions
.ARB_texture_cube_map
)
3280 return GL_INVALID_ENUM
; /*target*/
3281 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
3284 return GL_INVALID_ENUM
; /*target*/
3287 else if (dimensions
== 3) {
3288 /* 3D compressed textures not allowed */
3289 return GL_INVALID_ENUM
;
3292 maxTextureSize
= 1 << (maxLevels
- 1);
3294 /* This will detect any invalid internalFormat value */
3295 if (!is_compressed_format(ctx
, internalFormat
))
3296 return GL_INVALID_ENUM
;
3298 /* This should really never fail */
3299 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0)
3300 return GL_INVALID_ENUM
;
3303 return GL_INVALID_VALUE
;
3306 * XXX We should probably use the proxy texture error check function here.
3308 if (width
< 1 || width
> maxTextureSize
||
3309 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& !_mesa_is_pow_two(width
)))
3310 return GL_INVALID_VALUE
;
3312 if ((height
< 1 || height
> maxTextureSize
||
3313 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& !_mesa_is_pow_two(height
)))
3315 return GL_INVALID_VALUE
;
3317 if ((depth
< 1 || depth
> maxTextureSize
||
3318 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& !_mesa_is_pow_two(depth
)))
3320 return GL_INVALID_VALUE
;
3322 /* For cube map, width must equal height */
3323 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3324 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
&& width
!= height
)
3325 return GL_INVALID_VALUE
;
3327 if (level
< 0 || level
>= maxLevels
)
3328 return GL_INVALID_VALUE
;
3330 expectedSize
= _mesa_compressed_texture_size_glenum(ctx
, width
, height
,
3331 depth
, internalFormat
);
3332 if (expectedSize
!= imageSize
)
3333 return GL_INVALID_VALUE
;
3335 #if FEATURE_EXT_texture_sRGB
3336 if ((internalFormat
== GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
||
3337 internalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
||
3338 internalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
||
3339 internalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
)
3341 return GL_INVALID_OPERATION
;
3350 * Error checking for glCompressedTexSubImage[123]D().
3351 * \warning There are some bad assumptions here about the size of compressed
3352 * texture tiles (multiple of 4) used to test the validity of the
3353 * offset and size parameters.
3354 * \return error code or GL_NO_ERROR.
3357 compressed_subtexture_error_check(GLcontext
*ctx
, GLint dimensions
,
3358 GLenum target
, GLint level
,
3359 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3360 GLsizei width
, GLsizei height
, GLsizei depth
,
3361 GLenum format
, GLsizei imageSize
)
3363 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
3366 if (dimensions
== 1) {
3367 /* 1D compressed textures not allowed */
3368 return GL_INVALID_ENUM
;
3370 else if (dimensions
== 2) {
3371 if (target
== GL_PROXY_TEXTURE_2D
) {
3372 maxLevels
= ctx
->Const
.MaxTextureLevels
;
3374 else if (target
== GL_TEXTURE_2D
) {
3375 maxLevels
= ctx
->Const
.MaxTextureLevels
;
3377 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
3378 if (!ctx
->Extensions
.ARB_texture_cube_map
)
3379 return GL_INVALID_ENUM
; /*target*/
3380 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
3382 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3383 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
3384 if (!ctx
->Extensions
.ARB_texture_cube_map
)
3385 return GL_INVALID_ENUM
; /*target*/
3386 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
3389 return GL_INVALID_ENUM
; /*target*/
3392 else if (dimensions
== 3) {
3393 /* 3D compressed textures not allowed */
3394 return GL_INVALID_ENUM
;
3397 maxTextureSize
= 1 << (maxLevels
- 1);
3399 /* this will catch any invalid compressed format token */
3400 if (!is_compressed_format(ctx
, format
))
3401 return GL_INVALID_ENUM
;
3403 if (width
< 1 || width
> maxTextureSize
)
3404 return GL_INVALID_VALUE
;
3406 if ((height
< 1 || height
> maxTextureSize
)
3408 return GL_INVALID_VALUE
;
3410 if (level
< 0 || level
>= maxLevels
)
3411 return GL_INVALID_VALUE
;
3413 /* XXX these tests are specific to the compressed format.
3414 * this code should be generalized in some way.
3416 if ((xoffset
& 3) != 0 || (yoffset
& 3) != 0)
3417 return GL_INVALID_VALUE
;
3419 if ((width
& 3) != 0 && width
!= 2 && width
!= 1)
3420 return GL_INVALID_VALUE
;
3422 if ((height
& 3) != 0 && height
!= 2 && height
!= 1)
3423 return GL_INVALID_VALUE
;
3425 expectedSize
= _mesa_compressed_texture_size_glenum(ctx
, width
, height
,
3427 if (expectedSize
!= imageSize
)
3428 return GL_INVALID_VALUE
;
3436 _mesa_CompressedTexImage1DARB(GLenum target
, GLint level
,
3437 GLenum internalFormat
, GLsizei width
,
3438 GLint border
, GLsizei imageSize
,
3441 GET_CURRENT_CONTEXT(ctx
);
3442 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3444 if (target
== GL_TEXTURE_1D
) {
3445 /* non-proxy target */
3446 struct gl_texture_unit
*texUnit
;
3447 struct gl_texture_object
*texObj
;
3448 struct gl_texture_image
*texImage
;
3449 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
3450 internalFormat
, width
, 1, 1, border
, imageSize
);
3452 _mesa_error(ctx
, error
, "glCompressedTexImage1D");
3456 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3457 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3459 _mesa_lock_texture(ctx
, texObj
);
3461 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
3463 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage1D");
3467 if (texImage
->Data
) {
3468 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3470 ASSERT(texImage
->Data
== NULL
);
3472 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
3473 border
, internalFormat
);
3475 ASSERT(ctx
->Driver
.CompressedTexImage1D
);
3476 (*ctx
->Driver
.CompressedTexImage1D
)(ctx
, target
, level
,
3477 internalFormat
, width
, border
,
3482 texObj
->_Complete
= GL_FALSE
;
3483 ctx
->NewState
|= _NEW_TEXTURE
;
3486 _mesa_unlock_texture(ctx
, texObj
);
3488 else if (target
== GL_PROXY_TEXTURE_1D
) {
3489 /* Proxy texture: check for errors and update proxy state */
3490 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
3491 internalFormat
, width
, 1, 1, border
, imageSize
);
3493 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3494 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3495 internalFormat
, GL_NONE
, GL_NONE
,
3496 width
, 1, 1, border
);
3499 /* if error, clear all proxy texture image parameters */
3500 struct gl_texture_image
*texImage
;
3501 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3503 clear_teximage_fields(texImage
);
3506 /* store the teximage parameters */
3507 struct gl_texture_unit
*texUnit
;
3508 struct gl_texture_object
*texObj
;
3509 struct gl_texture_image
*texImage
;
3510 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3511 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3513 _mesa_lock_texture(ctx
, texObj
);
3515 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3516 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
3517 border
, internalFormat
);
3519 _mesa_unlock_texture(ctx
, texObj
);
3523 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage1D(target)");
3530 _mesa_CompressedTexImage2DARB(GLenum target
, GLint level
,
3531 GLenum internalFormat
, GLsizei width
,
3532 GLsizei height
, GLint border
, GLsizei imageSize
,
3535 GET_CURRENT_CONTEXT(ctx
);
3536 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3538 if (target
== GL_TEXTURE_2D
||
3539 (ctx
->Extensions
.ARB_texture_cube_map
&&
3540 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3541 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
3542 /* non-proxy target */
3543 struct gl_texture_unit
*texUnit
;
3544 struct gl_texture_object
*texObj
;
3545 struct gl_texture_image
*texImage
;
3546 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
3547 internalFormat
, width
, height
, 1, border
, imageSize
);
3549 _mesa_error(ctx
, error
, "glCompressedTexImage2D");
3553 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3554 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3556 _mesa_lock_texture(ctx
, texObj
);
3558 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
3560 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
3564 if (texImage
->Data
) {
3565 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3567 ASSERT(texImage
->Data
== NULL
);
3569 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
3570 border
, internalFormat
);
3572 ASSERT(ctx
->Driver
.CompressedTexImage2D
);
3573 (*ctx
->Driver
.CompressedTexImage2D
)(ctx
, target
, level
,
3574 internalFormat
, width
, height
,
3575 border
, imageSize
, data
,
3579 texObj
->_Complete
= GL_FALSE
;
3580 ctx
->NewState
|= _NEW_TEXTURE
;
3583 _mesa_unlock_texture(ctx
, texObj
);
3585 else if (target
== GL_PROXY_TEXTURE_2D
||
3586 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
3587 ctx
->Extensions
.ARB_texture_cube_map
)) {
3588 /* Proxy texture: check for errors and update proxy state */
3589 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
3590 internalFormat
, width
, height
, 1, border
, imageSize
);
3592 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3593 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3594 internalFormat
, GL_NONE
, GL_NONE
,
3595 width
, height
, 1, border
);
3598 /* if error, clear all proxy texture image parameters */
3599 struct gl_texture_image
*texImage
;
3600 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3602 clear_teximage_fields(texImage
);
3605 /* store the teximage parameters */
3606 struct gl_texture_unit
*texUnit
;
3607 struct gl_texture_object
*texObj
;
3608 struct gl_texture_image
*texImage
;
3609 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3610 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3612 _mesa_lock_texture(ctx
, texObj
);
3614 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3615 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
3616 border
, internalFormat
);
3618 _mesa_unlock_texture(ctx
, texObj
);
3622 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(target)");
3629 _mesa_CompressedTexImage3DARB(GLenum target
, GLint level
,
3630 GLenum internalFormat
, GLsizei width
,
3631 GLsizei height
, GLsizei depth
, GLint border
,
3632 GLsizei imageSize
, const GLvoid
*data
)
3634 GET_CURRENT_CONTEXT(ctx
);
3635 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3637 if (target
== GL_TEXTURE_3D
) {
3638 /* non-proxy target */
3639 struct gl_texture_unit
*texUnit
;
3640 struct gl_texture_object
*texObj
;
3641 struct gl_texture_image
*texImage
;
3642 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3643 internalFormat
, width
, height
, depth
, border
, imageSize
);
3645 _mesa_error(ctx
, error
, "glCompressedTexImage3D");
3649 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3650 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3651 _mesa_lock_texture(ctx
, texObj
);
3653 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
3655 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage3D");
3659 if (texImage
->Data
) {
3660 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3662 ASSERT(texImage
->Data
== NULL
);
3664 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, depth
,
3665 border
, internalFormat
);
3667 ASSERT(ctx
->Driver
.CompressedTexImage3D
);
3668 (*ctx
->Driver
.CompressedTexImage3D
)(ctx
, target
, level
,
3670 width
, height
, depth
,
3671 border
, imageSize
, data
,
3675 texObj
->_Complete
= GL_FALSE
;
3676 ctx
->NewState
|= _NEW_TEXTURE
;
3679 _mesa_unlock_texture(ctx
, texObj
);
3681 else if (target
== GL_PROXY_TEXTURE_3D
) {
3682 /* Proxy texture: check for errors and update proxy state */
3683 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3684 internalFormat
, width
, height
, depth
, border
, imageSize
);
3686 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3687 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3688 internalFormat
, GL_NONE
, GL_NONE
,
3689 width
, height
, depth
, border
);
3692 /* if error, clear all proxy texture image parameters */
3693 struct gl_texture_image
*texImage
;
3694 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3696 clear_teximage_fields(texImage
);
3699 /* store the teximage parameters */
3700 struct gl_texture_unit
*texUnit
;
3701 struct gl_texture_object
*texObj
;
3702 struct gl_texture_image
*texImage
;
3703 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3704 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3705 _mesa_lock_texture(ctx
, texObj
);
3707 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3708 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
,
3709 depth
, border
, internalFormat
);
3711 _mesa_unlock_texture(ctx
, texObj
);
3715 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage3D(target)");
3722 _mesa_CompressedTexSubImage1DARB(GLenum target
, GLint level
, GLint xoffset
,
3723 GLsizei width
, GLenum format
,
3724 GLsizei imageSize
, const GLvoid
*data
)
3726 struct gl_texture_unit
*texUnit
;
3727 struct gl_texture_object
*texObj
;
3728 struct gl_texture_image
*texImage
;
3730 GET_CURRENT_CONTEXT(ctx
);
3731 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3733 error
= compressed_subtexture_error_check(ctx
, 1, target
, level
,
3734 xoffset
, 0, 0, /* pos */
3735 width
, 1, 1, /* size */
3738 _mesa_error(ctx
, error
, "glCompressedTexSubImage1D");
3742 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3743 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3744 _mesa_lock_texture(ctx
, texObj
);
3746 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3749 if ((GLint
) format
!= texImage
->InternalFormat
) {
3750 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3751 "glCompressedTexSubImage1D(format)");
3755 if ((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) {
3756 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage1D(width)");
3761 goto out
; /* no-op, not an error */
3763 if (ctx
->Driver
.CompressedTexSubImage1D
) {
3764 (*ctx
->Driver
.CompressedTexSubImage1D
)(ctx
, target
, level
,
3766 format
, imageSize
, data
,
3769 ctx
->NewState
|= _NEW_TEXTURE
;
3772 _mesa_unlock_texture(ctx
, texObj
);
3777 _mesa_CompressedTexSubImage2DARB(GLenum target
, GLint level
, GLint xoffset
,
3778 GLint yoffset
, GLsizei width
, GLsizei height
,
3779 GLenum format
, GLsizei imageSize
,
3782 struct gl_texture_unit
*texUnit
;
3783 struct gl_texture_object
*texObj
;
3784 struct gl_texture_image
*texImage
;
3786 GET_CURRENT_CONTEXT(ctx
);
3787 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3789 error
= compressed_subtexture_error_check(ctx
, 2, target
, level
,
3790 xoffset
, yoffset
, 0, /* pos */
3791 width
, height
, 1, /* size */
3794 /* XXX proxy target? */
3795 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3799 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3800 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3801 _mesa_lock_texture(ctx
, texObj
);
3803 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3806 if ((GLint
) format
!= texImage
->InternalFormat
) {
3807 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3808 "glCompressedTexSubImage2D(format)");
3812 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3813 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
)) {
3814 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage2D(size)");
3818 if (width
== 0 || height
== 0)
3819 goto out
; /* no-op, not an error */
3821 if (ctx
->Driver
.CompressedTexSubImage2D
) {
3822 (*ctx
->Driver
.CompressedTexSubImage2D
)(ctx
, target
, level
,
3823 xoffset
, yoffset
, width
, height
,
3824 format
, imageSize
, data
,
3827 ctx
->NewState
|= _NEW_TEXTURE
;
3830 _mesa_unlock_texture(ctx
, texObj
);
3835 _mesa_CompressedTexSubImage3DARB(GLenum target
, GLint level
, GLint xoffset
,
3836 GLint yoffset
, GLint zoffset
, GLsizei width
,
3837 GLsizei height
, GLsizei depth
, GLenum format
,
3838 GLsizei imageSize
, const GLvoid
*data
)
3840 struct gl_texture_unit
*texUnit
;
3841 struct gl_texture_object
*texObj
;
3842 struct gl_texture_image
*texImage
;
3844 GET_CURRENT_CONTEXT(ctx
);
3845 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3847 error
= compressed_subtexture_error_check(ctx
, 3, target
, level
,
3848 xoffset
, yoffset
, zoffset
,/*pos*/
3849 width
, height
, depth
, /*size*/
3852 _mesa_error(ctx
, error
, "glCompressedTexSubImage3D");
3856 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3857 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3858 _mesa_lock_texture(ctx
, texObj
);
3860 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3863 if ((GLint
) format
!= texImage
->InternalFormat
) {
3864 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3865 "glCompressedTexSubImage3D(format)");
3869 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3870 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
) ||
3871 ((depth
== 1 || depth
== 2) && (GLuint
) depth
!= texImage
->Depth
)) {
3872 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage3D(size)");
3876 if (width
== 0 || height
== 0 || depth
== 0)
3877 goto out
; /* no-op, not an error */
3879 if (ctx
->Driver
.CompressedTexSubImage3D
) {
3880 (*ctx
->Driver
.CompressedTexSubImage3D
)(ctx
, target
, level
,
3881 xoffset
, yoffset
, zoffset
,
3882 width
, height
, depth
,
3883 format
, imageSize
, data
,
3886 ctx
->NewState
|= _NEW_TEXTURE
;
3889 _mesa_unlock_texture(ctx
, texObj
);
3894 _mesa_GetCompressedTexImageARB(GLenum target
, GLint level
, GLvoid
*img
)
3896 const struct gl_texture_unit
*texUnit
;
3897 struct gl_texture_object
*texObj
;
3898 struct gl_texture_image
*texImage
;
3900 GET_CURRENT_CONTEXT(ctx
);
3901 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3903 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3904 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3906 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB");
3910 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
3911 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
3913 if (level
< 0 || level
>= maxLevels
) {
3914 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3918 if (_mesa_is_proxy_texture(target
)) {
3919 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
3923 _mesa_lock_texture(ctx
, texObj
);
3925 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3927 if (texImage
->IsCompressed
) {
3928 /* this typically calls _mesa_get_compressed_teximage() */
3929 ctx
->Driver
.GetCompressedTexImage(ctx
, target
, level
, img
,
3933 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3934 "glGetCompressedTexImageARB");
3938 /* probably invalid mipmap level */
3939 _mesa_error(ctx
, GL_INVALID_VALUE
,
3940 "glGetCompressedTexImageARB(level)");
3943 _mesa_unlock_texture(ctx
, texObj
);