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
;
206 if (ctx
->Extensions
.EXT_paletted_texture
) {
207 switch (internalFormat
) {
209 case GL_COLOR_INDEX1_EXT
:
210 case GL_COLOR_INDEX2_EXT
:
211 case GL_COLOR_INDEX4_EXT
:
212 case GL_COLOR_INDEX8_EXT
:
213 case GL_COLOR_INDEX12_EXT
:
214 case GL_COLOR_INDEX16_EXT
:
215 return GL_COLOR_INDEX
;
221 if (ctx
->Extensions
.SGIX_depth_texture
) {
222 switch (internalFormat
) {
223 case GL_DEPTH_COMPONENT
:
224 case GL_DEPTH_COMPONENT16_SGIX
:
225 case GL_DEPTH_COMPONENT24_SGIX
:
226 case GL_DEPTH_COMPONENT32_SGIX
:
227 return GL_DEPTH_COMPONENT
;
233 if (ctx
->Extensions
.ARB_texture_compression
) {
234 switch (internalFormat
) {
235 case GL_COMPRESSED_ALPHA
:
237 case GL_COMPRESSED_LUMINANCE
:
239 case GL_COMPRESSED_LUMINANCE_ALPHA
:
240 return GL_LUMINANCE_ALPHA
;
241 case GL_COMPRESSED_INTENSITY
:
243 case GL_COMPRESSED_RGB
:
245 case GL_COMPRESSED_RGBA
:
252 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
) {
253 switch (internalFormat
) {
254 case GL_COMPRESSED_RGB_FXT1_3DFX
:
256 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
263 if (ctx
->Extensions
.EXT_texture_compression_s3tc
) {
264 switch (internalFormat
) {
265 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
267 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
268 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
269 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
276 if (ctx
->Extensions
.S3_s3tc
) {
277 switch (internalFormat
) {
289 if (ctx
->Extensions
.MESA_ycbcr_texture
) {
290 if (internalFormat
== GL_YCBCR_MESA
)
291 return GL_YCBCR_MESA
;
294 if (ctx
->Extensions
.ARB_texture_float
) {
295 switch (internalFormat
) {
296 case GL_ALPHA16F_ARB
:
297 case GL_ALPHA32F_ARB
:
305 case GL_INTENSITY16F_ARB
:
306 case GL_INTENSITY32F_ARB
:
308 case GL_LUMINANCE16F_ARB
:
309 case GL_LUMINANCE32F_ARB
:
311 case GL_LUMINANCE_ALPHA16F_ARB
:
312 case GL_LUMINANCE_ALPHA32F_ARB
:
313 return GL_LUMINANCE_ALPHA
;
319 return -1; /* error */
324 * Test if the given internal texture format is a color/RGBA format
325 * (i.e., not color index, depth, stencil, etc).
326 * \param internalFormat an internal texture format token (or 1, 2, 3, or 4)
327 * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
330 is_color_format(GLenum internalFormat
)
332 switch (internalFormat
) {
345 case GL_LUMINANCE_ALPHA
:
346 case GL_LUMINANCE4_ALPHA4
:
347 case GL_LUMINANCE6_ALPHA2
:
348 case GL_LUMINANCE8_ALPHA8
:
349 case GL_LUMINANCE12_ALPHA4
:
350 case GL_LUMINANCE12_ALPHA12
:
351 case GL_LUMINANCE16_ALPHA16
:
375 /* float texture formats */
376 case GL_ALPHA16F_ARB
:
377 case GL_ALPHA32F_ARB
:
378 case GL_LUMINANCE16F_ARB
:
379 case GL_LUMINANCE32F_ARB
:
380 case GL_LUMINANCE_ALPHA16F_ARB
:
381 case GL_LUMINANCE_ALPHA32F_ARB
:
382 case GL_INTENSITY16F_ARB
:
383 case GL_INTENSITY32F_ARB
:
389 case GL_YCBCR_MESA
: /* not considered to be RGB */
397 * Test if the given internal texture format is a color index format.
400 is_index_format(GLenum internalFormat
)
402 switch (internalFormat
) {
404 case GL_COLOR_INDEX1_EXT
:
405 case GL_COLOR_INDEX2_EXT
:
406 case GL_COLOR_INDEX4_EXT
:
407 case GL_COLOR_INDEX8_EXT
:
408 case GL_COLOR_INDEX12_EXT
:
409 case GL_COLOR_INDEX16_EXT
:
418 * Test if the given internal texture format is a depth component format.
421 is_depth_format(GLenum internalFormat
)
423 switch (internalFormat
) {
424 case GL_DEPTH_COMPONENT16_ARB
:
425 case GL_DEPTH_COMPONENT24_ARB
:
426 case GL_DEPTH_COMPONENT32_ARB
:
427 case GL_DEPTH_COMPONENT
:
436 * Test if the given internal texture format is a YCbCr format.
439 is_ycbcr_format(GLenum internalFormat
)
441 switch (internalFormat
) {
451 * Test if it is a supported compressed format.
453 * \param internalFormat the internal format token provided by the user.
455 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
456 * GL_FALSE otherwise.
458 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
462 is_compressed_format(GLcontext
*ctx
, GLenum internalFormat
)
464 switch (internalFormat
) {
465 case GL_COMPRESSED_RGB_FXT1_3DFX
:
466 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
467 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
468 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
469 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
470 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
483 * Store a gl_texture_image pointer in a gl_texture_object structure
484 * according to the target and level parameters.
486 * \param tObj texture object.
487 * \param target texture target.
488 * \param level image level.
489 * \param texImage texture image.
491 * This was basically prompted by the introduction of cube maps.
494 _mesa_set_tex_image(struct gl_texture_object
*tObj
,
495 GLenum target
, GLint level
,
496 struct gl_texture_image
*texImage
)
504 tObj
->Image
[0][level
] = texImage
;
506 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
507 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
508 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
509 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
510 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
511 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
: {
512 GLuint face
= ((GLuint
) target
-
513 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
514 tObj
->Image
[face
][level
] = texImage
;
517 case GL_TEXTURE_RECTANGLE_NV
:
519 tObj
->Image
[0][level
] = texImage
;
522 _mesa_problem(NULL
, "bad target in _mesa_set_tex_image()");
529 * Allocate a texture image structure.
531 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
534 * \return a pointer to gl_texture_image struct with all fields initialized to
537 struct gl_texture_image
*
538 _mesa_new_texture_image( GLcontext
*ctx
)
541 return CALLOC_STRUCT(gl_texture_image
);
546 * Free texture image.
548 * \param teximage texture image.
550 * Free the texture image structure and the associated image data if it's not
551 * marked as client data.
554 _mesa_delete_texture_image( struct gl_texture_image
*teximage
)
556 if (teximage
->Data
&& !teximage
->IsClientData
) {
557 MESA_PBUFFER_FREE( teximage
->Data
);
558 teximage
->Data
= NULL
;
565 * Test if a target is a proxy target.
567 * \param target texture target.
569 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
572 is_proxy_target(GLenum target
)
574 return (target
== GL_PROXY_TEXTURE_1D
||
575 target
== GL_PROXY_TEXTURE_2D
||
576 target
== GL_PROXY_TEXTURE_3D
||
577 target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
578 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
);
583 * Get the texture object that corresponds to the target of the given texture unit.
585 * \param ctx GL context.
586 * \param texUnit texture unit.
587 * \param target texture target.
589 * \return pointer to the texture object on success, or NULL on failure.
591 * \sa gl_texture_unit.
593 struct gl_texture_object
*
594 _mesa_select_tex_object(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
599 return texUnit
->Current1D
;
600 case GL_PROXY_TEXTURE_1D
:
601 return ctx
->Texture
.Proxy1D
;
603 return texUnit
->Current2D
;
604 case GL_PROXY_TEXTURE_2D
:
605 return ctx
->Texture
.Proxy2D
;
607 return texUnit
->Current3D
;
608 case GL_PROXY_TEXTURE_3D
:
609 return ctx
->Texture
.Proxy3D
;
610 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
611 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
612 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
613 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
614 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
615 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
616 case GL_TEXTURE_CUBE_MAP_ARB
:
617 return ctx
->Extensions
.ARB_texture_cube_map
618 ? texUnit
->CurrentCubeMap
: NULL
;
619 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
620 return ctx
->Extensions
.ARB_texture_cube_map
621 ? ctx
->Texture
.ProxyCubeMap
: NULL
;
622 case GL_TEXTURE_RECTANGLE_NV
:
623 return ctx
->Extensions
.NV_texture_rectangle
624 ? texUnit
->CurrentRect
: NULL
;
625 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
626 return ctx
->Extensions
.NV_texture_rectangle
627 ? ctx
->Texture
.ProxyRect
: NULL
;
629 _mesa_problem(NULL
, "bad target in _mesa_select_tex_object()");
636 * Get the texture image struct which corresponds to target and level
637 * of the given texture unit.
639 * \param ctx GL context.
640 * \param texUnit texture unit.
641 * \param target texture target.
642 * \param level image level.
644 * \return pointer to the texture image structure on success, or NULL on failure.
646 * \sa gl_texture_unit.
648 struct gl_texture_image
*
649 _mesa_select_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
650 GLenum target
, GLint level
)
653 ASSERT(level
< MAX_TEXTURE_LEVELS
);
656 return texUnit
->Current1D
->Image
[0][level
];
657 case GL_PROXY_TEXTURE_1D
:
658 return ctx
->Texture
.Proxy1D
->Image
[0][level
];
660 return texUnit
->Current2D
->Image
[0][level
];
661 case GL_PROXY_TEXTURE_2D
:
662 return ctx
->Texture
.Proxy2D
->Image
[0][level
];
664 return texUnit
->Current3D
->Image
[0][level
];
665 case GL_PROXY_TEXTURE_3D
:
666 return ctx
->Texture
.Proxy3D
->Image
[0][level
];
667 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
668 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
669 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
670 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
671 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
672 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
673 if (ctx
->Extensions
.ARB_texture_cube_map
) {
674 GLuint face
= ((GLuint
) target
-
675 (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
676 return texUnit
->CurrentCubeMap
->Image
[face
][level
];
680 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
681 if (ctx
->Extensions
.ARB_texture_cube_map
)
682 return ctx
->Texture
.ProxyCubeMap
->Image
[0][level
];
685 case GL_TEXTURE_RECTANGLE_NV
:
686 if (ctx
->Extensions
.NV_texture_rectangle
) {
688 return texUnit
->CurrentRect
->Image
[0][level
];
693 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
694 if (ctx
->Extensions
.NV_texture_rectangle
) {
696 return ctx
->Texture
.ProxyRect
->Image
[0][level
];
702 _mesa_problem(ctx
, "bad target in _mesa_select_tex_image()");
709 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
710 * it and install it. Only return NULL if passed a bad parameter or run
713 struct gl_texture_image
*
714 _mesa_get_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
715 GLenum target
, GLint level
)
717 struct gl_texture_image
*texImage
;
718 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
720 struct gl_texture_object
*texObj
;
721 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
723 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture image allocation");
726 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
728 _mesa_set_tex_image(texObj
, target
, level
, texImage
);
735 * Return pointer to the specified proxy texture image.
736 * Note that proxy textures are per-context, not per-texture unit.
737 * \return pointer to texture image or NULL if invalid target, invalid
738 * level, or out of memory.
740 struct gl_texture_image
*
741 _mesa_get_proxy_tex_image(GLcontext
*ctx
, GLenum target
, GLint level
)
743 struct gl_texture_image
*texImage
;
749 case GL_PROXY_TEXTURE_1D
:
750 if (level
>= ctx
->Const
.MaxTextureLevels
)
752 texImage
= ctx
->Texture
.Proxy1D
->Image
[0][level
];
754 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
756 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
759 ctx
->Texture
.Proxy1D
->Image
[0][level
] = texImage
;
762 case GL_PROXY_TEXTURE_2D
:
763 if (level
>= ctx
->Const
.MaxTextureLevels
)
765 texImage
= ctx
->Texture
.Proxy2D
->Image
[0][level
];
767 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
769 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
772 ctx
->Texture
.Proxy2D
->Image
[0][level
] = texImage
;
775 case GL_PROXY_TEXTURE_3D
:
776 if (level
>= ctx
->Const
.Max3DTextureLevels
)
778 texImage
= ctx
->Texture
.Proxy3D
->Image
[0][level
];
780 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
782 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
785 ctx
->Texture
.Proxy3D
->Image
[0][level
] = texImage
;
788 case GL_PROXY_TEXTURE_CUBE_MAP
:
789 if (level
>= ctx
->Const
.MaxCubeTextureLevels
)
791 texImage
= ctx
->Texture
.ProxyCubeMap
->Image
[0][level
];
793 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
795 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
798 ctx
->Texture
.ProxyCubeMap
->Image
[0][level
] = texImage
;
801 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
804 texImage
= ctx
->Texture
.ProxyRect
->Image
[0][level
];
806 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
808 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
811 ctx
->Texture
.ProxyRect
->Image
[0][level
] = texImage
;
821 * Get the maximum number of allowed mipmap levels.
823 * \param ctx GL context.
824 * \param target texture target.
826 * \return the maximum number of allowed mipmap levels for the given
827 * texture target, or zero if passed a bad target.
832 _mesa_max_texture_levels(GLcontext
*ctx
, GLenum target
)
836 case GL_PROXY_TEXTURE_1D
:
838 case GL_PROXY_TEXTURE_2D
:
839 return ctx
->Const
.MaxTextureLevels
;
841 case GL_PROXY_TEXTURE_3D
:
842 return ctx
->Const
.Max3DTextureLevels
;
843 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
844 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
845 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
846 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
847 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
848 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
849 case GL_TEXTURE_CUBE_MAP_ARB
:
850 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
851 return ctx
->Const
.MaxCubeTextureLevels
;
853 case GL_TEXTURE_RECTANGLE_NV
:
854 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
858 return 0; /* bad target */
864 #if 000 /* not used anymore */
866 * glTexImage[123]D can accept a NULL image pointer. In this case we
867 * create a texture image with unspecified image contents per the OpenGL
871 make_null_texture(GLint width
, GLint height
, GLint depth
, GLenum format
)
873 const GLint components
= _mesa_components_in_format(format
);
874 const GLint numPixels
= width
* height
* depth
;
875 GLubyte
*data
= (GLubyte
*) MALLOC(numPixels
* components
* sizeof(GLubyte
));
879 * Let's see if anyone finds this. If glTexImage2D() is called with
880 * a NULL image pointer then load the texture image with something
881 * interesting instead of leaving it indeterminate.
884 static const char message
[8][32] = {
888 " X X XXXX XXX XXXXX ",
891 " X X XXXXX XXX X X ",
895 GLubyte
*imgPtr
= data
;
897 for (h
= 0; h
< depth
; h
++) {
898 for (i
= 0; i
< height
; i
++) {
899 GLint srcRow
= 7 - (i
% 8);
900 for (j
= 0; j
< width
; j
++) {
901 GLint srcCol
= j
% 32;
902 GLubyte texel
= (message
[srcRow
][srcCol
]=='X') ? 255 : 70;
903 for (k
= 0; k
< components
; k
++) {
919 * Reset the fields of a gl_texture_image struct to zero.
921 * \param img texture image structure.
923 * This is called when a proxy texture test fails, we set all the
924 * image members (except DriverData) to zero.
925 * It's also used in glTexImage[123]D as a safeguard to be sure all
926 * required fields get initialized properly by the Driver.TexImage[123]D
930 clear_teximage_fields(struct gl_texture_image
*img
)
947 img
->TexFormat
= &_mesa_null_texformat
;
948 img
->FetchTexelc
= NULL
;
949 img
->FetchTexelf
= NULL
;
950 img
->IsCompressed
= 0;
951 img
->CompressedSize
= 0;
956 * Initialize basic fields of the gl_texture_image struct.
958 * \param ctx GL context.
959 * \param target texture target.
960 * \param img texture image structure to be initialized.
961 * \param width image width.
962 * \param height image height.
963 * \param depth image depth.
964 * \param border image border.
965 * \param internalFormat internal format.
967 * Fills in the fields of \p img with the given information.
968 * Note: width, height and depth include the border.
971 _mesa_init_teximage_fields(GLcontext
*ctx
, GLenum target
,
972 struct gl_texture_image
*img
,
973 GLsizei width
, GLsizei height
, GLsizei depth
,
974 GLint border
, GLenum internalFormat
)
977 img
->Format
= _mesa_base_tex_format( ctx
, internalFormat
);
978 ASSERT(img
->Format
> 0);
979 img
->IntFormat
= internalFormat
;
980 img
->Border
= border
;
982 img
->Height
= height
;
984 img
->RowStride
= width
;
985 img
->WidthLog2
= logbase2(width
- 2 * border
);
986 if (height
== 1) /* 1-D texture */
989 img
->HeightLog2
= logbase2(height
- 2 * border
);
990 if (depth
== 1) /* 2-D texture */
993 img
->DepthLog2
= logbase2(depth
- 2 * border
);
994 img
->Width2
= width
- 2 * border
; /*1 << img->WidthLog2;*/
995 img
->Height2
= height
- 2 * border
; /*1 << img->HeightLog2;*/
996 img
->Depth2
= depth
- 2 * border
; /*1 << img->DepthLog2;*/
997 img
->MaxLog2
= MAX2(img
->WidthLog2
, img
->HeightLog2
);
998 img
->IsCompressed
= is_compressed_format(ctx
, internalFormat
);
999 if (img
->IsCompressed
)
1000 img
->CompressedSize
= ctx
->Driver
.CompressedTextureSize(ctx
, width
,
1001 height
, depth
, internalFormat
);
1003 img
->CompressedSize
= 0;
1005 if ((width
== 1 || _mesa_bitcount(width
- 2 * border
) == 1) &&
1006 (height
== 1 || _mesa_bitcount(height
- 2 * border
) == 1) &&
1007 (depth
== 1 || _mesa_bitcount(depth
- 2 * border
) == 1))
1008 img
->_IsPowerOfTwo
= GL_TRUE
;
1010 img
->_IsPowerOfTwo
= GL_FALSE
;
1012 /* Compute Width/Height/DepthScale for mipmap lod computation */
1013 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1014 /* scale = 1.0 since texture coords directly map to texels */
1015 img
->WidthScale
= 1.0;
1016 img
->HeightScale
= 1.0;
1017 img
->DepthScale
= 1.0;
1020 img
->WidthScale
= (GLfloat
) img
->Width
;
1021 img
->HeightScale
= (GLfloat
) img
->Height
;
1022 img
->DepthScale
= (GLfloat
) img
->Depth
;
1028 * This is the fallback for Driver.TestProxyTexImage(). Test the texture
1029 * level, width, height and depth against the ctx->Const limits for textures.
1031 * A hardware driver might override this function if, for example, the
1032 * max 3D texture size is 512x512x64 (i.e. not a cube).
1034 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
1035 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
1036 * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
1037 * \param level as passed to glTexImage
1038 * \param internalFormat as passed to glTexImage
1039 * \param format as passed to glTexImage
1040 * \param type as passed to glTexImage
1041 * \param width as passed to glTexImage
1042 * \param height as passed to glTexImage
1043 * \param depth as passed to glTexImage
1044 * \param border as passed to glTexImage
1045 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1048 _mesa_test_proxy_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
1049 GLint internalFormat
, GLenum format
, GLenum type
,
1050 GLint width
, GLint height
, GLint depth
, GLint border
)
1054 (void) internalFormat
;
1059 case GL_PROXY_TEXTURE_1D
:
1060 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1061 if (width
< 2 * border
|| width
> 2 + maxSize
||
1062 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1063 _mesa_bitcount(width
- 2 * border
) != 1) ||
1064 level
>= ctx
->Const
.MaxTextureLevels
) {
1065 /* bad width or level */
1069 case GL_PROXY_TEXTURE_2D
:
1070 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
1071 if (width
< 2 * border
|| width
> 2 + maxSize
||
1072 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1073 _mesa_bitcount(width
- 2 * border
) != 1) ||
1074 height
< 2 * border
|| height
> 2 + maxSize
||
1075 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1076 _mesa_bitcount(height
- 2 * border
) != 1) ||
1077 level
>= ctx
->Const
.MaxTextureLevels
) {
1078 /* bad width or height or level */
1082 case GL_PROXY_TEXTURE_3D
:
1083 maxSize
= 1 << (ctx
->Const
.Max3DTextureLevels
- 1);
1084 if (width
< 2 * border
|| width
> 2 + maxSize
||
1085 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1086 _mesa_bitcount(width
- 2 * border
) != 1) ||
1087 height
< 2 * border
|| height
> 2 + maxSize
||
1088 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1089 _mesa_bitcount(height
- 2 * border
) != 1) ||
1090 depth
< 2 * border
|| depth
> 2 + maxSize
||
1091 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1092 _mesa_bitcount(depth
- 2 * border
) != 1) ||
1093 level
>= ctx
->Const
.Max3DTextureLevels
) {
1094 /* bad width or height or depth or level */
1098 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
1099 if (width
< 1 || width
> ctx
->Const
.MaxTextureRectSize
||
1100 height
< 1 || height
> ctx
->Const
.MaxTextureRectSize
||
1102 /* bad width or height or level */
1106 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
1107 maxSize
= 1 << (ctx
->Const
.MaxCubeTextureLevels
- 1);
1108 if (width
< 2 * border
|| width
> 2 + maxSize
||
1109 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1110 _mesa_bitcount(width
- 2 * border
) != 1) ||
1111 height
< 2 * border
|| height
> 2 + maxSize
||
1112 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1113 _mesa_bitcount(height
- 2 * border
) != 1) ||
1114 level
>= ctx
->Const
.MaxCubeTextureLevels
) {
1115 /* bad width or height */
1120 _mesa_problem(ctx
, "Invalid target in _mesa_test_proxy_teximage");
1127 * Test the glTexImage[123]D() parameters for errors.
1129 * \param ctx GL context.
1130 * \param target texture target given by the user.
1131 * \param level image level given by the user.
1132 * \param internalFormat internal format given by the user.
1133 * \param format pixel data format given by the user.
1134 * \param type pixel data type given by the user.
1135 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1136 * \param width image width given by the user.
1137 * \param height image height given by the user.
1138 * \param depth image depth given by the user.
1139 * \param border image border given by the user.
1141 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1143 * Verifies each of the parameters against the constants specified in
1144 * __GLcontextRec::Const and the supported extensions, and according to the
1145 * OpenGL specification.
1148 texture_error_check( GLcontext
*ctx
, GLenum target
,
1149 GLint level
, GLint internalFormat
,
1150 GLenum format
, GLenum type
,
1152 GLint width
, GLint height
,
1153 GLint depth
, GLint border
)
1155 const GLboolean isProxy
= is_proxy_target(target
);
1158 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1159 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1161 _mesa_error(ctx
, GL_INVALID_VALUE
,
1162 "glTexImage%dD(level=%d)", dimensions
, level
);
1168 if (border
< 0 || border
> 1 ||
1169 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1170 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1172 _mesa_error(ctx
, GL_INVALID_VALUE
,
1173 "glTexImage%dD(border=%d)", dimensions
, border
);
1178 if (width
< 0 || height
< 0 || depth
< 0) {
1180 _mesa_error(ctx
, GL_INVALID_VALUE
,
1181 "glTexImage%dD(width, height or depth < 0)", dimensions
);
1186 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1187 * level, width, height and depth.
1189 if (dimensions
== 1) {
1190 if (target
== GL_PROXY_TEXTURE_1D
|| target
== GL_TEXTURE_1D
) {
1191 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1192 level
, internalFormat
,
1194 width
, 1, 1, border
);
1197 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1201 else if (dimensions
== 2) {
1202 if (target
== GL_PROXY_TEXTURE_2D
|| target
== GL_TEXTURE_2D
) {
1203 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1204 level
, internalFormat
,
1206 width
, height
, 1, border
);
1208 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
1209 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1210 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
1211 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1212 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1215 sizeOK
= (width
== height
) &&
1216 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1217 level
, internalFormat
, format
, type
,
1218 width
, height
, 1, border
);
1220 else if (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
||
1221 target
== GL_TEXTURE_RECTANGLE_NV
) {
1222 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1223 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1226 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1227 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1228 level
, internalFormat
,
1230 width
, height
, 1, border
);
1233 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1237 else if (dimensions
== 3) {
1238 if (target
== GL_PROXY_TEXTURE_3D
|| target
== GL_TEXTURE_3D
) {
1239 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_3D
,
1240 level
, internalFormat
,
1242 width
, height
, depth
, border
);
1245 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1250 _mesa_problem( ctx
, "bad dims in texture_error_check" );
1256 _mesa_error(ctx
, GL_INVALID_VALUE
,
1257 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1258 dimensions
, level
, width
, height
, depth
);
1263 /* Check internalFormat */
1264 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1266 _mesa_error(ctx
, GL_INVALID_VALUE
,
1267 "glTexImage%dD(internalFormat=0x%x)",
1268 dimensions
, internalFormat
);
1273 /* Check incoming image format and type */
1274 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
1275 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1276 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1279 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1280 "glTexImage%dD(format or type)", dimensions
);
1285 if (format
== GL_YCBCR_MESA
|| internalFormat
== GL_YCBCR_MESA
) {
1286 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1287 if (format
!= GL_YCBCR_MESA
||
1288 internalFormat
!= GL_YCBCR_MESA
||
1289 (type
!= GL_UNSIGNED_SHORT_8_8_MESA
&&
1290 type
!= GL_UNSIGNED_SHORT_8_8_REV_MESA
)) {
1292 _mesa_sprintf(message
,
1293 "glTexImage%d(format/type/internalFormat YCBCR mismatch",
1295 _mesa_error(ctx
, GL_INVALID_ENUM
, message
);
1296 return GL_TRUE
; /* error */
1298 if (target
!= GL_TEXTURE_2D
&&
1299 target
!= GL_PROXY_TEXTURE_2D
&&
1300 target
!= GL_TEXTURE_RECTANGLE_NV
&&
1301 target
!= GL_PROXY_TEXTURE_RECTANGLE_NV
) {
1303 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage(target)");
1309 _mesa_sprintf(message
,
1310 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1311 dimensions
, border
);
1312 _mesa_error(ctx
, GL_INVALID_VALUE
, message
);
1318 if (is_compressed_format(ctx
, internalFormat
)) {
1319 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1322 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1323 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1324 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1325 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1330 _mesa_error(ctx
, GL_INVALID_ENUM
,
1331 "glTexImage%d(target)", dimensions
);
1337 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1338 "glTexImage%D(border!=0)", dimensions
);
1344 /* if we get here, the parameters are OK */
1350 * Test glTexSubImage[123]D() parameters for errors.
1352 * \param ctx GL context.
1353 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1354 * \param target texture target given by the user.
1355 * \param level image level given by the user.
1356 * \param xoffset sub-image x offset given by the user.
1357 * \param yoffset sub-image y offset given by the user.
1358 * \param zoffset sub-image z offset given by the user.
1359 * \param format pixel data format given by the user.
1360 * \param type pixel data type given by the user.
1361 * \param width image width given by the user.
1362 * \param height image height given by the user.
1363 * \param depth image depth given by the user.
1365 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1367 * Verifies each of the parameters against the constants specified in
1368 * __GLcontextRec::Const and the supported extensions, and according to the
1369 * OpenGL specification.
1372 subtexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1373 GLenum target
, GLint level
,
1374 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1375 GLint width
, GLint height
, GLint depth
,
1376 GLenum format
, GLenum type
)
1378 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1379 struct gl_texture_image
*destTex
;
1382 if (dimensions
== 1) {
1383 if (target
!= GL_TEXTURE_1D
) {
1384 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
1388 else if (dimensions
== 2) {
1389 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1390 target
<=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1391 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1392 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1396 else if (ctx
->Extensions
.NV_texture_rectangle
&&
1397 target
== GL_TEXTURE_RECTANGLE_NV
) {
1398 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1399 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1403 else if (target
!= GL_TEXTURE_2D
) {
1404 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1408 else if (dimensions
== 3) {
1409 if (target
!= GL_TEXTURE_3D
) {
1410 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
1415 _mesa_problem( ctx
, "invalid dims in texture_error_check" );
1419 /* Basic level check */
1420 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1421 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level=%d)", level
);
1426 _mesa_error(ctx
, GL_INVALID_VALUE
,
1427 "glTexSubImage%dD(width=%d)", dimensions
, width
);
1430 if (height
< 0 && dimensions
> 1) {
1431 _mesa_error(ctx
, GL_INVALID_VALUE
,
1432 "glTexSubImage%dD(height=%d)", dimensions
, height
);
1435 if (depth
< 0 && dimensions
> 2) {
1436 _mesa_error(ctx
, GL_INVALID_VALUE
,
1437 "glTexSubImage%dD(depth=%d)", dimensions
, depth
);
1441 destTex
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1444 /* undefined image level */
1445 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage%dD", dimensions
);
1449 if (xoffset
< -((GLint
)destTex
->Border
)) {
1450 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset)",
1454 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
1455 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset+width)",
1459 if (dimensions
> 1) {
1460 if (yoffset
< -((GLint
)destTex
->Border
)) {
1461 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset)",
1465 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
1466 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset+height)",
1471 if (dimensions
> 2) {
1472 if (zoffset
< -((GLint
)destTex
->Border
)) {
1473 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
1476 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+ destTex
->Border
)) {
1477 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
1482 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
1483 _mesa_error(ctx
, GL_INVALID_ENUM
,
1484 "glTexSubImage%dD(format or type)", dimensions
);
1488 if (destTex
->IsCompressed
) {
1489 const struct gl_texture_unit
*texUnit
;
1490 const struct gl_texture_image
*texImage
;
1491 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1492 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1494 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1497 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1498 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1499 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1500 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1504 _mesa_error(ctx
, GL_INVALID_ENUM
,
1505 "glTexSubImage%D(target)", dimensions
);
1508 /* offset must be multiple of 4 */
1509 if ((xoffset
& 3) || (yoffset
& 3)) {
1510 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1511 "glTexSubImage%D(xoffset or yoffset)", dimensions
);
1514 /* size must be multiple of 4 or equal to whole texture size */
1515 if ((width
& 3) && (GLuint
) width
!= texImage
->Width
) {
1516 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1517 "glTexSubImage%D(width)", dimensions
);
1520 if ((height
& 3) && (GLuint
) height
!= texImage
->Height
) {
1521 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1522 "glTexSubImage%D(width)", dimensions
);
1532 * Test glCopyTexImage[12]D() parameters for errors.
1534 * \param ctx GL context.
1535 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1536 * \param target texture target given by the user.
1537 * \param level image level given by the user.
1538 * \param internalFormat internal format given by the user.
1539 * \param width image width given by the user.
1540 * \param height image height given by the user.
1541 * \param depth image depth given by the user.
1542 * \param border texture border.
1544 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1546 * Verifies each of the parameters against the constants specified in
1547 * __GLcontextRec::Const and the supported extensions, and according to the
1548 * OpenGL specification.
1551 copytexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1552 GLenum target
, GLint level
, GLint internalFormat
,
1553 GLint width
, GLint height
, GLint border
)
1555 GLenum format
, type
;
1558 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1559 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1560 _mesa_error(ctx
, GL_INVALID_VALUE
,
1561 "glCopyTexImage%dD(level=%d)", dimensions
, level
);
1566 if (border
< 0 || border
> 1 ||
1567 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1568 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1572 /* The format and type aren't really significant here, but we need to pass
1573 * something to TestProxyTexImage().
1575 format
= _mesa_base_tex_format(ctx
, internalFormat
);
1578 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1579 * level, width, height and depth.
1581 if (dimensions
== 1) {
1582 if (target
== GL_TEXTURE_1D
) {
1583 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1584 level
, internalFormat
,
1586 width
, 1, 1, border
);
1589 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
1593 else if (dimensions
== 2) {
1594 if (target
== GL_TEXTURE_2D
) {
1595 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1596 level
, internalFormat
,
1598 width
, height
, 1, border
);
1600 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1601 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1602 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1603 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1606 sizeOK
= (width
== height
) &&
1607 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1608 level
, internalFormat
, format
, type
,
1609 width
, height
, 1, border
);
1611 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1612 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1613 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1616 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1617 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1618 level
, internalFormat
,
1620 width
, height
, 1, border
);
1623 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1628 _mesa_problem(ctx
, "invalid dimensions in copytexture_error_check");
1633 if (dimensions
== 1) {
1634 _mesa_error(ctx
, GL_INVALID_VALUE
,
1635 "glCopyTexImage1D(width=%d)", width
);
1638 ASSERT(dimensions
== 2);
1639 _mesa_error(ctx
, GL_INVALID_VALUE
,
1640 "glCopyTexImage2D(width=%d, height=%d)", width
, height
);
1645 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1646 _mesa_error(ctx
, GL_INVALID_VALUE
,
1647 "glCopyTexImage%dD(internalFormat)", dimensions
);
1651 if (is_compressed_format(ctx
, internalFormat
)) {
1652 if (target
!= GL_TEXTURE_2D
) {
1653 _mesa_error(ctx
, GL_INVALID_ENUM
,
1654 "glCopyTexImage%d(target)", dimensions
);
1658 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1659 "glCopyTexImage%D(border!=0)", dimensions
);
1664 /* if we get here, the parameters are OK */
1670 * Test glCopyTexImage[12]D() parameters for errors.
1672 * \param ctx GL context.
1673 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1674 * \param target texture target given by the user.
1675 * \param level image level given by the user.
1676 * \param xoffset sub-image x offset given by the user.
1677 * \param yoffset sub-image y offset given by the user.
1678 * \param zoffset sub-image z offset given by the user.
1679 * \param width image width given by the user.
1680 * \param height image height given by the user.
1682 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1684 * Verifies each of the parameters against the constants specified in
1685 * __GLcontextRec::Const and the supported extensions, and according to the
1686 * OpenGL specification.
1689 copytexsubimage_error_check( GLcontext
*ctx
, GLuint dimensions
,
1690 GLenum target
, GLint level
,
1691 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1692 GLsizei width
, GLsizei height
)
1694 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1695 struct gl_texture_image
*teximage
;
1698 if (dimensions
== 1) {
1699 if (target
!= GL_TEXTURE_1D
) {
1700 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
1704 else if (dimensions
== 2) {
1705 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1706 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1707 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1708 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1712 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1713 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1714 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1718 else if (target
!= GL_TEXTURE_2D
) {
1719 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1723 else if (dimensions
== 3) {
1724 if (target
!= GL_TEXTURE_3D
) {
1725 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
1731 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1732 _mesa_error(ctx
, GL_INVALID_VALUE
,
1733 "glCopyTexSubImage%dD(level=%d)", dimensions
, level
);
1739 _mesa_error(ctx
, GL_INVALID_VALUE
,
1740 "glCopyTexSubImage%dD(width=%d)", dimensions
, width
);
1743 if (dimensions
> 1 && height
< 0) {
1744 _mesa_error(ctx
, GL_INVALID_VALUE
,
1745 "glCopyTexSubImage%dD(height=%d)", dimensions
, height
);
1749 teximage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1751 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1752 "glCopyTexSubImage%dD(undefined texture level: %d)",
1757 if (xoffset
< -((GLint
)teximage
->Border
)) {
1758 _mesa_error(ctx
, GL_INVALID_VALUE
,
1759 "glCopyTexSubImage%dD(xoffset=%d)", dimensions
, xoffset
);
1762 if (xoffset
+ width
> (GLint
) (teximage
->Width
+ teximage
->Border
)) {
1763 _mesa_error(ctx
, GL_INVALID_VALUE
,
1764 "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
1767 if (dimensions
> 1) {
1768 if (yoffset
< -((GLint
)teximage
->Border
)) {
1769 _mesa_error(ctx
, GL_INVALID_VALUE
,
1770 "glCopyTexSubImage%dD(yoffset=%d)", dimensions
, yoffset
);
1773 /* NOTE: we're adding the border here, not subtracting! */
1774 if (yoffset
+ height
> (GLint
) (teximage
->Height
+ teximage
->Border
)) {
1775 _mesa_error(ctx
, GL_INVALID_VALUE
,
1776 "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
1781 if (dimensions
> 2) {
1782 if (zoffset
< -((GLint
)teximage
->Border
)) {
1783 _mesa_error(ctx
, GL_INVALID_VALUE
,
1784 "glCopyTexSubImage%dD(zoffset)", dimensions
);
1787 if (zoffset
> (GLint
) (teximage
->Depth
+ teximage
->Border
)) {
1788 _mesa_error(ctx
, GL_INVALID_VALUE
,
1789 "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
1794 if (teximage
->IsCompressed
) {
1795 if (target
!= GL_TEXTURE_2D
) {
1796 _mesa_error(ctx
, GL_INVALID_ENUM
,
1797 "glCopyTexSubImage%d(target)", dimensions
);
1800 /* offset must be multiple of 4 */
1801 if ((xoffset
& 3) || (yoffset
& 3)) {
1802 _mesa_error(ctx
, GL_INVALID_VALUE
,
1803 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions
);
1806 /* size must be multiple of 4 */
1807 if ((width
& 3) != 0 && (GLuint
) width
!= teximage
->Width
) {
1808 _mesa_error(ctx
, GL_INVALID_VALUE
,
1809 "glCopyTexSubImage%D(width)", dimensions
);
1812 if ((height
& 3) != 0 && (GLuint
) height
!= teximage
->Height
) {
1813 _mesa_error(ctx
, GL_INVALID_VALUE
,
1814 "glCopyTexSubImage%D(height)", dimensions
);
1819 if (teximage
->IntFormat
== GL_YCBCR_MESA
) {
1820 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glCopyTexSubImage2D");
1824 /* if we get here, the parameters are OK */
1830 * Get texture image. Called by glGetTexImage.
1832 * \param target texture target.
1833 * \param level image level.
1834 * \param format pixel data format for returned image.
1835 * \param type pixel data type for returned image.
1836 * \param pixels returned pixel data.
1839 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
1840 GLenum type
, GLvoid
*pixels
)
1842 const struct gl_texture_unit
*texUnit
;
1843 const struct gl_texture_object
*texObj
;
1844 const struct gl_texture_image
*texImage
;
1845 GLint maxLevels
= 0;
1846 GET_CURRENT_CONTEXT(ctx
);
1847 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
1849 texUnit
= &(ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
]);
1850 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
1851 if (!texObj
|| is_proxy_target(target
)) {
1852 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)");
1856 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
1857 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
1859 if (level
< 0 || level
>= maxLevels
) {
1860 _mesa_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
1864 if (_mesa_sizeof_packed_type(type
) <= 0) {
1865 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
1869 if (_mesa_components_in_format(format
) <= 0 ||
1870 format
== GL_STENCIL_INDEX
) {
1871 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
1875 if (!ctx
->Extensions
.EXT_paletted_texture
&& is_index_format(format
)) {
1876 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1879 if (!ctx
->Extensions
.SGIX_depth_texture
&& is_depth_format(format
)) {
1880 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1883 if (!ctx
->Extensions
.MESA_ycbcr_texture
&& is_ycbcr_format(format
)) {
1884 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1890 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1892 /* invalid mipmap level, not an error */
1896 if (!texImage
->Data
) {
1897 /* no image data, not an error */
1901 /* Make sure the requested image format is compatible with the
1904 if (is_color_format(format
)
1905 && !is_color_format(texImage
->TexFormat
->BaseFormat
)) {
1906 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
1909 else if (is_index_format(format
)
1910 && !is_index_format(texImage
->TexFormat
->BaseFormat
)) {
1911 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
1914 else if (is_depth_format(format
)
1915 && !is_depth_format(texImage
->TexFormat
->BaseFormat
)) {
1916 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
1919 else if (is_ycbcr_format(format
)
1920 && !is_ycbcr_format(texImage
->TexFormat
->BaseFormat
)) {
1921 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
1928 const GLint width
= texImage
->Width
;
1929 const GLint height
= texImage
->Height
;
1930 const GLint depth
= texImage
->Depth
;
1932 for (img
= 0; img
< depth
; img
++) {
1933 for (row
= 0; row
< height
; row
++) {
1934 /* compute destination address in client memory */
1935 GLvoid
*dest
= _mesa_image_address( &ctx
->Pack
, pixels
,
1936 width
, height
, format
, type
,
1940 if (format
== GL_COLOR_INDEX
) {
1941 GLuint indexRow
[MAX_WIDTH
];
1943 for (col
= 0; col
< width
; col
++) {
1945 (*texImage
->FetchTexelc
)(texImage
, col
, row
, img
, &indx
);
1946 indexRow
[col
] = indx
;
1948 _mesa_pack_index_span(ctx
, width
, type
, dest
,
1949 indexRow
, &ctx
->Pack
,
1950 0 /* no image transfer */);
1952 else if (format
== GL_DEPTH_COMPONENT
) {
1953 GLfloat depthRow
[MAX_WIDTH
];
1955 for (col
= 0; col
< width
; col
++) {
1956 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
,
1957 (GLvoid
*) &depthRow
[col
]);
1959 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
1960 depthRow
, &ctx
->Pack
);
1962 else if (format
== GL_YCBCR_MESA
) {
1963 /* No pixel transfer */
1964 const GLint rowstride
= texImage
->RowStride
;
1966 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
1967 width
* sizeof(GLushort
));
1968 /* check for byte swapping */
1969 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
1970 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
1971 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
1972 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
1973 if (!ctx
->Pack
.SwapBytes
)
1974 _mesa_swap2((GLushort
*) dest
, width
);
1976 else if (ctx
->Pack
.SwapBytes
) {
1977 _mesa_swap2((GLushort
*) dest
, width
);
1981 /* general case: convert row to RGBA format */
1982 GLfloat rgba
[MAX_WIDTH
][4];
1984 for (col
= 0; col
< width
; col
++) {
1985 (*texImage
->FetchTexelf
)(texImage
, col
, row
, img
, rgba
[col
]);
1987 _mesa_pack_rgba_span_float(ctx
, width
,
1988 (const GLfloat (*)[4]) rgba
,
1989 format
, type
, dest
, &ctx
->Pack
,
1990 0 /* no image transfer */);
2000 * Called from the API. Note that width includes the border.
2003 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalFormat
,
2004 GLsizei width
, GLint border
, GLenum format
,
2005 GLenum type
, const GLvoid
*pixels
)
2007 GLsizei postConvWidth
= width
;
2008 GET_CURRENT_CONTEXT(ctx
);
2009 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2011 if (is_color_format(internalFormat
)) {
2012 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2015 if (target
== GL_TEXTURE_1D
) {
2016 struct gl_texture_unit
*texUnit
;
2017 struct gl_texture_object
*texObj
;
2018 struct gl_texture_image
*texImage
;
2020 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2021 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2022 return; /* error was recorded */
2025 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2026 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2027 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2030 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
2033 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2034 /* free the old texture data */
2035 MESA_PBUFFER_FREE(texImage
->Data
);
2037 texImage
->Data
= NULL
;
2038 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2039 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2040 postConvWidth
, 1, 1,
2041 border
, internalFormat
);
2043 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2044 _mesa_update_state(ctx
);
2046 ASSERT(ctx
->Driver
.TexImage1D
);
2048 /* Give the texture to the driver! <pixels> may be null! */
2049 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
2050 width
, border
, format
, type
, pixels
,
2051 &ctx
->Unpack
, texObj
, texImage
);
2053 ASSERT(texImage
->TexFormat
);
2055 /* If driver didn't explicitly set this, use the defaults */
2056 if (!texImage
->FetchTexelc
)
2057 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2058 if (!texImage
->FetchTexelf
)
2059 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2060 ASSERT(texImage
->FetchTexelc
);
2061 ASSERT(texImage
->FetchTexelf
);
2064 texObj
->Complete
= GL_FALSE
;
2065 ctx
->NewState
|= _NEW_TEXTURE
;
2067 else if (target
== GL_PROXY_TEXTURE_1D
) {
2068 /* Proxy texture: check for errors and update proxy state */
2069 struct gl_texture_image
*texImage
;
2070 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2071 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2072 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
2073 /* when error, clear all proxy texture image parameters */
2075 clear_teximage_fields(texImage
);
2078 /* no error, set the tex image parameters */
2080 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2081 postConvWidth
, 1, 1,
2082 border
, internalFormat
);
2083 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2084 internalFormat
, format
, type
);
2088 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
2095 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalFormat
,
2096 GLsizei width
, GLsizei height
, GLint border
,
2097 GLenum format
, GLenum type
,
2098 const GLvoid
*pixels
)
2100 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2101 GET_CURRENT_CONTEXT(ctx
);
2102 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2104 if (is_color_format(internalFormat
)) {
2105 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2109 if (target
== GL_TEXTURE_2D
||
2110 (ctx
->Extensions
.ARB_texture_cube_map
&&
2111 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2112 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) ||
2113 (ctx
->Extensions
.NV_texture_rectangle
&&
2114 target
== GL_TEXTURE_RECTANGLE_NV
)) {
2115 /* non-proxy target */
2116 struct gl_texture_unit
*texUnit
;
2117 struct gl_texture_object
*texObj
;
2118 struct gl_texture_image
*texImage
;
2120 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2121 format
, type
, 2, postConvWidth
, postConvHeight
,
2123 return; /* error was recorded */
2126 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2127 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2128 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2130 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2133 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2134 /* free the old texture data */
2135 MESA_PBUFFER_FREE(texImage
->Data
);
2137 texImage
->Data
= NULL
;
2138 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2139 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2140 postConvWidth
, postConvHeight
, 1,
2141 border
, internalFormat
);
2143 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2144 _mesa_update_state(ctx
);
2146 ASSERT(ctx
->Driver
.TexImage2D
);
2148 /* Give the texture to the driver! <pixels> may be null! */
2149 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
2150 width
, height
, border
, format
, type
, pixels
,
2151 &ctx
->Unpack
, texObj
, texImage
);
2153 ASSERT(texImage
->TexFormat
);
2155 /* If driver didn't explicitly set these, use the defaults */
2156 if (!texImage
->FetchTexelc
)
2157 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2158 if (!texImage
->FetchTexelf
)
2159 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2160 ASSERT(texImage
->FetchTexelc
);
2161 ASSERT(texImage
->FetchTexelf
);
2164 texObj
->Complete
= GL_FALSE
;
2165 ctx
->NewState
|= _NEW_TEXTURE
;
2167 else if (target
== GL_PROXY_TEXTURE_2D
||
2168 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2169 ctx
->Extensions
.ARB_texture_cube_map
) ||
2170 (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
&&
2171 ctx
->Extensions
.NV_texture_rectangle
)) {
2172 /* Proxy texture: check for errors and update proxy state */
2173 struct gl_texture_image
*texImage
;
2174 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2175 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2176 format
, type
, 2, postConvWidth
, postConvHeight
,
2178 /* when error, clear all proxy texture image parameters */
2180 clear_teximage_fields(ctx
->Texture
.Proxy2D
->Image
[0][level
]);
2183 /* no error, set the tex image parameters */
2184 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2185 postConvWidth
, postConvHeight
, 1,
2186 border
, internalFormat
);
2187 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2188 internalFormat
, format
, type
);
2192 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
2199 * Called by the API or display list executor.
2200 * Note that width and height include the border.
2203 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalFormat
,
2204 GLsizei width
, GLsizei height
, GLsizei depth
,
2205 GLint border
, GLenum format
, GLenum type
,
2206 const GLvoid
*pixels
)
2208 GET_CURRENT_CONTEXT(ctx
);
2209 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2211 if (target
== GL_TEXTURE_3D
) {
2212 struct gl_texture_unit
*texUnit
;
2213 struct gl_texture_object
*texObj
;
2214 struct gl_texture_image
*texImage
;
2216 if (texture_error_check(ctx
, target
, level
, (GLint
) internalFormat
,
2217 format
, type
, 3, width
, height
, depth
, border
)) {
2218 return; /* error was recorded */
2221 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2222 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2223 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2225 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2228 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2229 MESA_PBUFFER_FREE(texImage
->Data
);
2231 texImage
->Data
= NULL
;
2232 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2233 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2234 width
, height
, depth
,
2235 border
, internalFormat
);
2237 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2238 _mesa_update_state(ctx
);
2240 ASSERT(ctx
->Driver
.TexImage3D
);
2242 /* Give the texture to the driver! <pixels> may be null! */
2243 (*ctx
->Driver
.TexImage3D
)(ctx
, target
, level
, internalFormat
,
2244 width
, height
, depth
, border
, format
, type
,
2245 pixels
, &ctx
->Unpack
, texObj
, texImage
);
2247 ASSERT(texImage
->TexFormat
);
2249 /* If driver didn't explicitly set these, use the defaults */
2250 if (!texImage
->FetchTexelc
)
2251 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel3D
;
2252 if (!texImage
->FetchTexelf
)
2253 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel3Df
;
2254 ASSERT(texImage
->FetchTexelc
);
2255 ASSERT(texImage
->FetchTexelf
);
2258 texObj
->Complete
= GL_FALSE
;
2259 ctx
->NewState
|= _NEW_TEXTURE
;
2261 else if (target
== GL_PROXY_TEXTURE_3D
) {
2262 /* Proxy texture: check for errors and update proxy state */
2263 struct gl_texture_image
*texImage
;
2264 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2265 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2266 format
, type
, 3, width
, height
, depth
, border
)) {
2267 /* when error, clear all proxy texture image parameters */
2269 clear_teximage_fields(texImage
);
2272 /* no error, set the tex image parameters */
2273 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2274 border
, internalFormat
);
2275 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2276 internalFormat
, format
, type
);
2280 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
2287 _mesa_TexImage3DEXT( GLenum target
, GLint level
, GLenum internalFormat
,
2288 GLsizei width
, GLsizei height
, GLsizei depth
,
2289 GLint border
, GLenum format
, GLenum type
,
2290 const GLvoid
*pixels
)
2292 _mesa_TexImage3D(target
, level
, (GLint
) internalFormat
, width
, height
,
2293 depth
, border
, format
, type
, pixels
);
2299 _mesa_TexSubImage1D( GLenum target
, GLint level
,
2300 GLint xoffset
, GLsizei width
,
2301 GLenum format
, GLenum type
,
2302 const GLvoid
*pixels
)
2304 GLsizei postConvWidth
= width
;
2305 struct gl_texture_unit
*texUnit
;
2306 struct gl_texture_object
*texObj
;
2307 struct gl_texture_image
*texImage
;
2308 GET_CURRENT_CONTEXT(ctx
);
2309 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2311 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2312 _mesa_update_state(ctx
);
2314 /* XXX should test internal format */
2315 if (is_color_format(format
)) {
2316 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2319 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
2320 postConvWidth
, 1, 1, format
, type
)) {
2321 return; /* error was detected */
2324 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2325 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2326 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2329 if (width
== 0 || !pixels
)
2330 return; /* no-op, not an error */
2332 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2333 xoffset
+= texImage
->Border
;
2335 ASSERT(ctx
->Driver
.TexSubImage1D
);
2336 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
2337 format
, type
, pixels
, &ctx
->Unpack
,
2339 ctx
->NewState
|= _NEW_TEXTURE
;
2344 _mesa_TexSubImage2D( GLenum target
, GLint level
,
2345 GLint xoffset
, GLint yoffset
,
2346 GLsizei width
, GLsizei height
,
2347 GLenum format
, GLenum type
,
2348 const GLvoid
*pixels
)
2350 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2351 struct gl_texture_unit
*texUnit
;
2352 struct gl_texture_object
*texObj
;
2353 struct gl_texture_image
*texImage
;
2354 GET_CURRENT_CONTEXT(ctx
);
2355 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2357 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2358 _mesa_update_state(ctx
);
2360 /* XXX should test internal format */
2361 if (is_color_format(format
)) {
2362 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2366 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2367 postConvWidth
, postConvHeight
, 1, format
, type
)) {
2368 return; /* error was detected */
2371 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2372 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2373 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2376 if (width
== 0 || height
== 0 || !pixels
)
2377 return; /* no-op, not an error */
2379 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2380 xoffset
+= texImage
->Border
;
2381 yoffset
+= texImage
->Border
;
2383 ASSERT(ctx
->Driver
.TexSubImage2D
);
2384 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
, xoffset
, yoffset
,
2385 width
, height
, format
, type
, pixels
,
2386 &ctx
->Unpack
, texObj
, texImage
);
2387 ctx
->NewState
|= _NEW_TEXTURE
;
2393 _mesa_TexSubImage3D( GLenum target
, GLint level
,
2394 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2395 GLsizei width
, GLsizei height
, GLsizei depth
,
2396 GLenum format
, GLenum type
,
2397 const GLvoid
*pixels
)
2399 struct gl_texture_unit
*texUnit
;
2400 struct gl_texture_object
*texObj
;
2401 struct gl_texture_image
*texImage
;
2402 GET_CURRENT_CONTEXT(ctx
);
2403 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2405 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2406 _mesa_update_state(ctx
);
2408 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2409 width
, height
, depth
, format
, type
)) {
2410 return; /* error was detected */
2413 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2414 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2415 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2418 if (width
== 0 || height
== 0 || height
== 0 || !pixels
)
2419 return; /* no-op, not an error */
2421 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2422 xoffset
+= texImage
->Border
;
2423 yoffset
+= texImage
->Border
;
2424 zoffset
+= texImage
->Border
;
2426 ASSERT(ctx
->Driver
.TexSubImage3D
);
2427 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
2428 xoffset
, yoffset
, zoffset
,
2429 width
, height
, depth
,
2430 format
, type
, pixels
,
2431 &ctx
->Unpack
, texObj
, texImage
);
2432 ctx
->NewState
|= _NEW_TEXTURE
;
2438 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
2439 GLenum internalFormat
,
2441 GLsizei width
, GLint border
)
2443 struct gl_texture_unit
*texUnit
;
2444 struct gl_texture_object
*texObj
;
2445 struct gl_texture_image
*texImage
;
2446 GLsizei postConvWidth
= width
;
2447 GET_CURRENT_CONTEXT(ctx
);
2448 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2450 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2451 _mesa_update_state(ctx
);
2453 if (is_color_format(internalFormat
)) {
2454 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2457 if (copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
2458 postConvWidth
, 1, border
))
2461 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2462 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2463 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2465 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
2468 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2469 /* free the old texture data */
2470 MESA_PBUFFER_FREE(texImage
->Data
);
2472 texImage
->Data
= NULL
;
2474 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2475 _mesa_init_teximage_fields(ctx
, target
, texImage
, postConvWidth
, 1, 1,
2476 border
, internalFormat
);
2479 ASSERT(ctx
->Driver
.CopyTexImage1D
);
2480 (*ctx
->Driver
.CopyTexImage1D
)(ctx
, target
, level
, internalFormat
,
2481 x
, y
, width
, border
);
2483 ASSERT(texImage
->TexFormat
);
2485 /* If driver didn't explicitly set these, use the defaults */
2486 if (!texImage
->FetchTexelc
)
2487 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel1D
;
2488 if (!texImage
->FetchTexelf
)
2489 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel1Df
;
2490 ASSERT(texImage
->FetchTexelc
);
2491 ASSERT(texImage
->FetchTexelf
);
2494 texObj
->Complete
= GL_FALSE
;
2495 ctx
->NewState
|= _NEW_TEXTURE
;
2501 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
2502 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2505 struct gl_texture_unit
*texUnit
;
2506 struct gl_texture_object
*texObj
;
2507 struct gl_texture_image
*texImage
;
2508 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2509 GET_CURRENT_CONTEXT(ctx
);
2510 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2512 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2513 _mesa_update_state(ctx
);
2515 if (is_color_format(internalFormat
)) {
2516 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2520 if (copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
2521 postConvWidth
, postConvHeight
, border
))
2524 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2525 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2526 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2528 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
2531 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2532 /* free the old texture data */
2533 MESA_PBUFFER_FREE(texImage
->Data
);
2535 texImage
->Data
= NULL
;
2537 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2538 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2539 postConvWidth
, postConvHeight
, 1,
2540 border
, internalFormat
);
2542 ASSERT(ctx
->Driver
.CopyTexImage2D
);
2543 (*ctx
->Driver
.CopyTexImage2D
)(ctx
, target
, level
, internalFormat
,
2544 x
, y
, width
, height
, border
);
2546 ASSERT(texImage
->TexFormat
);
2548 /* If driver didn't explicitly set these, use the defaults */
2549 if (!texImage
->FetchTexelc
)
2550 texImage
->FetchTexelc
= texImage
->TexFormat
->FetchTexel2D
;
2551 if (!texImage
->FetchTexelf
)
2552 texImage
->FetchTexelf
= texImage
->TexFormat
->FetchTexel2Df
;
2553 ASSERT(texImage
->FetchTexelc
);
2554 ASSERT(texImage
->FetchTexelf
);
2557 texObj
->Complete
= GL_FALSE
;
2558 ctx
->NewState
|= _NEW_TEXTURE
;
2564 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
2565 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
2567 struct gl_texture_unit
*texUnit
;
2568 struct gl_texture_image
*texImage
;
2569 GLsizei postConvWidth
= width
;
2570 GET_CURRENT_CONTEXT(ctx
);
2571 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2573 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2574 _mesa_update_state(ctx
);
2576 /* XXX should test internal format */
2577 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2579 if (copytexsubimage_error_check(ctx
, 1, target
, level
,
2580 xoffset
, 0, 0, postConvWidth
, 1))
2583 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2584 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2587 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2588 xoffset
+= texImage
->Border
;
2590 ASSERT(ctx
->Driver
.CopyTexSubImage1D
);
2591 (*ctx
->Driver
.CopyTexSubImage1D
)(ctx
, target
, level
, xoffset
, x
, y
, width
);
2592 ctx
->NewState
|= _NEW_TEXTURE
;
2598 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
2599 GLint xoffset
, GLint yoffset
,
2600 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2602 struct gl_texture_unit
*texUnit
;
2603 struct gl_texture_image
*texImage
;
2604 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2605 GET_CURRENT_CONTEXT(ctx
);
2606 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2608 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2609 _mesa_update_state(ctx
);
2611 /* XXX should test internal format */
2612 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2614 if (copytexsubimage_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2615 postConvWidth
, postConvHeight
))
2618 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2619 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2622 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2623 xoffset
+= texImage
->Border
;
2624 yoffset
+= texImage
->Border
;
2626 ASSERT(ctx
->Driver
.CopyTexSubImage2D
);
2627 (*ctx
->Driver
.CopyTexSubImage2D
)(ctx
, target
, level
,
2628 xoffset
, yoffset
, x
, y
, width
, height
);
2629 ctx
->NewState
|= _NEW_TEXTURE
;
2635 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
2636 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2637 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2639 struct gl_texture_unit
*texUnit
;
2640 struct gl_texture_image
*texImage
;
2641 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2642 GET_CURRENT_CONTEXT(ctx
);
2643 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2645 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2646 _mesa_update_state(ctx
);
2648 /* XXX should test internal format */
2649 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2651 if (copytexsubimage_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
,
2652 zoffset
, postConvWidth
, postConvHeight
))
2655 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2656 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2659 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2660 xoffset
+= texImage
->Border
;
2661 yoffset
+= texImage
->Border
;
2662 zoffset
+= texImage
->Border
;
2664 ASSERT(ctx
->Driver
.CopyTexSubImage3D
);
2665 (*ctx
->Driver
.CopyTexSubImage3D
)(ctx
, target
, level
,
2666 xoffset
, yoffset
, zoffset
,
2667 x
, y
, width
, height
);
2668 ctx
->NewState
|= _NEW_TEXTURE
;
2674 /**********************************************************************/
2675 /****** Compressed Textures ******/
2676 /**********************************************************************/
2680 * Error checking for glCompressedTexImage[123]D().
2681 * \return error code or GL_NO_ERROR.
2684 compressed_texture_error_check(GLcontext
*ctx
, GLint dimensions
,
2685 GLenum target
, GLint level
,
2686 GLenum internalFormat
, GLsizei width
,
2687 GLsizei height
, GLsizei depth
, GLint border
,
2690 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2692 if (dimensions
== 1) {
2693 /* 1D compressed textures not allowed */
2694 return GL_INVALID_ENUM
;
2696 else if (dimensions
== 2) {
2697 if (target
== GL_PROXY_TEXTURE_2D
) {
2698 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2700 else if (target
== GL_TEXTURE_2D
) {
2701 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2703 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2704 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2705 return GL_INVALID_ENUM
; /*target*/
2706 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2708 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2709 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2710 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2711 return GL_INVALID_ENUM
; /*target*/
2712 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2715 return GL_INVALID_ENUM
; /*target*/
2718 else if (dimensions
== 3) {
2719 /* 3D compressed textures not allowed */
2720 return GL_INVALID_ENUM
;
2723 maxTextureSize
= 1 << (maxLevels
- 1);
2725 if (!is_compressed_format(ctx
, internalFormat
))
2726 return GL_INVALID_ENUM
;
2729 return GL_INVALID_VALUE
;
2732 * XXX We should probably use the proxy texture error check function here.
2734 if (width
< 1 || width
> maxTextureSize
||
2735 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(width
) < 0))
2736 return GL_INVALID_VALUE
;
2738 if ((height
< 1 || height
> maxTextureSize
||
2739 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(height
) < 0))
2741 return GL_INVALID_VALUE
;
2743 if ((depth
< 1 || depth
> maxTextureSize
||
2744 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(depth
) < 0))
2746 return GL_INVALID_VALUE
;
2748 /* For cube map, width must equal height */
2749 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2750 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
&& width
!= height
)
2751 return GL_INVALID_VALUE
;
2753 if (level
< 0 || level
>= maxLevels
)
2754 return GL_INVALID_VALUE
;
2756 expectedSize
= ctx
->Driver
.CompressedTextureSize(ctx
, width
, height
, depth
,
2758 if (expectedSize
!= imageSize
)
2759 return GL_INVALID_VALUE
;
2766 * Error checking for glCompressedTexSubImage[123]D().
2767 * \return error code or GL_NO_ERROR.
2770 compressed_subtexture_error_check(GLcontext
*ctx
, GLint dimensions
,
2771 GLenum target
, GLint level
,
2772 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2773 GLsizei width
, GLsizei height
, GLsizei depth
,
2774 GLenum format
, GLsizei imageSize
)
2776 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2778 if (dimensions
== 1) {
2779 /* 1D compressed textures not allowed */
2780 return GL_INVALID_ENUM
;
2782 else if (dimensions
== 2) {
2783 if (target
== GL_PROXY_TEXTURE_2D
) {
2784 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2786 else if (target
== GL_TEXTURE_2D
) {
2787 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2789 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2790 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2791 return GL_INVALID_ENUM
; /*target*/
2792 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2794 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2795 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2796 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2797 return GL_INVALID_ENUM
; /*target*/
2798 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2801 return GL_INVALID_ENUM
; /*target*/
2804 else if (dimensions
== 3) {
2805 /* 3D compressed textures not allowed */
2806 return GL_INVALID_ENUM
;
2809 maxTextureSize
= 1 << (maxLevels
- 1);
2811 if (!is_compressed_format(ctx
, format
))
2812 return GL_INVALID_ENUM
;
2814 if (width
< 1 || width
> maxTextureSize
)
2815 return GL_INVALID_VALUE
;
2817 if ((height
< 1 || height
> maxTextureSize
)
2819 return GL_INVALID_VALUE
;
2821 if (level
< 0 || level
>= maxLevels
)
2822 return GL_INVALID_VALUE
;
2824 if ((xoffset
& 3) != 0 || (yoffset
& 3) != 0)
2825 return GL_INVALID_VALUE
;
2827 if ((width
& 3) != 0 && width
!= 2 && width
!= 1)
2828 return GL_INVALID_VALUE
;
2830 if ((height
& 3) != 0 && height
!= 2 && height
!= 1)
2831 return GL_INVALID_VALUE
;
2833 expectedSize
= ctx
->Driver
.CompressedTextureSize(ctx
, width
, height
, depth
,
2835 if (expectedSize
!= imageSize
)
2836 return GL_INVALID_VALUE
;
2844 _mesa_CompressedTexImage1DARB(GLenum target
, GLint level
,
2845 GLenum internalFormat
, GLsizei width
,
2846 GLint border
, GLsizei imageSize
,
2849 GET_CURRENT_CONTEXT(ctx
);
2850 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2852 if (target
== GL_TEXTURE_1D
) {
2853 struct gl_texture_unit
*texUnit
;
2854 struct gl_texture_object
*texObj
;
2855 struct gl_texture_image
*texImage
;
2856 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
2857 internalFormat
, width
, 1, 1, border
, imageSize
);
2859 _mesa_error(ctx
, error
, "glCompressedTexImage1D");
2863 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2864 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2865 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2867 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage1D");
2870 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2871 MESA_PBUFFER_FREE(texImage
->Data
);
2873 texImage
->Data
= NULL
;
2875 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
2876 border
, internalFormat
);
2878 ASSERT(ctx
->Driver
.CompressedTexImage1D
);
2879 (*ctx
->Driver
.CompressedTexImage1D
)(ctx
, target
, level
,
2880 internalFormat
, width
, border
,
2885 texObj
->Complete
= GL_FALSE
;
2886 ctx
->NewState
|= _NEW_TEXTURE
;
2888 else if (target
== GL_PROXY_TEXTURE_1D
) {
2889 /* Proxy texture: check for errors and update proxy state */
2890 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
2891 internalFormat
, width
, 1, 1, border
, imageSize
);
2893 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2894 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2895 internalFormat
, GL_NONE
, GL_NONE
,
2896 width
, 1, 1, border
);
2899 /* if error, clear all proxy texture image parameters */
2900 struct gl_texture_image
*texImage
;
2901 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2903 clear_teximage_fields(texImage
);
2906 /* store the teximage parameters */
2907 struct gl_texture_unit
*texUnit
;
2908 struct gl_texture_image
*texImage
;
2909 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2910 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2911 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
2912 border
, internalFormat
);
2916 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage1D(target)");
2923 _mesa_CompressedTexImage2DARB(GLenum target
, GLint level
,
2924 GLenum internalFormat
, GLsizei width
,
2925 GLsizei height
, GLint border
, GLsizei imageSize
,
2928 GET_CURRENT_CONTEXT(ctx
);
2929 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2931 if (target
== GL_TEXTURE_2D
||
2932 (ctx
->Extensions
.ARB_texture_cube_map
&&
2933 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2934 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
2935 struct gl_texture_unit
*texUnit
;
2936 struct gl_texture_object
*texObj
;
2937 struct gl_texture_image
*texImage
;
2938 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
2939 internalFormat
, width
, height
, 1, border
, imageSize
);
2941 _mesa_error(ctx
, error
, "glCompressedTexImage2D");
2945 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2946 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2947 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2949 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
2952 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2953 MESA_PBUFFER_FREE(texImage
->Data
);
2955 texImage
->Data
= NULL
;
2957 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2958 border
, internalFormat
);
2960 ASSERT(ctx
->Driver
.CompressedTexImage2D
);
2961 (*ctx
->Driver
.CompressedTexImage2D
)(ctx
, target
, level
,
2962 internalFormat
, width
, height
,
2963 border
, imageSize
, data
,
2967 texObj
->Complete
= GL_FALSE
;
2968 ctx
->NewState
|= _NEW_TEXTURE
;
2970 else if (target
== GL_PROXY_TEXTURE_2D
||
2971 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2972 ctx
->Extensions
.ARB_texture_cube_map
)) {
2973 /* Proxy texture: check for errors and update proxy state */
2974 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
2975 internalFormat
, width
, height
, 1, border
, imageSize
);
2977 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2978 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2979 internalFormat
, GL_NONE
, GL_NONE
,
2980 width
, height
, 1, border
);
2983 /* if error, clear all proxy texture image parameters */
2984 struct gl_texture_image
*texImage
;
2985 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2987 clear_teximage_fields(texImage
);
2990 /* store the teximage parameters */
2991 struct gl_texture_unit
*texUnit
;
2992 struct gl_texture_image
*texImage
;
2993 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2994 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2995 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2996 border
, internalFormat
);
3000 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(target)");
3007 _mesa_CompressedTexImage3DARB(GLenum target
, GLint level
,
3008 GLenum internalFormat
, GLsizei width
,
3009 GLsizei height
, GLsizei depth
, GLint border
,
3010 GLsizei imageSize
, const GLvoid
*data
)
3012 GET_CURRENT_CONTEXT(ctx
);
3013 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3015 if (target
== GL_TEXTURE_3D
) {
3016 struct gl_texture_unit
*texUnit
;
3017 struct gl_texture_object
*texObj
;
3018 struct gl_texture_image
*texImage
;
3019 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3020 internalFormat
, width
, height
, depth
, border
, imageSize
);
3022 _mesa_error(ctx
, error
, "glCompressedTexImage3D");
3026 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3027 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3028 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
3030 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage3D");
3033 else if (texImage
->Data
&& !texImage
->IsClientData
) {
3034 MESA_PBUFFER_FREE(texImage
->Data
);
3036 texImage
->Data
= NULL
;
3038 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, depth
,
3039 border
, internalFormat
);
3041 ASSERT(ctx
->Driver
.CompressedTexImage3D
);
3042 (*ctx
->Driver
.CompressedTexImage3D
)(ctx
, target
, level
,
3044 width
, height
, depth
,
3045 border
, imageSize
, data
,
3049 texObj
->Complete
= GL_FALSE
;
3050 ctx
->NewState
|= _NEW_TEXTURE
;
3052 else if (target
== GL_PROXY_TEXTURE_3D
) {
3053 /* Proxy texture: check for errors and update proxy state */
3054 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
3055 internalFormat
, width
, height
, depth
, border
, imageSize
);
3057 ASSERT(ctx
->Driver
.TestProxyTexImage
);
3058 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3059 internalFormat
, GL_NONE
, GL_NONE
,
3060 width
, height
, depth
, border
);
3063 /* if error, clear all proxy texture image parameters */
3064 struct gl_texture_image
*texImage
;
3065 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
3067 clear_teximage_fields(texImage
);
3070 /* store the teximage parameters */
3071 struct gl_texture_unit
*texUnit
;
3072 struct gl_texture_image
*texImage
;
3073 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3074 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3075 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
,
3076 depth
, border
, internalFormat
);
3080 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage3D(target)");
3087 _mesa_CompressedTexSubImage1DARB(GLenum target
, GLint level
, GLint xoffset
,
3088 GLsizei width
, GLenum format
,
3089 GLsizei imageSize
, const GLvoid
*data
)
3091 struct gl_texture_unit
*texUnit
;
3092 struct gl_texture_object
*texObj
;
3093 struct gl_texture_image
*texImage
;
3095 GET_CURRENT_CONTEXT(ctx
);
3096 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3098 error
= compressed_subtexture_error_check(ctx
, 1, target
, level
,
3099 xoffset
, 0, 0, width
, 1, 1, format
, imageSize
);
3101 _mesa_error(ctx
, error
, "glCompressedTexSubImage1D");
3105 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3106 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3107 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3110 if ((GLint
) format
!= texImage
->IntFormat
) {
3111 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3112 "glCompressedTexSubImage1D(format)");
3116 if ((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) {
3117 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage1D(width)");
3121 if (width
== 0 || !data
)
3122 return; /* no-op, not an error */
3124 if (ctx
->Driver
.CompressedTexSubImage1D
) {
3125 (*ctx
->Driver
.CompressedTexSubImage1D
)(ctx
, target
, level
,
3127 format
, imageSize
, data
,
3130 ctx
->NewState
|= _NEW_TEXTURE
;
3135 _mesa_CompressedTexSubImage2DARB(GLenum target
, GLint level
, GLint xoffset
,
3136 GLint yoffset
, GLsizei width
, GLsizei height
,
3137 GLenum format
, GLsizei imageSize
,
3140 struct gl_texture_unit
*texUnit
;
3141 struct gl_texture_object
*texObj
;
3142 struct gl_texture_image
*texImage
;
3144 GET_CURRENT_CONTEXT(ctx
);
3145 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3147 error
= compressed_subtexture_error_check(ctx
, 2, target
, level
,
3148 xoffset
, yoffset
, 0, width
, height
, 1, format
, imageSize
);
3150 /* XXX proxy target? */
3151 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3155 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3156 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3157 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3160 if ((GLint
) format
!= texImage
->IntFormat
) {
3161 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3162 "glCompressedTexSubImage2D(format)");
3166 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3167 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
)) {
3168 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage2D(size)");
3172 if (width
== 0 || height
== 0 || !data
)
3173 return; /* no-op, not an error */
3175 if (ctx
->Driver
.CompressedTexSubImage2D
) {
3176 (*ctx
->Driver
.CompressedTexSubImage2D
)(ctx
, target
, level
,
3177 xoffset
, yoffset
, width
, height
,
3178 format
, imageSize
, data
,
3181 ctx
->NewState
|= _NEW_TEXTURE
;
3186 _mesa_CompressedTexSubImage3DARB(GLenum target
, GLint level
, GLint xoffset
,
3187 GLint yoffset
, GLint zoffset
, GLsizei width
,
3188 GLsizei height
, GLsizei depth
, GLenum format
,
3189 GLsizei imageSize
, const GLvoid
*data
)
3191 struct gl_texture_unit
*texUnit
;
3192 struct gl_texture_object
*texObj
;
3193 struct gl_texture_image
*texImage
;
3195 GET_CURRENT_CONTEXT(ctx
);
3196 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3198 error
= compressed_subtexture_error_check(ctx
, 3, target
, level
,
3199 xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
, imageSize
);
3201 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3205 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3206 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3207 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3210 if ((GLint
) format
!= texImage
->IntFormat
) {
3211 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3212 "glCompressedTexSubImage3D(format)");
3216 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3217 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
) ||
3218 ((depth
== 1 || depth
== 2) && (GLuint
) depth
!= texImage
->Depth
)) {
3219 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage3D(size)");
3223 if (width
== 0 || height
== 0 || depth
== 0 || !data
)
3224 return; /* no-op, not an error */
3226 if (ctx
->Driver
.CompressedTexSubImage3D
) {
3227 (*ctx
->Driver
.CompressedTexSubImage3D
)(ctx
, target
, level
,
3228 xoffset
, yoffset
, zoffset
,
3229 width
, height
, depth
,
3230 format
, imageSize
, data
,
3233 ctx
->NewState
|= _NEW_TEXTURE
;
3238 _mesa_GetCompressedTexImageARB(GLenum target
, GLint level
, GLvoid
*img
)
3240 const struct gl_texture_unit
*texUnit
;
3241 const struct gl_texture_object
*texObj
;
3242 struct gl_texture_image
*texImage
;
3244 GET_CURRENT_CONTEXT(ctx
);
3245 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3247 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3248 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3250 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB");
3254 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
3255 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
3257 if (level
< 0 || level
>= maxLevels
) {
3258 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3262 if (is_proxy_target(target
)) {
3263 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
3267 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3269 /* probably invalid mipmap level */
3270 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3274 if (!texImage
->IsCompressed
) {
3275 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetCompressedTexImageARB");
3282 /* just memcpy, no pixelstore or pixel transfer */
3283 MEMCPY(img
, texImage
->Data
, texImage
->CompressedSize
);