2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * Texture image-related functions.
33 #include "bufferobj.h"
37 #include "framebuffer.h"
42 #include "texcompress.h"
43 #include "texformat.h"
51 * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
55 _mesa_alloc_texmemory(GLsizei bytes
)
57 return _mesa_align_malloc(bytes
, 512);
62 * Free texture memory allocated with _mesa_alloc_texmemory()
65 _mesa_free_texmemory(void *m
)
74 static void PrintTexture(GLcontext
*ctx
, const struct gl_texture_image
*img
)
76 #if CHAN_TYPE != GL_UNSIGNED_BYTE
77 _mesa_problem(NULL
, "PrintTexture not supported");
80 const GLubyte
*data
= (const GLubyte
*) img
->Data
;
83 _mesa_printf("No texture data\n");
87 switch (img
->Format
) {
94 case GL_LUMINANCE_ALPHA
:
104 _mesa_problem(NULL
, "error in PrintTexture\n");
108 for (i
= 0; i
< img
->Height
; i
++) {
109 for (j
= 0; j
< img
->Width
; j
++) {
111 _mesa_printf("%02x ", data
[0]);
113 _mesa_printf("%02x%02x ", data
[0], data
[1]);
115 _mesa_printf("%02x%02x%02x ", data
[0], data
[1], data
[2]);
117 _mesa_printf("%02x%02x%02x%02x ", data
[0], data
[1], data
[2], data
[3]);
118 data
+= (img
->RowStride
- img
->Width
) * c
;
120 /* XXX use img->ImageStride here */
129 * Compute floor(log_base_2(n)).
130 * If n < 0 return -1.
159 * Return the simple base format for a given internal texture format.
160 * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
162 * \param ctx GL context.
163 * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
165 * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
166 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
168 * This is the format which is used during texture application (i.e. the
169 * texture format and env mode determine the arithmetic used.
172 _mesa_base_tex_format( GLcontext
*ctx
, GLint internalFormat
)
174 switch (internalFormat
) {
189 case GL_LUMINANCE_ALPHA
:
190 case GL_LUMINANCE4_ALPHA4
:
191 case GL_LUMINANCE6_ALPHA2
:
192 case GL_LUMINANCE8_ALPHA8
:
193 case GL_LUMINANCE12_ALPHA4
:
194 case GL_LUMINANCE12_ALPHA12
:
195 case GL_LUMINANCE16_ALPHA16
:
196 return GL_LUMINANCE_ALPHA
;
227 if (ctx
->Extensions
.EXT_paletted_texture
) {
228 switch (internalFormat
) {
230 case GL_COLOR_INDEX1_EXT
:
231 case GL_COLOR_INDEX2_EXT
:
232 case GL_COLOR_INDEX4_EXT
:
233 case GL_COLOR_INDEX8_EXT
:
234 case GL_COLOR_INDEX12_EXT
:
235 case GL_COLOR_INDEX16_EXT
:
236 return GL_COLOR_INDEX
;
242 if (ctx
->Extensions
.SGIX_depth_texture
||
243 ctx
->Extensions
.ARB_depth_texture
) {
244 switch (internalFormat
) {
245 case GL_DEPTH_COMPONENT
:
246 case GL_DEPTH_COMPONENT16_SGIX
:
247 case GL_DEPTH_COMPONENT24_SGIX
:
248 case GL_DEPTH_COMPONENT32_SGIX
:
249 return GL_DEPTH_COMPONENT
;
255 if (ctx
->Extensions
.ARB_texture_compression
) {
256 switch (internalFormat
) {
257 case GL_COMPRESSED_ALPHA
:
259 case GL_COMPRESSED_LUMINANCE
:
261 case GL_COMPRESSED_LUMINANCE_ALPHA
:
262 return GL_LUMINANCE_ALPHA
;
263 case GL_COMPRESSED_INTENSITY
:
265 case GL_COMPRESSED_RGB
:
267 case GL_COMPRESSED_RGBA
:
274 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
) {
275 switch (internalFormat
) {
276 case GL_COMPRESSED_RGB_FXT1_3DFX
:
278 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
285 if (ctx
->Extensions
.EXT_texture_compression_s3tc
) {
286 switch (internalFormat
) {
287 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
289 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
290 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
291 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
298 if (ctx
->Extensions
.S3_s3tc
) {
299 switch (internalFormat
) {
311 if (ctx
->Extensions
.MESA_ycbcr_texture
) {
312 if (internalFormat
== GL_YCBCR_MESA
)
313 return GL_YCBCR_MESA
;
316 if (ctx
->Extensions
.ARB_texture_float
) {
317 switch (internalFormat
) {
318 case GL_ALPHA16F_ARB
:
319 case GL_ALPHA32F_ARB
:
327 case GL_INTENSITY16F_ARB
:
328 case GL_INTENSITY32F_ARB
:
330 case GL_LUMINANCE16F_ARB
:
331 case GL_LUMINANCE32F_ARB
:
333 case GL_LUMINANCE_ALPHA16F_ARB
:
334 case GL_LUMINANCE_ALPHA32F_ARB
:
335 return GL_LUMINANCE_ALPHA
;
341 if (ctx
->Extensions
.EXT_packed_depth_stencil
) {
342 switch (internalFormat
) {
343 case GL_DEPTH_STENCIL_EXT
:
344 case GL_DEPTH24_STENCIL8_EXT
:
345 return GL_DEPTH_STENCIL_EXT
;
351 #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.
392 is_color_format(GLenum format
)
410 case GL_LUMINANCE_ALPHA
:
411 case GL_LUMINANCE4_ALPHA4
:
412 case GL_LUMINANCE6_ALPHA2
:
413 case GL_LUMINANCE8_ALPHA8
:
414 case GL_LUMINANCE12_ALPHA4
:
415 case GL_LUMINANCE12_ALPHA12
:
416 case GL_LUMINANCE16_ALPHA16
:
443 /* float texture formats */
444 case GL_ALPHA16F_ARB
:
445 case GL_ALPHA32F_ARB
:
446 case GL_LUMINANCE16F_ARB
:
447 case GL_LUMINANCE32F_ARB
:
448 case GL_LUMINANCE_ALPHA16F_ARB
:
449 case GL_LUMINANCE_ALPHA32F_ARB
:
450 case GL_INTENSITY16F_ARB
:
451 case GL_INTENSITY32F_ARB
:
456 /* compressed formats */
457 case GL_COMPRESSED_ALPHA
:
458 case GL_COMPRESSED_LUMINANCE
:
459 case GL_COMPRESSED_LUMINANCE_ALPHA
:
460 case GL_COMPRESSED_INTENSITY
:
461 case GL_COMPRESSED_RGB
:
462 case GL_COMPRESSED_RGBA
:
467 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
468 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
469 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
470 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
471 case GL_COMPRESSED_RGB_FXT1_3DFX
:
472 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
473 #if FEATURE_EXT_texture_sRGB
476 case GL_SRGB_ALPHA_EXT
:
477 case GL_SRGB8_ALPHA8_EXT
:
478 case GL_SLUMINANCE_ALPHA_EXT
:
479 case GL_SLUMINANCE8_ALPHA8_EXT
:
480 case GL_SLUMINANCE_EXT
:
481 case GL_SLUMINANCE8_EXT
:
482 case GL_COMPRESSED_SRGB_EXT
:
483 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
:
484 case GL_COMPRESSED_SRGB_ALPHA_EXT
:
485 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
:
486 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
:
487 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
:
488 case GL_COMPRESSED_SLUMINANCE_EXT
:
489 case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT
:
490 #endif /* FEATURE_EXT_texture_sRGB */
492 case GL_YCBCR_MESA
: /* not considered to be RGB */
500 * Test if the given image format is a color index format.
503 is_index_format(GLenum format
)
507 case GL_COLOR_INDEX1_EXT
:
508 case GL_COLOR_INDEX2_EXT
:
509 case GL_COLOR_INDEX4_EXT
:
510 case GL_COLOR_INDEX8_EXT
:
511 case GL_COLOR_INDEX12_EXT
:
512 case GL_COLOR_INDEX16_EXT
:
521 * Test if the given image format is a depth component format.
524 is_depth_format(GLenum format
)
527 case GL_DEPTH_COMPONENT16_ARB
:
528 case GL_DEPTH_COMPONENT24_ARB
:
529 case GL_DEPTH_COMPONENT32_ARB
:
530 case GL_DEPTH_COMPONENT
:
539 * Test if the given image format is a YCbCr format.
542 is_ycbcr_format(GLenum format
)
554 * Test if the given image format is a Depth/Stencil format.
557 is_depthstencil_format(GLenum format
)
560 case GL_DEPTH24_STENCIL8_EXT
:
561 case GL_DEPTH_STENCIL_EXT
:
571 * Test if it is a supported compressed format.
573 * \param internalFormat the internal format token provided by the user.
575 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
576 * GL_FALSE otherwise.
578 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
582 is_compressed_format(GLcontext
*ctx
, GLenum internalFormat
)
584 GLint supported
[100]; /* 100 should be plenty */
587 n
= _mesa_get_compressed_formats(ctx
, supported
, GL_TRUE
);
589 for (i
= 0; i
< n
; i
++) {
590 if ((GLint
) internalFormat
== supported
[i
]) {
599 texture_face(GLenum target
)
601 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
602 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)
603 return (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
611 * Store a gl_texture_image pointer in a gl_texture_object structure
612 * according to the target and level parameters.
614 * \param tObj texture object.
615 * \param target texture target.
616 * \param level image level.
617 * \param texImage texture image.
619 * This was basically prompted by the introduction of cube maps.
622 _mesa_set_tex_image(struct gl_texture_object
*tObj
,
623 GLenum target
, GLint level
,
624 struct gl_texture_image
*texImage
)
632 tObj
->Image
[0][level
] = texImage
;
634 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
635 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
636 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
637 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
638 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
639 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
641 GLuint face
= ((GLuint
) target
-
642 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
643 tObj
->Image
[face
][level
] = texImage
;
646 case GL_TEXTURE_RECTANGLE_NV
:
648 tObj
->Image
[0][level
] = texImage
;
651 _mesa_problem(NULL
, "bad target in _mesa_set_tex_image()");
654 /* Set the 'back' pointer */
655 texImage
->TexObject
= tObj
;
660 * Allocate a texture image structure.
662 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
665 * \return a pointer to gl_texture_image struct with all fields initialized to
668 struct gl_texture_image
*
669 _mesa_new_texture_image( GLcontext
*ctx
)
672 return CALLOC_STRUCT(gl_texture_image
);
677 * Free texture image data.
678 * This function is a fallback called via ctx->Driver.FreeTexImageData().
680 * \param teximage texture image.
682 * Free the texture image data if it's not marked as client data.
685 _mesa_free_texture_image_data(GLcontext
*ctx
,
686 struct gl_texture_image
*texImage
)
690 if (texImage
->Data
&& !texImage
->IsClientData
) {
691 /* free the old texture data */
692 _mesa_free_texmemory(texImage
->Data
);
695 texImage
->Data
= NULL
;
700 * Free texture image.
702 * \param teximage texture image.
704 * Free the texture image structure and the associated image data.
707 _mesa_delete_texture_image( GLcontext
*ctx
, struct gl_texture_image
*texImage
)
709 /* Free texImage->Data and/or any other driver-specific texture
712 ASSERT(ctx
->Driver
.FreeTexImageData
);
713 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
715 ASSERT(texImage
->Data
== NULL
);
716 if (texImage
->ImageOffsets
)
717 _mesa_free(texImage
->ImageOffsets
);
718 _mesa_free(texImage
);
723 * Test if a target is a proxy target.
725 * \param target texture target.
727 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
730 _mesa_is_proxy_texture(GLenum target
)
732 return (target
== GL_PROXY_TEXTURE_1D
||
733 target
== GL_PROXY_TEXTURE_2D
||
734 target
== GL_PROXY_TEXTURE_3D
||
735 target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
736 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
);
741 * Get the texture object that corresponds to the target of the given texture unit.
743 * \param ctx GL context.
744 * \param texUnit texture unit.
745 * \param target texture target.
747 * \return pointer to the texture object on success, or NULL on failure.
749 * \sa gl_texture_unit.
751 struct gl_texture_object
*
752 _mesa_select_tex_object(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
757 return texUnit
->Current1D
;
758 case GL_PROXY_TEXTURE_1D
:
759 return ctx
->Texture
.Proxy1D
;
761 return texUnit
->Current2D
;
762 case GL_PROXY_TEXTURE_2D
:
763 return ctx
->Texture
.Proxy2D
;
765 return texUnit
->Current3D
;
766 case GL_PROXY_TEXTURE_3D
:
767 return ctx
->Texture
.Proxy3D
;
768 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
769 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
770 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
771 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
772 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
773 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
774 case GL_TEXTURE_CUBE_MAP_ARB
:
775 return ctx
->Extensions
.ARB_texture_cube_map
776 ? texUnit
->CurrentCubeMap
: NULL
;
777 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
778 return ctx
->Extensions
.ARB_texture_cube_map
779 ? ctx
->Texture
.ProxyCubeMap
: NULL
;
780 case GL_TEXTURE_RECTANGLE_NV
:
781 return ctx
->Extensions
.NV_texture_rectangle
782 ? texUnit
->CurrentRect
: NULL
;
783 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
784 return ctx
->Extensions
.NV_texture_rectangle
785 ? ctx
->Texture
.ProxyRect
: NULL
;
787 _mesa_problem(NULL
, "bad target in _mesa_select_tex_object()");
794 * Get the texture image struct which corresponds to target and level
795 * of the given texture unit.
797 * \param ctx GL context.
798 * \param texUnit texture unit.
799 * \param target texture target.
800 * \param level image level.
802 * \return pointer to the texture image structure on success, or NULL on failure.
804 * \sa gl_texture_unit.
806 struct gl_texture_image
*
807 _mesa_select_tex_image(GLcontext
*ctx
, const struct gl_texture_object
*texObj
,
808 GLenum target
, GLint level
)
812 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
)
817 case GL_PROXY_TEXTURE_1D
:
819 case GL_PROXY_TEXTURE_2D
:
821 case GL_PROXY_TEXTURE_3D
:
822 return texObj
->Image
[0][level
];
824 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
825 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
826 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
827 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
828 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
829 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
830 if (ctx
->Extensions
.ARB_texture_cube_map
) {
831 GLuint face
= ((GLuint
) target
-
832 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
833 return texObj
->Image
[face
][level
];
838 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
839 if (ctx
->Extensions
.ARB_texture_cube_map
)
840 return texObj
->Image
[0][level
];
844 case GL_TEXTURE_RECTANGLE_NV
:
845 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
846 if (ctx
->Extensions
.NV_texture_rectangle
&& level
== 0)
847 return texObj
->Image
[0][level
];
858 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
859 * it and install it. Only return NULL if passed a bad parameter or run
862 struct gl_texture_image
*
863 _mesa_get_tex_image(GLcontext
*ctx
, struct gl_texture_object
*texObj
,
864 GLenum target
, GLint level
)
866 struct gl_texture_image
*texImage
;
871 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
873 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
875 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture image allocation");
879 _mesa_set_tex_image(texObj
, target
, level
, texImage
);
887 * Return pointer to the specified proxy texture image.
888 * Note that proxy textures are per-context, not per-texture unit.
889 * \return pointer to texture image or NULL if invalid target, invalid
890 * level, or out of memory.
892 struct gl_texture_image
*
893 _mesa_get_proxy_tex_image(GLcontext
*ctx
, GLenum target
, GLint level
)
895 struct gl_texture_image
*texImage
;
901 case GL_PROXY_TEXTURE_1D
:
902 if (level
>= ctx
->Const
.MaxTextureLevels
)
904 texImage
= ctx
->Texture
.Proxy1D
->Image
[0][level
];
906 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
908 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
911 ctx
->Texture
.Proxy1D
->Image
[0][level
] = texImage
;
912 /* Set the 'back' pointer */
913 texImage
->TexObject
= ctx
->Texture
.Proxy1D
;
916 case GL_PROXY_TEXTURE_2D
:
917 if (level
>= ctx
->Const
.MaxTextureLevels
)
919 texImage
= ctx
->Texture
.Proxy2D
->Image
[0][level
];
921 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
923 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
926 ctx
->Texture
.Proxy2D
->Image
[0][level
] = texImage
;
927 /* Set the 'back' pointer */
928 texImage
->TexObject
= ctx
->Texture
.Proxy2D
;
931 case GL_PROXY_TEXTURE_3D
:
932 if (level
>= ctx
->Const
.Max3DTextureLevels
)
934 texImage
= ctx
->Texture
.Proxy3D
->Image
[0][level
];
936 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
938 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
941 ctx
->Texture
.Proxy3D
->Image
[0][level
] = texImage
;
942 /* Set the 'back' pointer */
943 texImage
->TexObject
= ctx
->Texture
.Proxy3D
;
946 case GL_PROXY_TEXTURE_CUBE_MAP
:
947 if (level
>= ctx
->Const
.MaxCubeTextureLevels
)
949 texImage
= ctx
->Texture
.ProxyCubeMap
->Image
[0][level
];
951 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
953 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
956 ctx
->Texture
.ProxyCubeMap
->Image
[0][level
] = texImage
;
957 /* Set the 'back' pointer */
958 texImage
->TexObject
= ctx
->Texture
.ProxyCubeMap
;
961 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
964 texImage
= ctx
->Texture
.ProxyRect
->Image
[0][level
];
966 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
968 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
971 ctx
->Texture
.ProxyRect
->Image
[0][level
] = texImage
;
972 /* Set the 'back' pointer */
973 texImage
->TexObject
= ctx
->Texture
.ProxyRect
;
983 * Get the maximum number of allowed mipmap levels.
985 * \param ctx GL context.
986 * \param target texture target.
988 * \return the maximum number of allowed mipmap levels for the given
989 * texture target, or zero if passed a bad target.
994 _mesa_max_texture_levels(GLcontext
*ctx
, GLenum target
)
998 case GL_PROXY_TEXTURE_1D
:
1000 case GL_PROXY_TEXTURE_2D
:
1001 return ctx
->Const
.MaxTextureLevels
;
1003 case GL_PROXY_TEXTURE_3D
:
1004 return ctx
->Const
.Max3DTextureLevels
;
1005 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
1006 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
1007 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
1008 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
1009 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
1010 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
1011 case GL_TEXTURE_CUBE_MAP_ARB
:
1012 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
1013 return ctx
->Const
.MaxCubeTextureLevels
;
1014 case GL_TEXTURE_RECTANGLE_NV
:
1015 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
1018 return 0; /* bad target */
1024 #if 000 /* not used anymore */
1026 * glTexImage[123]D can accept a NULL image pointer. In this case we
1027 * create a texture image with unspecified image contents per the OpenGL
1031 make_null_texture(GLint width
, GLint height
, GLint depth
, GLenum format
)
1033 const GLint components
= _mesa_components_in_format(format
);
1034 const GLint numPixels
= width
* height
* depth
;
1035 GLubyte
*data
= (GLubyte
*) MALLOC(numPixels
* components
* sizeof(GLubyte
));
1039 * Let's see if anyone finds this. If glTexImage2D() is called with
1040 * a NULL image pointer then load the texture image with something
1041 * interesting instead of leaving it indeterminate.
1044 static const char message
[8][32] = {
1045 " X X XXXXX XXX X ",
1046 " XX XX X X X X X ",
1048 " X X XXXX XXX XXXXX ",
1051 " X X XXXXX XXX X X ",
1055 GLubyte
*imgPtr
= data
;
1057 for (h
= 0; h
< depth
; h
++) {
1058 for (i
= 0; i
< height
; i
++) {
1059 GLint srcRow
= 7 - (i
% 8);
1060 for (j
= 0; j
< width
; j
++) {
1061 GLint srcCol
= j
% 32;
1062 GLubyte texel
= (message
[srcRow
][srcCol
]=='X') ? 255 : 70;
1063 for (k
= 0; k
< components
; k
++) {
1079 * Reset the fields of a gl_texture_image struct to zero.
1081 * \param img texture image structure.
1083 * This is called when a proxy texture test fails, we set all the
1084 * image members (except DriverData) to zero.
1085 * It's also used in glTexImage[123]D as a safeguard to be sure all
1086 * required fields get initialized properly by the Driver.TexImage[123]D
1090 clear_teximage_fields(struct gl_texture_image
*img
)
1093 img
->_BaseFormat
= 0;
1094 img
->InternalFormat
= 0;
1100 if (img
->ImageOffsets
) {
1101 _mesa_free(img
->ImageOffsets
);
1102 img
->ImageOffsets
= NULL
;
1108 img
->HeightLog2
= 0;
1111 img
->TexFormat
= &_mesa_null_texformat
;
1112 img
->FetchTexelc
= NULL
;
1113 img
->FetchTexelf
= NULL
;
1114 img
->IsCompressed
= 0;
1115 img
->CompressedSize
= 0;
1120 * Initialize basic fields of the gl_texture_image struct.
1122 * \param ctx GL context.
1123 * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
1124 * \param img texture image structure to be initialized.
1125 * \param width image width.
1126 * \param height image height.
1127 * \param depth image depth.
1128 * \param border image border.
1129 * \param internalFormat internal format.
1131 * Fills in the fields of \p img with the given information.
1132 * Note: width, height and depth include the border.
1135 _mesa_init_teximage_fields(GLcontext
*ctx
, GLenum target
,
1136 struct gl_texture_image
*img
,
1137 GLsizei width
, GLsizei height
, GLsizei depth
,
1138 GLint border
, GLenum internalFormat
)
1144 ASSERT(height
>= 0);
1147 img
->_BaseFormat
= _mesa_base_tex_format( ctx
, internalFormat
);
1148 ASSERT(img
->_BaseFormat
> 0);
1149 img
->InternalFormat
= internalFormat
;
1150 img
->Border
= border
;
1152 img
->Height
= height
;
1154 img
->Width2
= width
- 2 * border
; /* == 1 << img->WidthLog2; */
1155 img
->Height2
= height
- 2 * border
; /* == 1 << img->HeightLog2; */
1156 img
->Depth2
= depth
- 2 * border
; /* == 1 << img->DepthLog2; */
1157 img
->WidthLog2
= logbase2(img
->Width2
);
1158 if (height
== 1) /* 1-D texture */
1159 img
->HeightLog2
= 0;
1161 img
->HeightLog2
= logbase2(img
->Height2
);
1162 if (depth
== 1) /* 2-D texture */
1165 img
->DepthLog2
= logbase2(img
->Depth2
);
1166 img
->MaxLog2
= MAX2(img
->WidthLog2
, img
->HeightLog2
);
1167 img
->IsCompressed
= GL_FALSE
;
1168 img
->CompressedSize
= 0;
1170 if ((width
== 1 || _mesa_bitcount(img
->Width2
) == 1) &&
1171 (height
== 1 || _mesa_bitcount(img
->Height2
) == 1) &&
1172 (depth
== 1 || _mesa_bitcount(img
->Depth2
) == 1))
1173 img
->_IsPowerOfTwo
= GL_TRUE
;
1175 img
->_IsPowerOfTwo
= GL_FALSE
;
1177 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
1178 img
->RowStride
= width
;
1179 /* Allocate the ImageOffsets array and initialize to typical values.
1180 * We allocate the array for 1D/2D textures too in order to avoid special-
1181 * case code in the texstore routines.
1183 img
->ImageOffsets
= (GLuint
*) _mesa_malloc(depth
* sizeof(GLuint
));
1184 for (i
= 0; i
< depth
; i
++) {
1185 img
->ImageOffsets
[i
] = i
* width
* height
;
1188 /* Compute Width/Height/DepthScale for mipmap lod computation */
1189 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1190 /* scale = 1.0 since texture coords directly map to texels */
1191 img
->WidthScale
= 1.0;
1192 img
->HeightScale
= 1.0;
1193 img
->DepthScale
= 1.0;
1196 img
->WidthScale
= (GLfloat
) img
->Width
;
1197 img
->HeightScale
= (GLfloat
) img
->Height
;
1198 img
->DepthScale
= (GLfloat
) img
->Depth
;
1204 * This is the fallback for Driver.TestProxyTexImage(). Test the texture
1205 * level, width, height and depth against the ctx->Const limits for textures.
1207 * A hardware driver might override this function if, for example, the
1208 * max 3D texture size is 512x512x64 (i.e. not a cube).
1210 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
1211 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
1212 * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
1213 * \param level as passed to glTexImage
1214 * \param internalFormat as passed to glTexImage
1215 * \param format as passed to glTexImage
1216 * \param type as passed to glTexImage
1217 * \param width as passed to glTexImage
1218 * \param height as passed to glTexImage
1219 * \param depth as passed to glTexImage
1220 * \param border as passed to glTexImage
1221 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1224 _mesa_test_proxy_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
1225 GLint internalFormat
, GLenum format
, GLenum type
,
1226 GLint width
, GLint height
, GLint depth
, GLint border
)
1230 (void) internalFormat
;
1235 case GL_PROXY_TEXTURE_1D
:
1236 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1237 if (width
< 2 * border
|| width
> 2 + maxSize
||
1238 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1239 _mesa_bitcount(width
- 2 * border
) != 1) ||
1240 level
>= ctx
->Const
.MaxTextureLevels
) {
1241 /* bad width or level */
1245 case GL_PROXY_TEXTURE_2D
:
1246 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1247 if (width
< 2 * border
|| width
> 2 + maxSize
||
1248 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1249 _mesa_bitcount(width
- 2 * border
) != 1) ||
1250 height
< 2 * border
|| height
> 2 + maxSize
||
1251 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1252 _mesa_bitcount(height
- 2 * border
) != 1) ||
1253 level
>= ctx
->Const
.MaxTextureLevels
) {
1254 /* bad width or height or level */
1258 case GL_PROXY_TEXTURE_3D
:
1259 maxSize
= 1 << (ctx
->Const
.Max3DTextureLevels
- 1);
1260 if (width
< 2 * border
|| width
> 2 + maxSize
||
1261 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1262 _mesa_bitcount(width
- 2 * border
) != 1) ||
1263 height
< 2 * border
|| height
> 2 + maxSize
||
1264 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1265 _mesa_bitcount(height
- 2 * border
) != 1) ||
1266 depth
< 2 * border
|| depth
> 2 + maxSize
||
1267 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1268 _mesa_bitcount(depth
- 2 * border
) != 1) ||
1269 level
>= ctx
->Const
.Max3DTextureLevels
) {
1270 /* bad width or height or depth or level */
1274 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
1275 if (width
< 1 || width
> ctx
->Const
.MaxTextureRectSize
||
1276 height
< 1 || height
> ctx
->Const
.MaxTextureRectSize
||
1278 /* bad width or height or level */
1282 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
1283 maxSize
= 1 << (ctx
->Const
.MaxCubeTextureLevels
- 1);
1284 if (width
< 2 * border
|| width
> 2 + maxSize
||
1285 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1286 _mesa_bitcount(width
- 2 * border
) != 1) ||
1287 height
< 2 * border
|| height
> 2 + maxSize
||
1288 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1289 _mesa_bitcount(height
- 2 * border
) != 1) ||
1290 level
>= ctx
->Const
.MaxCubeTextureLevels
) {
1291 /* bad width or height */
1296 _mesa_problem(ctx
, "Invalid target in _mesa_test_proxy_teximage");
1303 * Test the glTexImage[123]D() parameters for errors.
1305 * \param ctx GL context.
1306 * \param target texture target given by the user.
1307 * \param level image level given by the user.
1308 * \param internalFormat internal format given by the user.
1309 * \param format pixel data format given by the user.
1310 * \param type pixel data type given by the user.
1311 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1312 * \param width image width given by the user.
1313 * \param height image height given by the user.
1314 * \param depth image depth given by the user.
1315 * \param border image border given by the user.
1317 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1319 * Verifies each of the parameters against the constants specified in
1320 * __GLcontextRec::Const and the supported extensions, and according to the
1321 * OpenGL specification.
1324 texture_error_check( GLcontext
*ctx
, GLenum target
,
1325 GLint level
, GLint internalFormat
,
1326 GLenum format
, GLenum type
,
1328 GLint width
, GLint height
,
1329 GLint depth
, GLint border
)
1331 const GLboolean isProxy
= _mesa_is_proxy_texture(target
);
1333 GLboolean colorFormat
, indexFormat
;
1335 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1336 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1338 _mesa_error(ctx
, GL_INVALID_VALUE
,
1339 "glTexImage%dD(level=%d)", dimensions
, level
);
1345 if (border
< 0 || border
> 1 ||
1346 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1347 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1349 _mesa_error(ctx
, GL_INVALID_VALUE
,
1350 "glTexImage%dD(border=%d)", dimensions
, border
);
1355 if (width
< 0 || height
< 0 || depth
< 0) {
1357 _mesa_error(ctx
, GL_INVALID_VALUE
,
1358 "glTexImage%dD(width, height or depth < 0)", dimensions
);
1363 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1364 * level, width, height and depth.
1366 if (dimensions
== 1) {
1367 if (target
== GL_PROXY_TEXTURE_1D
|| target
== GL_TEXTURE_1D
) {
1368 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1369 level
, internalFormat
,
1371 width
, 1, 1, border
);
1374 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1378 else if (dimensions
== 2) {
1379 if (target
== GL_PROXY_TEXTURE_2D
|| target
== GL_TEXTURE_2D
) {
1380 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1381 level
, internalFormat
,
1383 width
, height
, 1, border
);
1385 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
1386 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1387 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
1388 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1389 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1392 sizeOK
= (width
== height
) &&
1393 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1394 level
, internalFormat
, format
, type
,
1395 width
, height
, 1, border
);
1397 else if (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
||
1398 target
== GL_TEXTURE_RECTANGLE_NV
) {
1399 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1400 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1403 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1404 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1405 level
, internalFormat
,
1407 width
, height
, 1, border
);
1410 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1414 else if (dimensions
== 3) {
1415 if (target
== GL_PROXY_TEXTURE_3D
|| target
== GL_TEXTURE_3D
) {
1416 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_3D
,
1417 level
, internalFormat
,
1419 width
, height
, depth
, border
);
1422 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1427 _mesa_problem( ctx
, "bad dims in texture_error_check" );
1433 _mesa_error(ctx
, GL_INVALID_VALUE
,
1434 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1435 dimensions
, level
, width
, height
, depth
);
1440 /* Check internalFormat */
1441 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1443 _mesa_error(ctx
, GL_INVALID_VALUE
,
1444 "glTexImage%dD(internalFormat=0x%x)",
1445 dimensions
, internalFormat
);
1450 /* Check incoming image format and type */
1451 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
1452 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1453 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1456 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1457 "glTexImage%dD(format or type)", dimensions
);
1462 /* make sure internal format and format basically agree */
1463 colorFormat
= is_color_format(format
);
1464 indexFormat
= is_index_format(format
);
1465 if ((is_color_format(internalFormat
) && !colorFormat
&& !indexFormat
) ||
1466 (is_index_format(internalFormat
) && !indexFormat
) ||
1467 (is_depth_format(internalFormat
) != is_depth_format(format
)) ||
1468 (is_ycbcr_format(internalFormat
) != is_ycbcr_format(format
)) ||
1469 (is_depthstencil_format(internalFormat
) != is_depthstencil_format(format
))) {
1471 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1472 "glTexImage(internalFormat/format)");
1476 /* additional checks for ycbcr textures */
1477 if (internalFormat
== GL_YCBCR_MESA
) {
1478 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1479 if (type
!= GL_UNSIGNED_SHORT_8_8_MESA
&&
1480 type
!= GL_UNSIGNED_SHORT_8_8_REV_MESA
) {
1482 _mesa_sprintf(message
,
1483 "glTexImage%d(format/type YCBCR mismatch", dimensions
);
1484 _mesa_error(ctx
, GL_INVALID_ENUM
, message
);
1485 return GL_TRUE
; /* error */
1487 if (target
!= GL_TEXTURE_2D
&&
1488 target
!= GL_PROXY_TEXTURE_2D
&&
1489 target
!= GL_TEXTURE_RECTANGLE_NV
&&
1490 target
!= GL_PROXY_TEXTURE_RECTANGLE_NV
) {
1492 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage(target)");
1498 _mesa_sprintf(message
,
1499 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1500 dimensions
, border
);
1501 _mesa_error(ctx
, GL_INVALID_VALUE
, message
);
1507 /* additional checks for depth textures */
1508 if (_mesa_base_tex_format(ctx
, internalFormat
) == GL_DEPTH_COMPONENT
) {
1509 /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
1510 if (target
!= GL_TEXTURE_1D
&&
1511 target
!= GL_PROXY_TEXTURE_1D
&&
1512 target
!= GL_TEXTURE_2D
&&
1513 target
!= GL_PROXY_TEXTURE_2D
&&
1514 target
!= GL_TEXTURE_RECTANGLE_ARB
&&
1515 target
!= GL_PROXY_TEXTURE_RECTANGLE_ARB
) {
1517 _mesa_error(ctx
, GL_INVALID_ENUM
,
1518 "glTexImage(target/internalFormat)");
1523 /* additional checks for compressed textures */
1524 if (is_compressed_format(ctx
, internalFormat
)) {
1525 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1528 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1529 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1530 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1531 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1536 _mesa_error(ctx
, GL_INVALID_ENUM
,
1537 "glTexImage%d(target)", dimensions
);
1543 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1544 "glTexImage%D(border!=0)", dimensions
);
1550 /* if we get here, the parameters are OK */
1556 * Test glTexSubImage[123]D() parameters for errors.
1558 * \param ctx GL context.
1559 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1560 * \param target texture target given by the user.
1561 * \param level image level given by the user.
1562 * \param xoffset sub-image x offset given by the user.
1563 * \param yoffset sub-image y offset given by the user.
1564 * \param zoffset sub-image z offset given by the user.
1565 * \param format pixel data format given by the user.
1566 * \param type pixel data type given by the user.
1567 * \param width image width given by the user.
1568 * \param height image height given by the user.
1569 * \param depth image depth given by the user.
1571 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1573 * Verifies each of the parameters against the constants specified in
1574 * __GLcontextRec::Const and the supported extensions, and according to the
1575 * OpenGL specification.
1578 subtexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1579 GLenum target
, GLint level
,
1580 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1581 GLint width
, GLint height
, GLint depth
,
1582 GLenum format
, GLenum type
)
1585 if (dimensions
== 1) {
1586 if (target
!= GL_TEXTURE_1D
) {
1587 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
1591 else if (dimensions
== 2) {
1592 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1593 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1594 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1595 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1599 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1600 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1601 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1605 else if (target
!= GL_TEXTURE_2D
) {
1606 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1610 else if (dimensions
== 3) {
1611 if (target
!= GL_TEXTURE_3D
) {
1612 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
1617 _mesa_problem( ctx
, "invalid dims in texture_error_check" );
1621 /* Basic level check */
1622 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1623 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level=%d)", level
);
1628 _mesa_error(ctx
, GL_INVALID_VALUE
,
1629 "glTexSubImage%dD(width=%d)", dimensions
, width
);
1632 if (height
< 0 && dimensions
> 1) {
1633 _mesa_error(ctx
, GL_INVALID_VALUE
,
1634 "glTexSubImage%dD(height=%d)", dimensions
, height
);
1637 if (depth
< 0 && dimensions
> 2) {
1638 _mesa_error(ctx
, GL_INVALID_VALUE
,
1639 "glTexSubImage%dD(depth=%d)", dimensions
, depth
);
1643 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
1644 _mesa_error(ctx
, GL_INVALID_ENUM
,
1645 "glTexSubImage%dD(format or type)", dimensions
);
1653 subtexture_error_check2( GLcontext
*ctx
, GLuint dimensions
,
1654 GLenum target
, GLint level
,
1655 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1656 GLint width
, GLint height
, GLint depth
,
1657 GLenum format
, GLenum type
,
1658 const struct gl_texture_image
*destTex
)
1661 /* undefined image level */
1662 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage%dD", dimensions
);
1666 if (xoffset
< -((GLint
)destTex
->Border
)) {
1667 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset)",
1671 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
1672 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset+width)",
1676 if (dimensions
> 1) {
1677 if (yoffset
< -((GLint
)destTex
->Border
)) {
1678 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset)",
1682 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
1683 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset+height)",
1688 if (dimensions
> 2) {
1689 if (zoffset
< -((GLint
)destTex
->Border
)) {
1690 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
1693 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+ destTex
->Border
)) {
1694 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
1699 #if FEATURE_EXT_texture_sRGB
1700 if (destTex
->InternalFormat
== GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
||
1701 destTex
->InternalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
||
1702 destTex
->InternalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
||
1703 destTex
->InternalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
) {
1704 if ((width
& 0x3) || (height
& 0x3) ||
1705 (xoffset
& 0x3) || (yoffset
& 0x3))
1706 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1707 "glTexSubImage%dD(size or offset not multiple of 4)",
1713 if (destTex
->IsCompressed
) {
1714 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1717 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1718 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1719 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1720 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1724 _mesa_error(ctx
, GL_INVALID_ENUM
,
1725 "glTexSubImage%D(target)", dimensions
);
1728 /* offset must be multiple of 4 */
1729 if ((xoffset
& 3) || (yoffset
& 3)) {
1730 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1731 "glTexSubImage%D(xoffset or yoffset)", dimensions
);
1734 /* size must be multiple of 4 or equal to whole texture size */
1735 if ((width
& 3) && (GLuint
) width
!= destTex
->Width
) {
1736 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1737 "glTexSubImage%D(width)", dimensions
);
1740 if ((height
& 3) && (GLuint
) height
!= destTex
->Height
) {
1741 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1742 "glTexSubImage%D(width)", dimensions
);
1752 * Test glCopyTexImage[12]D() parameters for errors.
1754 * \param ctx GL context.
1755 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1756 * \param target texture target given by the user.
1757 * \param level image level given by the user.
1758 * \param internalFormat internal format given by the user.
1759 * \param width image width given by the user.
1760 * \param height image height given by the user.
1761 * \param depth image depth given by the user.
1762 * \param border texture border.
1764 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1766 * Verifies each of the parameters against the constants specified in
1767 * __GLcontextRec::Const and the supported extensions, and according to the
1768 * OpenGL specification.
1771 copytexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1772 GLenum target
, GLint level
, GLint internalFormat
,
1773 GLint width
, GLint height
, GLint border
)
1779 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1780 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1781 _mesa_error(ctx
, GL_INVALID_VALUE
,
1782 "glCopyTexImage%dD(level=%d)", dimensions
, level
);
1786 /* Check that the source buffer is complete */
1787 if (ctx
->ReadBuffer
->Name
) {
1788 _mesa_test_framebuffer_completeness(ctx
, ctx
->ReadBuffer
);
1789 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
1790 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
1791 "glCopyTexImage%dD(invalid readbuffer)", dimensions
);
1797 if (border
< 0 || border
> 1 ||
1798 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1799 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1803 format
= _mesa_base_tex_format(ctx
, internalFormat
);
1805 _mesa_error(ctx
, GL_INVALID_VALUE
,
1806 "glCopyTexImage%dD(internalFormat)", dimensions
);
1810 /* NOTE: the format and type aren't really significant for
1811 * TestProxyTexImage(). Only the internalformat really matters.
1812 if (!_mesa_source_buffer_exists(ctx, format)) {
1813 _mesa_error(ctx, GL_INVALID_OPERATION,
1814 "glCopyTexImage%dD(missing readbuffer)", dimensions);
1821 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1822 * level, width, height and depth.
1824 if (dimensions
== 1) {
1825 if (target
== GL_TEXTURE_1D
) {
1826 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1827 level
, internalFormat
,
1829 width
, 1, 1, border
);
1832 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
1836 else if (dimensions
== 2) {
1837 if (target
== GL_TEXTURE_2D
) {
1838 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1839 level
, internalFormat
,
1841 width
, height
, 1, border
);
1843 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1844 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1845 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1846 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1849 sizeOK
= (width
== height
) &&
1850 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1851 level
, internalFormat
, format
, type
,
1852 width
, height
, 1, border
);
1854 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1855 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1856 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1859 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1860 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1861 level
, internalFormat
,
1863 width
, height
, 1, border
);
1866 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1871 _mesa_problem(ctx
, "invalid dimensions in copytexture_error_check");
1876 if (dimensions
== 1) {
1877 _mesa_error(ctx
, GL_INVALID_VALUE
,
1878 "glCopyTexImage1D(width=%d)", width
);
1881 ASSERT(dimensions
== 2);
1882 _mesa_error(ctx
, GL_INVALID_VALUE
,
1883 "glCopyTexImage2D(width=%d, height=%d)", width
, height
);
1888 if (is_compressed_format(ctx
, internalFormat
)) {
1889 if (target
!= GL_TEXTURE_2D
) {
1890 _mesa_error(ctx
, GL_INVALID_ENUM
,
1891 "glCopyTexImage%d(target)", dimensions
);
1895 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1896 "glCopyTexImage%D(border!=0)", dimensions
);
1900 else if (is_depth_format(internalFormat
)) {
1901 /* make sure we have depth/stencil buffers */
1902 if (!ctx
->ReadBuffer
->_DepthBuffer
) {
1903 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1904 "glCopyTexImage%D(no depth)", dimensions
);
1908 else if (is_depthstencil_format(internalFormat
)) {
1909 /* make sure we have depth/stencil buffers */
1910 if (!ctx
->ReadBuffer
->_DepthBuffer
|| !ctx
->ReadBuffer
->_StencilBuffer
) {
1911 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1912 "glCopyTexImage%D(no depth/stencil buffer)", dimensions
);
1917 /* if we get here, the parameters are OK */
1923 * Test glCopyTexSubImage[12]D() parameters for errors.
1925 * \param ctx GL context.
1926 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1927 * \param target texture target given by the user.
1928 * \param level image level given by the user.
1929 * \param xoffset sub-image x offset given by the user.
1930 * \param yoffset sub-image y offset given by the user.
1931 * \param zoffset sub-image z offset given by the user.
1932 * \param width image width given by the user.
1933 * \param height image height given by the user.
1935 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1937 * Verifies each of the parameters against the constants specified in
1938 * __GLcontextRec::Const and the supported extensions, and according to the
1939 * OpenGL specification.
1942 copytexsubimage_error_check( GLcontext
*ctx
, GLuint dimensions
,
1943 GLenum target
, GLint level
,
1944 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1945 GLsizei width
, GLsizei height
)
1948 /* Check that the source buffer is complete */
1949 if (ctx
->ReadBuffer
->Name
) {
1950 _mesa_test_framebuffer_completeness(ctx
, ctx
->ReadBuffer
);
1951 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
1952 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
1953 "glCopyTexImage%dD(invalid readbuffer)", dimensions
);
1958 if (dimensions
== 1) {
1959 if (target
!= GL_TEXTURE_1D
) {
1960 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
1964 else if (dimensions
== 2) {
1965 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1966 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1967 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1968 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1972 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1973 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1974 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1978 else if (target
!= GL_TEXTURE_2D
) {
1979 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1983 else if (dimensions
== 3) {
1984 if (target
!= GL_TEXTURE_3D
) {
1985 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
1991 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1992 _mesa_error(ctx
, GL_INVALID_VALUE
,
1993 "glCopyTexSubImage%dD(level=%d)", dimensions
, level
);
1999 _mesa_error(ctx
, GL_INVALID_VALUE
,
2000 "glCopyTexSubImage%dD(width=%d)", dimensions
, width
);
2003 if (dimensions
> 1 && height
< 0) {
2004 _mesa_error(ctx
, GL_INVALID_VALUE
,
2005 "glCopyTexSubImage%dD(height=%d)", dimensions
, height
);
2013 copytexsubimage_error_check2( GLcontext
*ctx
, GLuint dimensions
,
2014 GLenum target
, GLint level
,
2015 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2016 GLsizei width
, GLsizei height
,
2017 const struct gl_texture_image
*teximage
)
2020 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2021 "glCopyTexSubImage%dD(undefined texture level: %d)",
2026 if (xoffset
< -((GLint
)teximage
->Border
)) {
2027 _mesa_error(ctx
, GL_INVALID_VALUE
,
2028 "glCopyTexSubImage%dD(xoffset=%d)", dimensions
, xoffset
);
2031 if (xoffset
+ width
> (GLint
) (teximage
->Width
+ teximage
->Border
)) {
2032 _mesa_error(ctx
, GL_INVALID_VALUE
,
2033 "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
2036 if (dimensions
> 1) {
2037 if (yoffset
< -((GLint
)teximage
->Border
)) {
2038 _mesa_error(ctx
, GL_INVALID_VALUE
,
2039 "glCopyTexSubImage%dD(yoffset=%d)", dimensions
, yoffset
);
2042 /* NOTE: we're adding the border here, not subtracting! */
2043 if (yoffset
+ height
> (GLint
) (teximage
->Height
+ teximage
->Border
)) {
2044 _mesa_error(ctx
, GL_INVALID_VALUE
,
2045 "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
2050 if (dimensions
> 2) {
2051 if (zoffset
< -((GLint
)teximage
->Border
)) {
2052 _mesa_error(ctx
, GL_INVALID_VALUE
,
2053 "glCopyTexSubImage%dD(zoffset)", dimensions
);
2056 if (zoffset
> (GLint
) (teximage
->Depth
+ teximage
->Border
)) {
2057 _mesa_error(ctx
, GL_INVALID_VALUE
,
2058 "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
2063 if (teximage
->IsCompressed
) {
2064 if (target
!= GL_TEXTURE_2D
) {
2065 _mesa_error(ctx
, GL_INVALID_ENUM
,
2066 "glCopyTexSubImage%d(target)", dimensions
);
2069 /* offset must be multiple of 4 */
2070 if ((xoffset
& 3) || (yoffset
& 3)) {
2071 _mesa_error(ctx
, GL_INVALID_VALUE
,
2072 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions
);
2075 /* size must be multiple of 4 */
2076 if ((width
& 3) != 0 && (GLuint
) width
!= teximage
->Width
) {
2077 _mesa_error(ctx
, GL_INVALID_VALUE
,
2078 "glCopyTexSubImage%D(width)", dimensions
);
2081 if ((height
& 3) != 0 && (GLuint
) height
!= teximage
->Height
) {
2082 _mesa_error(ctx
, GL_INVALID_VALUE
,
2083 "glCopyTexSubImage%D(height)", dimensions
);
2088 if (teximage
->InternalFormat
== GL_YCBCR_MESA
) {
2089 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glCopyTexSubImage2D");
2093 if (!_mesa_source_buffer_exists(ctx
, teximage
->_BaseFormat
)) {
2094 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2095 "glCopyTexSubImage%dD(missing readbuffer)", dimensions
);
2099 if (teximage
->_BaseFormat
== GL_DEPTH_COMPONENT
) {
2100 if (!ctx
->ReadBuffer
->_DepthBuffer
) {
2101 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2102 "glCopyTexSubImage%D(no depth buffer)",
2107 else if (teximage
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
2108 if (!ctx
->ReadBuffer
->_DepthBuffer
|| !ctx
->ReadBuffer
->_StencilBuffer
) {
2109 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2110 "glCopyTexSubImage%D(no depth/stencil buffer)",
2116 /* if we get here, the parameters are OK */
2122 * Get texture image. Called by glGetTexImage.
2124 * \param target texture target.
2125 * \param level image level.
2126 * \param format pixel data format for returned image.
2127 * \param type pixel data type for returned image.
2128 * \param pixels returned pixel data.
2131 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
2132 GLenum type
, GLvoid
*pixels
)
2134 const struct gl_texture_unit
*texUnit
;
2135 struct gl_texture_object
*texObj
;
2136 struct gl_texture_image
*texImage
;
2137 GLint maxLevels
= 0;
2138 GET_CURRENT_CONTEXT(ctx
);
2139 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2141 texUnit
= &(ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
]);
2142 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2143 if (!texObj
|| _mesa_is_proxy_texture(target
)) {
2144 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)");
2148 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
2149 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
2151 if (level
< 0 || level
>= maxLevels
) {
2152 _mesa_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
2156 if (_mesa_sizeof_packed_type(type
) <= 0) {
2157 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
2161 if (_mesa_components_in_format(format
) <= 0 ||
2162 format
== GL_STENCIL_INDEX
) {
2163 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
2167 if (!ctx
->Extensions
.EXT_paletted_texture
&& is_index_format(format
)) {
2168 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2172 if (!ctx
->Extensions
.SGIX_depth_texture
&&
2173 !ctx
->Extensions
.ARB_depth_texture
&& is_depth_format(format
)) {
2174 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2178 if (!ctx
->Extensions
.MESA_ycbcr_texture
&& is_ycbcr_format(format
)) {
2179 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2183 if (!ctx
->Extensions
.EXT_packed_depth_stencil
2184 && is_depthstencil_format(format
)) {
2185 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
2192 _mesa_lock_texture(ctx
, texObj
);
2194 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2196 /* invalid mipmap level, not an error */
2201 /* Make sure the requested image format is compatible with the
2202 * texture's format. Note that a color index texture can be converted
2203 * to RGBA so that combo is allowed.
2205 if (is_color_format(format
)
2206 && !is_color_format(texImage
->TexFormat
->BaseFormat
)
2207 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
2208 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2211 else if (is_index_format(format
)
2212 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
2213 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2216 else if (is_depth_format(format
)
2217 && !is_depth_format(texImage
->TexFormat
->BaseFormat
)
2218 && !is_depthstencil_format(texImage
->TexFormat
->BaseFormat
)) {
2219 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2222 else if (is_ycbcr_format(format
)
2223 && !is_ycbcr_format(texImage
->TexFormat
->BaseFormat
)) {
2224 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2227 else if (is_depthstencil_format(format
)
2228 && !is_depthstencil_format(texImage
->TexFormat
->BaseFormat
)) {
2229 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
2233 if (ctx
->Pack
.BufferObj
->Name
) {
2234 /* packing texture image into a PBO */
2235 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
2236 if (!_mesa_validate_pbo_access(dimensions
, &ctx
->Pack
, texImage
->Width
,
2237 texImage
->Height
, texImage
->Depth
,
2238 format
, type
, pixels
)) {
2239 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2240 "glGetTexImage(invalid PBO access)");
2245 /* typically, this will call _mesa_get_teximage() */
2246 ctx
->Driver
.GetTexImage(ctx
, target
, level
, format
, type
, pixels
,
2251 _mesa_unlock_texture(ctx
, texObj
);
2257 * Check if the given texture image is bound to any framebuffer objects
2258 * and update/invalidate them.
2259 * XXX We're only checking the currently bound framebuffer object for now.
2260 * In the future, perhaps struct gl_texture_image should have a pointer (or
2261 * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to.
2264 update_fbo_texture(GLcontext
*ctx
, struct gl_texture_object
*texObj
,
2265 GLuint face
, GLuint level
)
2267 if (ctx
->DrawBuffer
->Name
) {
2269 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
2270 struct gl_renderbuffer_attachment
*att
=
2271 ctx
->DrawBuffer
->Attachment
+ i
;
2272 if (att
->Type
== GL_TEXTURE
&&
2273 att
->Texture
== texObj
&&
2274 att
->TextureLevel
== level
&&
2275 att
->CubeMapFace
== face
) {
2276 ASSERT(att
->Texture
->Image
[att
->CubeMapFace
][att
->TextureLevel
]);
2277 /* Tell driver about the new renderbuffer texture */
2278 ctx
->Driver
.RenderTexture(ctx
, ctx
->DrawBuffer
, att
);
2287 * Called from the API. Note that width includes the border.
2290 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalFormat
,
2291 GLsizei width
, GLint border
, GLenum format
,
2292 GLenum type
, const GLvoid
*pixels
)
2294 GLsizei postConvWidth
= width
;
2295 GET_CURRENT_CONTEXT(ctx
);
2296 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2298 if (is_color_format(internalFormat
)) {
2299 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2302 if (target
== GL_TEXTURE_1D
) {
2303 /* non-proxy target */
2304 struct gl_texture_unit
*texUnit
;
2305 struct gl_texture_object
*texObj
;
2306 struct gl_texture_image
*texImage
;
2307 const GLuint face
= texture_face(target
);
2309 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2310 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2311 return; /* error was recorded */
2314 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2315 _mesa_update_state(ctx
);
2317 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2318 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2319 _mesa_lock_texture(ctx
, texObj
);
2321 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
2323 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2327 if (texImage
->Data
) {
2328 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2331 ASSERT(texImage
->Data
== NULL
);
2333 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2334 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2335 postConvWidth
, 1, 1,
2336 border
, internalFormat
);
2338 ASSERT(ctx
->Driver
.TexImage1D
);
2340 /* Give the texture to the driver! <pixels> may be null! */
2341 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
2342 width
, border
, format
, type
, pixels
,
2343 &ctx
->Unpack
, texObj
, texImage
);
2345 ASSERT(texImage
->TexFormat
);
2347 update_fbo_texture(ctx
, texObj
, face
, level
);
2350 texObj
->Complete
= GL_FALSE
;
2351 ctx
->NewState
|= _NEW_TEXTURE
;
2354 _mesa_unlock_texture(ctx
, texObj
);
2356 else if (target
== GL_PROXY_TEXTURE_1D
) {
2357 /* Proxy texture: check for errors and update proxy state */
2358 struct gl_texture_image
*texImage
;
2359 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2360 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2361 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2362 /* when error, clear all proxy texture image parameters */
2364 clear_teximage_fields(texImage
);
2367 /* no error, set the tex image parameters */
2369 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2370 postConvWidth
, 1, 1,
2371 border
, internalFormat
);
2372 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2373 internalFormat
, format
, type
);
2377 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
2384 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalFormat
,
2385 GLsizei width
, GLsizei height
, GLint border
,
2386 GLenum format
, GLenum type
,
2387 const GLvoid
*pixels
)
2389 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2390 GET_CURRENT_CONTEXT(ctx
);
2391 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2393 if (is_color_format(internalFormat
)) {
2394 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2398 if (target
== GL_TEXTURE_2D
||
2399 (ctx
->Extensions
.ARB_texture_cube_map
&&
2400 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2401 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) ||
2402 (ctx
->Extensions
.NV_texture_rectangle
&&
2403 target
== GL_TEXTURE_RECTANGLE_NV
)) {
2404 /* non-proxy target */
2405 struct gl_texture_unit
*texUnit
;
2406 struct gl_texture_object
*texObj
;
2407 struct gl_texture_image
*texImage
;
2408 const GLuint face
= texture_face(target
);
2410 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2411 format
, type
, 2, postConvWidth
, postConvHeight
,
2413 return; /* error was recorded */
2416 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2417 _mesa_update_state(ctx
);
2419 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2420 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2421 _mesa_lock_texture(ctx
, texObj
);
2423 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
2425 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2429 if (texImage
->Data
) {
2430 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2433 ASSERT(texImage
->Data
== NULL
);
2434 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2435 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2436 postConvWidth
, postConvHeight
, 1,
2437 border
, internalFormat
);
2439 ASSERT(ctx
->Driver
.TexImage2D
);
2441 /* Give the texture to the driver! <pixels> may be null! */
2442 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
2443 width
, height
, border
, format
, type
, pixels
,
2444 &ctx
->Unpack
, texObj
, texImage
);
2446 ASSERT(texImage
->TexFormat
);
2448 update_fbo_texture(ctx
, texObj
, face
, level
);
2451 texObj
->Complete
= GL_FALSE
;
2452 ctx
->NewState
|= _NEW_TEXTURE
;
2455 _mesa_unlock_texture(ctx
, texObj
);
2457 else if (target
== GL_PROXY_TEXTURE_2D
||
2458 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2459 ctx
->Extensions
.ARB_texture_cube_map
) ||
2460 (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
&&
2461 ctx
->Extensions
.NV_texture_rectangle
)) {
2462 /* Proxy texture: check for errors and update proxy state */
2463 struct gl_texture_image
*texImage
;
2464 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2465 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2466 format
, type
, 2, postConvWidth
, postConvHeight
,
2468 /* when error, clear all proxy texture image parameters */
2470 clear_teximage_fields(ctx
->Texture
.Proxy2D
->Image
[0][level
]);
2473 /* no error, set the tex image parameters */
2474 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2475 postConvWidth
, postConvHeight
, 1,
2476 border
, internalFormat
);
2477 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2478 internalFormat
, format
, type
);
2482 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
2489 * Called by the API or display list executor.
2490 * Note that width and height include the border.
2493 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalFormat
,
2494 GLsizei width
, GLsizei height
, GLsizei depth
,
2495 GLint border
, GLenum format
, GLenum type
,
2496 const GLvoid
*pixels
)
2498 GET_CURRENT_CONTEXT(ctx
);
2499 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2501 if (target
== GL_TEXTURE_3D
) {
2502 /* non-proxy target */
2503 struct gl_texture_unit
*texUnit
;
2504 struct gl_texture_object
*texObj
;
2505 struct gl_texture_image
*texImage
;
2506 const GLuint face
= texture_face(target
);
2508 if (texture_error_check(ctx
, target
, level
, (GLint
) internalFormat
,
2509 format
, type
, 3, width
, height
, depth
, border
)) {
2510 return; /* error was recorded */
2513 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2514 _mesa_update_state(ctx
);
2516 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2517 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2518 _mesa_lock_texture(ctx
, texObj
);
2520 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
2522 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2526 if (texImage
->Data
) {
2527 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2530 ASSERT(texImage
->Data
== NULL
);
2531 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2532 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2533 width
, height
, depth
,
2534 border
, internalFormat
);
2536 ASSERT(ctx
->Driver
.TexImage3D
);
2538 /* Give the texture to the driver! <pixels> may be null! */
2539 (*ctx
->Driver
.TexImage3D
)(ctx
, target
, level
, internalFormat
,
2540 width
, height
, depth
, border
, format
, type
,
2541 pixels
, &ctx
->Unpack
, texObj
, texImage
);
2543 ASSERT(texImage
->TexFormat
);
2545 update_fbo_texture(ctx
, texObj
, face
, level
);
2548 texObj
->Complete
= GL_FALSE
;
2549 ctx
->NewState
|= _NEW_TEXTURE
;
2552 _mesa_unlock_texture(ctx
, texObj
);
2554 else if (target
== GL_PROXY_TEXTURE_3D
) {
2555 /* Proxy texture: check for errors and update proxy state */
2556 struct gl_texture_image
*texImage
;
2557 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2558 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2559 format
, type
, 3, width
, height
, depth
, border
)) {
2560 /* when error, clear all proxy texture image parameters */
2562 clear_teximage_fields(texImage
);
2565 /* no error, set the tex image parameters */
2566 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2567 border
, internalFormat
);
2568 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2569 internalFormat
, format
, type
);
2573 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
2580 _mesa_TexImage3DEXT( GLenum target
, GLint level
, GLenum internalFormat
,
2581 GLsizei width
, GLsizei height
, GLsizei depth
,
2582 GLint border
, GLenum format
, GLenum type
,
2583 const GLvoid
*pixels
)
2585 _mesa_TexImage3D(target
, level
, (GLint
) internalFormat
, width
, height
,
2586 depth
, border
, format
, type
, pixels
);
2592 _mesa_TexSubImage1D( GLenum target
, GLint level
,
2593 GLint xoffset
, GLsizei width
,
2594 GLenum format
, GLenum type
,
2595 const GLvoid
*pixels
)
2597 GLsizei postConvWidth
= width
;
2598 struct gl_texture_unit
*texUnit
;
2599 struct gl_texture_object
*texObj
;
2600 struct gl_texture_image
*texImage
= NULL
;
2601 GET_CURRENT_CONTEXT(ctx
);
2602 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2604 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2605 _mesa_update_state(ctx
);
2607 /* XXX should test internal format */
2608 if (is_color_format(format
)) {
2609 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2612 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
2613 postConvWidth
, 1, 1, format
, type
)) {
2614 return; /* error was detected */
2618 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2619 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2622 _mesa_lock_texture(ctx
, texObj
);
2624 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2626 if (subtexture_error_check2(ctx
, 1, target
, level
, xoffset
, 0, 0,
2627 postConvWidth
, 1, 1, format
, type
, texImage
)) {
2628 goto out
; /* error was detected */
2632 goto out
; /* no-op, not an error */
2634 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2635 xoffset
+= texImage
->Border
;
2637 ASSERT(ctx
->Driver
.TexSubImage1D
);
2638 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
2639 format
, type
, pixels
, &ctx
->Unpack
,
2641 ctx
->NewState
|= _NEW_TEXTURE
;
2644 _mesa_unlock_texture(ctx
, texObj
);
2649 _mesa_TexSubImage2D( GLenum target
, GLint level
,
2650 GLint xoffset
, GLint yoffset
,
2651 GLsizei width
, GLsizei height
,
2652 GLenum format
, GLenum type
,
2653 const GLvoid
*pixels
)
2655 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2656 struct gl_texture_unit
*texUnit
;
2657 struct gl_texture_object
*texObj
;
2658 struct gl_texture_image
*texImage
;
2659 GET_CURRENT_CONTEXT(ctx
);
2660 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2662 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2663 _mesa_update_state(ctx
);
2665 /* XXX should test internal format */
2666 if (is_color_format(format
)) {
2667 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2671 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2672 postConvWidth
, postConvHeight
, 1, format
, type
)) {
2673 return; /* error was detected */
2676 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2677 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2678 _mesa_lock_texture(ctx
, texObj
);
2680 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2682 if (subtexture_error_check2(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2683 postConvWidth
, postConvHeight
, 1, format
, type
,
2685 goto out
; /* error was detected */
2688 if (width
== 0 || height
== 0)
2689 goto out
; /* no-op, not an error */
2691 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2692 xoffset
+= texImage
->Border
;
2693 yoffset
+= texImage
->Border
;
2695 ASSERT(ctx
->Driver
.TexSubImage2D
);
2696 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
, xoffset
, yoffset
,
2697 width
, height
, format
, type
, pixels
,
2698 &ctx
->Unpack
, texObj
, texImage
);
2699 ctx
->NewState
|= _NEW_TEXTURE
;
2702 _mesa_unlock_texture(ctx
, texObj
);
2708 _mesa_TexSubImage3D( GLenum target
, GLint level
,
2709 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2710 GLsizei width
, GLsizei height
, GLsizei depth
,
2711 GLenum format
, GLenum type
,
2712 const GLvoid
*pixels
)
2714 struct gl_texture_unit
*texUnit
;
2715 struct gl_texture_object
*texObj
;
2716 struct gl_texture_image
*texImage
;
2717 GET_CURRENT_CONTEXT(ctx
);
2718 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2720 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2721 _mesa_update_state(ctx
);
2723 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2724 width
, height
, depth
, format
, type
)) {
2725 return; /* error was detected */
2728 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2729 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2731 _mesa_lock_texture(ctx
, texObj
);
2733 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2735 if (subtexture_error_check2(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2736 width
, height
, depth
, format
, type
, texImage
)) {
2737 goto out
; /* error was detected */
2740 if (width
== 0 || height
== 0 || height
== 0)
2741 goto out
; /* no-op, not an error */
2743 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2744 xoffset
+= texImage
->Border
;
2745 yoffset
+= texImage
->Border
;
2746 zoffset
+= texImage
->Border
;
2748 ASSERT(ctx
->Driver
.TexSubImage3D
);
2749 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
2750 xoffset
, yoffset
, zoffset
,
2751 width
, height
, depth
,
2752 format
, type
, pixels
,
2753 &ctx
->Unpack
, texObj
, texImage
);
2754 ctx
->NewState
|= _NEW_TEXTURE
;
2757 _mesa_unlock_texture(ctx
, texObj
);
2763 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
2764 GLenum internalFormat
,
2766 GLsizei width
, GLint border
)
2768 struct gl_texture_unit
*texUnit
;
2769 struct gl_texture_object
*texObj
;
2770 struct gl_texture_image
*texImage
;
2771 GLsizei postConvWidth
= width
;
2772 const GLuint face
= texture_face(target
);
2773 GET_CURRENT_CONTEXT(ctx
);
2774 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2776 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2777 _mesa_update_state(ctx
);
2779 if (is_color_format(internalFormat
)) {
2780 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2783 if (copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
2784 postConvWidth
, 1, border
))
2787 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2788 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2789 _mesa_lock_texture(ctx
, texObj
);
2791 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
2793 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
2797 if (texImage
->Data
) {
2798 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2801 ASSERT(texImage
->Data
== NULL
);
2803 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2804 _mesa_init_teximage_fields(ctx
, target
, texImage
, postConvWidth
, 1, 1,
2805 border
, internalFormat
);
2808 ASSERT(ctx
->Driver
.CopyTexImage1D
);
2809 (*ctx
->Driver
.CopyTexImage1D
)(ctx
, target
, level
, internalFormat
,
2810 x
, y
, width
, border
);
2812 ASSERT(texImage
->TexFormat
);
2814 update_fbo_texture(ctx
, texObj
, face
, level
);
2817 texObj
->Complete
= GL_FALSE
;
2818 ctx
->NewState
|= _NEW_TEXTURE
;
2821 _mesa_unlock_texture(ctx
, texObj
);
2827 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
2828 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2831 struct gl_texture_unit
*texUnit
;
2832 struct gl_texture_object
*texObj
;
2833 struct gl_texture_image
*texImage
;
2834 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2835 const GLuint face
= texture_face(target
);
2836 GET_CURRENT_CONTEXT(ctx
);
2837 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2839 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2840 _mesa_update_state(ctx
);
2842 if (is_color_format(internalFormat
)) {
2843 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2847 if (copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
2848 postConvWidth
, postConvHeight
, border
))
2851 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2852 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2854 _mesa_lock_texture(ctx
, texObj
);
2856 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
2859 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
2863 if (texImage
->Data
) {
2864 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
2867 ASSERT(texImage
->Data
== NULL
);
2869 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2870 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2871 postConvWidth
, postConvHeight
, 1,
2872 border
, internalFormat
);
2874 ASSERT(ctx
->Driver
.CopyTexImage2D
);
2875 (*ctx
->Driver
.CopyTexImage2D
)(ctx
, target
, level
, internalFormat
,
2876 x
, y
, width
, height
, border
);
2878 ASSERT(texImage
->TexFormat
);
2880 update_fbo_texture(ctx
, texObj
, face
, level
);
2883 texObj
->Complete
= GL_FALSE
;
2884 ctx
->NewState
|= _NEW_TEXTURE
;
2887 _mesa_unlock_texture(ctx
, texObj
);
2892 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
2893 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
2895 struct gl_texture_unit
*texUnit
;
2896 struct gl_texture_object
*texObj
;
2897 struct gl_texture_image
*texImage
;
2898 GLsizei postConvWidth
= width
;
2899 GET_CURRENT_CONTEXT(ctx
);
2900 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2902 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2903 _mesa_update_state(ctx
);
2905 /* XXX should test internal format */
2906 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2908 if (copytexsubimage_error_check(ctx
, 1, target
, level
,
2909 xoffset
, 0, 0, postConvWidth
, 1))
2912 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2913 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2915 _mesa_lock_texture(ctx
, texObj
);
2917 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2919 if (copytexsubimage_error_check2(ctx
, 1, target
, level
,
2920 xoffset
, 0, 0, postConvWidth
, 1,
2925 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2926 xoffset
+= texImage
->Border
;
2928 ASSERT(ctx
->Driver
.CopyTexSubImage1D
);
2929 (*ctx
->Driver
.CopyTexSubImage1D
)(ctx
, target
, level
, xoffset
, x
, y
, width
);
2930 ctx
->NewState
|= _NEW_TEXTURE
;
2933 _mesa_unlock_texture(ctx
, texObj
);
2939 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
2940 GLint xoffset
, GLint yoffset
,
2941 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2943 struct gl_texture_unit
*texUnit
;
2944 struct gl_texture_object
*texObj
;
2945 struct gl_texture_image
*texImage
;
2946 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2947 GET_CURRENT_CONTEXT(ctx
);
2948 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2950 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2951 _mesa_update_state(ctx
);
2953 /* XXX should test internal format */
2954 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2956 if (copytexsubimage_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2957 postConvWidth
, postConvHeight
))
2960 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2961 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2963 _mesa_lock_texture(ctx
, texObj
);
2965 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2967 if (copytexsubimage_error_check2(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2968 postConvWidth
, postConvHeight
, texImage
))
2971 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2972 xoffset
+= texImage
->Border
;
2973 yoffset
+= texImage
->Border
;
2975 ASSERT(ctx
->Driver
.CopyTexSubImage2D
);
2976 (*ctx
->Driver
.CopyTexSubImage2D
)(ctx
, target
, level
,
2977 xoffset
, yoffset
, x
, y
, width
, height
);
2978 ctx
->NewState
|= _NEW_TEXTURE
;
2981 _mesa_unlock_texture(ctx
, texObj
);
2987 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
2988 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2989 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2991 struct gl_texture_unit
*texUnit
;
2992 struct gl_texture_object
*texObj
;
2993 struct gl_texture_image
*texImage
;
2994 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2995 GET_CURRENT_CONTEXT(ctx
);
2996 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2998 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2999 _mesa_update_state(ctx
);
3001 /* XXX should test internal format */
3002 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
3004 if (copytexsubimage_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
,
3005 zoffset
, postConvWidth
, postConvHeight
))
3008 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3009 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3011 _mesa_lock_texture(ctx
, texObj
);
3013 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3015 if (copytexsubimage_error_check2(ctx
, 3, target
, level
, xoffset
, yoffset
,
3016 zoffset
, postConvWidth
, postConvHeight
,
3020 /* If we have a border, xoffset=-1 is legal. Bias by border width */
3021 xoffset
+= texImage
->Border
;
3022 yoffset
+= texImage
->Border
;
3023 zoffset
+= texImage
->Border
;
3025 ASSERT(ctx
->Driver
.CopyTexSubImage3D
);
3026 (*ctx
->Driver
.CopyTexSubImage3D
)(ctx
, target
, level
,
3027 xoffset
, yoffset
, zoffset
,
3028 x
, y
, width
, height
);
3029 ctx
->NewState
|= _NEW_TEXTURE
;
3032 _mesa_unlock_texture(ctx
, texObj
);
3038 /**********************************************************************/
3039 /****** Compressed Textures ******/
3040 /**********************************************************************/
3044 * Error checking for glCompressedTexImage[123]D().
3045 * \return error code or GL_NO_ERROR.
3048 compressed_texture_error_check(GLcontext
*ctx
, GLint dimensions
,
3049 GLenum target
, GLint level
,
3050 GLenum internalFormat
, GLsizei width
,
3051 GLsizei height
, GLsizei depth
, GLint border
,
3054 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
3056 if (dimensions
== 1) {
3057 /* 1D compressed textures not allowed */
3058 return GL_INVALID_ENUM
;
3060 else if (dimensions
== 2) {
3061 if (target
== GL_PROXY_TEXTURE_2D
) {
3062 maxLevels
= ctx
->Const
.MaxTextureLevels
;
3064 else if (target
== GL_TEXTURE_2D
) {
3065 maxLevels
= ctx
->Const
.MaxTextureLevels
;
3067 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
3068 if (!ctx
->Extensions
.ARB_texture_cube_map
)
3069 return GL_INVALID_ENUM
; /*target*/
3070 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
3072 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3073 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
3074 if (!ctx
->Extensions
.ARB_texture_cube_map
)
3075 return GL_INVALID_ENUM
; /*target*/
3076 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
3079 return GL_INVALID_ENUM
; /*target*/
3082 else if (dimensions
== 3) {
3083 /* 3D compressed textures not allowed */
3084 return GL_INVALID_ENUM
;
3087 maxTextureSize
= 1 << (maxLevels
- 1);
3089 /* This will detect any invalid internalFormat value */
3090 if (!is_compressed_format(ctx
, internalFormat
))
3091 return GL_INVALID_ENUM
;
3093 /* This should really never fail */
3094 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0)
3095 return GL_INVALID_ENUM
;
3098 return GL_INVALID_VALUE
;
3101 * XXX We should probably use the proxy texture error check function here.
3103 if (width
< 1 || width
> maxTextureSize
||
3104 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(width
) != 1))
3105 return GL_INVALID_VALUE
;
3107 if ((height
< 1 || height
> maxTextureSize
||
3108 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(height
) != 1))
3110 return GL_INVALID_VALUE
;
3112 if ((depth
< 1 || depth
> maxTextureSize
||
3113 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& _mesa_bitcount(depth
) != 1))
3115 return GL_INVALID_VALUE
;
3117 /* For cube map, width must equal height */
3118 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3119 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
&& width
!= height
)
3120 return GL_INVALID_VALUE
;
3122 if (level
< 0 || level
>= maxLevels
)
3123 return GL_INVALID_VALUE
;
3125 expectedSize
= _mesa_compressed_texture_size_glenum(ctx
, width
, height
,
3126 depth
, internalFormat
);
3127 if (expectedSize
!= imageSize
)
3128 return GL_INVALID_VALUE
;
3130 #if FEATURE_EXT_texture_sRGB
3131 if ((internalFormat
== GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
||
3132 internalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
||
3133 internalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
||
3134 internalFormat
== GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
)
3136 return GL_INVALID_OPERATION
;
3145 * Error checking for glCompressedTexSubImage[123]D().
3146 * \warning There are some bad assumptions here about the size of compressed
3147 * texture tiles (multiple of 4) used to test the validity of the
3148 * offset and size parameters.
3149 * \return error code or GL_NO_ERROR.
3152 compressed_subtexture_error_check(GLcontext
*ctx
, GLint dimensions
,
3153 GLenum target
, GLint level
,
3154 GLint xoffset
, GLint yoffset
, GLint zoffset
,
3155 GLsizei width
, GLsizei height
, GLsizei depth
,
3156 GLenum format
, GLsizei imageSize
)
3158 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
3161 if (dimensions
== 1) {
3162 /* 1D compressed textures not allowed */
3163 return GL_INVALID_ENUM
;
3165 else if (dimensions
== 2) {
3166 if (target
== GL_PROXY_TEXTURE_2D
) {
3167 maxLevels
= ctx
->Const
.MaxTextureLevels
;
3169 else if (target
== GL_TEXTURE_2D
) {
3170 maxLevels
= ctx
->Const
.MaxTextureLevels
;
3172 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
3173 if (!ctx
->Extensions
.ARB_texture_cube_map
)
3174 return GL_INVALID_ENUM
; /*target*/
3175 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
3177 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3178 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
3179 if (!ctx
->Extensions
.ARB_texture_cube_map
)
3180 return GL_INVALID_ENUM
; /*target*/
3181 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
3184 return GL_INVALID_ENUM
; /*target*/
3187 else if (dimensions
== 3) {
3188 /* 3D compressed textures not allowed */
3189 return GL_INVALID_ENUM
;
3192 maxTextureSize
= 1 << (maxLevels
- 1);
3194 /* this will catch any invalid compressed format token */
3195 if (!is_compressed_format(ctx
, format
))
3196 return GL_INVALID_ENUM
;
3198 if (width
< 1 || width
> maxTextureSize
)
3199 return GL_INVALID_VALUE
;
3201 if ((height
< 1 || height
> maxTextureSize
)
3203 return GL_INVALID_VALUE
;
3205 if (level
< 0 || level
>= maxLevels
)
3206 return GL_INVALID_VALUE
;
3208 /* XXX these tests are specific to the compressed format.
3209 * this code should be generalized in some way.
3211 if ((xoffset
& 3) != 0 || (yoffset
& 3) != 0)
3212 return GL_INVALID_VALUE
;
3214 if ((width
& 3) != 0 && width
!= 2 && width
!= 1)
3215 return GL_INVALID_VALUE
;
3217 if ((height
& 3) != 0 && height
!= 2 && height
!= 1)
3218 return GL_INVALID_VALUE
;
3220 expectedSize
= _mesa_compressed_texture_size_glenum(ctx
, width
, height
,
3222 if (expectedSize
!= imageSize
)
3223 return GL_INVALID_VALUE
;
3231 _mesa_CompressedTexImage1DARB(GLenum target
, GLint level
,
3232 GLenum internalFormat
, GLsizei width
,
3233 GLint border
, GLsizei imageSize
,
3236 GET_CURRENT_CONTEXT(ctx
);
3237 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3239 if (target
== GL_TEXTURE_1D
) {
3240 /* non-proxy target */
3241 struct gl_texture_unit
*texUnit
;
3242 struct gl_texture_object
*texObj
;
3243 struct gl_texture_image
*texImage
;
3244 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
3245 internalFormat
, width
, 1, 1, border
, imageSize
);
3247 _mesa_error(ctx
, error
, "glCompressedTexImage1D");
3251 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3252 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3254 _mesa_lock_texture(ctx
, texObj
);
3256 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
3258 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage1D");
3262 if (texImage
->Data
) {
3263 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3265 ASSERT(texImage
->Data
== NULL
);
3267 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
3268 border
, internalFormat
);
3270 ASSERT(ctx
->Driver
.CompressedTexImage1D
);
3271 (*ctx
->Driver
.CompressedTexImage1D
)(ctx
, target
, level
,
3272 internalFormat
, width
, border
,
3277 texObj
->Complete
= GL_FALSE
;
3278 ctx
->NewState
|= _NEW_TEXTURE
;
3281 _mesa_unlock_texture(ctx
, texObj
);
3283 else if (target
== GL_PROXY_TEXTURE_1D
) {
3284 /* Proxy texture: check for errors and update proxy state */
3285 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
3286 internalFormat
, width
, 1, 1, border
, imageSize
);
3288 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3289 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3290 internalFormat
, GL_NONE
, GL_NONE
,
3291 width
, 1, 1, border
);
3294 /* if error, clear all proxy texture image parameters */
3295 struct gl_texture_image
*texImage
;
3296 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3298 clear_teximage_fields(texImage
);
3301 /* store the teximage parameters */
3302 struct gl_texture_unit
*texUnit
;
3303 struct gl_texture_object
*texObj
;
3304 struct gl_texture_image
*texImage
;
3305 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3306 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3308 _mesa_lock_texture(ctx
, texObj
);
3310 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3311 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
3312 border
, internalFormat
);
3314 _mesa_unlock_texture(ctx
, texObj
);
3318 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage1D(target)");
3325 _mesa_CompressedTexImage2DARB(GLenum target
, GLint level
,
3326 GLenum internalFormat
, GLsizei width
,
3327 GLsizei height
, GLint border
, GLsizei imageSize
,
3330 GET_CURRENT_CONTEXT(ctx
);
3331 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3333 if (target
== GL_TEXTURE_2D
||
3334 (ctx
->Extensions
.ARB_texture_cube_map
&&
3335 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3336 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
3337 /* non-proxy target */
3338 struct gl_texture_unit
*texUnit
;
3339 struct gl_texture_object
*texObj
;
3340 struct gl_texture_image
*texImage
;
3341 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
3342 internalFormat
, width
, height
, 1, border
, imageSize
);
3344 _mesa_error(ctx
, error
, "glCompressedTexImage2D");
3348 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3349 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3351 _mesa_lock_texture(ctx
, texObj
);
3353 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
3355 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
3359 if (texImage
->Data
) {
3360 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3362 ASSERT(texImage
->Data
== NULL
);
3364 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
3365 border
, internalFormat
);
3367 ASSERT(ctx
->Driver
.CompressedTexImage2D
);
3368 (*ctx
->Driver
.CompressedTexImage2D
)(ctx
, target
, level
,
3369 internalFormat
, width
, height
,
3370 border
, imageSize
, data
,
3374 texObj
->Complete
= GL_FALSE
;
3375 ctx
->NewState
|= _NEW_TEXTURE
;
3378 _mesa_unlock_texture(ctx
, texObj
);
3380 else if (target
== GL_PROXY_TEXTURE_2D
||
3381 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
3382 ctx
->Extensions
.ARB_texture_cube_map
)) {
3383 /* Proxy texture: check for errors and update proxy state */
3384 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
3385 internalFormat
, width
, height
, 1, border
, imageSize
);
3387 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3388 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3389 internalFormat
, GL_NONE
, GL_NONE
,
3390 width
, height
, 1, border
);
3393 /* if error, clear all proxy texture image parameters */
3394 struct gl_texture_image
*texImage
;
3395 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3397 clear_teximage_fields(texImage
);
3400 /* store the teximage parameters */
3401 struct gl_texture_unit
*texUnit
;
3402 struct gl_texture_object
*texObj
;
3403 struct gl_texture_image
*texImage
;
3404 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3405 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3407 _mesa_lock_texture(ctx
, texObj
);
3409 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3410 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
3411 border
, internalFormat
);
3413 _mesa_unlock_texture(ctx
, texObj
);
3417 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(target)");
3424 _mesa_CompressedTexImage3DARB(GLenum target
, GLint level
,
3425 GLenum internalFormat
, GLsizei width
,
3426 GLsizei height
, GLsizei depth
, GLint border
,
3427 GLsizei imageSize
, const GLvoid
*data
)
3429 GET_CURRENT_CONTEXT(ctx
);
3430 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3432 if (target
== GL_TEXTURE_3D
) {
3433 /* non-proxy target */
3434 struct gl_texture_unit
*texUnit
;
3435 struct gl_texture_object
*texObj
;
3436 struct gl_texture_image
*texImage
;
3437 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3438 internalFormat
, width
, height
, depth
, border
, imageSize
);
3440 _mesa_error(ctx
, error
, "glCompressedTexImage3D");
3444 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3445 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3446 _mesa_lock_texture(ctx
, texObj
);
3448 texImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
3450 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage3D");
3454 if (texImage
->Data
) {
3455 ctx
->Driver
.FreeTexImageData( ctx
, texImage
);
3457 ASSERT(texImage
->Data
== NULL
);
3459 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, depth
,
3460 border
, internalFormat
);
3462 ASSERT(ctx
->Driver
.CompressedTexImage3D
);
3463 (*ctx
->Driver
.CompressedTexImage3D
)(ctx
, target
, level
,
3465 width
, height
, depth
,
3466 border
, imageSize
, data
,
3470 texObj
->Complete
= GL_FALSE
;
3471 ctx
->NewState
|= _NEW_TEXTURE
;
3474 _mesa_unlock_texture(ctx
, texObj
);
3476 else if (target
== GL_PROXY_TEXTURE_3D
) {
3477 /* Proxy texture: check for errors and update proxy state */
3478 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3479 internalFormat
, width
, height
, depth
, border
, imageSize
);
3481 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3482 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3483 internalFormat
, GL_NONE
, GL_NONE
,
3484 width
, height
, depth
, border
);
3487 /* if error, clear all proxy texture image parameters */
3488 struct gl_texture_image
*texImage
;
3489 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3491 clear_teximage_fields(texImage
);
3494 /* store the teximage parameters */
3495 struct gl_texture_unit
*texUnit
;
3496 struct gl_texture_object
*texObj
;
3497 struct gl_texture_image
*texImage
;
3498 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3499 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3500 _mesa_lock_texture(ctx
, texObj
);
3502 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3503 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
,
3504 depth
, border
, internalFormat
);
3506 _mesa_unlock_texture(ctx
, texObj
);
3510 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage3D(target)");
3517 _mesa_CompressedTexSubImage1DARB(GLenum target
, GLint level
, GLint xoffset
,
3518 GLsizei width
, GLenum format
,
3519 GLsizei imageSize
, const GLvoid
*data
)
3521 struct gl_texture_unit
*texUnit
;
3522 struct gl_texture_object
*texObj
;
3523 struct gl_texture_image
*texImage
;
3525 GET_CURRENT_CONTEXT(ctx
);
3526 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3528 error
= compressed_subtexture_error_check(ctx
, 1, target
, level
,
3529 xoffset
, 0, 0, /* pos */
3530 width
, 1, 1, /* size */
3533 _mesa_error(ctx
, error
, "glCompressedTexSubImage1D");
3537 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3538 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3539 _mesa_lock_texture(ctx
, texObj
);
3541 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3544 if ((GLint
) format
!= texImage
->InternalFormat
) {
3545 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3546 "glCompressedTexSubImage1D(format)");
3550 if ((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) {
3551 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage1D(width)");
3556 goto out
; /* no-op, not an error */
3558 if (ctx
->Driver
.CompressedTexSubImage1D
) {
3559 (*ctx
->Driver
.CompressedTexSubImage1D
)(ctx
, target
, level
,
3561 format
, imageSize
, data
,
3564 ctx
->NewState
|= _NEW_TEXTURE
;
3567 _mesa_unlock_texture(ctx
, texObj
);
3572 _mesa_CompressedTexSubImage2DARB(GLenum target
, GLint level
, GLint xoffset
,
3573 GLint yoffset
, GLsizei width
, GLsizei height
,
3574 GLenum format
, GLsizei imageSize
,
3577 struct gl_texture_unit
*texUnit
;
3578 struct gl_texture_object
*texObj
;
3579 struct gl_texture_image
*texImage
;
3581 GET_CURRENT_CONTEXT(ctx
);
3582 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3584 error
= compressed_subtexture_error_check(ctx
, 2, target
, level
,
3585 xoffset
, yoffset
, 0, /* pos */
3586 width
, height
, 1, /* size */
3589 /* XXX proxy target? */
3590 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3594 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3595 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3596 _mesa_lock_texture(ctx
, texObj
);
3598 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3601 if ((GLint
) format
!= texImage
->InternalFormat
) {
3602 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3603 "glCompressedTexSubImage2D(format)");
3607 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3608 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
)) {
3609 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage2D(size)");
3613 if (width
== 0 || height
== 0)
3614 goto out
; /* no-op, not an error */
3616 if (ctx
->Driver
.CompressedTexSubImage2D
) {
3617 (*ctx
->Driver
.CompressedTexSubImage2D
)(ctx
, target
, level
,
3618 xoffset
, yoffset
, width
, height
,
3619 format
, imageSize
, data
,
3622 ctx
->NewState
|= _NEW_TEXTURE
;
3625 _mesa_unlock_texture(ctx
, texObj
);
3630 _mesa_CompressedTexSubImage3DARB(GLenum target
, GLint level
, GLint xoffset
,
3631 GLint yoffset
, GLint zoffset
, GLsizei width
,
3632 GLsizei height
, GLsizei depth
, GLenum format
,
3633 GLsizei imageSize
, const GLvoid
*data
)
3635 struct gl_texture_unit
*texUnit
;
3636 struct gl_texture_object
*texObj
;
3637 struct gl_texture_image
*texImage
;
3639 GET_CURRENT_CONTEXT(ctx
);
3640 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3642 error
= compressed_subtexture_error_check(ctx
, 3, target
, level
,
3643 xoffset
, yoffset
, zoffset
,/*pos*/
3644 width
, height
, depth
, /*size*/
3647 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3651 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3652 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3653 _mesa_lock_texture(ctx
, texObj
);
3655 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3658 if ((GLint
) format
!= texImage
->InternalFormat
) {
3659 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3660 "glCompressedTexSubImage3D(format)");
3664 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3665 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
) ||
3666 ((depth
== 1 || depth
== 2) && (GLuint
) depth
!= texImage
->Depth
)) {
3667 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage3D(size)");
3671 if (width
== 0 || height
== 0 || depth
== 0)
3672 goto out
; /* no-op, not an error */
3674 if (ctx
->Driver
.CompressedTexSubImage3D
) {
3675 (*ctx
->Driver
.CompressedTexSubImage3D
)(ctx
, target
, level
,
3676 xoffset
, yoffset
, zoffset
,
3677 width
, height
, depth
,
3678 format
, imageSize
, data
,
3681 ctx
->NewState
|= _NEW_TEXTURE
;
3684 _mesa_unlock_texture(ctx
, texObj
);
3689 _mesa_GetCompressedTexImageARB(GLenum target
, GLint level
, GLvoid
*img
)
3691 const struct gl_texture_unit
*texUnit
;
3692 struct gl_texture_object
*texObj
;
3693 struct gl_texture_image
*texImage
;
3695 GET_CURRENT_CONTEXT(ctx
);
3696 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3699 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3700 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3702 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB");
3706 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
3707 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
3709 if (level
< 0 || level
>= maxLevels
) {
3710 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3714 if (_mesa_is_proxy_texture(target
)) {
3715 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
3720 _mesa_lock_texture(ctx
, texObj
);
3722 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
3724 /* probably invalid mipmap level */
3725 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3729 if (!texImage
->IsCompressed
) {
3730 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetCompressedTexImageARB");
3734 /* this typically calls _mesa_get_compressed_teximage() */
3735 ctx
->Driver
.GetCompressedTexImage(ctx
, target
, level
, img
, texObj
,texImage
);
3738 _mesa_unlock_texture(ctx
, texObj
);