3 * Texture images manipulation functions.
5 * \note Mesa's native texture data type is GLchan. Native formats are
6 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA, and
9 * \note Device drivers are free to implement any internal format they want.
13 * Mesa 3-D graphics library
16 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
18 * Permission is hereby granted, free of charge, to any person obtaining a
19 * copy of this software and associated documentation files (the "Software"),
20 * to deal in the Software without restriction, including without limitation
21 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
22 * and/or sell copies of the Software, and to permit persons to whom the
23 * Software is furnished to do so, subject to the following conditions:
25 * The above copyright notice and this permission notice shall be included
26 * in all copies or substantial portions of the Software.
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
29 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
31 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
32 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
33 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
44 #include "texcompress.h"
45 #include "texformat.h"
53 static void PrintTexture(GLcontext
*ctx
, const struct gl_texture_image
*img
)
55 #if CHAN_TYPE == GL_FLOAT
56 _mesa_problem(NULL
, "PrintTexture doesn't support float channels");
59 const GLchan
*data
= (const GLchan
*) img
->Data
;
62 _mesa_printf("No texture data\n");
66 switch (img
->Format
) {
73 case GL_LUMINANCE_ALPHA
:
83 _mesa_problem(NULL
, "error in PrintTexture\n");
87 for (i
= 0; i
< img
->Height
; i
++) {
88 for (j
= 0; j
< img
->Width
; j
++) {
90 _mesa_printf("%02x ", data
[0]);
92 _mesa_printf("%02x%02x ", data
[0], data
[1]);
94 _mesa_printf("%02x%02x%02x ", data
[0], data
[1], data
[2]);
96 _mesa_printf("%02x%02x%02x%02x ", data
[0], data
[1], data
[2], data
[3]);
97 data
+= (img
->RowStride
- img
->Width
) * c
;
107 * Compute floor(log_base_2(n)).
108 * If n < 0 return -1.
137 * Get base internal format.
139 * \param ctx GL context.
140 * \param format internal texture format enum or 1, 2, 3, 4.
142 * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
143 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
145 * This is the format which is used during texture application (i.e. the
146 * texture format and env mode determine the arithmetic used.
149 _mesa_base_tex_format( GLcontext
*ctx
, GLint format
)
152 * Ask the driver for the base format, if it doesn't
153 * know, it will return -1;
170 case GL_LUMINANCE_ALPHA
:
171 case GL_LUMINANCE4_ALPHA4
:
172 case GL_LUMINANCE6_ALPHA2
:
173 case GL_LUMINANCE8_ALPHA8
:
174 case GL_LUMINANCE12_ALPHA4
:
175 case GL_LUMINANCE12_ALPHA12
:
176 case GL_LUMINANCE16_ALPHA16
:
177 return GL_LUMINANCE_ALPHA
;
205 case GL_COLOR_INDEX1_EXT
:
206 case GL_COLOR_INDEX2_EXT
:
207 case GL_COLOR_INDEX4_EXT
:
208 case GL_COLOR_INDEX8_EXT
:
209 case GL_COLOR_INDEX12_EXT
:
210 case GL_COLOR_INDEX16_EXT
:
211 if (ctx
->Extensions
.EXT_paletted_texture
)
212 return GL_COLOR_INDEX
;
215 case GL_DEPTH_COMPONENT
:
216 case GL_DEPTH_COMPONENT16_SGIX
:
217 case GL_DEPTH_COMPONENT24_SGIX
:
218 case GL_DEPTH_COMPONENT32_SGIX
:
219 if (ctx
->Extensions
.SGIX_depth_texture
)
220 return GL_DEPTH_COMPONENT
;
224 /* GL_ARB_texture_compression */
225 case GL_COMPRESSED_ALPHA
:
226 if (ctx
->Extensions
.ARB_texture_compression
)
230 case GL_COMPRESSED_LUMINANCE
:
231 if (ctx
->Extensions
.ARB_texture_compression
)
235 case GL_COMPRESSED_LUMINANCE_ALPHA
:
236 if (ctx
->Extensions
.ARB_texture_compression
)
237 return GL_LUMINANCE_ALPHA
;
240 case GL_COMPRESSED_INTENSITY
:
241 if (ctx
->Extensions
.ARB_texture_compression
)
245 case GL_COMPRESSED_RGB
:
246 if (ctx
->Extensions
.ARB_texture_compression
)
250 case GL_COMPRESSED_RGBA
:
251 if (ctx
->Extensions
.ARB_texture_compression
)
255 case GL_COMPRESSED_RGB_FXT1_3DFX
:
256 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
)
260 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
261 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
)
265 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
266 if (ctx
->Extensions
.EXT_texture_compression_s3tc
)
270 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
271 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
272 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
273 if (ctx
->Extensions
.EXT_texture_compression_s3tc
)
279 if (ctx
->Extensions
.S3_s3tc
)
285 if (ctx
->Extensions
.S3_s3tc
)
291 if (ctx
->Extensions
.MESA_ycbcr_texture
)
292 return GL_YCBCR_MESA
;
297 return -1; /* error */
303 * Test if the given image format is a color/RGBA format, i.e., not
304 * color index, depth, stencil, etc.
307 is_color_format(GLenum format
)
322 case GL_LUMINANCE_ALPHA
:
323 case GL_LUMINANCE4_ALPHA4
:
324 case GL_LUMINANCE6_ALPHA2
:
325 case GL_LUMINANCE8_ALPHA8
:
326 case GL_LUMINANCE12_ALPHA4
:
327 case GL_LUMINANCE12_ALPHA12
:
328 case GL_LUMINANCE16_ALPHA16
:
353 case GL_YCBCR_MESA
: /* not considered to be RGB */
361 * Test if the given image format is a color index format.
364 is_index_format(GLenum format
)
368 case GL_COLOR_INDEX1_EXT
:
369 case GL_COLOR_INDEX2_EXT
:
370 case GL_COLOR_INDEX4_EXT
:
371 case GL_COLOR_INDEX8_EXT
:
372 case GL_COLOR_INDEX12_EXT
:
373 case GL_COLOR_INDEX16_EXT
:
382 * Test if it is a supported compressed format.
384 * \param internalFormat the internal format token provided by the user.
386 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
387 * GL_FALSE otherwise.
389 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
393 is_compressed_format(GLcontext
*ctx
, GLenum internalFormat
)
395 switch (internalFormat
) {
396 case GL_COMPRESSED_RGB_FXT1_3DFX
:
397 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
398 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
399 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
400 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
401 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
408 if (ctx
->Driver
.IsCompressedFormat
) {
409 return ctx
->Driver
.IsCompressedFormat(ctx
, internalFormat
);
417 * Store a gl_texture_image pointer in a gl_texture_object structure
418 * according to the target and level parameters.
420 * \param tObj texture object.
421 * \param target texture target.
422 * \param level image level.
423 * \param texImage texture image.
425 * This was basically prompted by the introduction of cube maps.
428 _mesa_set_tex_image(struct gl_texture_object
*tObj
,
429 GLenum target
, GLint level
,
430 struct gl_texture_image
*texImage
)
438 tObj
->Image
[level
] = texImage
;
440 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
441 tObj
->Image
[level
] = texImage
;
443 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
444 tObj
->NegX
[level
] = texImage
;
446 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
447 tObj
->PosY
[level
] = texImage
;
449 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
450 tObj
->NegY
[level
] = texImage
;
452 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
453 tObj
->PosZ
[level
] = texImage
;
455 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
456 tObj
->NegZ
[level
] = texImage
;
458 case GL_TEXTURE_RECTANGLE_NV
:
460 tObj
->Image
[level
] = texImage
;
463 _mesa_problem(NULL
, "bad target in _mesa_set_tex_image()");
470 * Allocate a texture image structure.
472 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
475 * \return a pointer to gl_texture_image struct with all fields initialized to
478 struct gl_texture_image
*
479 _mesa_new_texture_image( GLcontext
*ctx
)
482 return CALLOC_STRUCT(gl_texture_image
);
487 * Free texture image.
489 * \param teximage texture image.
491 * Free the texture image structure and the associated image data if it's not
492 * marked as client data.
495 _mesa_delete_texture_image( struct gl_texture_image
*teximage
)
497 if (teximage
->Data
&& !teximage
->IsClientData
) {
498 MESA_PBUFFER_FREE( teximage
->Data
);
499 teximage
->Data
= NULL
;
506 * Test if a target is a proxy target.
508 * \param target texture target.
510 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
513 is_proxy_target(GLenum target
)
515 return (target
== GL_PROXY_TEXTURE_1D
||
516 target
== GL_PROXY_TEXTURE_2D
||
517 target
== GL_PROXY_TEXTURE_3D
||
518 target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
519 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
);
524 * Get the texture object that corresponds to the target of the given texture unit.
526 * \param ctx GL context.
527 * \param texUnit texture unit.
528 * \param target texture target.
530 * \return pointer to the texture object on success, or NULL on failure.
532 * \sa gl_texture_unit.
534 struct gl_texture_object
*
535 _mesa_select_tex_object(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
540 return texUnit
->Current1D
;
541 case GL_PROXY_TEXTURE_1D
:
542 return ctx
->Texture
.Proxy1D
;
544 return texUnit
->Current2D
;
545 case GL_PROXY_TEXTURE_2D
:
546 return ctx
->Texture
.Proxy2D
;
548 return texUnit
->Current3D
;
549 case GL_PROXY_TEXTURE_3D
:
550 return ctx
->Texture
.Proxy3D
;
551 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
552 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
553 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
554 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
555 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
556 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
557 case GL_TEXTURE_CUBE_MAP_ARB
:
558 return ctx
->Extensions
.ARB_texture_cube_map
559 ? texUnit
->CurrentCubeMap
: NULL
;
560 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
561 return ctx
->Extensions
.ARB_texture_cube_map
562 ? ctx
->Texture
.ProxyCubeMap
: NULL
;
563 case GL_TEXTURE_RECTANGLE_NV
:
564 return ctx
->Extensions
.NV_texture_rectangle
565 ? texUnit
->CurrentRect
: NULL
;
566 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
567 return ctx
->Extensions
.NV_texture_rectangle
568 ? ctx
->Texture
.ProxyRect
: NULL
;
570 _mesa_problem(NULL
, "bad target in _mesa_select_tex_object()");
577 * Get the texture image struct which corresponds to target and level
578 * of the given texture unit.
580 * \param ctx GL context.
581 * \param texUnit texture unit.
582 * \param target texture target.
583 * \param level image level.
585 * \return pointer to the texture image structure on success, or NULL on failure.
587 * \sa gl_texture_unit.
589 struct gl_texture_image
*
590 _mesa_select_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
591 GLenum target
, GLint level
)
594 ASSERT(level
< MAX_TEXTURE_LEVELS
);
597 return texUnit
->Current1D
->Image
[level
];
598 case GL_PROXY_TEXTURE_1D
:
599 return ctx
->Texture
.Proxy1D
->Image
[level
];
601 return texUnit
->Current2D
->Image
[level
];
602 case GL_PROXY_TEXTURE_2D
:
603 return ctx
->Texture
.Proxy2D
->Image
[level
];
605 return texUnit
->Current3D
->Image
[level
];
606 case GL_PROXY_TEXTURE_3D
:
607 return ctx
->Texture
.Proxy3D
->Image
[level
];
608 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
609 if (ctx
->Extensions
.ARB_texture_cube_map
)
610 return texUnit
->CurrentCubeMap
->Image
[level
];
613 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
614 if (ctx
->Extensions
.ARB_texture_cube_map
)
615 return texUnit
->CurrentCubeMap
->NegX
[level
];
618 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
619 if (ctx
->Extensions
.ARB_texture_cube_map
)
620 return texUnit
->CurrentCubeMap
->PosY
[level
];
623 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
624 if (ctx
->Extensions
.ARB_texture_cube_map
)
625 return texUnit
->CurrentCubeMap
->NegY
[level
];
628 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
629 if (ctx
->Extensions
.ARB_texture_cube_map
)
630 return texUnit
->CurrentCubeMap
->PosZ
[level
];
633 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
634 if (ctx
->Extensions
.ARB_texture_cube_map
)
635 return texUnit
->CurrentCubeMap
->NegZ
[level
];
638 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
639 if (ctx
->Extensions
.ARB_texture_cube_map
)
640 return ctx
->Texture
.ProxyCubeMap
->Image
[level
];
643 case GL_TEXTURE_RECTANGLE_NV
:
644 if (ctx
->Extensions
.NV_texture_rectangle
) {
646 return texUnit
->CurrentRect
->Image
[level
];
651 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
652 if (ctx
->Extensions
.NV_texture_rectangle
) {
654 return ctx
->Texture
.ProxyRect
->Image
[level
];
660 _mesa_problem(ctx
, "bad target in _mesa_select_tex_image()");
667 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
668 * it and install it. Only return NULL if passed a bad parameter or run
671 struct gl_texture_image
*
672 _mesa_get_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
673 GLenum target
, GLint level
)
675 struct gl_texture_image
*texImage
;
676 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
678 struct gl_texture_object
*texObj
;
679 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
681 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture image allocation");
684 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
686 _mesa_set_tex_image(texObj
, target
, level
, texImage
);
693 * Return pointer to the specified proxy texture image.
694 * Note that proxy textures are per-context, not per-texture unit.
695 * \return pointer to texture image or NULL if invalid target, invalid
696 * level, or out of memory.
698 struct gl_texture_image
*
699 _mesa_get_proxy_tex_image(GLcontext
*ctx
, GLenum target
, GLint level
)
701 struct gl_texture_image
*texImage
;
707 case GL_PROXY_TEXTURE_1D
:
708 if (level
>= ctx
->Const
.MaxTextureLevels
)
710 texImage
= ctx
->Texture
.Proxy1D
->Image
[level
];
712 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
714 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
717 ctx
->Texture
.Proxy1D
->Image
[level
] = texImage
;
720 case GL_PROXY_TEXTURE_2D
:
721 if (level
>= ctx
->Const
.MaxTextureLevels
)
723 texImage
= ctx
->Texture
.Proxy2D
->Image
[level
];
725 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
727 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
730 ctx
->Texture
.Proxy2D
->Image
[level
] = texImage
;
733 case GL_PROXY_TEXTURE_3D
:
734 if (level
>= ctx
->Const
.Max3DTextureLevels
)
736 texImage
= ctx
->Texture
.Proxy3D
->Image
[level
];
738 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
740 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
743 ctx
->Texture
.Proxy3D
->Image
[level
] = texImage
;
746 case GL_PROXY_TEXTURE_CUBE_MAP
:
747 if (level
>= ctx
->Const
.MaxCubeTextureLevels
)
749 texImage
= ctx
->Texture
.ProxyCubeMap
->Image
[level
];
751 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
753 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
756 ctx
->Texture
.ProxyCubeMap
->Image
[level
] = texImage
;
759 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
762 texImage
= ctx
->Texture
.ProxyRect
->Image
[level
];
764 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
766 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
769 ctx
->Texture
.ProxyRect
->Image
[level
] = texImage
;
779 * Get the maximum number of allowed mipmap levels.
781 * \param ctx GL context.
782 * \param target texture target.
784 * \return the maximum number of allowed mipmap levels for the given
785 * texture target, or zero if passed a bad target.
790 _mesa_max_texture_levels(GLcontext
*ctx
, GLenum target
)
794 case GL_PROXY_TEXTURE_1D
:
796 case GL_PROXY_TEXTURE_2D
:
797 return ctx
->Const
.MaxTextureLevels
;
799 case GL_PROXY_TEXTURE_3D
:
800 return ctx
->Const
.Max3DTextureLevels
;
801 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
802 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
803 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
804 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
805 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
806 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
807 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
808 return ctx
->Const
.MaxCubeTextureLevels
;
810 case GL_TEXTURE_RECTANGLE_NV
:
811 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
815 return 0; /* bad target */
821 #if 000 /* not used anymore */
823 * glTexImage[123]D can accept a NULL image pointer. In this case we
824 * create a texture image with unspecified image contents per the OpenGL
828 make_null_texture(GLint width
, GLint height
, GLint depth
, GLenum format
)
830 const GLint components
= _mesa_components_in_format(format
);
831 const GLint numPixels
= width
* height
* depth
;
832 GLubyte
*data
= (GLubyte
*) MALLOC(numPixels
* components
* sizeof(GLubyte
));
836 * Let's see if anyone finds this. If glTexImage2D() is called with
837 * a NULL image pointer then load the texture image with something
838 * interesting instead of leaving it indeterminate.
841 static const char message
[8][32] = {
845 " X X XXXX XXX XXXXX ",
848 " X X XXXXX XXX X X ",
852 GLubyte
*imgPtr
= data
;
854 for (h
= 0; h
< depth
; h
++) {
855 for (i
= 0; i
< height
; i
++) {
856 GLint srcRow
= 7 - (i
% 8);
857 for (j
= 0; j
< width
; j
++) {
858 GLint srcCol
= j
% 32;
859 GLubyte texel
= (message
[srcRow
][srcCol
]=='X') ? 255 : 70;
860 for (k
= 0; k
< components
; k
++) {
876 * Reset the fields of a gl_texture_image struct to zero.
878 * \param img texture image structure.
880 * This is called when a proxy texture test fails, we set all the
881 * image members (except DriverData) to zero.
882 * It's also used in glTexImage[123]D as a safeguard to be sure all
883 * required fields get initialized properly by the Driver.TexImage[123]D
887 clear_teximage_fields(struct gl_texture_image
*img
)
904 img
->TexFormat
= &_mesa_null_texformat
;
905 img
->FetchTexel
= NULL
;
906 img
->IsCompressed
= 0;
907 img
->CompressedSize
= 0;
912 * Initialize basic fields of the gl_texture_image struct.
914 * \param ctx GL context.
915 * \param target texture target.
916 * \param img texture image structure to be initialized.
917 * \param width image width.
918 * \param height image height.
919 * \param depth image depth.
920 * \param border image border.
921 * \param internalFormat internal format.
923 * Fills in the fields of \p img with the given information.
924 * Note: width, height and depth include the border.
927 _mesa_init_teximage_fields(GLcontext
*ctx
, GLenum target
,
928 struct gl_texture_image
*img
,
929 GLsizei width
, GLsizei height
, GLsizei depth
,
930 GLint border
, GLenum internalFormat
)
933 img
->Format
= _mesa_base_tex_format( ctx
, internalFormat
);
934 ASSERT(img
->Format
> 0);
935 img
->IntFormat
= internalFormat
;
936 img
->Border
= border
;
938 img
->Height
= height
;
940 img
->RowStride
= width
;
941 img
->WidthLog2
= logbase2(width
- 2 * border
);
942 if (height
== 1) /* 1-D texture */
945 img
->HeightLog2
= logbase2(height
- 2 * border
);
946 if (depth
== 1) /* 2-D texture */
949 img
->DepthLog2
= logbase2(depth
- 2 * border
);
950 img
->Width2
= width
- 2 * border
; /*1 << img->WidthLog2;*/
951 img
->Height2
= height
- 2 * border
; /*1 << img->HeightLog2;*/
952 img
->Depth2
= depth
- 2 * border
; /*1 << img->DepthLog2;*/
953 img
->MaxLog2
= MAX2(img
->WidthLog2
, img
->HeightLog2
);
954 img
->IsCompressed
= is_compressed_format(ctx
, internalFormat
);
955 if (img
->IsCompressed
)
956 img
->CompressedSize
= _mesa_compressed_texture_size(ctx
, width
, height
,
957 depth
, internalFormat
);
959 img
->CompressedSize
= 0;
961 if ((width
== 1 || _mesa_bitcount(width
- 2 * border
) == 1) &&
962 (height
== 1 || _mesa_bitcount(height
- 2 * border
) == 1) &&
963 (depth
== 1 || _mesa_bitcount(depth
- 2 * border
) == 1))
964 img
->_IsPowerOfTwo
= GL_TRUE
;
966 img
->_IsPowerOfTwo
= GL_FALSE
;
968 /* Compute Width/Height/DepthScale for mipmap lod computation */
969 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
970 /* scale = 1.0 since texture coords directly map to texels */
971 img
->WidthScale
= 1.0;
972 img
->HeightScale
= 1.0;
973 img
->DepthScale
= 1.0;
976 img
->WidthScale
= (GLfloat
) img
->Width
;
977 img
->HeightScale
= (GLfloat
) img
->Height
;
978 img
->DepthScale
= (GLfloat
) img
->Depth
;
984 * This is the fallback for Driver.TestProxyTexImage(). Test the texture
985 * level, width, height and depth against the ctx->Const limits for textures.
987 * A hardware driver might override this function if, for example, the
988 * max 3D texture size is 512x512x64 (i.e. not a cube).
990 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
991 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
992 * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
993 * \param level as passed to glTexImage
994 * \param internalFormat as passed to glTexImage
995 * \param format as passed to glTexImage
996 * \param type as passed to glTexImage
997 * \param width as passed to glTexImage
998 * \param height as passed to glTexImage
999 * \param depth as passed to glTexImage
1000 * \param border as passed to glTexImage
1001 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1004 _mesa_test_proxy_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
1005 GLint internalFormat
, GLenum format
, GLenum type
,
1006 GLint width
, GLint height
, GLint depth
, GLint border
)
1010 (void) internalFormat
;
1015 case GL_PROXY_TEXTURE_1D
:
1016 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1017 if (width
< 2 * border
|| width
> 2 + maxSize
||
1018 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1019 _mesa_bitcount(width
- 2 * border
) != 1) ||
1020 level
>= ctx
->Const
.MaxTextureLevels
) {
1021 /* bad width or level */
1025 case GL_PROXY_TEXTURE_2D
:
1026 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1027 if (width
< 2 * border
|| width
> 2 + maxSize
||
1028 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1029 _mesa_bitcount(width
- 2 * border
) != 1) ||
1030 height
< 2 * border
|| height
> 2 + maxSize
||
1031 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1032 _mesa_bitcount(height
- 2 * border
) != 1) ||
1033 level
>= ctx
->Const
.MaxTextureLevels
) {
1034 /* bad width or height or level */
1038 case GL_PROXY_TEXTURE_3D
:
1039 maxSize
= 1 << (ctx
->Const
.Max3DTextureLevels
- 1);
1040 if (width
< 2 * border
|| width
> 2 + maxSize
||
1041 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1042 _mesa_bitcount(width
- 2 * border
) != 1) ||
1043 height
< 2 * border
|| height
> 2 + maxSize
||
1044 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1045 _mesa_bitcount(height
- 2 * border
) != 1) ||
1046 depth
< 2 * border
|| depth
> 2 + maxSize
||
1047 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1048 _mesa_bitcount(depth
- 2 * border
) != 1) ||
1049 level
>= ctx
->Const
.Max3DTextureLevels
) {
1050 /* bad width or height or depth or level */
1054 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
1055 if (width
< 1 || width
> ctx
->Const
.MaxTextureRectSize
||
1056 height
< 1 || height
> ctx
->Const
.MaxTextureRectSize
||
1058 /* bad width or height or level */
1062 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
1063 maxSize
= 1 << (ctx
->Const
.MaxCubeTextureLevels
- 1);
1064 if (width
< 2 * border
|| width
> 2 + maxSize
||
1065 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1066 _mesa_bitcount(width
- 2 * border
) != 1) ||
1067 height
< 2 * border
|| height
> 2 + maxSize
||
1068 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1069 _mesa_bitcount(height
- 2 * border
) != 1) ||
1070 level
>= ctx
->Const
.MaxCubeTextureLevels
) {
1071 /* bad width or height */
1076 _mesa_problem(ctx
, "Invalid target in _mesa_test_proxy_teximage");
1083 * Test the glTexImage[123]D() parameters for errors.
1085 * \param ctx GL context.
1086 * \param target texture target given by the user.
1087 * \param level image level given by the user.
1088 * \param internalFormat internal format given by the user.
1089 * \param format pixel data format given by the user.
1090 * \param type pixel data type given by the user.
1091 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1092 * \param width image width given by the user.
1093 * \param height image height given by the user.
1094 * \param depth image depth given by the user.
1095 * \param border image border given by the user.
1097 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1099 * Verifies each of the parameters against the constants specified in
1100 * __GLcontextRec::Const and the supported extensions, and according to the
1101 * OpenGL specification.
1104 texture_error_check( GLcontext
*ctx
, GLenum target
,
1105 GLint level
, GLint internalFormat
,
1106 GLenum format
, GLenum type
,
1108 GLint width
, GLint height
,
1109 GLint depth
, GLint border
)
1111 const GLboolean isProxy
= is_proxy_target(target
);
1114 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1115 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1117 _mesa_error(ctx
, GL_INVALID_VALUE
,
1118 "glTexImage%dD(level=%d)", dimensions
, level
);
1124 if (border
< 0 || border
> 1 ||
1125 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1126 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1128 _mesa_error(ctx
, GL_INVALID_VALUE
,
1129 "glTexImage%dD(border=%d)", dimensions
, border
);
1134 if (width
< 0 || height
< 0 || depth
< 0) {
1136 _mesa_error(ctx
, GL_INVALID_VALUE
,
1137 "glTexImage%dD(width, height or depth < 0)", dimensions
);
1142 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1143 * level, width, height and depth.
1145 if (dimensions
== 1) {
1146 if (target
== GL_PROXY_TEXTURE_1D
|| target
== GL_TEXTURE_1D
) {
1147 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1148 level
, internalFormat
,
1150 width
, 1, 1, border
);
1153 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1157 else if (dimensions
== 2) {
1158 if (target
== GL_PROXY_TEXTURE_2D
|| target
== GL_TEXTURE_2D
) {
1159 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1160 level
, internalFormat
,
1162 width
, height
, 1, border
);
1164 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
1165 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1166 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
1167 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1168 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1171 sizeOK
= (width
== height
) &&
1172 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1173 level
, internalFormat
, format
, type
,
1174 width
, height
, 1, border
);
1176 else if (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
||
1177 target
== GL_TEXTURE_RECTANGLE_NV
) {
1178 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1179 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1182 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1183 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1184 level
, internalFormat
,
1186 width
, height
, 1, border
);
1189 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1193 else if (dimensions
== 3) {
1194 if (target
== GL_PROXY_TEXTURE_3D
|| target
== GL_TEXTURE_3D
) {
1195 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_3D
,
1196 level
, internalFormat
,
1198 width
, height
, depth
, border
);
1201 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1206 _mesa_problem( ctx
, "bad dims in texture_error_check" );
1212 _mesa_error(ctx
, GL_INVALID_VALUE
,
1213 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1214 dimensions
, level
, width
, height
, depth
);
1219 /* Check internalFormat */
1220 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1222 _mesa_error(ctx
, GL_INVALID_VALUE
,
1223 "glTexImage%dD(internalFormat=0x%x)",
1224 dimensions
, internalFormat
);
1229 /* Check incoming image format and type */
1230 if (!_mesa_is_legal_format_and_type(format
, type
)) {
1231 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1232 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1235 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1236 "glTexImage%dD(format or type)", dimensions
);
1241 if (format
== GL_YCBCR_MESA
|| internalFormat
== GL_YCBCR_MESA
) {
1242 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1243 if (format
!= GL_YCBCR_MESA
||
1244 internalFormat
!= GL_YCBCR_MESA
||
1245 (type
!= GL_UNSIGNED_SHORT_8_8_MESA
&&
1246 type
!= GL_UNSIGNED_SHORT_8_8_REV_MESA
)) {
1248 _mesa_sprintf(message
,
1249 "glTexImage%d(format/type/internalFormat YCBCR mismatch",
1251 _mesa_error(ctx
, GL_INVALID_ENUM
, message
);
1252 return GL_TRUE
; /* error */
1254 if (target
!= GL_TEXTURE_2D
&&
1255 target
!= GL_PROXY_TEXTURE_2D
&&
1256 target
!= GL_TEXTURE_RECTANGLE_NV
&&
1257 target
!= GL_PROXY_TEXTURE_RECTANGLE_NV
) {
1259 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage(target)");
1265 _mesa_sprintf(message
,
1266 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1267 dimensions
, border
);
1268 _mesa_error(ctx
, GL_INVALID_VALUE
, message
);
1274 if (is_compressed_format(ctx
, internalFormat
)) {
1275 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1278 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1279 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1280 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1281 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1286 _mesa_error(ctx
, GL_INVALID_ENUM
,
1287 "glTexImage%d(target)", dimensions
);
1293 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1294 "glTexImage%D(border!=0)", dimensions
);
1300 /* if we get here, the parameters are OK */
1306 * Test glTexSubImage[123]D() parameters for errors.
1308 * \param ctx GL context.
1309 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1310 * \param target texture target given by the user.
1311 * \param level image level given by the user.
1312 * \param xoffset sub-image x offset given by the user.
1313 * \param yoffset sub-image y offset given by the user.
1314 * \param zoffset sub-image z offset given by the user.
1315 * \param format pixel data format given by the user.
1316 * \param type pixel data type given by the user.
1317 * \param width image width given by the user.
1318 * \param height image height given by the user.
1319 * \param depth image depth given by the user.
1321 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1323 * Verifies each of the parameters against the constants specified in
1324 * __GLcontextRec::Const and the supported extensions, and according to the
1325 * OpenGL specification.
1328 subtexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1329 GLenum target
, GLint level
,
1330 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1331 GLint width
, GLint height
, GLint depth
,
1332 GLenum format
, GLenum type
)
1334 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1335 struct gl_texture_image
*destTex
;
1338 if (dimensions
== 1) {
1339 if (target
!= GL_TEXTURE_1D
) {
1340 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
1344 else if (dimensions
== 2) {
1345 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1346 target
<=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1347 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1348 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1352 else if (ctx
->Extensions
.NV_texture_rectangle
&&
1353 target
== GL_TEXTURE_RECTANGLE_NV
) {
1354 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1355 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1359 else if (target
!= GL_TEXTURE_2D
) {
1360 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1364 else if (dimensions
== 3) {
1365 if (target
!= GL_TEXTURE_3D
) {
1366 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
1371 _mesa_problem( ctx
, "invalid dims in texture_error_check" );
1375 /* Basic level check */
1376 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1377 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level=%d)", level
);
1382 _mesa_error(ctx
, GL_INVALID_VALUE
,
1383 "glTexSubImage%dD(width=%d)", dimensions
, width
);
1386 if (height
< 0 && dimensions
> 1) {
1387 _mesa_error(ctx
, GL_INVALID_VALUE
,
1388 "glTexSubImage%dD(height=%d)", dimensions
, height
);
1391 if (depth
< 0 && dimensions
> 2) {
1392 _mesa_error(ctx
, GL_INVALID_VALUE
,
1393 "glTexSubImage%dD(depth=%d)", dimensions
, depth
);
1397 destTex
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1400 /* undefined image level */
1401 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage%dD", dimensions
);
1405 if (xoffset
< -((GLint
)destTex
->Border
)) {
1406 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset)",
1410 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
1411 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset+width)",
1415 if (dimensions
> 1) {
1416 if (yoffset
< -((GLint
)destTex
->Border
)) {
1417 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset)",
1421 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
1422 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset+height)",
1427 if (dimensions
> 2) {
1428 if (zoffset
< -((GLint
)destTex
->Border
)) {
1429 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
1432 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+ destTex
->Border
)) {
1433 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
1438 if (!_mesa_is_legal_format_and_type(format
, type
)) {
1439 _mesa_error(ctx
, GL_INVALID_ENUM
,
1440 "glTexSubImage%dD(format or type)", dimensions
);
1444 if (destTex
->IsCompressed
) {
1445 const struct gl_texture_unit
*texUnit
;
1446 const struct gl_texture_image
*texImage
;
1447 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1448 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1450 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1453 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1454 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1455 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1456 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1460 _mesa_error(ctx
, GL_INVALID_ENUM
,
1461 "glTexSubImage%D(target)", dimensions
);
1464 /* offset must be multiple of 4 */
1465 if ((xoffset
& 3) || (yoffset
& 3)) {
1466 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1467 "glTexSubImage%D(xoffset or yoffset)", dimensions
);
1470 /* size must be multiple of 4 or equal to whole texture size */
1471 if ((width
& 3) && (GLuint
) width
!= texImage
->Width
) {
1472 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1473 "glTexSubImage%D(width)", dimensions
);
1476 if ((height
& 3) && (GLuint
) height
!= texImage
->Height
) {
1477 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1478 "glTexSubImage%D(width)", dimensions
);
1488 * Test glCopyTexImage[12]D() parameters for errors.
1490 * \param ctx GL context.
1491 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1492 * \param target texture target given by the user.
1493 * \param level image level given by the user.
1494 * \param internalFormat internal format given by the user.
1495 * \param width image width given by the user.
1496 * \param height image height given by the user.
1497 * \param depth image depth given by the user.
1498 * \param border texture border.
1500 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1502 * Verifies each of the parameters against the constants specified in
1503 * __GLcontextRec::Const and the supported extensions, and according to the
1504 * OpenGL specification.
1507 copytexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1508 GLenum target
, GLint level
, GLint internalFormat
,
1509 GLint width
, GLint height
, GLint border
)
1511 GLenum format
, type
;
1514 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1515 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1516 _mesa_error(ctx
, GL_INVALID_VALUE
,
1517 "glCopyTexImage%dD(level=%d)", dimensions
, level
);
1522 if (border
< 0 || border
> 1 ||
1523 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1524 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1528 /* The format and type aren't really significant here, but we need to pass
1529 * something to TestProxyTexImage().
1531 format
= _mesa_base_tex_format(ctx
, internalFormat
);
1534 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1535 * level, width, height and depth.
1537 if (dimensions
== 1) {
1538 if (target
== GL_TEXTURE_1D
) {
1539 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1540 level
, internalFormat
,
1542 width
, 1, 1, border
);
1545 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
1549 else if (dimensions
== 2) {
1550 if (target
== GL_TEXTURE_2D
) {
1551 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1552 level
, internalFormat
,
1554 width
, height
, 1, border
);
1556 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1557 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1558 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1559 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1562 sizeOK
= (width
== height
) &&
1563 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1564 level
, internalFormat
, format
, type
,
1565 width
, height
, 1, border
);
1567 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1568 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1569 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1572 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1573 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1574 level
, internalFormat
,
1576 width
, height
, 1, border
);
1579 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1584 _mesa_problem(ctx
, "invalid dimensions in copytexture_error_check");
1589 if (dimensions
== 1) {
1590 _mesa_error(ctx
, GL_INVALID_VALUE
,
1591 "glCopyTexImage1D(width=%d)", width
);
1594 ASSERT(dimensions
== 2);
1595 _mesa_error(ctx
, GL_INVALID_VALUE
,
1596 "glCopyTexImage2D(width=%d, height=%d)", width
, height
);
1601 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1602 _mesa_error(ctx
, GL_INVALID_VALUE
,
1603 "glCopyTexImage%dD(internalFormat)", dimensions
);
1607 if (is_compressed_format(ctx
, internalFormat
)) {
1608 if (target
!= GL_TEXTURE_2D
) {
1609 _mesa_error(ctx
, GL_INVALID_ENUM
,
1610 "glCopyTexImage%d(target)", dimensions
);
1614 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1615 "glCopyTexImage%D(border!=0)", dimensions
);
1620 /* if we get here, the parameters are OK */
1626 * Test glCopyTexImage[12]D() parameters for errors.
1628 * \param ctx GL context.
1629 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1630 * \param target texture target given by the user.
1631 * \param level image level given by the user.
1632 * \param xoffset sub-image x offset given by the user.
1633 * \param yoffset sub-image y offset given by the user.
1634 * \param zoffset sub-image z offset given by the user.
1635 * \param width image width given by the user.
1636 * \param height image height given by the user.
1638 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1640 * Verifies each of the parameters against the constants specified in
1641 * __GLcontextRec::Const and the supported extensions, and according to the
1642 * OpenGL specification.
1645 copytexsubimage_error_check( GLcontext
*ctx
, GLuint dimensions
,
1646 GLenum target
, GLint level
,
1647 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1648 GLsizei width
, GLsizei height
)
1650 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1651 struct gl_texture_image
*teximage
;
1654 if (dimensions
== 1) {
1655 if (target
!= GL_TEXTURE_1D
) {
1656 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
1660 else if (dimensions
== 2) {
1661 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1662 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1663 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1664 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1668 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1669 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1670 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1674 else if (target
!= GL_TEXTURE_2D
) {
1675 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1679 else if (dimensions
== 3) {
1680 if (target
!= GL_TEXTURE_3D
) {
1681 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
1687 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1688 _mesa_error(ctx
, GL_INVALID_VALUE
,
1689 "glCopyTexSubImage%dD(level=%d)", dimensions
, level
);
1695 _mesa_error(ctx
, GL_INVALID_VALUE
,
1696 "glCopyTexSubImage%dD(width=%d)", dimensions
, width
);
1699 if (dimensions
> 1 && height
< 0) {
1700 _mesa_error(ctx
, GL_INVALID_VALUE
,
1701 "glCopyTexSubImage%dD(height=%d)", dimensions
, height
);
1705 teximage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1707 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1708 "glCopyTexSubImage%dD(undefined texture level: %d)",
1713 if (xoffset
< -((GLint
)teximage
->Border
)) {
1714 _mesa_error(ctx
, GL_INVALID_VALUE
,
1715 "glCopyTexSubImage%dD(xoffset=%d)", dimensions
, xoffset
);
1718 if (xoffset
+ width
> (GLint
) (teximage
->Width
+ teximage
->Border
)) {
1719 _mesa_error(ctx
, GL_INVALID_VALUE
,
1720 "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
1723 if (dimensions
> 1) {
1724 if (yoffset
< -((GLint
)teximage
->Border
)) {
1725 _mesa_error(ctx
, GL_INVALID_VALUE
,
1726 "glCopyTexSubImage%dD(yoffset=%d)", dimensions
, yoffset
);
1729 /* NOTE: we're adding the border here, not subtracting! */
1730 if (yoffset
+ height
> (GLint
) (teximage
->Height
+ teximage
->Border
)) {
1731 _mesa_error(ctx
, GL_INVALID_VALUE
,
1732 "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
1737 if (dimensions
> 2) {
1738 if (zoffset
< -((GLint
)teximage
->Border
)) {
1739 _mesa_error(ctx
, GL_INVALID_VALUE
,
1740 "glCopyTexSubImage%dD(zoffset)", dimensions
);
1743 if (zoffset
> (GLint
) (teximage
->Depth
+ teximage
->Border
)) {
1744 _mesa_error(ctx
, GL_INVALID_VALUE
,
1745 "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
1750 if (teximage
->IsCompressed
) {
1751 if (target
!= GL_TEXTURE_2D
) {
1752 _mesa_error(ctx
, GL_INVALID_ENUM
,
1753 "glCopyTexSubImage%d(target)", dimensions
);
1756 /* offset must be multiple of 4 */
1757 if ((xoffset
& 3) || (yoffset
& 3)) {
1758 _mesa_error(ctx
, GL_INVALID_VALUE
,
1759 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions
);
1762 /* size must be multiple of 4 */
1763 if ((width
& 3) != 0 && (GLuint
) width
!= teximage
->Width
) {
1764 _mesa_error(ctx
, GL_INVALID_VALUE
,
1765 "glCopyTexSubImage%D(width)", dimensions
);
1768 if ((height
& 3) != 0 && (GLuint
) height
!= teximage
->Height
) {
1769 _mesa_error(ctx
, GL_INVALID_VALUE
,
1770 "glCopyTexSubImage%D(height)", dimensions
);
1775 if (teximage
->IntFormat
== GL_YCBCR_MESA
) {
1776 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glCopyTexSubImage2D");
1780 /* if we get here, the parameters are OK */
1786 * Get texture image.
1788 * \param target texture target.
1789 * \param level image level.
1790 * \param format pixel data format.
1791 * \param type pixel data type.
1792 * \param pixels pixel data.
1795 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
1796 GLenum type
, GLvoid
*pixels
)
1798 const struct gl_texture_unit
*texUnit
;
1799 const struct gl_texture_object
*texObj
;
1800 const struct gl_texture_image
*texImage
;
1801 GLint maxLevels
= 0;
1802 GET_CURRENT_CONTEXT(ctx
);
1803 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
1805 texUnit
= &(ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
]);
1806 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
1807 if (!texObj
|| is_proxy_target(target
)) {
1808 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)");
1812 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
1813 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
1815 if (level
< 0 || level
>= maxLevels
) {
1816 _mesa_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
1820 if (_mesa_sizeof_packed_type(type
) <= 0) {
1821 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
1825 if (_mesa_components_in_format(format
) <= 0 ||
1826 format
== GL_STENCIL_INDEX
) {
1827 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
1831 if (!ctx
->Extensions
.EXT_paletted_texture
&& is_index_format(format
)) {
1832 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1835 if (!ctx
->Extensions
.SGIX_depth_texture
&& format
== GL_DEPTH_COMPONENT
) {
1836 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1839 if (!ctx
->Extensions
.MESA_ycbcr_texture
&& format
== GL_YCBCR_MESA
) {
1840 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1843 /* XXX what if format/type doesn't match texture format/type? */
1848 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1850 /* invalid mipmap level, not an error */
1854 if (!texImage
->Data
) {
1855 /* no image data, not an error */
1860 const GLint width
= texImage
->Width
;
1861 const GLint height
= texImage
->Height
;
1862 const GLint depth
= texImage
->Depth
;
1864 for (img
= 0; img
< depth
; img
++) {
1865 for (row
= 0; row
< height
; row
++) {
1866 /* compute destination address in client memory */
1867 GLvoid
*dest
= _mesa_image_address( &ctx
->Pack
, pixels
,
1868 width
, height
, format
, type
,
1872 if (format
== GL_COLOR_INDEX
) {
1873 GLuint indexRow
[MAX_WIDTH
];
1875 for (col
= 0; col
< width
; col
++) {
1876 (*texImage
->FetchTexel
)(texImage
, col
, row
, img
,
1877 (GLvoid
*) &indexRow
[col
]);
1879 _mesa_pack_index_span(ctx
, width
, type
, dest
,
1880 indexRow
, &ctx
->Pack
,
1881 0 /* no image transfer */);
1883 else if (format
== GL_DEPTH_COMPONENT
) {
1884 GLfloat depthRow
[MAX_WIDTH
];
1886 for (col
= 0; col
< width
; col
++) {
1887 (*texImage
->FetchTexel
)(texImage
, col
, row
, img
,
1888 (GLvoid
*) &depthRow
[col
]);
1890 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
1891 depthRow
, &ctx
->Pack
);
1893 else if (format
== GL_YCBCR_MESA
) {
1894 /* No pixel transfer */
1895 const GLint rowstride
= texImage
->RowStride
;
1897 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
1898 width
* sizeof(GLushort
));
1899 /* check for byte swapping */
1900 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
1901 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
1902 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
1903 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
1904 if (!ctx
->Pack
.SwapBytes
)
1905 _mesa_swap2((GLushort
*) dest
, width
);
1907 else if (ctx
->Pack
.SwapBytes
) {
1908 _mesa_swap2((GLushort
*) dest
, width
);
1912 /* general case: convert row to RGBA format */
1913 GLchan rgba
[MAX_WIDTH
][4];
1915 for (col
= 0; col
< width
; col
++) {
1916 (*texImage
->FetchTexel
)(texImage
, col
, row
, img
,
1917 (GLvoid
*) rgba
[col
]);
1919 _mesa_pack_rgba_span(ctx
, width
, (const GLchan (*)[4])rgba
,
1920 format
, type
, dest
, &ctx
->Pack
,
1921 0 /* no image transfer */);
1931 * Called from the API. Note that width includes the border.
1934 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalFormat
,
1935 GLsizei width
, GLint border
, GLenum format
,
1936 GLenum type
, const GLvoid
*pixels
)
1938 GLsizei postConvWidth
= width
;
1939 GET_CURRENT_CONTEXT(ctx
);
1940 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
1942 if (is_color_format(internalFormat
)) {
1943 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
1946 if (target
== GL_TEXTURE_1D
) {
1947 struct gl_texture_unit
*texUnit
;
1948 struct gl_texture_object
*texObj
;
1949 struct gl_texture_image
*texImage
;
1951 if (texture_error_check(ctx
, target
, level
, internalFormat
,
1952 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
1953 return; /* error was recorded */
1956 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1957 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
1958 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
1961 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
1964 else if (texImage
->Data
&& !texImage
->IsClientData
) {
1965 /* free the old texture data */
1966 MESA_PBUFFER_FREE(texImage
->Data
);
1968 texImage
->Data
= NULL
;
1969 clear_teximage_fields(texImage
); /* not really needed, but helpful */
1970 _mesa_init_teximage_fields(ctx
, target
, texImage
,
1971 postConvWidth
, 1, 1,
1972 border
, internalFormat
);
1974 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
1975 _mesa_update_state(ctx
);
1977 ASSERT(ctx
->Driver
.TexImage1D
);
1979 /* Give the texture to the driver! <pixels> may be null! */
1980 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
1981 width
, border
, format
, type
, pixels
,
1982 &ctx
->Unpack
, texObj
, texImage
);
1984 ASSERT(texImage
->TexFormat
);
1985 if (!texImage
->FetchTexel
) {
1986 /* If driver didn't explicitly set this, use the default */
1987 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel1D
;
1989 ASSERT(texImage
->FetchTexel
);
1992 texObj
->Complete
= GL_FALSE
;
1993 ctx
->NewState
|= _NEW_TEXTURE
;
1995 else if (target
== GL_PROXY_TEXTURE_1D
) {
1996 /* Proxy texture: check for errors and update proxy state */
1997 struct gl_texture_image
*texImage
;
1998 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
1999 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2000 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2001 /* when error, clear all proxy texture image parameters */
2003 clear_teximage_fields(texImage
);
2006 /* no error, set the tex image parameters */
2008 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2009 postConvWidth
, 1, 1,
2010 border
, internalFormat
);
2011 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2012 internalFormat
, format
, type
);
2016 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
2023 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalFormat
,
2024 GLsizei width
, GLsizei height
, GLint border
,
2025 GLenum format
, GLenum type
,
2026 const GLvoid
*pixels
)
2028 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2029 GET_CURRENT_CONTEXT(ctx
);
2030 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2032 if (is_color_format(internalFormat
)) {
2033 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2037 if (target
== GL_TEXTURE_2D
||
2038 (ctx
->Extensions
.ARB_texture_cube_map
&&
2039 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2040 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) ||
2041 (ctx
->Extensions
.NV_texture_rectangle
&&
2042 target
== GL_TEXTURE_RECTANGLE_NV
)) {
2043 /* non-proxy target */
2044 struct gl_texture_unit
*texUnit
;
2045 struct gl_texture_object
*texObj
;
2046 struct gl_texture_image
*texImage
;
2048 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2049 format
, type
, 2, postConvWidth
, postConvHeight
,
2051 return; /* error was recorded */
2054 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2055 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2056 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2058 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2061 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2062 /* free the old texture data */
2063 MESA_PBUFFER_FREE(texImage
->Data
);
2065 texImage
->Data
= NULL
;
2066 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2067 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2068 postConvWidth
, postConvHeight
, 1,
2069 border
, internalFormat
);
2071 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2072 _mesa_update_state(ctx
);
2074 ASSERT(ctx
->Driver
.TexImage2D
);
2076 /* Give the texture to the driver! <pixels> may be null! */
2077 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
2078 width
, height
, border
, format
, type
, pixels
,
2079 &ctx
->Unpack
, texObj
, texImage
);
2081 ASSERT(texImage
->TexFormat
);
2082 if (!texImage
->FetchTexel
) {
2083 /* If driver didn't explicitly set this, use the default */
2084 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel2D
;
2086 ASSERT(texImage
->FetchTexel
);
2089 texObj
->Complete
= GL_FALSE
;
2090 ctx
->NewState
|= _NEW_TEXTURE
;
2092 else if (target
== GL_PROXY_TEXTURE_2D
||
2093 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2094 ctx
->Extensions
.ARB_texture_cube_map
) ||
2095 (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
&&
2096 ctx
->Extensions
.NV_texture_rectangle
)) {
2097 /* Proxy texture: check for errors and update proxy state */
2098 struct gl_texture_image
*texImage
;
2099 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2100 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2101 format
, type
, 2, postConvWidth
, postConvHeight
,
2103 /* when error, clear all proxy texture image parameters */
2105 clear_teximage_fields(ctx
->Texture
.Proxy2D
->Image
[level
]);
2108 /* no error, set the tex image parameters */
2109 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2110 postConvWidth
, postConvHeight
, 1,
2111 border
, internalFormat
);
2112 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2113 internalFormat
, format
, type
);
2117 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
2124 * Called by the API or display list executor.
2125 * Note that width and height include the border.
2128 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalFormat
,
2129 GLsizei width
, GLsizei height
, GLsizei depth
,
2130 GLint border
, GLenum format
, GLenum type
,
2131 const GLvoid
*pixels
)
2133 GET_CURRENT_CONTEXT(ctx
);
2134 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2136 if (target
== GL_TEXTURE_3D
) {
2137 struct gl_texture_unit
*texUnit
;
2138 struct gl_texture_object
*texObj
;
2139 struct gl_texture_image
*texImage
;
2141 if (texture_error_check(ctx
, target
, level
, (GLint
) internalFormat
,
2142 format
, type
, 3, width
, height
, depth
, border
)) {
2143 return; /* error was recorded */
2146 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2147 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2148 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2150 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2153 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2154 MESA_PBUFFER_FREE(texImage
->Data
);
2156 texImage
->Data
= NULL
;
2157 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2158 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2159 width
, height
, depth
,
2160 border
, internalFormat
);
2162 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2163 _mesa_update_state(ctx
);
2165 ASSERT(ctx
->Driver
.TexImage3D
);
2167 /* Give the texture to the driver! <pixels> may be null! */
2168 (*ctx
->Driver
.TexImage3D
)(ctx
, target
, level
, internalFormat
,
2169 width
, height
, depth
, border
, format
, type
,
2170 pixels
, &ctx
->Unpack
, texObj
, texImage
);
2172 ASSERT(texImage
->TexFormat
);
2173 if (!texImage
->FetchTexel
) {
2174 /* If driver didn't explicitly set this, use the default */
2175 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel3D
;
2177 ASSERT(texImage
->FetchTexel
);
2180 texObj
->Complete
= GL_FALSE
;
2181 ctx
->NewState
|= _NEW_TEXTURE
;
2183 else if (target
== GL_PROXY_TEXTURE_3D
) {
2184 /* Proxy texture: check for errors and update proxy state */
2185 struct gl_texture_image
*texImage
;
2186 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2187 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2188 format
, type
, 3, width
, height
, depth
, border
)) {
2189 /* when error, clear all proxy texture image parameters */
2191 clear_teximage_fields(texImage
);
2194 /* no error, set the tex image parameters */
2195 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2196 border
, internalFormat
);
2197 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2198 internalFormat
, format
, type
);
2202 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
2209 _mesa_TexImage3DEXT( GLenum target
, GLint level
, GLenum internalFormat
,
2210 GLsizei width
, GLsizei height
, GLsizei depth
,
2211 GLint border
, GLenum format
, GLenum type
,
2212 const GLvoid
*pixels
)
2214 _mesa_TexImage3D(target
, level
, (GLint
) internalFormat
, width
, height
,
2215 depth
, border
, format
, type
, pixels
);
2221 _mesa_TexSubImage1D( GLenum target
, GLint level
,
2222 GLint xoffset
, GLsizei width
,
2223 GLenum format
, GLenum type
,
2224 const GLvoid
*pixels
)
2226 GLsizei postConvWidth
= width
;
2227 struct gl_texture_unit
*texUnit
;
2228 struct gl_texture_object
*texObj
;
2229 struct gl_texture_image
*texImage
;
2230 GET_CURRENT_CONTEXT(ctx
);
2231 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2233 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2234 _mesa_update_state(ctx
);
2236 /* XXX should test internal format */
2237 if (is_color_format(format
)) {
2238 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2241 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
2242 postConvWidth
, 1, 1, format
, type
)) {
2243 return; /* error was detected */
2246 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2247 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2248 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2251 if (width
== 0 || !pixels
)
2252 return; /* no-op, not an error */
2254 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2255 xoffset
+= texImage
->Border
;
2257 ASSERT(ctx
->Driver
.TexSubImage1D
);
2258 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
2259 format
, type
, pixels
, &ctx
->Unpack
,
2261 ctx
->NewState
|= _NEW_TEXTURE
;
2266 _mesa_TexSubImage2D( GLenum target
, GLint level
,
2267 GLint xoffset
, GLint yoffset
,
2268 GLsizei width
, GLsizei height
,
2269 GLenum format
, GLenum type
,
2270 const GLvoid
*pixels
)
2272 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2273 struct gl_texture_unit
*texUnit
;
2274 struct gl_texture_object
*texObj
;
2275 struct gl_texture_image
*texImage
;
2276 GET_CURRENT_CONTEXT(ctx
);
2277 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2279 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2280 _mesa_update_state(ctx
);
2282 /* XXX should test internal format */
2283 if (is_color_format(format
)) {
2284 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2288 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2289 postConvWidth
, postConvHeight
, 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 || height
== 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
;
2303 yoffset
+= texImage
->Border
;
2305 ASSERT(ctx
->Driver
.TexSubImage2D
);
2306 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
, xoffset
, yoffset
,
2307 width
, height
, format
, type
, pixels
,
2308 &ctx
->Unpack
, texObj
, texImage
);
2309 ctx
->NewState
|= _NEW_TEXTURE
;
2315 _mesa_TexSubImage3D( GLenum target
, GLint level
,
2316 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2317 GLsizei width
, GLsizei height
, GLsizei depth
,
2318 GLenum format
, GLenum type
,
2319 const GLvoid
*pixels
)
2321 struct gl_texture_unit
*texUnit
;
2322 struct gl_texture_object
*texObj
;
2323 struct gl_texture_image
*texImage
;
2324 GET_CURRENT_CONTEXT(ctx
);
2325 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2327 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2328 _mesa_update_state(ctx
);
2330 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2331 width
, height
, depth
, format
, type
)) {
2332 return; /* error was detected */
2335 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2336 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2337 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2340 if (width
== 0 || height
== 0 || height
== 0 || !pixels
)
2341 return; /* no-op, not an error */
2343 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2344 xoffset
+= texImage
->Border
;
2345 yoffset
+= texImage
->Border
;
2346 zoffset
+= texImage
->Border
;
2348 ASSERT(ctx
->Driver
.TexSubImage3D
);
2349 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
2350 xoffset
, yoffset
, zoffset
,
2351 width
, height
, depth
,
2352 format
, type
, pixels
,
2353 &ctx
->Unpack
, texObj
, texImage
);
2354 ctx
->NewState
|= _NEW_TEXTURE
;
2360 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
2361 GLenum internalFormat
,
2363 GLsizei width
, GLint border
)
2365 struct gl_texture_unit
*texUnit
;
2366 struct gl_texture_object
*texObj
;
2367 struct gl_texture_image
*texImage
;
2368 GLsizei postConvWidth
= width
;
2369 GET_CURRENT_CONTEXT(ctx
);
2370 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2372 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2373 _mesa_update_state(ctx
);
2375 if (is_color_format(internalFormat
)) {
2376 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2379 if (copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
2380 postConvWidth
, 1, border
))
2383 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2384 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2385 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2387 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
2390 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2391 /* free the old texture data */
2392 MESA_PBUFFER_FREE(texImage
->Data
);
2394 texImage
->Data
= NULL
;
2396 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2397 _mesa_init_teximage_fields(ctx
, target
, texImage
, postConvWidth
, 1, 1,
2398 border
, internalFormat
);
2401 ASSERT(ctx
->Driver
.CopyTexImage1D
);
2402 (*ctx
->Driver
.CopyTexImage1D
)(ctx
, target
, level
, internalFormat
,
2403 x
, y
, width
, border
);
2405 ASSERT(texImage
->TexFormat
);
2406 if (!texImage
->FetchTexel
) {
2407 /* If driver didn't explicitly set this, use the default */
2408 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel1D
;
2410 ASSERT(texImage
->FetchTexel
);
2413 texObj
->Complete
= GL_FALSE
;
2414 ctx
->NewState
|= _NEW_TEXTURE
;
2420 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
2421 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2424 struct gl_texture_unit
*texUnit
;
2425 struct gl_texture_object
*texObj
;
2426 struct gl_texture_image
*texImage
;
2427 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2428 GET_CURRENT_CONTEXT(ctx
);
2429 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2431 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2432 _mesa_update_state(ctx
);
2434 if (is_color_format(internalFormat
)) {
2435 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2439 if (copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
2440 postConvWidth
, postConvHeight
, border
))
2443 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2444 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2445 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2447 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
2450 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2451 /* free the old texture data */
2452 MESA_PBUFFER_FREE(texImage
->Data
);
2454 texImage
->Data
= NULL
;
2456 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2457 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2458 postConvWidth
, postConvHeight
, 1,
2459 border
, internalFormat
);
2461 ASSERT(ctx
->Driver
.CopyTexImage2D
);
2462 (*ctx
->Driver
.CopyTexImage2D
)(ctx
, target
, level
, internalFormat
,
2463 x
, y
, width
, height
, border
);
2465 ASSERT(texImage
->TexFormat
);
2466 if (!texImage
->FetchTexel
) {
2467 /* If driver didn't explicitly set this, use the default */
2468 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel2D
;
2470 ASSERT(texImage
->FetchTexel
);
2473 texObj
->Complete
= GL_FALSE
;
2474 ctx
->NewState
|= _NEW_TEXTURE
;
2480 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
2481 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
2483 struct gl_texture_unit
*texUnit
;
2484 struct gl_texture_object
*texObj
;
2485 struct gl_texture_image
*texImage
;
2486 GLsizei postConvWidth
= width
;
2487 GET_CURRENT_CONTEXT(ctx
);
2488 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2490 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2491 _mesa_update_state(ctx
);
2493 /* XXX should test internal format */
2494 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2496 if (copytexsubimage_error_check(ctx
, 1, target
, level
,
2497 xoffset
, 0, 0, postConvWidth
, 1))
2500 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2501 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2502 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2505 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2506 xoffset
+= texImage
->Border
;
2508 ASSERT(ctx
->Driver
.CopyTexSubImage1D
);
2509 (*ctx
->Driver
.CopyTexSubImage1D
)(ctx
, target
, level
, xoffset
, x
, y
, width
);
2510 ctx
->NewState
|= _NEW_TEXTURE
;
2516 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
2517 GLint xoffset
, GLint yoffset
,
2518 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2520 struct gl_texture_unit
*texUnit
;
2521 struct gl_texture_object
*texObj
;
2522 struct gl_texture_image
*texImage
;
2523 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2524 GET_CURRENT_CONTEXT(ctx
);
2525 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2527 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2528 _mesa_update_state(ctx
);
2530 /* XXX should test internal format */
2531 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2533 if (copytexsubimage_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2534 postConvWidth
, postConvHeight
))
2537 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2538 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2539 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2542 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2543 xoffset
+= texImage
->Border
;
2544 yoffset
+= texImage
->Border
;
2546 ASSERT(ctx
->Driver
.CopyTexSubImage2D
);
2547 (*ctx
->Driver
.CopyTexSubImage2D
)(ctx
, target
, level
,
2548 xoffset
, yoffset
, x
, y
, width
, height
);
2549 ctx
->NewState
|= _NEW_TEXTURE
;
2555 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
2556 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2557 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2559 struct gl_texture_unit
*texUnit
;
2560 struct gl_texture_object
*texObj
;
2561 struct gl_texture_image
*texImage
;
2562 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2563 GET_CURRENT_CONTEXT(ctx
);
2564 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2566 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2567 _mesa_update_state(ctx
);
2569 /* XXX should test internal format */
2570 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2572 if (copytexsubimage_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
,
2573 zoffset
, postConvWidth
, postConvHeight
))
2576 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2577 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2578 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2581 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2582 xoffset
+= texImage
->Border
;
2583 yoffset
+= texImage
->Border
;
2584 zoffset
+= texImage
->Border
;
2586 ASSERT(ctx
->Driver
.CopyTexSubImage3D
);
2587 (*ctx
->Driver
.CopyTexSubImage3D
)(ctx
, target
, level
,
2588 xoffset
, yoffset
, zoffset
,
2589 x
, y
, width
, height
);
2590 ctx
->NewState
|= _NEW_TEXTURE
;
2596 /**********************************************************************/
2597 /****** Compressed Textures ******/
2598 /**********************************************************************/
2602 * Error checking for glCompressedTexImage[123]D().
2603 * \return error code or GL_NO_ERROR.
2606 compressed_texture_error_check(GLcontext
*ctx
, GLint dimensions
,
2607 GLenum target
, GLint level
,
2608 GLenum internalFormat
, GLsizei width
,
2609 GLsizei height
, GLsizei depth
, GLint border
,
2612 GLboolean isProxy
= GL_FALSE
;
2613 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2615 if (dimensions
== 1) {
2616 /* 1D compressed textures not allowed */
2617 return GL_INVALID_ENUM
;
2619 else if (dimensions
== 2) {
2620 if (target
== GL_PROXY_TEXTURE_2D
) {
2621 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2624 else if (target
== GL_TEXTURE_2D
) {
2625 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2627 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2628 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2629 return GL_INVALID_ENUM
; /*target*/
2630 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2633 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2634 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2635 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2636 return GL_INVALID_ENUM
; /*target*/
2637 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2640 return GL_INVALID_ENUM
; /*target*/
2643 else if (dimensions
== 3) {
2644 /* 3D compressed textures not allowed */
2645 return GL_INVALID_ENUM
;
2648 maxTextureSize
= 1 << (maxLevels
- 1);
2650 if (!is_compressed_format(ctx
, internalFormat
))
2651 return GL_INVALID_ENUM
;
2654 return GL_INVALID_VALUE
;
2657 * XXX We should probably use the proxy texture error check function here.
2659 if (width
< 1 || width
> maxTextureSize
||
2660 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(width
) < 0))
2661 return GL_INVALID_VALUE
;
2663 if ((height
< 1 || height
> maxTextureSize
||
2664 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(height
) < 0))
2666 return GL_INVALID_VALUE
;
2668 if ((depth
< 1 || depth
> maxTextureSize
||
2669 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(depth
) < 0))
2671 return GL_INVALID_VALUE
;
2673 /* For cube map, width must equal height */
2674 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2675 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
&& width
!= height
)
2676 return GL_INVALID_VALUE
;
2678 if (level
< 0 || level
>= maxLevels
)
2679 return GL_INVALID_VALUE
;
2681 expectedSize
= _mesa_compressed_texture_size(ctx
, width
, height
, depth
,
2683 if (expectedSize
!= imageSize
)
2684 return GL_INVALID_VALUE
;
2691 * Error checking for glCompressedTexSubImage[123]D().
2692 * \return error code or GL_NO_ERROR.
2695 compressed_subtexture_error_check(GLcontext
*ctx
, GLint dimensions
,
2696 GLenum target
, GLint level
,
2697 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2698 GLsizei width
, GLsizei height
, GLsizei depth
,
2699 GLenum format
, GLsizei imageSize
)
2701 GLboolean isProxy
= GL_FALSE
;
2702 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2704 if (dimensions
== 1) {
2705 /* 1D compressed textures not allowed */
2706 return GL_INVALID_ENUM
;
2708 else if (dimensions
== 2) {
2709 if (target
== GL_PROXY_TEXTURE_2D
) {
2710 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2713 else if (target
== GL_TEXTURE_2D
) {
2714 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2716 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2717 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2718 return GL_INVALID_ENUM
; /*target*/
2719 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2722 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2723 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2724 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2725 return GL_INVALID_ENUM
; /*target*/
2726 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2729 return GL_INVALID_ENUM
; /*target*/
2732 else if (dimensions
== 3) {
2733 /* 3D compressed textures not allowed */
2734 return GL_INVALID_ENUM
;
2737 maxTextureSize
= 1 << (maxLevels
- 1);
2739 if (!is_compressed_format(ctx
, format
))
2740 return GL_INVALID_ENUM
;
2742 if (width
< 1 || width
> maxTextureSize
)
2743 return GL_INVALID_VALUE
;
2745 if ((height
< 1 || height
> maxTextureSize
)
2747 return GL_INVALID_VALUE
;
2749 if (level
< 0 || level
>= maxLevels
)
2750 return GL_INVALID_VALUE
;
2752 if ((xoffset
& 3) != 0 || (yoffset
& 3) != 0)
2753 return GL_INVALID_VALUE
;
2755 if ((width
& 3) != 0 && width
!= 2 && width
!= 1)
2756 return GL_INVALID_VALUE
;
2758 if ((height
& 3) != 0 && height
!= 2 && height
!= 1)
2759 return GL_INVALID_VALUE
;
2761 expectedSize
= _mesa_compressed_texture_size(ctx
, width
, height
, depth
,
2763 if (expectedSize
!= imageSize
)
2764 return GL_INVALID_VALUE
;
2772 _mesa_CompressedTexImage1DARB(GLenum target
, GLint level
,
2773 GLenum internalFormat
, GLsizei width
,
2774 GLint border
, GLsizei imageSize
,
2777 GET_CURRENT_CONTEXT(ctx
);
2778 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2780 if (target
== GL_TEXTURE_1D
) {
2781 struct gl_texture_unit
*texUnit
;
2782 struct gl_texture_object
*texObj
;
2783 struct gl_texture_image
*texImage
;
2784 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
2785 internalFormat
, width
, 1, 1, border
, imageSize
);
2787 _mesa_error(ctx
, error
, "glCompressedTexImage1D");
2791 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2792 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2793 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2795 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage1D");
2798 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2799 MESA_PBUFFER_FREE(texImage
->Data
);
2801 texImage
->Data
= NULL
;
2803 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
2804 border
, internalFormat
);
2806 ASSERT(ctx
->Driver
.CompressedTexImage1D
);
2807 (*ctx
->Driver
.CompressedTexImage1D
)(ctx
, target
, level
,
2808 internalFormat
, width
, border
,
2813 texObj
->Complete
= GL_FALSE
;
2814 ctx
->NewState
|= _NEW_TEXTURE
;
2816 else if (target
== GL_PROXY_TEXTURE_1D
) {
2817 /* Proxy texture: check for errors and update proxy state */
2818 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
2819 internalFormat
, width
, 1, 1, border
, imageSize
);
2821 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2822 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2823 internalFormat
, GL_NONE
, GL_NONE
,
2824 width
, 1, 1, border
);
2827 /* if error, clear all proxy texture image parameters */
2828 struct gl_texture_image
*texImage
;
2829 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2831 clear_teximage_fields(texImage
);
2834 /* store the teximage parameters */
2835 struct gl_texture_unit
*texUnit
;
2836 struct gl_texture_image
*texImage
;
2837 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2838 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2839 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
2840 border
, internalFormat
);
2844 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage1D(target)");
2851 _mesa_CompressedTexImage2DARB(GLenum target
, GLint level
,
2852 GLenum internalFormat
, GLsizei width
,
2853 GLsizei height
, GLint border
, GLsizei imageSize
,
2856 GET_CURRENT_CONTEXT(ctx
);
2857 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2859 if (target
== GL_TEXTURE_2D
||
2860 (ctx
->Extensions
.ARB_texture_cube_map
&&
2861 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2862 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
2863 struct gl_texture_unit
*texUnit
;
2864 struct gl_texture_object
*texObj
;
2865 struct gl_texture_image
*texImage
;
2866 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
2867 internalFormat
, width
, height
, 1, border
, imageSize
);
2869 _mesa_error(ctx
, error
, "glCompressedTexImage2D");
2873 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2874 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2875 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2877 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
2880 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2881 MESA_PBUFFER_FREE(texImage
->Data
);
2883 texImage
->Data
= NULL
;
2885 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2886 border
, internalFormat
);
2888 ASSERT(ctx
->Driver
.CompressedTexImage2D
);
2889 (*ctx
->Driver
.CompressedTexImage2D
)(ctx
, target
, level
,
2890 internalFormat
, width
, height
,
2891 border
, imageSize
, data
,
2895 texObj
->Complete
= GL_FALSE
;
2896 ctx
->NewState
|= _NEW_TEXTURE
;
2898 else if (target
== GL_PROXY_TEXTURE_2D
||
2899 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2900 ctx
->Extensions
.ARB_texture_cube_map
)) {
2901 /* Proxy texture: check for errors and update proxy state */
2902 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
2903 internalFormat
, width
, height
, 1, border
, imageSize
);
2905 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2906 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2907 internalFormat
, GL_NONE
, GL_NONE
,
2908 width
, height
, 1, border
);
2911 /* if error, clear all proxy texture image parameters */
2912 struct gl_texture_image
*texImage
;
2913 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2915 clear_teximage_fields(texImage
);
2918 /* store the teximage parameters */
2919 struct gl_texture_unit
*texUnit
;
2920 struct gl_texture_image
*texImage
;
2921 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2922 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2923 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2924 border
, internalFormat
);
2928 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(target)");
2935 _mesa_CompressedTexImage3DARB(GLenum target
, GLint level
,
2936 GLenum internalFormat
, GLsizei width
,
2937 GLsizei height
, GLsizei depth
, GLint border
,
2938 GLsizei imageSize
, const GLvoid
*data
)
2940 GET_CURRENT_CONTEXT(ctx
);
2941 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2943 if (target
== GL_TEXTURE_3D
) {
2944 struct gl_texture_unit
*texUnit
;
2945 struct gl_texture_object
*texObj
;
2946 struct gl_texture_image
*texImage
;
2947 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
2948 internalFormat
, width
, height
, depth
, border
, imageSize
);
2950 _mesa_error(ctx
, error
, "glCompressedTexImage3D");
2954 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2955 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2956 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2958 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage3D");
2961 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2962 MESA_PBUFFER_FREE(texImage
->Data
);
2964 texImage
->Data
= NULL
;
2966 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, depth
,
2967 border
, internalFormat
);
2969 ASSERT(ctx
->Driver
.CompressedTexImage3D
);
2970 (*ctx
->Driver
.CompressedTexImage3D
)(ctx
, target
, level
,
2972 width
, height
, depth
,
2973 border
, imageSize
, data
,
2977 texObj
->Complete
= GL_FALSE
;
2978 ctx
->NewState
|= _NEW_TEXTURE
;
2980 else if (target
== GL_PROXY_TEXTURE_3D
) {
2981 /* Proxy texture: check for errors and update proxy state */
2982 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
2983 internalFormat
, width
, height
, depth
, border
, imageSize
);
2985 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2986 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2987 internalFormat
, GL_NONE
, GL_NONE
,
2988 width
, height
, depth
, border
);
2991 /* if error, clear all proxy texture image parameters */
2992 struct gl_texture_image
*texImage
;
2993 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2995 clear_teximage_fields(texImage
);
2998 /* store the teximage parameters */
2999 struct gl_texture_unit
*texUnit
;
3000 struct gl_texture_image
*texImage
;
3001 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3002 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3003 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
,
3004 depth
, border
, internalFormat
);
3008 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage3D(target)");
3015 _mesa_CompressedTexSubImage1DARB(GLenum target
, GLint level
, GLint xoffset
,
3016 GLsizei width
, GLenum format
,
3017 GLsizei imageSize
, const GLvoid
*data
)
3019 struct gl_texture_unit
*texUnit
;
3020 struct gl_texture_object
*texObj
;
3021 struct gl_texture_image
*texImage
;
3023 GET_CURRENT_CONTEXT(ctx
);
3024 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3026 error
= compressed_subtexture_error_check(ctx
, 1, target
, level
,
3027 xoffset
, 0, 0, width
, 1, 1, format
, imageSize
);
3029 _mesa_error(ctx
, error
, "glCompressedTexSubImage1D");
3033 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3034 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3035 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3038 if ((GLint
) format
!= texImage
->IntFormat
) {
3039 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3040 "glCompressedTexSubImage1D(format)");
3044 if ((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) {
3045 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage1D(width)");
3049 if (width
== 0 || !data
)
3050 return; /* no-op, not an error */
3052 if (ctx
->Driver
.CompressedTexSubImage1D
) {
3053 (*ctx
->Driver
.CompressedTexSubImage1D
)(ctx
, target
, level
,
3055 format
, imageSize
, data
,
3058 ctx
->NewState
|= _NEW_TEXTURE
;
3063 _mesa_CompressedTexSubImage2DARB(GLenum target
, GLint level
, GLint xoffset
,
3064 GLint yoffset
, GLsizei width
, GLsizei height
,
3065 GLenum format
, GLsizei imageSize
,
3068 struct gl_texture_unit
*texUnit
;
3069 struct gl_texture_object
*texObj
;
3070 struct gl_texture_image
*texImage
;
3072 GET_CURRENT_CONTEXT(ctx
);
3073 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3075 error
= compressed_subtexture_error_check(ctx
, 2, target
, level
,
3076 xoffset
, yoffset
, 0, width
, height
, 1, format
, imageSize
);
3078 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3082 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3083 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3084 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3087 if ((GLint
) format
!= texImage
->IntFormat
) {
3088 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3089 "glCompressedTexSubImage2D(format)");
3093 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3094 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
)) {
3095 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage2D(size)");
3099 if (width
== 0 || height
== 0 || !data
)
3100 return; /* no-op, not an error */
3102 if (ctx
->Driver
.CompressedTexSubImage2D
) {
3103 (*ctx
->Driver
.CompressedTexSubImage2D
)(ctx
, target
, level
,
3104 xoffset
, yoffset
, width
, height
,
3105 format
, imageSize
, data
,
3108 ctx
->NewState
|= _NEW_TEXTURE
;
3113 _mesa_CompressedTexSubImage3DARB(GLenum target
, GLint level
, GLint xoffset
,
3114 GLint yoffset
, GLint zoffset
, GLsizei width
,
3115 GLsizei height
, GLsizei depth
, GLenum format
,
3116 GLsizei imageSize
, const GLvoid
*data
)
3118 struct gl_texture_unit
*texUnit
;
3119 struct gl_texture_object
*texObj
;
3120 struct gl_texture_image
*texImage
;
3122 GET_CURRENT_CONTEXT(ctx
);
3123 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3125 error
= compressed_subtexture_error_check(ctx
, 3, target
, level
,
3126 xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
, imageSize
);
3128 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3132 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3133 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3134 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3137 if ((GLint
) format
!= texImage
->IntFormat
) {
3138 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3139 "glCompressedTexSubImage3D(format)");
3143 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3144 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
) ||
3145 ((depth
== 1 || depth
== 2) && (GLuint
) depth
!= texImage
->Depth
)) {
3146 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage3D(size)");
3150 if (width
== 0 || height
== 0 || depth
== 0 || !data
)
3151 return; /* no-op, not an error */
3153 if (ctx
->Driver
.CompressedTexSubImage3D
) {
3154 (*ctx
->Driver
.CompressedTexSubImage3D
)(ctx
, target
, level
,
3155 xoffset
, yoffset
, zoffset
,
3156 width
, height
, depth
,
3157 format
, imageSize
, data
,
3160 ctx
->NewState
|= _NEW_TEXTURE
;
3165 _mesa_GetCompressedTexImageARB(GLenum target
, GLint level
, GLvoid
*img
)
3167 const struct gl_texture_unit
*texUnit
;
3168 const struct gl_texture_object
*texObj
;
3169 struct gl_texture_image
*texImage
;
3171 GET_CURRENT_CONTEXT(ctx
);
3172 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3174 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3175 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3177 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB");
3181 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
3182 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
3184 if (level
< 0 || level
>= maxLevels
) {
3185 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3189 if (is_proxy_target(target
)) {
3190 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
3194 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3196 /* probably invalid mipmap level */
3197 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3201 if (!texImage
->IsCompressed
) {
3202 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetCompressedTexImageARB");
3209 /* just memcpy, no pixelstore or pixel transfer */
3210 MEMCPY(img
, texImage
->Data
, texImage
->CompressedSize
);