2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * Texture images manipulation functions.
30 * \note Mesa's native texture data type is GLchan. Native formats are
31 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA, and
34 * \note Device drivers are free to implement any internal format they want.
45 #include "texcompress.h"
46 #include "texformat.h"
54 static void PrintTexture(GLcontext
*ctx
, const struct gl_texture_image
*img
)
56 #if CHAN_TYPE == GL_FLOAT
57 _mesa_problem(NULL
, "PrintTexture doesn't support float channels");
60 const GLchan
*data
= (const GLchan
*) img
->Data
;
63 _mesa_printf("No texture data\n");
67 switch (img
->Format
) {
74 case GL_LUMINANCE_ALPHA
:
84 _mesa_problem(NULL
, "error in PrintTexture\n");
88 for (i
= 0; i
< img
->Height
; i
++) {
89 for (j
= 0; j
< img
->Width
; j
++) {
91 _mesa_printf("%02x ", data
[0]);
93 _mesa_printf("%02x%02x ", data
[0], data
[1]);
95 _mesa_printf("%02x%02x%02x ", data
[0], data
[1], data
[2]);
97 _mesa_printf("%02x%02x%02x%02x ", data
[0], data
[1], data
[2], data
[3]);
98 data
+= (img
->RowStride
- img
->Width
) * c
;
108 * Compute floor(log_base_2(n)).
109 * If n < 0 return -1.
138 * Return the simple base format for a given internal texture format.
139 * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
141 * \param ctx GL context.
142 * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
144 * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
145 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
147 * This is the format which is used during texture application (i.e. the
148 * texture format and env mode determine the arithmetic used.
151 _mesa_base_tex_format( GLcontext
*ctx
, GLint internalFormat
)
153 switch (internalFormat
) {
168 case GL_LUMINANCE_ALPHA
:
169 case GL_LUMINANCE4_ALPHA4
:
170 case GL_LUMINANCE6_ALPHA2
:
171 case GL_LUMINANCE8_ALPHA8
:
172 case GL_LUMINANCE12_ALPHA4
:
173 case GL_LUMINANCE12_ALPHA12
:
174 case GL_LUMINANCE16_ALPHA16
:
175 return GL_LUMINANCE_ALPHA
;
203 case GL_COLOR_INDEX1_EXT
:
204 case GL_COLOR_INDEX2_EXT
:
205 case GL_COLOR_INDEX4_EXT
:
206 case GL_COLOR_INDEX8_EXT
:
207 case GL_COLOR_INDEX12_EXT
:
208 case GL_COLOR_INDEX16_EXT
:
209 if (ctx
->Extensions
.EXT_paletted_texture
)
210 return GL_COLOR_INDEX
;
213 case GL_DEPTH_COMPONENT
:
214 case GL_DEPTH_COMPONENT16_SGIX
:
215 case GL_DEPTH_COMPONENT24_SGIX
:
216 case GL_DEPTH_COMPONENT32_SGIX
:
217 if (ctx
->Extensions
.SGIX_depth_texture
)
218 return GL_DEPTH_COMPONENT
;
222 /* GL_ARB_texture_compression */
223 case GL_COMPRESSED_ALPHA
:
224 if (ctx
->Extensions
.ARB_texture_compression
)
228 case GL_COMPRESSED_LUMINANCE
:
229 if (ctx
->Extensions
.ARB_texture_compression
)
233 case GL_COMPRESSED_LUMINANCE_ALPHA
:
234 if (ctx
->Extensions
.ARB_texture_compression
)
235 return GL_LUMINANCE_ALPHA
;
238 case GL_COMPRESSED_INTENSITY
:
239 if (ctx
->Extensions
.ARB_texture_compression
)
243 case GL_COMPRESSED_RGB
:
244 if (ctx
->Extensions
.ARB_texture_compression
)
248 case GL_COMPRESSED_RGBA
:
249 if (ctx
->Extensions
.ARB_texture_compression
)
253 case GL_COMPRESSED_RGB_FXT1_3DFX
:
254 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
)
258 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
259 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
)
263 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
264 if (ctx
->Extensions
.EXT_texture_compression_s3tc
)
268 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
269 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
270 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
271 if (ctx
->Extensions
.EXT_texture_compression_s3tc
)
277 if (ctx
->Extensions
.S3_s3tc
)
283 if (ctx
->Extensions
.S3_s3tc
)
289 if (ctx
->Extensions
.MESA_ycbcr_texture
)
290 return GL_YCBCR_MESA
;
294 /* XXX add float texture formats here */
297 return -1; /* error */
303 * Test if the given internal texture format is a color/RGBA format
304 * (i.e., not color index, depth, stencil, etc).
305 * \param internalFormat an internal texture format token (or 1, 2, 3, or 4)
306 * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
309 is_color_format(GLenum internalFormat
)
311 switch (internalFormat
) {
324 case GL_LUMINANCE_ALPHA
:
325 case GL_LUMINANCE4_ALPHA4
:
326 case GL_LUMINANCE6_ALPHA2
:
327 case GL_LUMINANCE8_ALPHA8
:
328 case GL_LUMINANCE12_ALPHA4
:
329 case GL_LUMINANCE12_ALPHA12
:
330 case GL_LUMINANCE16_ALPHA16
:
354 /* XXX add float texture formats here */
356 case GL_YCBCR_MESA
: /* not considered to be RGB */
364 * Test if the given internal texture format is a color index format.
367 is_index_format(GLenum internalFormat
)
369 switch (internalFormat
) {
371 case GL_COLOR_INDEX1_EXT
:
372 case GL_COLOR_INDEX2_EXT
:
373 case GL_COLOR_INDEX4_EXT
:
374 case GL_COLOR_INDEX8_EXT
:
375 case GL_COLOR_INDEX12_EXT
:
376 case GL_COLOR_INDEX16_EXT
:
385 * Test if the given internal texture format is a depth component format.
388 is_depth_format(GLenum internalFormat
)
390 switch (internalFormat
) {
391 case GL_DEPTH_COMPONENT16_ARB
:
392 case GL_DEPTH_COMPONENT24_ARB
:
393 case GL_DEPTH_COMPONENT32_ARB
:
394 case GL_DEPTH_COMPONENT
:
403 * Test if the given internal texture format is a YCbCr format.
406 is_ycbcr_format(GLenum internalFormat
)
408 switch (internalFormat
) {
418 * Test if it is a supported compressed format.
420 * \param internalFormat the internal format token provided by the user.
422 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
423 * GL_FALSE otherwise.
425 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
429 is_compressed_format(GLcontext
*ctx
, GLenum internalFormat
)
431 switch (internalFormat
) {
432 case GL_COMPRESSED_RGB_FXT1_3DFX
:
433 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
434 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
435 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
436 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
437 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
444 if (ctx
->Driver
.IsCompressedFormat
) {
445 return ctx
->Driver
.IsCompressedFormat(ctx
, internalFormat
);
453 * Store a gl_texture_image pointer in a gl_texture_object structure
454 * according to the target and level parameters.
456 * \param tObj texture object.
457 * \param target texture target.
458 * \param level image level.
459 * \param texImage texture image.
461 * This was basically prompted by the introduction of cube maps.
464 _mesa_set_tex_image(struct gl_texture_object
*tObj
,
465 GLenum target
, GLint level
,
466 struct gl_texture_image
*texImage
)
474 tObj
->Image
[0][level
] = texImage
;
476 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
477 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
478 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
479 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
480 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
481 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
: {
482 GLuint face
= ((GLuint
) target
-
483 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
484 tObj
->Image
[face
][level
] = texImage
;
487 case GL_TEXTURE_RECTANGLE_NV
:
489 tObj
->Image
[0][level
] = texImage
;
492 _mesa_problem(NULL
, "bad target in _mesa_set_tex_image()");
499 * Allocate a texture image structure.
501 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
504 * \return a pointer to gl_texture_image struct with all fields initialized to
507 struct gl_texture_image
*
508 _mesa_new_texture_image( GLcontext
*ctx
)
511 return CALLOC_STRUCT(gl_texture_image
);
516 * Free texture image.
518 * \param teximage texture image.
520 * Free the texture image structure and the associated image data if it's not
521 * marked as client data.
524 _mesa_delete_texture_image( struct gl_texture_image
*teximage
)
526 if (teximage
->Data
&& !teximage
->IsClientData
) {
527 MESA_PBUFFER_FREE( teximage
->Data
);
528 teximage
->Data
= NULL
;
535 * Test if a target is a proxy target.
537 * \param target texture target.
539 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
542 is_proxy_target(GLenum target
)
544 return (target
== GL_PROXY_TEXTURE_1D
||
545 target
== GL_PROXY_TEXTURE_2D
||
546 target
== GL_PROXY_TEXTURE_3D
||
547 target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
548 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
);
553 * Get the texture object that corresponds to the target of the given texture unit.
555 * \param ctx GL context.
556 * \param texUnit texture unit.
557 * \param target texture target.
559 * \return pointer to the texture object on success, or NULL on failure.
561 * \sa gl_texture_unit.
563 struct gl_texture_object
*
564 _mesa_select_tex_object(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
569 return texUnit
->Current1D
;
570 case GL_PROXY_TEXTURE_1D
:
571 return ctx
->Texture
.Proxy1D
;
573 return texUnit
->Current2D
;
574 case GL_PROXY_TEXTURE_2D
:
575 return ctx
->Texture
.Proxy2D
;
577 return texUnit
->Current3D
;
578 case GL_PROXY_TEXTURE_3D
:
579 return ctx
->Texture
.Proxy3D
;
580 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
581 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
582 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
583 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
584 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
585 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
586 case GL_TEXTURE_CUBE_MAP_ARB
:
587 return ctx
->Extensions
.ARB_texture_cube_map
588 ? texUnit
->CurrentCubeMap
: NULL
;
589 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
590 return ctx
->Extensions
.ARB_texture_cube_map
591 ? ctx
->Texture
.ProxyCubeMap
: NULL
;
592 case GL_TEXTURE_RECTANGLE_NV
:
593 return ctx
->Extensions
.NV_texture_rectangle
594 ? texUnit
->CurrentRect
: NULL
;
595 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
596 return ctx
->Extensions
.NV_texture_rectangle
597 ? ctx
->Texture
.ProxyRect
: NULL
;
599 _mesa_problem(NULL
, "bad target in _mesa_select_tex_object()");
606 * Get the texture image struct which corresponds to target and level
607 * of the given texture unit.
609 * \param ctx GL context.
610 * \param texUnit texture unit.
611 * \param target texture target.
612 * \param level image level.
614 * \return pointer to the texture image structure on success, or NULL on failure.
616 * \sa gl_texture_unit.
618 struct gl_texture_image
*
619 _mesa_select_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
620 GLenum target
, GLint level
)
623 ASSERT(level
< MAX_TEXTURE_LEVELS
);
626 return texUnit
->Current1D
->Image
[0][level
];
627 case GL_PROXY_TEXTURE_1D
:
628 return ctx
->Texture
.Proxy1D
->Image
[0][level
];
630 return texUnit
->Current2D
->Image
[0][level
];
631 case GL_PROXY_TEXTURE_2D
:
632 return ctx
->Texture
.Proxy2D
->Image
[0][level
];
634 return texUnit
->Current3D
->Image
[0][level
];
635 case GL_PROXY_TEXTURE_3D
:
636 return ctx
->Texture
.Proxy3D
->Image
[0][level
];
637 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
638 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
639 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
640 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
641 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
642 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
643 if (ctx
->Extensions
.ARB_texture_cube_map
) {
644 GLuint face
= ((GLuint
) target
-
645 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
646 return texUnit
->CurrentCubeMap
->Image
[face
][level
];
650 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
651 if (ctx
->Extensions
.ARB_texture_cube_map
)
652 return ctx
->Texture
.ProxyCubeMap
->Image
[0][level
];
655 case GL_TEXTURE_RECTANGLE_NV
:
656 if (ctx
->Extensions
.NV_texture_rectangle
) {
658 return texUnit
->CurrentRect
->Image
[0][level
];
663 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
664 if (ctx
->Extensions
.NV_texture_rectangle
) {
666 return ctx
->Texture
.ProxyRect
->Image
[0][level
];
672 _mesa_problem(ctx
, "bad target in _mesa_select_tex_image()");
679 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
680 * it and install it. Only return NULL if passed a bad parameter or run
683 struct gl_texture_image
*
684 _mesa_get_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
685 GLenum target
, GLint level
)
687 struct gl_texture_image
*texImage
;
688 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
690 struct gl_texture_object
*texObj
;
691 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
693 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture image allocation");
696 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
698 _mesa_set_tex_image(texObj
, target
, level
, texImage
);
705 * Return pointer to the specified proxy texture image.
706 * Note that proxy textures are per-context, not per-texture unit.
707 * \return pointer to texture image or NULL if invalid target, invalid
708 * level, or out of memory.
710 struct gl_texture_image
*
711 _mesa_get_proxy_tex_image(GLcontext
*ctx
, GLenum target
, GLint level
)
713 struct gl_texture_image
*texImage
;
719 case GL_PROXY_TEXTURE_1D
:
720 if (level
>= ctx
->Const
.MaxTextureLevels
)
722 texImage
= ctx
->Texture
.Proxy1D
->Image
[0][level
];
724 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
726 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
729 ctx
->Texture
.Proxy1D
->Image
[0][level
] = texImage
;
732 case GL_PROXY_TEXTURE_2D
:
733 if (level
>= ctx
->Const
.MaxTextureLevels
)
735 texImage
= ctx
->Texture
.Proxy2D
->Image
[0][level
];
737 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
739 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
742 ctx
->Texture
.Proxy2D
->Image
[0][level
] = texImage
;
745 case GL_PROXY_TEXTURE_3D
:
746 if (level
>= ctx
->Const
.Max3DTextureLevels
)
748 texImage
= ctx
->Texture
.Proxy3D
->Image
[0][level
];
750 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
752 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
755 ctx
->Texture
.Proxy3D
->Image
[0][level
] = texImage
;
758 case GL_PROXY_TEXTURE_CUBE_MAP
:
759 if (level
>= ctx
->Const
.MaxCubeTextureLevels
)
761 texImage
= ctx
->Texture
.ProxyCubeMap
->Image
[0][level
];
763 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
765 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
768 ctx
->Texture
.ProxyCubeMap
->Image
[0][level
] = texImage
;
771 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
774 texImage
= ctx
->Texture
.ProxyRect
->Image
[0][level
];
776 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
778 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
781 ctx
->Texture
.ProxyRect
->Image
[0][level
] = texImage
;
791 * Get the maximum number of allowed mipmap levels.
793 * \param ctx GL context.
794 * \param target texture target.
796 * \return the maximum number of allowed mipmap levels for the given
797 * texture target, or zero if passed a bad target.
802 _mesa_max_texture_levels(GLcontext
*ctx
, GLenum target
)
806 case GL_PROXY_TEXTURE_1D
:
808 case GL_PROXY_TEXTURE_2D
:
809 return ctx
->Const
.MaxTextureLevels
;
811 case GL_PROXY_TEXTURE_3D
:
812 return ctx
->Const
.Max3DTextureLevels
;
813 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
814 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
815 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
816 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
817 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
818 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
819 case GL_TEXTURE_CUBE_MAP_ARB
:
820 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
821 return ctx
->Const
.MaxCubeTextureLevels
;
823 case GL_TEXTURE_RECTANGLE_NV
:
824 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
828 return 0; /* bad target */
834 #if 000 /* not used anymore */
836 * glTexImage[123]D can accept a NULL image pointer. In this case we
837 * create a texture image with unspecified image contents per the OpenGL
841 make_null_texture(GLint width
, GLint height
, GLint depth
, GLenum format
)
843 const GLint components
= _mesa_components_in_format(format
);
844 const GLint numPixels
= width
* height
* depth
;
845 GLubyte
*data
= (GLubyte
*) MALLOC(numPixels
* components
* sizeof(GLubyte
));
849 * Let's see if anyone finds this. If glTexImage2D() is called with
850 * a NULL image pointer then load the texture image with something
851 * interesting instead of leaving it indeterminate.
854 static const char message
[8][32] = {
858 " X X XXXX XXX XXXXX ",
861 " X X XXXXX XXX X X ",
865 GLubyte
*imgPtr
= data
;
867 for (h
= 0; h
< depth
; h
++) {
868 for (i
= 0; i
< height
; i
++) {
869 GLint srcRow
= 7 - (i
% 8);
870 for (j
= 0; j
< width
; j
++) {
871 GLint srcCol
= j
% 32;
872 GLubyte texel
= (message
[srcRow
][srcCol
]=='X') ? 255 : 70;
873 for (k
= 0; k
< components
; k
++) {
889 * Reset the fields of a gl_texture_image struct to zero.
891 * \param img texture image structure.
893 * This is called when a proxy texture test fails, we set all the
894 * image members (except DriverData) to zero.
895 * It's also used in glTexImage[123]D as a safeguard to be sure all
896 * required fields get initialized properly by the Driver.TexImage[123]D
900 clear_teximage_fields(struct gl_texture_image
*img
)
917 img
->TexFormat
= &_mesa_null_texformat
;
918 img
->FetchTexelc
= NULL
;
919 img
->FetchTexelf
= NULL
;
920 img
->IsCompressed
= 0;
921 img
->CompressedSize
= 0;
926 * Initialize basic fields of the gl_texture_image struct.
928 * \param ctx GL context.
929 * \param target texture target.
930 * \param img texture image structure to be initialized.
931 * \param width image width.
932 * \param height image height.
933 * \param depth image depth.
934 * \param border image border.
935 * \param internalFormat internal format.
937 * Fills in the fields of \p img with the given information.
938 * Note: width, height and depth include the border.
941 _mesa_init_teximage_fields(GLcontext
*ctx
, GLenum target
,
942 struct gl_texture_image
*img
,
943 GLsizei width
, GLsizei height
, GLsizei depth
,
944 GLint border
, GLenum internalFormat
)
947 img
->Format
= _mesa_base_tex_format( ctx
, internalFormat
);
948 ASSERT(img
->Format
> 0);
949 img
->IntFormat
= internalFormat
;
950 img
->Border
= border
;
952 img
->Height
= height
;
954 img
->RowStride
= width
;
955 img
->WidthLog2
= logbase2(width
- 2 * border
);
956 if (height
== 1) /* 1-D texture */
959 img
->HeightLog2
= logbase2(height
- 2 * border
);
960 if (depth
== 1) /* 2-D texture */
963 img
->DepthLog2
= logbase2(depth
- 2 * border
);
964 img
->Width2
= width
- 2 * border
; /*1 << img->WidthLog2;*/
965 img
->Height2
= height
- 2 * border
; /*1 << img->HeightLog2;*/
966 img
->Depth2
= depth
- 2 * border
; /*1 << img->DepthLog2;*/
967 img
->MaxLog2
= MAX2(img
->WidthLog2
, img
->HeightLog2
);
968 img
->IsCompressed
= is_compressed_format(ctx
, internalFormat
);
969 if (img
->IsCompressed
)
970 img
->CompressedSize
= _mesa_compressed_texture_size(ctx
, width
, height
,
971 depth
, internalFormat
);
973 img
->CompressedSize
= 0;
975 if ((width
== 1 || _mesa_bitcount(width
- 2 * border
) == 1) &&
976 (height
== 1 || _mesa_bitcount(height
- 2 * border
) == 1) &&
977 (depth
== 1 || _mesa_bitcount(depth
- 2 * border
) == 1))
978 img
->_IsPowerOfTwo
= GL_TRUE
;
980 img
->_IsPowerOfTwo
= GL_FALSE
;
982 /* Compute Width/Height/DepthScale for mipmap lod computation */
983 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
984 /* scale = 1.0 since texture coords directly map to texels */
985 img
->WidthScale
= 1.0;
986 img
->HeightScale
= 1.0;
987 img
->DepthScale
= 1.0;
990 img
->WidthScale
= (GLfloat
) img
->Width
;
991 img
->HeightScale
= (GLfloat
) img
->Height
;
992 img
->DepthScale
= (GLfloat
) img
->Depth
;
998 * This is the fallback for Driver.TestProxyTexImage(). Test the texture
999 * level, width, height and depth against the ctx->Const limits for textures.
1001 * A hardware driver might override this function if, for example, the
1002 * max 3D texture size is 512x512x64 (i.e. not a cube).
1004 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
1005 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
1006 * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
1007 * \param level as passed to glTexImage
1008 * \param internalFormat as passed to glTexImage
1009 * \param format as passed to glTexImage
1010 * \param type as passed to glTexImage
1011 * \param width as passed to glTexImage
1012 * \param height as passed to glTexImage
1013 * \param depth as passed to glTexImage
1014 * \param border as passed to glTexImage
1015 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1018 _mesa_test_proxy_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
1019 GLint internalFormat
, GLenum format
, GLenum type
,
1020 GLint width
, GLint height
, GLint depth
, GLint border
)
1024 (void) internalFormat
;
1029 case GL_PROXY_TEXTURE_1D
:
1030 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1031 if (width
< 2 * border
|| width
> 2 + maxSize
||
1032 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1033 _mesa_bitcount(width
- 2 * border
) != 1) ||
1034 level
>= ctx
->Const
.MaxTextureLevels
) {
1035 /* bad width or level */
1039 case GL_PROXY_TEXTURE_2D
:
1040 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1041 if (width
< 2 * border
|| width
> 2 + maxSize
||
1042 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1043 _mesa_bitcount(width
- 2 * border
) != 1) ||
1044 height
< 2 * border
|| height
> 2 + maxSize
||
1045 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1046 _mesa_bitcount(height
- 2 * border
) != 1) ||
1047 level
>= ctx
->Const
.MaxTextureLevels
) {
1048 /* bad width or height or level */
1052 case GL_PROXY_TEXTURE_3D
:
1053 maxSize
= 1 << (ctx
->Const
.Max3DTextureLevels
- 1);
1054 if (width
< 2 * border
|| width
> 2 + maxSize
||
1055 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1056 _mesa_bitcount(width
- 2 * border
) != 1) ||
1057 height
< 2 * border
|| height
> 2 + maxSize
||
1058 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1059 _mesa_bitcount(height
- 2 * border
) != 1) ||
1060 depth
< 2 * border
|| depth
> 2 + maxSize
||
1061 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1062 _mesa_bitcount(depth
- 2 * border
) != 1) ||
1063 level
>= ctx
->Const
.Max3DTextureLevels
) {
1064 /* bad width or height or depth or level */
1068 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
1069 if (width
< 1 || width
> ctx
->Const
.MaxTextureRectSize
||
1070 height
< 1 || height
> ctx
->Const
.MaxTextureRectSize
||
1072 /* bad width or height or level */
1076 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
1077 maxSize
= 1 << (ctx
->Const
.MaxCubeTextureLevels
- 1);
1078 if (width
< 2 * border
|| width
> 2 + maxSize
||
1079 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1080 _mesa_bitcount(width
- 2 * border
) != 1) ||
1081 height
< 2 * border
|| height
> 2 + maxSize
||
1082 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1083 _mesa_bitcount(height
- 2 * border
) != 1) ||
1084 level
>= ctx
->Const
.MaxCubeTextureLevels
) {
1085 /* bad width or height */
1090 _mesa_problem(ctx
, "Invalid target in _mesa_test_proxy_teximage");
1097 * Test the glTexImage[123]D() parameters for errors.
1099 * \param ctx GL context.
1100 * \param target texture target given by the user.
1101 * \param level image level given by the user.
1102 * \param internalFormat internal format given by the user.
1103 * \param format pixel data format given by the user.
1104 * \param type pixel data type given by the user.
1105 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1106 * \param width image width given by the user.
1107 * \param height image height given by the user.
1108 * \param depth image depth given by the user.
1109 * \param border image border given by the user.
1111 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1113 * Verifies each of the parameters against the constants specified in
1114 * __GLcontextRec::Const and the supported extensions, and according to the
1115 * OpenGL specification.
1118 texture_error_check( GLcontext
*ctx
, GLenum target
,
1119 GLint level
, GLint internalFormat
,
1120 GLenum format
, GLenum type
,
1122 GLint width
, GLint height
,
1123 GLint depth
, GLint border
)
1125 const GLboolean isProxy
= is_proxy_target(target
);
1128 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1129 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1131 _mesa_error(ctx
, GL_INVALID_VALUE
,
1132 "glTexImage%dD(level=%d)", dimensions
, level
);
1138 if (border
< 0 || border
> 1 ||
1139 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1140 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1142 _mesa_error(ctx
, GL_INVALID_VALUE
,
1143 "glTexImage%dD(border=%d)", dimensions
, border
);
1148 if (width
< 0 || height
< 0 || depth
< 0) {
1150 _mesa_error(ctx
, GL_INVALID_VALUE
,
1151 "glTexImage%dD(width, height or depth < 0)", dimensions
);
1156 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1157 * level, width, height and depth.
1159 if (dimensions
== 1) {
1160 if (target
== GL_PROXY_TEXTURE_1D
|| target
== GL_TEXTURE_1D
) {
1161 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1162 level
, internalFormat
,
1164 width
, 1, 1, border
);
1167 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1171 else if (dimensions
== 2) {
1172 if (target
== GL_PROXY_TEXTURE_2D
|| target
== GL_TEXTURE_2D
) {
1173 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1174 level
, internalFormat
,
1176 width
, height
, 1, border
);
1178 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
1179 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1180 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
1181 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1182 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1185 sizeOK
= (width
== height
) &&
1186 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1187 level
, internalFormat
, format
, type
,
1188 width
, height
, 1, border
);
1190 else if (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
||
1191 target
== GL_TEXTURE_RECTANGLE_NV
) {
1192 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1193 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1196 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1197 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1198 level
, internalFormat
,
1200 width
, height
, 1, border
);
1203 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1207 else if (dimensions
== 3) {
1208 if (target
== GL_PROXY_TEXTURE_3D
|| target
== GL_TEXTURE_3D
) {
1209 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_3D
,
1210 level
, internalFormat
,
1212 width
, height
, depth
, border
);
1215 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1220 _mesa_problem( ctx
, "bad dims in texture_error_check" );
1226 _mesa_error(ctx
, GL_INVALID_VALUE
,
1227 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1228 dimensions
, level
, width
, height
, depth
);
1233 /* Check internalFormat */
1234 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1236 _mesa_error(ctx
, GL_INVALID_VALUE
,
1237 "glTexImage%dD(internalFormat=0x%x)",
1238 dimensions
, internalFormat
);
1243 /* Check incoming image format and type */
1244 if (!_mesa_is_legal_format_and_type(format
, type
)) {
1245 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1246 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1249 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1250 "glTexImage%dD(format or type)", dimensions
);
1255 if (format
== GL_YCBCR_MESA
|| internalFormat
== GL_YCBCR_MESA
) {
1256 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1257 if (format
!= GL_YCBCR_MESA
||
1258 internalFormat
!= GL_YCBCR_MESA
||
1259 (type
!= GL_UNSIGNED_SHORT_8_8_MESA
&&
1260 type
!= GL_UNSIGNED_SHORT_8_8_REV_MESA
)) {
1262 _mesa_sprintf(message
,
1263 "glTexImage%d(format/type/internalFormat YCBCR mismatch",
1265 _mesa_error(ctx
, GL_INVALID_ENUM
, message
);
1266 return GL_TRUE
; /* error */
1268 if (target
!= GL_TEXTURE_2D
&&
1269 target
!= GL_PROXY_TEXTURE_2D
&&
1270 target
!= GL_TEXTURE_RECTANGLE_NV
&&
1271 target
!= GL_PROXY_TEXTURE_RECTANGLE_NV
) {
1273 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage(target)");
1279 _mesa_sprintf(message
,
1280 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1281 dimensions
, border
);
1282 _mesa_error(ctx
, GL_INVALID_VALUE
, message
);
1288 if (is_compressed_format(ctx
, internalFormat
)) {
1289 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1292 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1293 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1294 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1295 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1300 _mesa_error(ctx
, GL_INVALID_ENUM
,
1301 "glTexImage%d(target)", dimensions
);
1307 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1308 "glTexImage%D(border!=0)", dimensions
);
1314 /* if we get here, the parameters are OK */
1320 * Test glTexSubImage[123]D() parameters for errors.
1322 * \param ctx GL context.
1323 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1324 * \param target texture target given by the user.
1325 * \param level image level given by the user.
1326 * \param xoffset sub-image x offset given by the user.
1327 * \param yoffset sub-image y offset given by the user.
1328 * \param zoffset sub-image z offset given by the user.
1329 * \param format pixel data format given by the user.
1330 * \param type pixel data type given by the user.
1331 * \param width image width given by the user.
1332 * \param height image height given by the user.
1333 * \param depth image depth given by the user.
1335 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1337 * Verifies each of the parameters against the constants specified in
1338 * __GLcontextRec::Const and the supported extensions, and according to the
1339 * OpenGL specification.
1342 subtexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1343 GLenum target
, GLint level
,
1344 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1345 GLint width
, GLint height
, GLint depth
,
1346 GLenum format
, GLenum type
)
1348 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1349 struct gl_texture_image
*destTex
;
1352 if (dimensions
== 1) {
1353 if (target
!= GL_TEXTURE_1D
) {
1354 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
1358 else if (dimensions
== 2) {
1359 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1360 target
<=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1361 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1362 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1366 else if (ctx
->Extensions
.NV_texture_rectangle
&&
1367 target
== GL_TEXTURE_RECTANGLE_NV
) {
1368 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1369 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1373 else if (target
!= GL_TEXTURE_2D
) {
1374 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1378 else if (dimensions
== 3) {
1379 if (target
!= GL_TEXTURE_3D
) {
1380 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
1385 _mesa_problem( ctx
, "invalid dims in texture_error_check" );
1389 /* Basic level check */
1390 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1391 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level=%d)", level
);
1396 _mesa_error(ctx
, GL_INVALID_VALUE
,
1397 "glTexSubImage%dD(width=%d)", dimensions
, width
);
1400 if (height
< 0 && dimensions
> 1) {
1401 _mesa_error(ctx
, GL_INVALID_VALUE
,
1402 "glTexSubImage%dD(height=%d)", dimensions
, height
);
1405 if (depth
< 0 && dimensions
> 2) {
1406 _mesa_error(ctx
, GL_INVALID_VALUE
,
1407 "glTexSubImage%dD(depth=%d)", dimensions
, depth
);
1411 destTex
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1414 /* undefined image level */
1415 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage%dD", dimensions
);
1419 if (xoffset
< -((GLint
)destTex
->Border
)) {
1420 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset)",
1424 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
1425 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset+width)",
1429 if (dimensions
> 1) {
1430 if (yoffset
< -((GLint
)destTex
->Border
)) {
1431 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset)",
1435 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
1436 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset+height)",
1441 if (dimensions
> 2) {
1442 if (zoffset
< -((GLint
)destTex
->Border
)) {
1443 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
1446 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+ destTex
->Border
)) {
1447 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
1452 if (!_mesa_is_legal_format_and_type(format
, type
)) {
1453 _mesa_error(ctx
, GL_INVALID_ENUM
,
1454 "glTexSubImage%dD(format or type)", dimensions
);
1458 if (destTex
->IsCompressed
) {
1459 const struct gl_texture_unit
*texUnit
;
1460 const struct gl_texture_image
*texImage
;
1461 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1462 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1464 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1467 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1468 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1469 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1470 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1474 _mesa_error(ctx
, GL_INVALID_ENUM
,
1475 "glTexSubImage%D(target)", dimensions
);
1478 /* offset must be multiple of 4 */
1479 if ((xoffset
& 3) || (yoffset
& 3)) {
1480 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1481 "glTexSubImage%D(xoffset or yoffset)", dimensions
);
1484 /* size must be multiple of 4 or equal to whole texture size */
1485 if ((width
& 3) && (GLuint
) width
!= texImage
->Width
) {
1486 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1487 "glTexSubImage%D(width)", dimensions
);
1490 if ((height
& 3) && (GLuint
) height
!= texImage
->Height
) {
1491 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1492 "glTexSubImage%D(width)", dimensions
);
1502 * Test glCopyTexImage[12]D() parameters for errors.
1504 * \param ctx GL context.
1505 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1506 * \param target texture target given by the user.
1507 * \param level image level given by the user.
1508 * \param internalFormat internal format given by the user.
1509 * \param width image width given by the user.
1510 * \param height image height given by the user.
1511 * \param depth image depth given by the user.
1512 * \param border texture border.
1514 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1516 * Verifies each of the parameters against the constants specified in
1517 * __GLcontextRec::Const and the supported extensions, and according to the
1518 * OpenGL specification.
1521 copytexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1522 GLenum target
, GLint level
, GLint internalFormat
,
1523 GLint width
, GLint height
, GLint border
)
1525 GLenum format
, type
;
1528 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1529 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1530 _mesa_error(ctx
, GL_INVALID_VALUE
,
1531 "glCopyTexImage%dD(level=%d)", dimensions
, level
);
1536 if (border
< 0 || border
> 1 ||
1537 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1538 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1542 /* The format and type aren't really significant here, but we need to pass
1543 * something to TestProxyTexImage().
1545 format
= _mesa_base_tex_format(ctx
, internalFormat
);
1548 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1549 * level, width, height and depth.
1551 if (dimensions
== 1) {
1552 if (target
== GL_TEXTURE_1D
) {
1553 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1554 level
, internalFormat
,
1556 width
, 1, 1, border
);
1559 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
1563 else if (dimensions
== 2) {
1564 if (target
== GL_TEXTURE_2D
) {
1565 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1566 level
, internalFormat
,
1568 width
, height
, 1, border
);
1570 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1571 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1572 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1573 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1576 sizeOK
= (width
== height
) &&
1577 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1578 level
, internalFormat
, format
, type
,
1579 width
, height
, 1, border
);
1581 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1582 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1583 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1586 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1587 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1588 level
, internalFormat
,
1590 width
, height
, 1, border
);
1593 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1598 _mesa_problem(ctx
, "invalid dimensions in copytexture_error_check");
1603 if (dimensions
== 1) {
1604 _mesa_error(ctx
, GL_INVALID_VALUE
,
1605 "glCopyTexImage1D(width=%d)", width
);
1608 ASSERT(dimensions
== 2);
1609 _mesa_error(ctx
, GL_INVALID_VALUE
,
1610 "glCopyTexImage2D(width=%d, height=%d)", width
, height
);
1615 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1616 _mesa_error(ctx
, GL_INVALID_VALUE
,
1617 "glCopyTexImage%dD(internalFormat)", dimensions
);
1621 if (is_compressed_format(ctx
, internalFormat
)) {
1622 if (target
!= GL_TEXTURE_2D
) {
1623 _mesa_error(ctx
, GL_INVALID_ENUM
,
1624 "glCopyTexImage%d(target)", dimensions
);
1628 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1629 "glCopyTexImage%D(border!=0)", dimensions
);
1634 /* if we get here, the parameters are OK */
1640 * Test glCopyTexImage[12]D() parameters for errors.
1642 * \param ctx GL context.
1643 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1644 * \param target texture target given by the user.
1645 * \param level image level given by the user.
1646 * \param xoffset sub-image x offset given by the user.
1647 * \param yoffset sub-image y offset given by the user.
1648 * \param zoffset sub-image z offset given by the user.
1649 * \param width image width given by the user.
1650 * \param height image height given by the user.
1652 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1654 * Verifies each of the parameters against the constants specified in
1655 * __GLcontextRec::Const and the supported extensions, and according to the
1656 * OpenGL specification.
1659 copytexsubimage_error_check( GLcontext
*ctx
, GLuint dimensions
,
1660 GLenum target
, GLint level
,
1661 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1662 GLsizei width
, GLsizei height
)
1664 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1665 struct gl_texture_image
*teximage
;
1668 if (dimensions
== 1) {
1669 if (target
!= GL_TEXTURE_1D
) {
1670 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
1674 else if (dimensions
== 2) {
1675 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1676 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1677 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1678 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1682 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1683 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1684 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1688 else if (target
!= GL_TEXTURE_2D
) {
1689 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1693 else if (dimensions
== 3) {
1694 if (target
!= GL_TEXTURE_3D
) {
1695 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
1701 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1702 _mesa_error(ctx
, GL_INVALID_VALUE
,
1703 "glCopyTexSubImage%dD(level=%d)", dimensions
, level
);
1709 _mesa_error(ctx
, GL_INVALID_VALUE
,
1710 "glCopyTexSubImage%dD(width=%d)", dimensions
, width
);
1713 if (dimensions
> 1 && height
< 0) {
1714 _mesa_error(ctx
, GL_INVALID_VALUE
,
1715 "glCopyTexSubImage%dD(height=%d)", dimensions
, height
);
1719 teximage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1721 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1722 "glCopyTexSubImage%dD(undefined texture level: %d)",
1727 if (xoffset
< -((GLint
)teximage
->Border
)) {
1728 _mesa_error(ctx
, GL_INVALID_VALUE
,
1729 "glCopyTexSubImage%dD(xoffset=%d)", dimensions
, xoffset
);
1732 if (xoffset
+ width
> (GLint
) (teximage
->Width
+ teximage
->Border
)) {
1733 _mesa_error(ctx
, GL_INVALID_VALUE
,
1734 "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
1737 if (dimensions
> 1) {
1738 if (yoffset
< -((GLint
)teximage
->Border
)) {
1739 _mesa_error(ctx
, GL_INVALID_VALUE
,
1740 "glCopyTexSubImage%dD(yoffset=%d)", dimensions
, yoffset
);
1743 /* NOTE: we're adding the border here, not subtracting! */
1744 if (yoffset
+ height
> (GLint
) (teximage
->Height
+ teximage
->Border
)) {
1745 _mesa_error(ctx
, GL_INVALID_VALUE
,
1746 "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
1751 if (dimensions
> 2) {
1752 if (zoffset
< -((GLint
)teximage
->Border
)) {
1753 _mesa_error(ctx
, GL_INVALID_VALUE
,
1754 "glCopyTexSubImage%dD(zoffset)", dimensions
);
1757 if (zoffset
> (GLint
) (teximage
->Depth
+ teximage
->Border
)) {
1758 _mesa_error(ctx
, GL_INVALID_VALUE
,
1759 "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
1764 if (teximage
->IsCompressed
) {
1765 if (target
!= GL_TEXTURE_2D
) {
1766 _mesa_error(ctx
, GL_INVALID_ENUM
,
1767 "glCopyTexSubImage%d(target)", dimensions
);
1770 /* offset must be multiple of 4 */
1771 if ((xoffset
& 3) || (yoffset
& 3)) {
1772 _mesa_error(ctx
, GL_INVALID_VALUE
,
1773 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions
);
1776 /* size must be multiple of 4 */
1777 if ((width
& 3) != 0 && (GLuint
) width
!= teximage
->Width
) {
1778 _mesa_error(ctx
, GL_INVALID_VALUE
,
1779 "glCopyTexSubImage%D(width)", dimensions
);
1782 if ((height
& 3) != 0 && (GLuint
) height
!= teximage
->Height
) {
1783 _mesa_error(ctx
, GL_INVALID_VALUE
,
1784 "glCopyTexSubImage%D(height)", dimensions
);
1789 if (teximage
->IntFormat
== GL_YCBCR_MESA
) {
1790 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glCopyTexSubImage2D");
1794 /* if we get here, the parameters are OK */
1800 * Get texture image. Called by glGetTexImage.
1802 * \param target texture target.
1803 * \param level image level.
1804 * \param format pixel data format for returned image.
1805 * \param type pixel data type for returned image.
1806 * \param pixels returned pixel data.
1809 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
1810 GLenum type
, GLvoid
*pixels
)
1812 const struct gl_texture_unit
*texUnit
;
1813 const struct gl_texture_object
*texObj
;
1814 const struct gl_texture_image
*texImage
;
1815 GLint maxLevels
= 0;
1816 GET_CURRENT_CONTEXT(ctx
);
1817 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
1819 texUnit
= &(ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
]);
1820 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
1821 if (!texObj
|| is_proxy_target(target
)) {
1822 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)");
1826 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
1827 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
1829 if (level
< 0 || level
>= maxLevels
) {
1830 _mesa_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
1834 if (_mesa_sizeof_packed_type(type
) <= 0) {
1835 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
1839 if (_mesa_components_in_format(format
) <= 0 ||
1840 format
== GL_STENCIL_INDEX
) {
1841 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
1845 if (!ctx
->Extensions
.EXT_paletted_texture
&& is_index_format(format
)) {
1846 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1849 if (!ctx
->Extensions
.SGIX_depth_texture
&& is_depth_format(format
)) {
1850 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1853 if (!ctx
->Extensions
.MESA_ycbcr_texture
&& is_ycbcr_format(format
)) {
1854 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1860 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1862 /* invalid mipmap level, not an error */
1866 if (!texImage
->Data
) {
1867 /* no image data, not an error */
1871 /* Make sure the requested image format is compatible with the
1874 if (is_color_format(format
)
1875 && !is_color_format(texImage
->TexFormat
->BaseFormat
)) {
1876 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
1879 else if (is_index_format(format
)
1880 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
1881 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
1884 else if (is_depth_format(format
)
1885 && !is_depth_format(texImage
->TexFormat
->BaseFormat
)) {
1886 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
1889 else if (is_ycbcr_format(format
)
1890 && !is_ycbcr_format(texImage
->TexFormat
->BaseFormat
)) {
1891 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
1898 const GLint width
= texImage
->Width
;
1899 const GLint height
= texImage
->Height
;
1900 const GLint depth
= texImage
->Depth
;
1902 for (img
= 0; img
< depth
; img
++) {
1903 for (row
= 0; row
< height
; row
++) {
1904 /* compute destination address in client memory */
1905 GLvoid
*dest
= _mesa_image_address( &ctx
->Pack
, pixels
,
1906 width
, height
, format
, type
,
1910 if (format
== GL_COLOR_INDEX
) {
1911 GLuint indexRow
[MAX_WIDTH
];
1913 for (col
= 0; col
< width
; col
++) {
1915 (*texImage
->FetchTexelc
)(texImage
, col
, row
, img
, &indx
);
1916 indexRow
[col
] = indx
;
1918 _mesa_pack_index_span(ctx
, width
, type
, dest
,
1919 indexRow
, &ctx
->Pack
,
1920 0 /* no image transfer */);
1922 else if (format
== GL_DEPTH_COMPONENT
) {
1923 GLfloat depthRow
[MAX_WIDTH
];
1925 for (col
= 0; col
< width
; col
++) {
1926 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
1927 (GLvoid
*) &depthRow
[col
]);
1929 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
1930 depthRow
, &ctx
->Pack
);
1932 else if (format
== GL_YCBCR_MESA
) {
1933 /* No pixel transfer */
1934 const GLint rowstride
= texImage
->RowStride
;
1936 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
1937 width
* sizeof(GLushort
));
1938 /* check for byte swapping */
1939 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
1940 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
1941 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
1942 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
1943 if (!ctx
->Pack
.SwapBytes
)
1944 _mesa_swap2((GLushort
*) dest
, width
);
1946 else if (ctx
->Pack
.SwapBytes
) {
1947 _mesa_swap2((GLushort
*) dest
, width
);
1951 /* general case: convert row to RGBA format */
1952 GLchan rgba
[MAX_WIDTH
][4];
1954 for (col
= 0; col
< width
; col
++) {
1955 (*texImage
->FetchTexelc
)(texImage
, col
, row
, img
, rgba
[col
]);
1957 _mesa_pack_rgba_span(ctx
, width
, (const GLchan (*)[4])rgba
,
1958 format
, type
, dest
, &ctx
->Pack
,
1959 0 /* no image transfer */);
1969 * Called from the API. Note that width includes the border.
1972 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalFormat
,
1973 GLsizei width
, GLint border
, GLenum format
,
1974 GLenum type
, const GLvoid
*pixels
)
1976 GLsizei postConvWidth
= width
;
1977 GET_CURRENT_CONTEXT(ctx
);
1978 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
1980 if (is_color_format(internalFormat
)) {
1981 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
1984 if (target
== GL_TEXTURE_1D
) {
1985 struct gl_texture_unit
*texUnit
;
1986 struct gl_texture_object
*texObj
;
1987 struct gl_texture_image
*texImage
;
1989 if (texture_error_check(ctx
, target
, level
, internalFormat
,
1990 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
1991 return; /* error was recorded */
1994 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1995 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
1996 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
1999 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2002 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2003 /* free the old texture data */
2004 MESA_PBUFFER_FREE(texImage
->Data
);
2006 texImage
->Data
= NULL
;
2007 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2008 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2009 postConvWidth
, 1, 1,
2010 border
, internalFormat
);
2012 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2013 _mesa_update_state(ctx
);
2015 ASSERT(ctx
->Driver
.TexImage1D
);
2017 /* Give the texture to the driver! <pixels> may be null! */
2018 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
2019 width
, border
, format
, type
, pixels
,
2020 &ctx
->Unpack
, texObj
, texImage
);
2022 ASSERT(texImage
->TexFormat
);
2024 /* If driver didn't explicitly set this, use the defaults */
2025 if (!texImage
->FetchTexelc
)
2026 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2027 if (!texImage
->FetchTexelf
)
2028 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2029 ASSERT(texImage
->FetchTexelc
);
2030 ASSERT(texImage
->FetchTexelf
);
2033 texObj
->Complete
= GL_FALSE
;
2034 ctx
->NewState
|= _NEW_TEXTURE
;
2036 else if (target
== GL_PROXY_TEXTURE_1D
) {
2037 /* Proxy texture: check for errors and update proxy state */
2038 struct gl_texture_image
*texImage
;
2039 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2040 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2041 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2042 /* when error, clear all proxy texture image parameters */
2044 clear_teximage_fields(texImage
);
2047 /* no error, set the tex image parameters */
2049 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2050 postConvWidth
, 1, 1,
2051 border
, internalFormat
);
2052 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2053 internalFormat
, format
, type
);
2057 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
2064 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalFormat
,
2065 GLsizei width
, GLsizei height
, GLint border
,
2066 GLenum format
, GLenum type
,
2067 const GLvoid
*pixels
)
2069 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2070 GET_CURRENT_CONTEXT(ctx
);
2071 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2073 if (is_color_format(internalFormat
)) {
2074 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2078 if (target
== GL_TEXTURE_2D
||
2079 (ctx
->Extensions
.ARB_texture_cube_map
&&
2080 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2081 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) ||
2082 (ctx
->Extensions
.NV_texture_rectangle
&&
2083 target
== GL_TEXTURE_RECTANGLE_NV
)) {
2084 /* non-proxy target */
2085 struct gl_texture_unit
*texUnit
;
2086 struct gl_texture_object
*texObj
;
2087 struct gl_texture_image
*texImage
;
2089 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2090 format
, type
, 2, postConvWidth
, postConvHeight
,
2092 return; /* error was recorded */
2095 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2096 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2097 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2099 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2102 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2103 /* free the old texture data */
2104 MESA_PBUFFER_FREE(texImage
->Data
);
2106 texImage
->Data
= NULL
;
2107 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2108 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2109 postConvWidth
, postConvHeight
, 1,
2110 border
, internalFormat
);
2112 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2113 _mesa_update_state(ctx
);
2115 ASSERT(ctx
->Driver
.TexImage2D
);
2117 /* Give the texture to the driver! <pixels> may be null! */
2118 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
2119 width
, height
, border
, format
, type
, pixels
,
2120 &ctx
->Unpack
, texObj
, texImage
);
2122 ASSERT(texImage
->TexFormat
);
2124 /* If driver didn't explicitly set these, use the defaults */
2125 if (!texImage
->FetchTexelc
)
2126 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2127 if (!texImage
->FetchTexelf
)
2128 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2129 ASSERT(texImage
->FetchTexelc
);
2130 ASSERT(texImage
->FetchTexelf
);
2133 texObj
->Complete
= GL_FALSE
;
2134 ctx
->NewState
|= _NEW_TEXTURE
;
2136 else if (target
== GL_PROXY_TEXTURE_2D
||
2137 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2138 ctx
->Extensions
.ARB_texture_cube_map
) ||
2139 (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
&&
2140 ctx
->Extensions
.NV_texture_rectangle
)) {
2141 /* Proxy texture: check for errors and update proxy state */
2142 struct gl_texture_image
*texImage
;
2143 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2144 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2145 format
, type
, 2, postConvWidth
, postConvHeight
,
2147 /* when error, clear all proxy texture image parameters */
2149 clear_teximage_fields(ctx
->Texture
.Proxy2D
->Image
[0][level
]);
2152 /* no error, set the tex image parameters */
2153 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2154 postConvWidth
, postConvHeight
, 1,
2155 border
, internalFormat
);
2156 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2157 internalFormat
, format
, type
);
2161 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
2168 * Called by the API or display list executor.
2169 * Note that width and height include the border.
2172 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalFormat
,
2173 GLsizei width
, GLsizei height
, GLsizei depth
,
2174 GLint border
, GLenum format
, GLenum type
,
2175 const GLvoid
*pixels
)
2177 GET_CURRENT_CONTEXT(ctx
);
2178 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2180 if (target
== GL_TEXTURE_3D
) {
2181 struct gl_texture_unit
*texUnit
;
2182 struct gl_texture_object
*texObj
;
2183 struct gl_texture_image
*texImage
;
2185 if (texture_error_check(ctx
, target
, level
, (GLint
) internalFormat
,
2186 format
, type
, 3, width
, height
, depth
, border
)) {
2187 return; /* error was recorded */
2190 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2191 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2192 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2194 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2197 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2198 MESA_PBUFFER_FREE(texImage
->Data
);
2200 texImage
->Data
= NULL
;
2201 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2202 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2203 width
, height
, depth
,
2204 border
, internalFormat
);
2206 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2207 _mesa_update_state(ctx
);
2209 ASSERT(ctx
->Driver
.TexImage3D
);
2211 /* Give the texture to the driver! <pixels> may be null! */
2212 (*ctx
->Driver
.TexImage3D
)(ctx
, target
, level
, internalFormat
,
2213 width
, height
, depth
, border
, format
, type
,
2214 pixels
, &ctx
->Unpack
, texObj
, texImage
);
2216 ASSERT(texImage
->TexFormat
);
2218 /* If driver didn't explicitly set these, use the defaults */
2219 if (!texImage
->FetchTexelc
)
2220 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2221 if (!texImage
->FetchTexelf
)
2222 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2223 ASSERT(texImage
->FetchTexelc
);
2224 ASSERT(texImage
->FetchTexelf
);
2227 texObj
->Complete
= GL_FALSE
;
2228 ctx
->NewState
|= _NEW_TEXTURE
;
2230 else if (target
== GL_PROXY_TEXTURE_3D
) {
2231 /* Proxy texture: check for errors and update proxy state */
2232 struct gl_texture_image
*texImage
;
2233 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2234 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2235 format
, type
, 3, width
, height
, depth
, border
)) {
2236 /* when error, clear all proxy texture image parameters */
2238 clear_teximage_fields(texImage
);
2241 /* no error, set the tex image parameters */
2242 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2243 border
, internalFormat
);
2244 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2245 internalFormat
, format
, type
);
2249 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
2256 _mesa_TexImage3DEXT( GLenum target
, GLint level
, GLenum internalFormat
,
2257 GLsizei width
, GLsizei height
, GLsizei depth
,
2258 GLint border
, GLenum format
, GLenum type
,
2259 const GLvoid
*pixels
)
2261 _mesa_TexImage3D(target
, level
, (GLint
) internalFormat
, width
, height
,
2262 depth
, border
, format
, type
, pixels
);
2268 _mesa_TexSubImage1D( GLenum target
, GLint level
,
2269 GLint xoffset
, GLsizei width
,
2270 GLenum format
, GLenum type
,
2271 const GLvoid
*pixels
)
2273 GLsizei postConvWidth
= width
;
2274 struct gl_texture_unit
*texUnit
;
2275 struct gl_texture_object
*texObj
;
2276 struct gl_texture_image
*texImage
;
2277 GET_CURRENT_CONTEXT(ctx
);
2278 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2280 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2281 _mesa_update_state(ctx
);
2283 /* XXX should test internal format */
2284 if (is_color_format(format
)) {
2285 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2288 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
2289 postConvWidth
, 1, 1, format
, type
)) {
2290 return; /* error was detected */
2293 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2294 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2295 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2298 if (width
== 0 || !pixels
)
2299 return; /* no-op, not an error */
2301 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2302 xoffset
+= texImage
->Border
;
2304 ASSERT(ctx
->Driver
.TexSubImage1D
);
2305 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
2306 format
, type
, pixels
, &ctx
->Unpack
,
2308 ctx
->NewState
|= _NEW_TEXTURE
;
2313 _mesa_TexSubImage2D( GLenum target
, GLint level
,
2314 GLint xoffset
, GLint yoffset
,
2315 GLsizei width
, GLsizei height
,
2316 GLenum format
, GLenum type
,
2317 const GLvoid
*pixels
)
2319 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2320 struct gl_texture_unit
*texUnit
;
2321 struct gl_texture_object
*texObj
;
2322 struct gl_texture_image
*texImage
;
2323 GET_CURRENT_CONTEXT(ctx
);
2324 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2326 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2327 _mesa_update_state(ctx
);
2329 /* XXX should test internal format */
2330 if (is_color_format(format
)) {
2331 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2335 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2336 postConvWidth
, postConvHeight
, 1, format
, type
)) {
2337 return; /* error was detected */
2340 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2341 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2342 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2345 if (width
== 0 || height
== 0 || !pixels
)
2346 return; /* no-op, not an error */
2348 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2349 xoffset
+= texImage
->Border
;
2350 yoffset
+= texImage
->Border
;
2352 ASSERT(ctx
->Driver
.TexSubImage2D
);
2353 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
, xoffset
, yoffset
,
2354 width
, height
, format
, type
, pixels
,
2355 &ctx
->Unpack
, texObj
, texImage
);
2356 ctx
->NewState
|= _NEW_TEXTURE
;
2362 _mesa_TexSubImage3D( GLenum target
, GLint level
,
2363 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2364 GLsizei width
, GLsizei height
, GLsizei depth
,
2365 GLenum format
, GLenum type
,
2366 const GLvoid
*pixels
)
2368 struct gl_texture_unit
*texUnit
;
2369 struct gl_texture_object
*texObj
;
2370 struct gl_texture_image
*texImage
;
2371 GET_CURRENT_CONTEXT(ctx
);
2372 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2374 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2375 _mesa_update_state(ctx
);
2377 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2378 width
, height
, depth
, format
, type
)) {
2379 return; /* error was detected */
2382 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2383 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2384 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2387 if (width
== 0 || height
== 0 || height
== 0 || !pixels
)
2388 return; /* no-op, not an error */
2390 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2391 xoffset
+= texImage
->Border
;
2392 yoffset
+= texImage
->Border
;
2393 zoffset
+= texImage
->Border
;
2395 ASSERT(ctx
->Driver
.TexSubImage3D
);
2396 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
2397 xoffset
, yoffset
, zoffset
,
2398 width
, height
, depth
,
2399 format
, type
, pixels
,
2400 &ctx
->Unpack
, texObj
, texImage
);
2401 ctx
->NewState
|= _NEW_TEXTURE
;
2407 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
2408 GLenum internalFormat
,
2410 GLsizei width
, GLint border
)
2412 struct gl_texture_unit
*texUnit
;
2413 struct gl_texture_object
*texObj
;
2414 struct gl_texture_image
*texImage
;
2415 GLsizei postConvWidth
= width
;
2416 GET_CURRENT_CONTEXT(ctx
);
2417 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2419 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2420 _mesa_update_state(ctx
);
2422 if (is_color_format(internalFormat
)) {
2423 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2426 if (copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
2427 postConvWidth
, 1, border
))
2430 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2431 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2432 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2434 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
2437 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2438 /* free the old texture data */
2439 MESA_PBUFFER_FREE(texImage
->Data
);
2441 texImage
->Data
= NULL
;
2443 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2444 _mesa_init_teximage_fields(ctx
, target
, texImage
, postConvWidth
, 1, 1,
2445 border
, internalFormat
);
2448 ASSERT(ctx
->Driver
.CopyTexImage1D
);
2449 (*ctx
->Driver
.CopyTexImage1D
)(ctx
, target
, level
, internalFormat
,
2450 x
, y
, width
, border
);
2452 ASSERT(texImage
->TexFormat
);
2454 /* If driver didn't explicitly set these, use the defaults */
2455 if (!texImage
->FetchTexelc
)
2456 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2457 if (!texImage
->FetchTexelf
)
2458 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2459 ASSERT(texImage
->FetchTexelc
);
2460 ASSERT(texImage
->FetchTexelf
);
2463 texObj
->Complete
= GL_FALSE
;
2464 ctx
->NewState
|= _NEW_TEXTURE
;
2470 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
2471 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2474 struct gl_texture_unit
*texUnit
;
2475 struct gl_texture_object
*texObj
;
2476 struct gl_texture_image
*texImage
;
2477 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2478 GET_CURRENT_CONTEXT(ctx
);
2479 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2481 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2482 _mesa_update_state(ctx
);
2484 if (is_color_format(internalFormat
)) {
2485 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2489 if (copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
2490 postConvWidth
, postConvHeight
, border
))
2493 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2494 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2495 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2497 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
2500 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2501 /* free the old texture data */
2502 MESA_PBUFFER_FREE(texImage
->Data
);
2504 texImage
->Data
= NULL
;
2506 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2507 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2508 postConvWidth
, postConvHeight
, 1,
2509 border
, internalFormat
);
2511 ASSERT(ctx
->Driver
.CopyTexImage2D
);
2512 (*ctx
->Driver
.CopyTexImage2D
)(ctx
, target
, level
, internalFormat
,
2513 x
, y
, width
, height
, border
);
2515 ASSERT(texImage
->TexFormat
);
2517 /* If driver didn't explicitly set these, use the defaults */
2518 if (!texImage
->FetchTexelc
)
2519 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2520 if (!texImage
->FetchTexelf
)
2521 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2522 ASSERT(texImage
->FetchTexelc
);
2523 ASSERT(texImage
->FetchTexelf
);
2526 texObj
->Complete
= GL_FALSE
;
2527 ctx
->NewState
|= _NEW_TEXTURE
;
2533 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
2534 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
2536 struct gl_texture_unit
*texUnit
;
2537 struct gl_texture_image
*texImage
;
2538 GLsizei postConvWidth
= width
;
2539 GET_CURRENT_CONTEXT(ctx
);
2540 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2542 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2543 _mesa_update_state(ctx
);
2545 /* XXX should test internal format */
2546 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2548 if (copytexsubimage_error_check(ctx
, 1, target
, level
,
2549 xoffset
, 0, 0, postConvWidth
, 1))
2552 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2553 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2556 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2557 xoffset
+= texImage
->Border
;
2559 ASSERT(ctx
->Driver
.CopyTexSubImage1D
);
2560 (*ctx
->Driver
.CopyTexSubImage1D
)(ctx
, target
, level
, xoffset
, x
, y
, width
);
2561 ctx
->NewState
|= _NEW_TEXTURE
;
2567 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
2568 GLint xoffset
, GLint yoffset
,
2569 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2571 struct gl_texture_unit
*texUnit
;
2572 struct gl_texture_image
*texImage
;
2573 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2574 GET_CURRENT_CONTEXT(ctx
);
2575 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2577 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2578 _mesa_update_state(ctx
);
2580 /* XXX should test internal format */
2581 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2583 if (copytexsubimage_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2584 postConvWidth
, postConvHeight
))
2587 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2588 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2591 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2592 xoffset
+= texImage
->Border
;
2593 yoffset
+= texImage
->Border
;
2595 ASSERT(ctx
->Driver
.CopyTexSubImage2D
);
2596 (*ctx
->Driver
.CopyTexSubImage2D
)(ctx
, target
, level
,
2597 xoffset
, yoffset
, x
, y
, width
, height
);
2598 ctx
->NewState
|= _NEW_TEXTURE
;
2604 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
2605 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2606 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2608 struct gl_texture_unit
*texUnit
;
2609 struct gl_texture_image
*texImage
;
2610 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2611 GET_CURRENT_CONTEXT(ctx
);
2612 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2614 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2615 _mesa_update_state(ctx
);
2617 /* XXX should test internal format */
2618 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2620 if (copytexsubimage_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
,
2621 zoffset
, postConvWidth
, postConvHeight
))
2624 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2625 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2628 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2629 xoffset
+= texImage
->Border
;
2630 yoffset
+= texImage
->Border
;
2631 zoffset
+= texImage
->Border
;
2633 ASSERT(ctx
->Driver
.CopyTexSubImage3D
);
2634 (*ctx
->Driver
.CopyTexSubImage3D
)(ctx
, target
, level
,
2635 xoffset
, yoffset
, zoffset
,
2636 x
, y
, width
, height
);
2637 ctx
->NewState
|= _NEW_TEXTURE
;
2643 /**********************************************************************/
2644 /****** Compressed Textures ******/
2645 /**********************************************************************/
2649 * Error checking for glCompressedTexImage[123]D().
2650 * \return error code or GL_NO_ERROR.
2653 compressed_texture_error_check(GLcontext
*ctx
, GLint dimensions
,
2654 GLenum target
, GLint level
,
2655 GLenum internalFormat
, GLsizei width
,
2656 GLsizei height
, GLsizei depth
, GLint border
,
2659 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2661 if (dimensions
== 1) {
2662 /* 1D compressed textures not allowed */
2663 return GL_INVALID_ENUM
;
2665 else if (dimensions
== 2) {
2666 if (target
== GL_PROXY_TEXTURE_2D
) {
2667 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2669 else if (target
== GL_TEXTURE_2D
) {
2670 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2672 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2673 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2674 return GL_INVALID_ENUM
; /*target*/
2675 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2677 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2678 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2679 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2680 return GL_INVALID_ENUM
; /*target*/
2681 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2684 return GL_INVALID_ENUM
; /*target*/
2687 else if (dimensions
== 3) {
2688 /* 3D compressed textures not allowed */
2689 return GL_INVALID_ENUM
;
2692 maxTextureSize
= 1 << (maxLevels
- 1);
2694 if (!is_compressed_format(ctx
, internalFormat
))
2695 return GL_INVALID_ENUM
;
2698 return GL_INVALID_VALUE
;
2701 * XXX We should probably use the proxy texture error check function here.
2703 if (width
< 1 || width
> maxTextureSize
||
2704 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(width
) < 0))
2705 return GL_INVALID_VALUE
;
2707 if ((height
< 1 || height
> maxTextureSize
||
2708 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(height
) < 0))
2710 return GL_INVALID_VALUE
;
2712 if ((depth
< 1 || depth
> maxTextureSize
||
2713 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(depth
) < 0))
2715 return GL_INVALID_VALUE
;
2717 /* For cube map, width must equal height */
2718 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2719 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
&& width
!= height
)
2720 return GL_INVALID_VALUE
;
2722 if (level
< 0 || level
>= maxLevels
)
2723 return GL_INVALID_VALUE
;
2725 expectedSize
= _mesa_compressed_texture_size(ctx
, width
, height
, depth
,
2727 if (expectedSize
!= imageSize
)
2728 return GL_INVALID_VALUE
;
2735 * Error checking for glCompressedTexSubImage[123]D().
2736 * \return error code or GL_NO_ERROR.
2739 compressed_subtexture_error_check(GLcontext
*ctx
, GLint dimensions
,
2740 GLenum target
, GLint level
,
2741 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2742 GLsizei width
, GLsizei height
, GLsizei depth
,
2743 GLenum format
, GLsizei imageSize
)
2745 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2747 if (dimensions
== 1) {
2748 /* 1D compressed textures not allowed */
2749 return GL_INVALID_ENUM
;
2751 else if (dimensions
== 2) {
2752 if (target
== GL_PROXY_TEXTURE_2D
) {
2753 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2755 else if (target
== GL_TEXTURE_2D
) {
2756 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2758 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2759 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2760 return GL_INVALID_ENUM
; /*target*/
2761 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2763 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2764 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2765 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2766 return GL_INVALID_ENUM
; /*target*/
2767 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2770 return GL_INVALID_ENUM
; /*target*/
2773 else if (dimensions
== 3) {
2774 /* 3D compressed textures not allowed */
2775 return GL_INVALID_ENUM
;
2778 maxTextureSize
= 1 << (maxLevels
- 1);
2780 if (!is_compressed_format(ctx
, format
))
2781 return GL_INVALID_ENUM
;
2783 if (width
< 1 || width
> maxTextureSize
)
2784 return GL_INVALID_VALUE
;
2786 if ((height
< 1 || height
> maxTextureSize
)
2788 return GL_INVALID_VALUE
;
2790 if (level
< 0 || level
>= maxLevels
)
2791 return GL_INVALID_VALUE
;
2793 if ((xoffset
& 3) != 0 || (yoffset
& 3) != 0)
2794 return GL_INVALID_VALUE
;
2796 if ((width
& 3) != 0 && width
!= 2 && width
!= 1)
2797 return GL_INVALID_VALUE
;
2799 if ((height
& 3) != 0 && height
!= 2 && height
!= 1)
2800 return GL_INVALID_VALUE
;
2802 expectedSize
= _mesa_compressed_texture_size(ctx
, width
, height
, depth
,
2804 if (expectedSize
!= imageSize
)
2805 return GL_INVALID_VALUE
;
2813 _mesa_CompressedTexImage1DARB(GLenum target
, GLint level
,
2814 GLenum internalFormat
, GLsizei width
,
2815 GLint border
, GLsizei imageSize
,
2818 GET_CURRENT_CONTEXT(ctx
);
2819 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2821 if (target
== GL_TEXTURE_1D
) {
2822 struct gl_texture_unit
*texUnit
;
2823 struct gl_texture_object
*texObj
;
2824 struct gl_texture_image
*texImage
;
2825 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
2826 internalFormat
, width
, 1, 1, border
, imageSize
);
2828 _mesa_error(ctx
, error
, "glCompressedTexImage1D");
2832 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2833 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2834 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2836 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage1D");
2839 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2840 MESA_PBUFFER_FREE(texImage
->Data
);
2842 texImage
->Data
= NULL
;
2844 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
2845 border
, internalFormat
);
2847 ASSERT(ctx
->Driver
.CompressedTexImage1D
);
2848 (*ctx
->Driver
.CompressedTexImage1D
)(ctx
, target
, level
,
2849 internalFormat
, width
, border
,
2854 texObj
->Complete
= GL_FALSE
;
2855 ctx
->NewState
|= _NEW_TEXTURE
;
2857 else if (target
== GL_PROXY_TEXTURE_1D
) {
2858 /* Proxy texture: check for errors and update proxy state */
2859 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
2860 internalFormat
, width
, 1, 1, border
, imageSize
);
2862 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2863 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2864 internalFormat
, GL_NONE
, GL_NONE
,
2865 width
, 1, 1, border
);
2868 /* if error, clear all proxy texture image parameters */
2869 struct gl_texture_image
*texImage
;
2870 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2872 clear_teximage_fields(texImage
);
2875 /* store the teximage parameters */
2876 struct gl_texture_unit
*texUnit
;
2877 struct gl_texture_image
*texImage
;
2878 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2879 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2880 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
2881 border
, internalFormat
);
2885 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage1D(target)");
2892 _mesa_CompressedTexImage2DARB(GLenum target
, GLint level
,
2893 GLenum internalFormat
, GLsizei width
,
2894 GLsizei height
, GLint border
, GLsizei imageSize
,
2897 GET_CURRENT_CONTEXT(ctx
);
2898 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2900 if (target
== GL_TEXTURE_2D
||
2901 (ctx
->Extensions
.ARB_texture_cube_map
&&
2902 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2903 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
2904 struct gl_texture_unit
*texUnit
;
2905 struct gl_texture_object
*texObj
;
2906 struct gl_texture_image
*texImage
;
2907 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
2908 internalFormat
, width
, height
, 1, border
, imageSize
);
2910 _mesa_error(ctx
, error
, "glCompressedTexImage2D");
2914 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2915 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2916 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2918 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
2921 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2922 MESA_PBUFFER_FREE(texImage
->Data
);
2924 texImage
->Data
= NULL
;
2926 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2927 border
, internalFormat
);
2929 ASSERT(ctx
->Driver
.CompressedTexImage2D
);
2930 (*ctx
->Driver
.CompressedTexImage2D
)(ctx
, target
, level
,
2931 internalFormat
, width
, height
,
2932 border
, imageSize
, data
,
2936 texObj
->Complete
= GL_FALSE
;
2937 ctx
->NewState
|= _NEW_TEXTURE
;
2939 else if (target
== GL_PROXY_TEXTURE_2D
||
2940 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2941 ctx
->Extensions
.ARB_texture_cube_map
)) {
2942 /* Proxy texture: check for errors and update proxy state */
2943 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
2944 internalFormat
, width
, height
, 1, border
, imageSize
);
2946 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2947 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2948 internalFormat
, GL_NONE
, GL_NONE
,
2949 width
, height
, 1, border
);
2952 /* if error, clear all proxy texture image parameters */
2953 struct gl_texture_image
*texImage
;
2954 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2956 clear_teximage_fields(texImage
);
2959 /* store the teximage parameters */
2960 struct gl_texture_unit
*texUnit
;
2961 struct gl_texture_image
*texImage
;
2962 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2963 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2964 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2965 border
, internalFormat
);
2969 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(target)");
2976 _mesa_CompressedTexImage3DARB(GLenum target
, GLint level
,
2977 GLenum internalFormat
, GLsizei width
,
2978 GLsizei height
, GLsizei depth
, GLint border
,
2979 GLsizei imageSize
, const GLvoid
*data
)
2981 GET_CURRENT_CONTEXT(ctx
);
2982 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2984 if (target
== GL_TEXTURE_3D
) {
2985 struct gl_texture_unit
*texUnit
;
2986 struct gl_texture_object
*texObj
;
2987 struct gl_texture_image
*texImage
;
2988 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
2989 internalFormat
, width
, height
, depth
, border
, imageSize
);
2991 _mesa_error(ctx
, error
, "glCompressedTexImage3D");
2995 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2996 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2997 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2999 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage3D");
3002 else if (texImage
->Data
&& !texImage
->IsClientData
) {
3003 MESA_PBUFFER_FREE(texImage
->Data
);
3005 texImage
->Data
= NULL
;
3007 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, depth
,
3008 border
, internalFormat
);
3010 ASSERT(ctx
->Driver
.CompressedTexImage3D
);
3011 (*ctx
->Driver
.CompressedTexImage3D
)(ctx
, target
, level
,
3013 width
, height
, depth
,
3014 border
, imageSize
, data
,
3018 texObj
->Complete
= GL_FALSE
;
3019 ctx
->NewState
|= _NEW_TEXTURE
;
3021 else if (target
== GL_PROXY_TEXTURE_3D
) {
3022 /* Proxy texture: check for errors and update proxy state */
3023 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3024 internalFormat
, width
, height
, depth
, border
, imageSize
);
3026 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3027 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3028 internalFormat
, GL_NONE
, GL_NONE
,
3029 width
, height
, depth
, border
);
3032 /* if error, clear all proxy texture image parameters */
3033 struct gl_texture_image
*texImage
;
3034 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3036 clear_teximage_fields(texImage
);
3039 /* store the teximage parameters */
3040 struct gl_texture_unit
*texUnit
;
3041 struct gl_texture_image
*texImage
;
3042 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3043 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3044 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
,
3045 depth
, border
, internalFormat
);
3049 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage3D(target)");
3056 _mesa_CompressedTexSubImage1DARB(GLenum target
, GLint level
, GLint xoffset
,
3057 GLsizei width
, GLenum format
,
3058 GLsizei imageSize
, const GLvoid
*data
)
3060 struct gl_texture_unit
*texUnit
;
3061 struct gl_texture_object
*texObj
;
3062 struct gl_texture_image
*texImage
;
3064 GET_CURRENT_CONTEXT(ctx
);
3065 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3067 error
= compressed_subtexture_error_check(ctx
, 1, target
, level
,
3068 xoffset
, 0, 0, width
, 1, 1, format
, imageSize
);
3070 _mesa_error(ctx
, error
, "glCompressedTexSubImage1D");
3074 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3075 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3076 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3079 if ((GLint
) format
!= texImage
->IntFormat
) {
3080 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3081 "glCompressedTexSubImage1D(format)");
3085 if ((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) {
3086 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage1D(width)");
3090 if (width
== 0 || !data
)
3091 return; /* no-op, not an error */
3093 if (ctx
->Driver
.CompressedTexSubImage1D
) {
3094 (*ctx
->Driver
.CompressedTexSubImage1D
)(ctx
, target
, level
,
3096 format
, imageSize
, data
,
3099 ctx
->NewState
|= _NEW_TEXTURE
;
3104 _mesa_CompressedTexSubImage2DARB(GLenum target
, GLint level
, GLint xoffset
,
3105 GLint yoffset
, GLsizei width
, GLsizei height
,
3106 GLenum format
, GLsizei imageSize
,
3109 struct gl_texture_unit
*texUnit
;
3110 struct gl_texture_object
*texObj
;
3111 struct gl_texture_image
*texImage
;
3113 GET_CURRENT_CONTEXT(ctx
);
3114 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3116 error
= compressed_subtexture_error_check(ctx
, 2, target
, level
,
3117 xoffset
, yoffset
, 0, width
, height
, 1, format
, imageSize
);
3119 /* XXX proxy target? */
3120 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3124 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3125 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3126 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3129 if ((GLint
) format
!= texImage
->IntFormat
) {
3130 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3131 "glCompressedTexSubImage2D(format)");
3135 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3136 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
)) {
3137 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage2D(size)");
3141 if (width
== 0 || height
== 0 || !data
)
3142 return; /* no-op, not an error */
3144 if (ctx
->Driver
.CompressedTexSubImage2D
) {
3145 (*ctx
->Driver
.CompressedTexSubImage2D
)(ctx
, target
, level
,
3146 xoffset
, yoffset
, width
, height
,
3147 format
, imageSize
, data
,
3150 ctx
->NewState
|= _NEW_TEXTURE
;
3155 _mesa_CompressedTexSubImage3DARB(GLenum target
, GLint level
, GLint xoffset
,
3156 GLint yoffset
, GLint zoffset
, GLsizei width
,
3157 GLsizei height
, GLsizei depth
, GLenum format
,
3158 GLsizei imageSize
, const GLvoid
*data
)
3160 struct gl_texture_unit
*texUnit
;
3161 struct gl_texture_object
*texObj
;
3162 struct gl_texture_image
*texImage
;
3164 GET_CURRENT_CONTEXT(ctx
);
3165 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3167 error
= compressed_subtexture_error_check(ctx
, 3, target
, level
,
3168 xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
, imageSize
);
3170 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3174 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3175 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3176 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3179 if ((GLint
) format
!= texImage
->IntFormat
) {
3180 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3181 "glCompressedTexSubImage3D(format)");
3185 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3186 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
) ||
3187 ((depth
== 1 || depth
== 2) && (GLuint
) depth
!= texImage
->Depth
)) {
3188 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage3D(size)");
3192 if (width
== 0 || height
== 0 || depth
== 0 || !data
)
3193 return; /* no-op, not an error */
3195 if (ctx
->Driver
.CompressedTexSubImage3D
) {
3196 (*ctx
->Driver
.CompressedTexSubImage3D
)(ctx
, target
, level
,
3197 xoffset
, yoffset
, zoffset
,
3198 width
, height
, depth
,
3199 format
, imageSize
, data
,
3202 ctx
->NewState
|= _NEW_TEXTURE
;
3207 _mesa_GetCompressedTexImageARB(GLenum target
, GLint level
, GLvoid
*img
)
3209 const struct gl_texture_unit
*texUnit
;
3210 const struct gl_texture_object
*texObj
;
3211 struct gl_texture_image
*texImage
;
3213 GET_CURRENT_CONTEXT(ctx
);
3214 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3216 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3217 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3219 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB");
3223 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
3224 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
3226 if (level
< 0 || level
>= maxLevels
) {
3227 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3231 if (is_proxy_target(target
)) {
3232 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
3236 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3238 /* probably invalid mipmap level */
3239 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3243 if (!texImage
->IsCompressed
) {
3244 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetCompressedTexImageARB");
3251 /* just memcpy, no pixelstore or pixel transfer */
3252 MEMCPY(img
, texImage
->Data
, texImage
->CompressedSize
);