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.
135 * Get base internal format.
137 * \param ctx GL context.
138 * \param format internal texture format enum or 1, 2, 3, 4.
140 * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
141 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
143 * This is the format which is used during texture application (i.e. the
144 * texture format and env mode determine the arithmetic used.
147 _mesa_base_tex_format( GLcontext
*ctx
, GLint format
)
150 * Ask the driver for the base format, if it doesn't
151 * know, it will return -1;
168 case GL_LUMINANCE_ALPHA
:
169 case GL_LUMINANCE4_ALPHA4
:
170 case GL_LUMINANCE6_ALPHA2
:
171 case GL_LUMINANCE8_ALPHA8
:
172 case GL_LUMINANCE12_ALPHA4
:
173 case GL_LUMINANCE12_ALPHA12
:
174 case GL_LUMINANCE16_ALPHA16
:
175 return GL_LUMINANCE_ALPHA
;
203 case GL_COLOR_INDEX1_EXT
:
204 case GL_COLOR_INDEX2_EXT
:
205 case GL_COLOR_INDEX4_EXT
:
206 case GL_COLOR_INDEX8_EXT
:
207 case GL_COLOR_INDEX12_EXT
:
208 case GL_COLOR_INDEX16_EXT
:
209 if (ctx
->Extensions
.EXT_paletted_texture
)
210 return GL_COLOR_INDEX
;
213 case GL_DEPTH_COMPONENT
:
214 case GL_DEPTH_COMPONENT16_SGIX
:
215 case GL_DEPTH_COMPONENT24_SGIX
:
216 case GL_DEPTH_COMPONENT32_SGIX
:
217 if (ctx
->Extensions
.SGIX_depth_texture
)
218 return GL_DEPTH_COMPONENT
;
222 /* GL_ARB_texture_compression */
223 case GL_COMPRESSED_ALPHA
:
224 if (ctx
->Extensions
.ARB_texture_compression
)
228 case GL_COMPRESSED_LUMINANCE
:
229 if (ctx
->Extensions
.ARB_texture_compression
)
233 case GL_COMPRESSED_LUMINANCE_ALPHA
:
234 if (ctx
->Extensions
.ARB_texture_compression
)
235 return GL_LUMINANCE_ALPHA
;
238 case GL_COMPRESSED_INTENSITY
:
239 if (ctx
->Extensions
.ARB_texture_compression
)
243 case GL_COMPRESSED_RGB
:
244 if (ctx
->Extensions
.ARB_texture_compression
)
248 case GL_COMPRESSED_RGBA
:
249 if (ctx
->Extensions
.ARB_texture_compression
)
253 case GL_COMPRESSED_RGB_FXT1_3DFX
:
254 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
)
258 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
259 if (ctx
->Extensions
.TDFX_texture_compression_FXT1
)
265 if (ctx
->Extensions
.MESA_ycbcr_texture
)
266 return GL_YCBCR_MESA
;
271 return -1; /* error */
277 * Test if the given image format is a color/RGBA format, i.e., not
278 * color index, depth, stencil, etc.
281 is_color_format(GLenum format
)
296 case GL_LUMINANCE_ALPHA
:
297 case GL_LUMINANCE4_ALPHA4
:
298 case GL_LUMINANCE6_ALPHA2
:
299 case GL_LUMINANCE8_ALPHA8
:
300 case GL_LUMINANCE12_ALPHA4
:
301 case GL_LUMINANCE12_ALPHA12
:
302 case GL_LUMINANCE16_ALPHA16
:
327 case GL_YCBCR_MESA
: /* not considered to be RGB */
335 * Test if the given image format is a color index format.
338 is_index_format(GLenum format
)
342 case GL_COLOR_INDEX1_EXT
:
343 case GL_COLOR_INDEX2_EXT
:
344 case GL_COLOR_INDEX4_EXT
:
345 case GL_COLOR_INDEX8_EXT
:
346 case GL_COLOR_INDEX12_EXT
:
347 case GL_COLOR_INDEX16_EXT
:
356 * Test if it is a supported compressed format.
358 * \param internalFormat the internal format token provided by the user.
360 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
361 * GL_FALSE otherwise.
363 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
367 is_compressed_format(GLenum internalFormat
)
369 switch (internalFormat
) {
370 case GL_COMPRESSED_RGB_FXT1_3DFX
:
371 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
380 * Store a gl_texture_image pointer in a gl_texture_object structure
381 * according to the target and level parameters.
383 * \param tObj texture object.
384 * \param target texture target.
385 * \param level image level.
386 * \param texImage texture image.
388 * This was basically prompted by the introduction of cube maps.
391 _mesa_set_tex_image(struct gl_texture_object
*tObj
,
392 GLenum target
, GLint level
,
393 struct gl_texture_image
*texImage
)
401 tObj
->Image
[level
] = texImage
;
403 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
404 tObj
->Image
[level
] = texImage
;
406 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
407 tObj
->NegX
[level
] = texImage
;
409 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
410 tObj
->PosY
[level
] = texImage
;
412 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
413 tObj
->NegY
[level
] = texImage
;
415 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
416 tObj
->PosZ
[level
] = texImage
;
418 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
419 tObj
->NegZ
[level
] = texImage
;
421 case GL_TEXTURE_RECTANGLE_NV
:
423 tObj
->Image
[level
] = texImage
;
426 _mesa_problem(NULL
, "bad target in _mesa_set_tex_image()");
433 * Allocate a texture image structure.
435 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
438 * \return a pointer to gl_texture_image struct with all fields initialized to
441 struct gl_texture_image
*
442 _mesa_new_texture_image( GLcontext
*ctx
)
445 return CALLOC_STRUCT(gl_texture_image
);
450 * Free texture image.
452 * \param teximage texture image.
454 * Free the texture image structure and the associated image data if it's not
455 * marked as client data.
458 _mesa_delete_texture_image( struct gl_texture_image
*teximage
)
460 if (teximage
->Data
&& !teximage
->IsClientData
) {
461 MESA_PBUFFER_FREE( teximage
->Data
);
462 teximage
->Data
= NULL
;
469 * Test if a target is a proxy target.
471 * \param target texture target.
473 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
476 is_proxy_target(GLenum target
)
478 return (target
== GL_PROXY_TEXTURE_1D
||
479 target
== GL_PROXY_TEXTURE_2D
||
480 target
== GL_PROXY_TEXTURE_3D
||
481 target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
482 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
);
487 * Get the texture object that corresponds to the target of the given texture unit.
489 * \param ctx GL context.
490 * \param texUnit texture unit.
491 * \param target texture target.
493 * \return pointer to the texture object on success, or NULL on failure.
495 * \sa gl_texture_unit.
497 struct gl_texture_object
*
498 _mesa_select_tex_object(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
503 return texUnit
->Current1D
;
504 case GL_PROXY_TEXTURE_1D
:
505 return ctx
->Texture
.Proxy1D
;
507 return texUnit
->Current2D
;
508 case GL_PROXY_TEXTURE_2D
:
509 return ctx
->Texture
.Proxy2D
;
511 return texUnit
->Current3D
;
512 case GL_PROXY_TEXTURE_3D
:
513 return ctx
->Texture
.Proxy3D
;
514 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
515 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
516 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
517 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
518 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
519 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
520 case GL_TEXTURE_CUBE_MAP_ARB
:
521 return ctx
->Extensions
.ARB_texture_cube_map
522 ? texUnit
->CurrentCubeMap
: NULL
;
523 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
524 return ctx
->Extensions
.ARB_texture_cube_map
525 ? ctx
->Texture
.ProxyCubeMap
: NULL
;
526 case GL_TEXTURE_RECTANGLE_NV
:
527 return ctx
->Extensions
.NV_texture_rectangle
528 ? texUnit
->CurrentRect
: NULL
;
529 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
530 return ctx
->Extensions
.NV_texture_rectangle
531 ? ctx
->Texture
.ProxyRect
: NULL
;
533 _mesa_problem(NULL
, "bad target in _mesa_select_tex_object()");
540 * Get the texture image struct which corresponds to target and level
541 * of the given texture unit.
543 * \param ctx GL context.
544 * \param texUnit texture unit.
545 * \param target texture target.
546 * \param level image level.
548 * \return pointer to the texture image structure on success, or NULL on failure.
550 * \sa gl_texture_unit.
552 struct gl_texture_image
*
553 _mesa_select_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
554 GLenum target
, GLint level
)
557 ASSERT(level
< MAX_TEXTURE_LEVELS
);
560 return texUnit
->Current1D
->Image
[level
];
561 case GL_PROXY_TEXTURE_1D
:
562 return ctx
->Texture
.Proxy1D
->Image
[level
];
564 return texUnit
->Current2D
->Image
[level
];
565 case GL_PROXY_TEXTURE_2D
:
566 return ctx
->Texture
.Proxy2D
->Image
[level
];
568 return texUnit
->Current3D
->Image
[level
];
569 case GL_PROXY_TEXTURE_3D
:
570 return ctx
->Texture
.Proxy3D
->Image
[level
];
571 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
572 if (ctx
->Extensions
.ARB_texture_cube_map
)
573 return texUnit
->CurrentCubeMap
->Image
[level
];
576 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
577 if (ctx
->Extensions
.ARB_texture_cube_map
)
578 return texUnit
->CurrentCubeMap
->NegX
[level
];
581 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
582 if (ctx
->Extensions
.ARB_texture_cube_map
)
583 return texUnit
->CurrentCubeMap
->PosY
[level
];
586 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
587 if (ctx
->Extensions
.ARB_texture_cube_map
)
588 return texUnit
->CurrentCubeMap
->NegY
[level
];
591 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
592 if (ctx
->Extensions
.ARB_texture_cube_map
)
593 return texUnit
->CurrentCubeMap
->PosZ
[level
];
596 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
597 if (ctx
->Extensions
.ARB_texture_cube_map
)
598 return texUnit
->CurrentCubeMap
->NegZ
[level
];
601 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
602 if (ctx
->Extensions
.ARB_texture_cube_map
)
603 return ctx
->Texture
.ProxyCubeMap
->Image
[level
];
606 case GL_TEXTURE_RECTANGLE_NV
:
607 if (ctx
->Extensions
.NV_texture_rectangle
) {
609 return texUnit
->CurrentRect
->Image
[level
];
614 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
615 if (ctx
->Extensions
.NV_texture_rectangle
) {
617 return ctx
->Texture
.ProxyRect
->Image
[level
];
623 _mesa_problem(ctx
, "bad target in _mesa_select_tex_image()");
630 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
631 * it and install it. Only return NULL if passed a bad parameter or run
634 struct gl_texture_image
*
635 _mesa_get_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
636 GLenum target
, GLint level
)
638 struct gl_texture_image
*texImage
;
639 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
641 struct gl_texture_object
*texObj
;
642 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
644 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture image allocation");
647 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
649 _mesa_set_tex_image(texObj
, target
, level
, texImage
);
656 * Return pointer to the specified proxy texture image.
657 * Note that proxy textures are per-context, not per-texture unit.
658 * \return pointer to texture image or NULL if invalid target, invalid
659 * level, or out of memory.
661 struct gl_texture_image
*
662 _mesa_get_proxy_tex_image(GLcontext
*ctx
, GLenum target
, GLint level
)
664 struct gl_texture_image
*texImage
;
670 case GL_PROXY_TEXTURE_1D
:
671 if (level
>= ctx
->Const
.MaxTextureLevels
)
673 texImage
= ctx
->Texture
.Proxy1D
->Image
[level
];
675 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
677 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
680 ctx
->Texture
.Proxy1D
->Image
[level
] = texImage
;
683 case GL_PROXY_TEXTURE_2D
:
684 if (level
>= ctx
->Const
.MaxTextureLevels
)
686 texImage
= ctx
->Texture
.Proxy2D
->Image
[level
];
688 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
690 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
693 ctx
->Texture
.Proxy2D
->Image
[level
] = texImage
;
696 case GL_PROXY_TEXTURE_3D
:
697 if (level
>= ctx
->Const
.Max3DTextureLevels
)
699 texImage
= ctx
->Texture
.Proxy3D
->Image
[level
];
701 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
703 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
706 ctx
->Texture
.Proxy3D
->Image
[level
] = texImage
;
709 case GL_PROXY_TEXTURE_CUBE_MAP
:
710 if (level
>= ctx
->Const
.MaxCubeTextureLevels
)
712 texImage
= ctx
->Texture
.ProxyCubeMap
->Image
[level
];
714 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
716 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
719 ctx
->Texture
.ProxyCubeMap
->Image
[level
] = texImage
;
722 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
725 texImage
= ctx
->Texture
.ProxyRect
->Image
[level
];
727 texImage
= ctx
->Driver
.NewTextureImage(ctx
);
729 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "proxy texture allocation");
732 ctx
->Texture
.ProxyRect
->Image
[level
] = texImage
;
742 * Get the maximum number of allowed mipmap levels.
744 * \param ctx GL context.
745 * \param target texture target.
747 * \return the maximum number of allowed mipmap levels for the given
748 * texture target, or zero if passed a bad target.
753 _mesa_max_texture_levels(GLcontext
*ctx
, GLenum target
)
757 case GL_PROXY_TEXTURE_1D
:
759 case GL_PROXY_TEXTURE_2D
:
760 return ctx
->Const
.MaxTextureLevels
;
762 case GL_PROXY_TEXTURE_3D
:
763 return ctx
->Const
.Max3DTextureLevels
;
764 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
765 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
766 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
767 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
768 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
769 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
770 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
771 return ctx
->Const
.MaxCubeTextureLevels
;
773 case GL_TEXTURE_RECTANGLE_NV
:
774 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
778 return 0; /* bad target */
784 #if 000 /* not used anymore */
786 * glTexImage[123]D can accept a NULL image pointer. In this case we
787 * create a texture image with unspecified image contents per the OpenGL
791 make_null_texture(GLint width
, GLint height
, GLint depth
, GLenum format
)
793 const GLint components
= _mesa_components_in_format(format
);
794 const GLint numPixels
= width
* height
* depth
;
795 GLubyte
*data
= (GLubyte
*) MALLOC(numPixels
* components
* sizeof(GLubyte
));
799 * Let's see if anyone finds this. If glTexImage2D() is called with
800 * a NULL image pointer then load the texture image with something
801 * interesting instead of leaving it indeterminate.
804 static const char message
[8][32] = {
808 " X X XXXX XXX XXXXX ",
811 " X X XXXXX XXX X X ",
815 GLubyte
*imgPtr
= data
;
817 for (h
= 0; h
< depth
; h
++) {
818 for (i
= 0; i
< height
; i
++) {
819 GLint srcRow
= 7 - (i
% 8);
820 for (j
= 0; j
< width
; j
++) {
821 GLint srcCol
= j
% 32;
822 GLubyte texel
= (message
[srcRow
][srcCol
]=='X') ? 255 : 70;
823 for (k
= 0; k
< components
; k
++) {
839 * Reset the fields of a gl_texture_image struct to zero.
841 * \param img texture image structure.
843 * This is called when a proxy texture test fails, we set all the
844 * image members (except DriverData) to zero.
845 * It's also used in glTexImage[123]D as a safeguard to be sure all
846 * required fields get initialized properly by the Driver.TexImage[123]D
850 clear_teximage_fields(struct gl_texture_image
*img
)
867 img
->TexFormat
= &_mesa_null_texformat
;
868 img
->FetchTexel
= NULL
;
869 img
->IsCompressed
= 0;
870 img
->CompressedSize
= 0;
875 * Initialize basic fields of the gl_texture_image struct.
877 * \param ctx GL context.
878 * \param target texture target.
879 * \param img texture image structure to be initialized.
880 * \param width image width.
881 * \param height image height.
882 * \param depth image depth.
883 * \param border image border.
884 * \param internalFormat internal format.
886 * Fills in the fields of \p img with the given information.
887 * Note: width, height and depth include the border.
890 _mesa_init_teximage_fields(GLcontext
*ctx
, GLenum target
,
891 struct gl_texture_image
*img
,
892 GLsizei width
, GLsizei height
, GLsizei depth
,
893 GLint border
, GLenum internalFormat
)
896 img
->Format
= _mesa_base_tex_format( ctx
, internalFormat
);
897 ASSERT(img
->Format
> 0);
898 img
->IntFormat
= internalFormat
;
899 img
->Border
= border
;
901 img
->Height
= height
;
903 img
->RowStride
= width
;
904 img
->WidthLog2
= logbase2(width
- 2 * border
);
905 if (height
== 1) /* 1-D texture */
908 img
->HeightLog2
= logbase2(height
- 2 * border
);
909 if (depth
== 1) /* 2-D texture */
912 img
->DepthLog2
= logbase2(depth
- 2 * border
);
913 img
->Width2
= width
- 2 * border
; /*1 << img->WidthLog2;*/
914 img
->Height2
= height
- 2 * border
; /*1 << img->HeightLog2;*/
915 img
->Depth2
= depth
- 2 * border
; /*1 << img->DepthLog2;*/
916 img
->MaxLog2
= MAX2(img
->WidthLog2
, img
->HeightLog2
);
917 img
->IsCompressed
= is_compressed_format(internalFormat
);
918 if (img
->IsCompressed
)
919 img
->CompressedSize
= _mesa_compressed_texture_size(ctx
, width
, height
,
920 depth
, internalFormat
);
922 img
->CompressedSize
= 0;
924 if ((width
== 1 || _mesa_bitcount(width
- 2 * border
) == 1) &&
925 (height
== 1 || _mesa_bitcount(height
- 2 * border
) == 1) &&
926 (depth
== 1 || _mesa_bitcount(depth
- 2 * border
) == 1))
927 img
->_IsPowerOfTwo
= GL_TRUE
;
929 img
->_IsPowerOfTwo
= GL_FALSE
;
931 /* Compute Width/Height/DepthScale for mipmap lod computation */
932 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
933 /* scale = 1.0 since texture coords directly map to texels */
934 img
->WidthScale
= 1.0;
935 img
->HeightScale
= 1.0;
936 img
->DepthScale
= 1.0;
939 img
->WidthScale
= (GLfloat
) img
->Width
;
940 img
->HeightScale
= (GLfloat
) img
->Height
;
941 img
->DepthScale
= (GLfloat
) img
->Depth
;
947 * This is the fallback for Driver.TestProxyTexImage(). Test the texture
948 * level, width, height and depth against the ctx->Const limits for textures.
950 * A hardware driver might override this function if, for example, the
951 * max 3D texture size is 512x512x64 (i.e. not a cube).
953 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
954 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
955 * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
956 * \param level as passed to glTexImage
957 * \param internalFormat as passed to glTexImage
958 * \param format as passed to glTexImage
959 * \param type as passed to glTexImage
960 * \param width as passed to glTexImage
961 * \param height as passed to glTexImage
962 * \param depth as passed to glTexImage
963 * \param border as passed to glTexImage
964 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
967 _mesa_test_proxy_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
968 GLint internalFormat
, GLenum format
, GLenum type
,
969 GLint width
, GLint height
, GLint depth
, GLint border
)
973 (void) internalFormat
;
978 case GL_PROXY_TEXTURE_1D
:
979 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
980 if (width
< 2 * border
|| width
> 2 + maxSize
||
981 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
982 _mesa_bitcount(width
- 2 * border
) != 1) ||
983 level
>= ctx
->Const
.MaxTextureLevels
) {
984 /* bad width or level */
988 case GL_PROXY_TEXTURE_2D
:
989 maxSize
= 1 << (ctx
->Const
.MaxTextureLevels
- 1);
990 if (width
< 2 * border
|| width
> 2 + maxSize
||
991 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
992 _mesa_bitcount(width
- 2 * border
) != 1) ||
993 height
< 2 * border
|| height
> 2 + maxSize
||
994 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
995 _mesa_bitcount(height
- 2 * border
) != 1) ||
996 level
>= ctx
->Const
.MaxTextureLevels
) {
997 /* bad width or height or level */
1001 case GL_PROXY_TEXTURE_3D
:
1002 maxSize
= 1 << (ctx
->Const
.Max3DTextureLevels
- 1);
1003 if (width
< 2 * border
|| width
> 2 + maxSize
||
1004 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1005 _mesa_bitcount(width
- 2 * border
) != 1) ||
1006 height
< 2 * border
|| height
> 2 + maxSize
||
1007 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1008 _mesa_bitcount(height
- 2 * border
) != 1) ||
1009 depth
< 2 * border
|| depth
> 2 + maxSize
||
1010 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&&
1011 _mesa_bitcount(depth
- 2 * border
) != 1) ||
1012 level
>= ctx
->Const
.Max3DTextureLevels
) {
1013 /* bad width or height or depth or level */
1017 case GL_PROXY_TEXTURE_RECTANGLE_NV
:
1018 if (width
< 1 || width
> ctx
->Const
.MaxTextureRectSize
||
1019 height
< 1 || height
> ctx
->Const
.MaxTextureRectSize
||
1021 /* bad width or height or level */
1025 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
1026 maxSize
= 1 << (ctx
->Const
.MaxCubeTextureLevels
- 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
.MaxCubeTextureLevels
) {
1034 /* bad width or height */
1039 _mesa_problem(ctx
, "Invalid target in _mesa_test_proxy_teximage");
1046 * Test the glTexImage[123]D() parameters for errors.
1048 * \param ctx GL context.
1049 * \param target texture target given by the user.
1050 * \param level image level given by the user.
1051 * \param internalFormat internal format given by the user.
1052 * \param format pixel data format given by the user.
1053 * \param type pixel data type given by the user.
1054 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1055 * \param width image width given by the user.
1056 * \param height image height given by the user.
1057 * \param depth image depth given by the user.
1058 * \param border image border given by the user.
1060 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1062 * Verifies each of the parameters against the constants specified in
1063 * __GLcontextRec::Const and the supported extensions, and according to the
1064 * OpenGL specification.
1067 texture_error_check( GLcontext
*ctx
, GLenum target
,
1068 GLint level
, GLint internalFormat
,
1069 GLenum format
, GLenum type
,
1071 GLint width
, GLint height
,
1072 GLint depth
, GLint border
)
1074 const GLboolean isProxy
= is_proxy_target(target
);
1077 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1078 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1080 _mesa_error(ctx
, GL_INVALID_VALUE
,
1081 "glTexImage%dD(level=%d)", dimensions
, level
);
1087 if (border
< 0 || border
> 1 ||
1088 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1089 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1091 _mesa_error(ctx
, GL_INVALID_VALUE
,
1092 "glTexImage%dD(border=%d)", dimensions
, border
);
1097 if (width
< 1 || height
< 1 || depth
< 1) {
1099 _mesa_error(ctx
, GL_INVALID_VALUE
,
1100 "glTexImage%dD(width, height or depth < 1)", dimensions
);
1105 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1106 * level, width, height and depth.
1108 if (dimensions
== 1) {
1109 if (target
== GL_PROXY_TEXTURE_1D
|| target
== GL_TEXTURE_1D
) {
1110 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1111 level
, internalFormat
,
1113 width
, 1, 1, border
);
1116 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1120 else if (dimensions
== 2) {
1121 if (target
== GL_PROXY_TEXTURE_2D
|| target
== GL_TEXTURE_2D
) {
1122 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1123 level
, internalFormat
,
1125 width
, height
, 1, border
);
1127 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
||
1128 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1129 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
1130 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1131 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1134 sizeOK
= (width
== height
) &&
1135 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1136 level
, internalFormat
, format
, type
,
1137 width
, height
, 1, border
);
1139 else if (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
||
1140 target
== GL_TEXTURE_RECTANGLE_NV
) {
1141 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1142 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1145 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1146 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1147 level
, internalFormat
,
1149 width
, height
, 1, border
);
1152 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)");
1156 else if (dimensions
== 3) {
1157 if (target
== GL_PROXY_TEXTURE_3D
|| target
== GL_TEXTURE_3D
) {
1158 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_3D
,
1159 level
, internalFormat
,
1161 width
, height
, depth
, border
);
1164 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1169 _mesa_problem( ctx
, "bad dims in texture_error_check" );
1175 _mesa_error(ctx
, GL_INVALID_VALUE
,
1176 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1177 dimensions
, level
, width
, height
, depth
);
1182 /* Check internalFormat */
1183 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1185 _mesa_error(ctx
, GL_INVALID_VALUE
,
1186 "glTexImage%dD(internalFormat=0x%x)",
1187 dimensions
, internalFormat
);
1192 /* Check incoming image format and type */
1193 if (!_mesa_is_legal_format_and_type(format
, type
)) {
1194 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1195 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1198 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1199 "glTexImage%dD(format or type)", dimensions
);
1204 if (format
== GL_YCBCR_MESA
|| internalFormat
== GL_YCBCR_MESA
) {
1205 ASSERT(ctx
->Extensions
.MESA_ycbcr_texture
);
1206 if (format
!= GL_YCBCR_MESA
||
1207 internalFormat
!= GL_YCBCR_MESA
||
1208 (type
!= GL_UNSIGNED_SHORT_8_8_MESA
&&
1209 type
!= GL_UNSIGNED_SHORT_8_8_REV_MESA
)) {
1211 _mesa_sprintf(message
,
1212 "glTexImage%d(format/type/internalFormat YCBCR mismatch",
1214 _mesa_error(ctx
, GL_INVALID_ENUM
, message
);
1215 return GL_TRUE
; /* error */
1217 if (target
!= GL_TEXTURE_2D
&&
1218 target
!= GL_PROXY_TEXTURE_2D
&&
1219 target
!= GL_TEXTURE_RECTANGLE_NV
&&
1220 target
!= GL_PROXY_TEXTURE_RECTANGLE_NV
) {
1222 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexImage(target)");
1228 _mesa_sprintf(message
,
1229 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1230 dimensions
, border
);
1231 _mesa_error(ctx
, GL_INVALID_VALUE
, message
);
1237 if (is_compressed_format(internalFormat
)) {
1238 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1241 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1242 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1243 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1244 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1249 _mesa_error(ctx
, GL_INVALID_ENUM
,
1250 "glTexImage%d(target)", dimensions
);
1256 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1257 "glTexImage%D(border!=0)", dimensions
);
1263 /* if we get here, the parameters are OK */
1269 * Test glTexSubImage[123]D() parameters for errors.
1271 * \param ctx GL context.
1272 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1273 * \param target texture target given by the user.
1274 * \param level image level given by the user.
1275 * \param xoffset sub-image x offset given by the user.
1276 * \param yoffset sub-image y offset given by the user.
1277 * \param zoffset sub-image z offset given by the user.
1278 * \param format pixel data format given by the user.
1279 * \param type pixel data type given by the user.
1280 * \param width image width given by the user.
1281 * \param height image height given by the user.
1282 * \param depth image depth given by the user.
1284 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1286 * Verifies each of the parameters against the constants specified in
1287 * __GLcontextRec::Const and the supported extensions, and according to the
1288 * OpenGL specification.
1291 subtexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1292 GLenum target
, GLint level
,
1293 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1294 GLint width
, GLint height
, GLint depth
,
1295 GLenum format
, GLenum type
)
1297 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1298 struct gl_texture_image
*destTex
;
1301 if (dimensions
== 1) {
1302 if (target
!= GL_TEXTURE_1D
) {
1303 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
1307 else if (dimensions
== 2) {
1308 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1309 target
<=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1310 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1311 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1315 else if (ctx
->Extensions
.NV_texture_rectangle
&&
1316 target
== GL_TEXTURE_RECTANGLE_NV
) {
1317 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1318 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1322 else if (target
!= GL_TEXTURE_2D
) {
1323 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1327 else if (dimensions
== 3) {
1328 if (target
!= GL_TEXTURE_3D
) {
1329 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
1334 _mesa_problem( ctx
, "invalid dims in texture_error_check" );
1338 /* Basic level check */
1339 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1340 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level=%d)", level
);
1345 _mesa_error(ctx
, GL_INVALID_VALUE
,
1346 "glTexSubImage%dD(width=%d)", dimensions
, width
);
1349 if (height
< 0 && dimensions
> 1) {
1350 _mesa_error(ctx
, GL_INVALID_VALUE
,
1351 "glTexSubImage%dD(height=%d)", dimensions
, height
);
1354 if (depth
< 0 && dimensions
> 2) {
1355 _mesa_error(ctx
, GL_INVALID_VALUE
,
1356 "glTexSubImage%dD(depth=%d)", dimensions
, depth
);
1360 destTex
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1363 /* undefined image level */
1364 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage%dD", dimensions
);
1368 if (xoffset
< -((GLint
)destTex
->Border
)) {
1369 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset)",
1373 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
1374 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(xoffset+width)",
1378 if (dimensions
> 1) {
1379 if (yoffset
< -((GLint
)destTex
->Border
)) {
1380 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset)",
1384 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
1385 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage%dD(yoffset+height)",
1390 if (dimensions
> 2) {
1391 if (zoffset
< -((GLint
)destTex
->Border
)) {
1392 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
1395 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+ destTex
->Border
)) {
1396 _mesa_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
1401 if (!_mesa_is_legal_format_and_type(format
, type
)) {
1402 _mesa_error(ctx
, GL_INVALID_ENUM
,
1403 "glTexSubImage%dD(format or type)", dimensions
);
1407 if (destTex
->IsCompressed
) {
1408 const struct gl_texture_unit
*texUnit
;
1409 const struct gl_texture_image
*texImage
;
1410 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1411 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1413 if (target
== GL_TEXTURE_2D
|| target
== GL_PROXY_TEXTURE_2D
) {
1416 else if (ctx
->Extensions
.ARB_texture_cube_map
&&
1417 (target
== GL_PROXY_TEXTURE_CUBE_MAP
||
1418 (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
1419 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
1423 _mesa_error(ctx
, GL_INVALID_ENUM
,
1424 "glTexSubImage%D(target)", dimensions
);
1427 /* offset must be multiple of 4 */
1428 if ((xoffset
& 3) || (yoffset
& 3)) {
1429 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1430 "glTexSubImage%D(xoffset or yoffset)", dimensions
);
1433 /* size must be multiple of 4 or equal to whole texture size */
1434 if ((width
& 3) && (GLuint
) width
!= texImage
->Width
) {
1435 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1436 "glTexSubImage%D(width)", dimensions
);
1439 if ((height
& 3) && (GLuint
) height
!= texImage
->Height
) {
1440 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1441 "glTexSubImage%D(width)", dimensions
);
1451 * Test glCopyTexImage[12]D() parameters for errors.
1453 * \param ctx GL context.
1454 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1455 * \param target texture target given by the user.
1456 * \param level image level given by the user.
1457 * \param internalFormat internal format given by the user.
1458 * \param width image width given by the user.
1459 * \param height image height given by the user.
1460 * \param depth image depth given by the user.
1461 * \param border texture border.
1463 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1465 * Verifies each of the parameters against the constants specified in
1466 * __GLcontextRec::Const and the supported extensions, and according to the
1467 * OpenGL specification.
1470 copytexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1471 GLenum target
, GLint level
, GLint internalFormat
,
1472 GLint width
, GLint height
, GLint border
)
1474 GLenum format
, type
;
1477 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1478 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1479 _mesa_error(ctx
, GL_INVALID_VALUE
,
1480 "glCopyTexImage%dD(level=%d)", dimensions
, level
);
1485 if (border
< 0 || border
> 1 ||
1486 ((target
== GL_TEXTURE_RECTANGLE_NV
||
1487 target
== GL_PROXY_TEXTURE_RECTANGLE_NV
) && border
!= 0)) {
1491 /* The format and type aren't really significant here, but we need to pass
1492 * something to TestProxyTexImage().
1494 format
= _mesa_base_tex_format(ctx
, internalFormat
);
1497 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1498 * level, width, height and depth.
1500 if (dimensions
== 1) {
1501 if (target
== GL_TEXTURE_1D
) {
1502 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_1D
,
1503 level
, internalFormat
,
1505 width
, 1, 1, border
);
1508 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
1512 else if (dimensions
== 2) {
1513 if (target
== GL_TEXTURE_2D
) {
1514 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_2D
,
1515 level
, internalFormat
,
1517 width
, height
, 1, border
);
1519 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1520 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1521 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1522 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1525 sizeOK
= (width
== height
) &&
1526 ctx
->Driver
.TestProxyTexImage(ctx
, GL_PROXY_TEXTURE_CUBE_MAP_ARB
,
1527 level
, internalFormat
, format
, type
,
1528 width
, height
, 1, border
);
1530 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1531 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1532 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1535 sizeOK
= ctx
->Driver
.TestProxyTexImage(ctx
,
1536 GL_PROXY_TEXTURE_RECTANGLE_NV
,
1537 level
, internalFormat
,
1539 width
, height
, 1, border
);
1542 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1547 _mesa_problem(ctx
, "invalid dimensions in copytexture_error_check");
1552 if (dimensions
== 1) {
1553 _mesa_error(ctx
, GL_INVALID_VALUE
,
1554 "glCopyTexImage1D(width=%d)", width
);
1557 ASSERT(dimensions
== 2);
1558 _mesa_error(ctx
, GL_INVALID_VALUE
,
1559 "glCopyTexImage2D(width=%d, height=%d)", width
, height
);
1564 if (_mesa_base_tex_format(ctx
, internalFormat
) < 0) {
1565 _mesa_error(ctx
, GL_INVALID_VALUE
,
1566 "glCopyTexImage%dD(internalFormat)", dimensions
);
1570 if (is_compressed_format(internalFormat
)) {
1571 if (target
!= GL_TEXTURE_2D
) {
1572 _mesa_error(ctx
, GL_INVALID_ENUM
,
1573 "glCopyTexImage%d(target)", dimensions
);
1577 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1578 "glCopyTexImage%D(border!=0)", dimensions
);
1583 /* if we get here, the parameters are OK */
1589 * Test glCopyTexImage[12]D() parameters for errors.
1591 * \param ctx GL context.
1592 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1593 * \param target texture target given by the user.
1594 * \param level image level given by the user.
1595 * \param xoffset sub-image x offset given by the user.
1596 * \param yoffset sub-image y offset given by the user.
1597 * \param zoffset sub-image z offset given by the user.
1598 * \param width image width given by the user.
1599 * \param height image height given by the user.
1601 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1603 * Verifies each of the parameters against the constants specified in
1604 * __GLcontextRec::Const and the supported extensions, and according to the
1605 * OpenGL specification.
1608 copytexsubimage_error_check( GLcontext
*ctx
, GLuint dimensions
,
1609 GLenum target
, GLint level
,
1610 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1611 GLsizei width
, GLsizei height
)
1613 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1614 struct gl_texture_image
*teximage
;
1617 if (dimensions
== 1) {
1618 if (target
!= GL_TEXTURE_1D
) {
1619 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
1623 else if (dimensions
== 2) {
1624 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1625 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1626 if (!ctx
->Extensions
.ARB_texture_cube_map
) {
1627 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1631 else if (target
== GL_TEXTURE_RECTANGLE_NV
) {
1632 if (!ctx
->Extensions
.NV_texture_rectangle
) {
1633 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1637 else if (target
!= GL_TEXTURE_2D
) {
1638 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1642 else if (dimensions
== 3) {
1643 if (target
!= GL_TEXTURE_3D
) {
1644 _mesa_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
1650 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
1651 _mesa_error(ctx
, GL_INVALID_VALUE
,
1652 "glCopyTexSubImage%dD(level=%d)", dimensions
, level
);
1658 _mesa_error(ctx
, GL_INVALID_VALUE
,
1659 "glCopyTexSubImage%dD(width=%d)", dimensions
, width
);
1662 if (dimensions
> 1 && height
< 0) {
1663 _mesa_error(ctx
, GL_INVALID_VALUE
,
1664 "glCopyTexSubImage%dD(height=%d)", dimensions
, height
);
1668 teximage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1670 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1671 "glCopyTexSubImage%dD(undefined texture level: %d)",
1676 if (xoffset
< -((GLint
)teximage
->Border
)) {
1677 _mesa_error(ctx
, GL_INVALID_VALUE
,
1678 "glCopyTexSubImage%dD(xoffset=%d)", dimensions
, xoffset
);
1681 if (xoffset
+ width
> (GLint
) (teximage
->Width
+ teximage
->Border
)) {
1682 _mesa_error(ctx
, GL_INVALID_VALUE
,
1683 "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
1686 if (dimensions
> 1) {
1687 if (yoffset
< -((GLint
)teximage
->Border
)) {
1688 _mesa_error(ctx
, GL_INVALID_VALUE
,
1689 "glCopyTexSubImage%dD(yoffset=%d)", dimensions
, yoffset
);
1692 /* NOTE: we're adding the border here, not subtracting! */
1693 if (yoffset
+ height
> (GLint
) (teximage
->Height
+ teximage
->Border
)) {
1694 _mesa_error(ctx
, GL_INVALID_VALUE
,
1695 "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
1700 if (dimensions
> 2) {
1701 if (zoffset
< -((GLint
)teximage
->Border
)) {
1702 _mesa_error(ctx
, GL_INVALID_VALUE
,
1703 "glCopyTexSubImage%dD(zoffset)", dimensions
);
1706 if (zoffset
> (GLint
) (teximage
->Depth
+ teximage
->Border
)) {
1707 _mesa_error(ctx
, GL_INVALID_VALUE
,
1708 "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
1713 if (teximage
->IsCompressed
) {
1714 if (target
!= GL_TEXTURE_2D
) {
1715 _mesa_error(ctx
, GL_INVALID_ENUM
,
1716 "glCopyTexSubImage%d(target)", dimensions
);
1719 /* offset must be multiple of 4 */
1720 if ((xoffset
& 3) || (yoffset
& 3)) {
1721 _mesa_error(ctx
, GL_INVALID_VALUE
,
1722 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions
);
1725 /* size must be multiple of 4 */
1726 if ((width
& 3) != 0 && (GLuint
) width
!= teximage
->Width
) {
1727 _mesa_error(ctx
, GL_INVALID_VALUE
,
1728 "glCopyTexSubImage%D(width)", dimensions
);
1731 if ((height
& 3) != 0 && (GLuint
) height
!= teximage
->Height
) {
1732 _mesa_error(ctx
, GL_INVALID_VALUE
,
1733 "glCopyTexSubImage%D(height)", dimensions
);
1738 if (teximage
->IntFormat
== GL_YCBCR_MESA
) {
1739 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glCopyTexSubImage2D");
1743 /* if we get here, the parameters are OK */
1749 * Get texture image.
1751 * \param target texture target.
1752 * \param level image level.
1753 * \param format pixel data format.
1754 * \param type pixel data type.
1755 * \param pixels pixel data.
1758 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
1759 GLenum type
, GLvoid
*pixels
)
1761 const struct gl_texture_unit
*texUnit
;
1762 const struct gl_texture_object
*texObj
;
1763 const struct gl_texture_image
*texImage
;
1764 GLint maxLevels
= 0;
1765 GET_CURRENT_CONTEXT(ctx
);
1766 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
1768 texUnit
= &(ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
]);
1769 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
1770 if (!texObj
|| is_proxy_target(target
)) {
1771 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)");
1775 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
1776 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
1778 if (level
< 0 || level
>= maxLevels
) {
1779 _mesa_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
1783 if (_mesa_sizeof_packed_type(type
) <= 0) {
1784 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
1788 if (_mesa_components_in_format(format
) <= 0 ||
1789 format
== GL_STENCIL_INDEX
) {
1790 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
1794 if (!ctx
->Extensions
.EXT_paletted_texture
&& is_index_format(format
)) {
1795 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1798 if (!ctx
->Extensions
.SGIX_depth_texture
&& format
== GL_DEPTH_COMPONENT
) {
1799 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1802 if (!ctx
->Extensions
.MESA_ycbcr_texture
&& format
== GL_YCBCR_MESA
) {
1803 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
1806 /* XXX what if format/type doesn't match texture format/type? */
1811 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1813 /* invalid mipmap level, not an error */
1817 if (!texImage
->Data
) {
1818 /* no image data, not an error */
1823 const GLint width
= texImage
->Width
;
1824 const GLint height
= texImage
->Height
;
1825 const GLint depth
= texImage
->Depth
;
1827 for (img
= 0; img
< depth
; img
++) {
1828 for (row
= 0; row
< height
; row
++) {
1829 /* compute destination address in client memory */
1830 GLvoid
*dest
= _mesa_image_address( &ctx
->Pack
, pixels
,
1831 width
, height
, format
, type
,
1835 if (format
== GL_COLOR_INDEX
) {
1836 GLuint indexRow
[MAX_WIDTH
];
1838 for (col
= 0; col
< width
; col
++) {
1839 (*texImage
->FetchTexel
)(texImage
, col
, row
, img
,
1840 (GLvoid
*) &indexRow
[col
]);
1842 _mesa_pack_index_span(ctx
, width
, type
, dest
,
1843 indexRow
, &ctx
->Pack
,
1844 0 /* no image transfer */);
1846 else if (format
== GL_DEPTH_COMPONENT
) {
1847 GLfloat depthRow
[MAX_WIDTH
];
1849 for (col
= 0; col
< width
; col
++) {
1850 (*texImage
->FetchTexel
)(texImage
, col
, row
, img
,
1851 (GLvoid
*) &depthRow
[col
]);
1853 _mesa_pack_depth_span(ctx
, width
, dest
, type
,
1854 depthRow
, &ctx
->Pack
);
1856 else if (format
== GL_YCBCR_MESA
) {
1857 /* No pixel transfer */
1858 const GLint rowstride
= texImage
->RowStride
;
1860 (const GLushort
*) texImage
->Data
+ row
* rowstride
,
1861 width
* sizeof(GLushort
));
1862 /* check for byte swapping */
1863 if ((texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR
1864 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
1865 (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_YCBCR_REV
1866 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
1867 if (!ctx
->Pack
.SwapBytes
)
1868 _mesa_swap2((GLushort
*) dest
, width
);
1870 else if (ctx
->Pack
.SwapBytes
) {
1871 _mesa_swap2((GLushort
*) dest
, width
);
1875 /* general case: convert row to RGBA format */
1876 GLchan rgba
[MAX_WIDTH
][4];
1878 for (col
= 0; col
< width
; col
++) {
1879 (*texImage
->FetchTexel
)(texImage
, col
, row
, img
,
1880 (GLvoid
*) rgba
[col
]);
1882 _mesa_pack_rgba_span(ctx
, width
, (const GLchan (*)[4])rgba
,
1883 format
, type
, dest
, &ctx
->Pack
,
1884 0 /* no image transfer */);
1894 * Called from the API. Note that width includes the border.
1897 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalFormat
,
1898 GLsizei width
, GLint border
, GLenum format
,
1899 GLenum type
, const GLvoid
*pixels
)
1901 GLsizei postConvWidth
= width
;
1902 GET_CURRENT_CONTEXT(ctx
);
1903 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
1905 if (is_color_format(internalFormat
)) {
1906 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
1909 if (target
== GL_TEXTURE_1D
) {
1910 struct gl_texture_unit
*texUnit
;
1911 struct gl_texture_object
*texObj
;
1912 struct gl_texture_image
*texImage
;
1914 if (texture_error_check(ctx
, target
, level
, internalFormat
,
1915 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
1916 return; /* error was recorded */
1919 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1920 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
1921 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
1924 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
1927 else if (texImage
->Data
&& !texImage
->IsClientData
) {
1928 /* free the old texture data */
1929 MESA_PBUFFER_FREE(texImage
->Data
);
1931 texImage
->Data
= NULL
;
1932 clear_teximage_fields(texImage
); /* not really needed, but helpful */
1933 _mesa_init_teximage_fields(ctx
, target
, texImage
,
1934 postConvWidth
, 1, 1,
1935 border
, internalFormat
);
1937 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
1938 _mesa_update_state(ctx
);
1940 ASSERT(ctx
->Driver
.TexImage1D
);
1942 /* Give the texture to the driver! <pixels> may be null! */
1943 (*ctx
->Driver
.TexImage1D
)(ctx
, target
, level
, internalFormat
,
1944 width
, border
, format
, type
, pixels
,
1945 &ctx
->Unpack
, texObj
, texImage
);
1947 ASSERT(texImage
->TexFormat
);
1948 if (!texImage
->FetchTexel
) {
1949 /* If driver didn't explicitly set this, use the default */
1950 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel1D
;
1952 ASSERT(texImage
->FetchTexel
);
1955 texObj
->Complete
= GL_FALSE
;
1956 ctx
->NewState
|= _NEW_TEXTURE
;
1958 else if (target
== GL_PROXY_TEXTURE_1D
) {
1959 /* Proxy texture: check for errors and update proxy state */
1960 struct gl_texture_image
*texImage
;
1961 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
1962 if (texture_error_check(ctx
, target
, level
, internalFormat
,
1963 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
1964 /* when error, clear all proxy texture image parameters */
1966 clear_teximage_fields(texImage
);
1969 /* no error, set the tex image parameters */
1971 _mesa_init_teximage_fields(ctx
, target
, texImage
,
1972 postConvWidth
, 1, 1,
1973 border
, internalFormat
);
1974 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
1975 internalFormat
, format
, type
);
1979 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1986 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalFormat
,
1987 GLsizei width
, GLsizei height
, GLint border
,
1988 GLenum format
, GLenum type
,
1989 const GLvoid
*pixels
)
1991 GLsizei postConvWidth
= width
, postConvHeight
= height
;
1992 GET_CURRENT_CONTEXT(ctx
);
1993 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
1995 if (is_color_format(internalFormat
)) {
1996 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2000 if (target
== GL_TEXTURE_2D
||
2001 (ctx
->Extensions
.ARB_texture_cube_map
&&
2002 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2003 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) ||
2004 (ctx
->Extensions
.NV_texture_rectangle
&&
2005 target
== GL_TEXTURE_RECTANGLE_NV
)) {
2006 /* non-proxy target */
2007 struct gl_texture_unit
*texUnit
;
2008 struct gl_texture_object
*texObj
;
2009 struct gl_texture_image
*texImage
;
2011 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2012 format
, type
, 2, postConvWidth
, postConvHeight
,
2014 return; /* error was recorded */
2017 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2018 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2019 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2021 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
2024 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2025 /* free the old texture data */
2026 MESA_PBUFFER_FREE(texImage
->Data
);
2028 texImage
->Data
= NULL
;
2029 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2030 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2031 postConvWidth
, postConvHeight
, 1,
2032 border
, internalFormat
);
2034 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2035 _mesa_update_state(ctx
);
2037 ASSERT(ctx
->Driver
.TexImage2D
);
2039 /* Give the texture to the driver! <pixels> may be null! */
2040 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, internalFormat
,
2041 width
, height
, border
, format
, type
, pixels
,
2042 &ctx
->Unpack
, texObj
, texImage
);
2044 ASSERT(texImage
->TexFormat
);
2045 if (!texImage
->FetchTexel
) {
2046 /* If driver didn't explicitly set this, use the default */
2047 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel2D
;
2049 ASSERT(texImage
->FetchTexel
);
2052 texObj
->Complete
= GL_FALSE
;
2053 ctx
->NewState
|= _NEW_TEXTURE
;
2055 else if (target
== GL_PROXY_TEXTURE_2D
||
2056 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2057 ctx
->Extensions
.ARB_texture_cube_map
) ||
2058 (target
== GL_PROXY_TEXTURE_RECTANGLE_NV
&&
2059 ctx
->Extensions
.NV_texture_rectangle
)) {
2060 /* Proxy texture: check for errors and update proxy state */
2061 struct gl_texture_image
*texImage
;
2062 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2063 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2064 format
, type
, 2, postConvWidth
, postConvHeight
,
2066 /* when error, clear all proxy texture image parameters */
2068 clear_teximage_fields(ctx
->Texture
.Proxy2D
->Image
[level
]);
2071 /* no error, set the tex image parameters */
2072 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2073 postConvWidth
, postConvHeight
, 1,
2074 border
, internalFormat
);
2075 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2076 internalFormat
, format
, type
);
2080 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
2087 * Called by the API or display list executor.
2088 * Note that width and height include the border.
2091 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalFormat
,
2092 GLsizei width
, GLsizei height
, GLsizei depth
,
2093 GLint border
, GLenum format
, GLenum type
,
2094 const GLvoid
*pixels
)
2096 GET_CURRENT_CONTEXT(ctx
);
2097 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2099 if (target
== GL_TEXTURE_3D
) {
2100 struct gl_texture_unit
*texUnit
;
2101 struct gl_texture_object
*texObj
;
2102 struct gl_texture_image
*texImage
;
2104 if (texture_error_check(ctx
, target
, level
, (GLint
) internalFormat
,
2105 format
, type
, 3, width
, height
, depth
, border
)) {
2106 return; /* error was recorded */
2109 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2110 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2111 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2113 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
2116 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2117 MESA_PBUFFER_FREE(texImage
->Data
);
2119 texImage
->Data
= NULL
;
2120 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2121 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2122 width
, height
, depth
,
2123 border
, internalFormat
);
2125 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2126 _mesa_update_state(ctx
);
2128 ASSERT(ctx
->Driver
.TexImage3D
);
2130 /* Give the texture to the driver! <pixels> may be null! */
2131 (*ctx
->Driver
.TexImage3D
)(ctx
, target
, level
, internalFormat
,
2132 width
, height
, depth
, border
, format
, type
,
2133 pixels
, &ctx
->Unpack
, texObj
, texImage
);
2135 ASSERT(texImage
->TexFormat
);
2136 if (!texImage
->FetchTexel
) {
2137 /* If driver didn't explicitly set this, use the default */
2138 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel3D
;
2140 ASSERT(texImage
->FetchTexel
);
2143 texObj
->Complete
= GL_FALSE
;
2144 ctx
->NewState
|= _NEW_TEXTURE
;
2146 else if (target
== GL_PROXY_TEXTURE_3D
) {
2147 /* Proxy texture: check for errors and update proxy state */
2148 struct gl_texture_image
*texImage
;
2149 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2150 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2151 format
, type
, 3, width
, height
, depth
, border
)) {
2152 /* when error, clear all proxy texture image parameters */
2154 clear_teximage_fields(texImage
);
2157 /* no error, set the tex image parameters */
2158 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2159 border
, internalFormat
);
2160 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
2161 internalFormat
, format
, type
);
2165 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
2172 _mesa_TexImage3DEXT( GLenum target
, GLint level
, GLenum internalFormat
,
2173 GLsizei width
, GLsizei height
, GLsizei depth
,
2174 GLint border
, GLenum format
, GLenum type
,
2175 const GLvoid
*pixels
)
2177 _mesa_TexImage3D(target
, level
, (GLint
) internalFormat
, width
, height
,
2178 depth
, border
, format
, type
, pixels
);
2184 _mesa_TexSubImage1D( GLenum target
, GLint level
,
2185 GLint xoffset
, GLsizei width
,
2186 GLenum format
, GLenum type
,
2187 const GLvoid
*pixels
)
2189 GLsizei postConvWidth
= width
;
2190 struct gl_texture_unit
*texUnit
;
2191 struct gl_texture_object
*texObj
;
2192 struct gl_texture_image
*texImage
;
2193 GET_CURRENT_CONTEXT(ctx
);
2194 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2196 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2197 _mesa_update_state(ctx
);
2199 /* XXX should test internal format */
2200 if (is_color_format(format
)) {
2201 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2204 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
2205 postConvWidth
, 1, 1, format
, type
)) {
2206 return; /* error was detected */
2209 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2210 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2211 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2214 if (width
== 0 || !pixels
)
2215 return; /* no-op, not an error */
2217 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2218 xoffset
+= texImage
->Border
;
2220 ASSERT(ctx
->Driver
.TexSubImage1D
);
2221 (*ctx
->Driver
.TexSubImage1D
)(ctx
, target
, level
, xoffset
, width
,
2222 format
, type
, pixels
, &ctx
->Unpack
,
2224 ctx
->NewState
|= _NEW_TEXTURE
;
2229 _mesa_TexSubImage2D( GLenum target
, GLint level
,
2230 GLint xoffset
, GLint yoffset
,
2231 GLsizei width
, GLsizei height
,
2232 GLenum format
, GLenum type
,
2233 const GLvoid
*pixels
)
2235 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2236 struct gl_texture_unit
*texUnit
;
2237 struct gl_texture_object
*texObj
;
2238 struct gl_texture_image
*texImage
;
2239 GET_CURRENT_CONTEXT(ctx
);
2240 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2242 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2243 _mesa_update_state(ctx
);
2245 /* XXX should test internal format */
2246 if (is_color_format(format
)) {
2247 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2251 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2252 postConvWidth
, postConvHeight
, 1, format
, type
)) {
2253 return; /* error was detected */
2256 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2257 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2258 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2261 if (width
== 0 || height
== 0 || !pixels
)
2262 return; /* no-op, not an error */
2264 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2265 xoffset
+= texImage
->Border
;
2266 yoffset
+= texImage
->Border
;
2268 ASSERT(ctx
->Driver
.TexSubImage2D
);
2269 (*ctx
->Driver
.TexSubImage2D
)(ctx
, target
, level
, xoffset
, yoffset
,
2270 width
, height
, format
, type
, pixels
,
2271 &ctx
->Unpack
, texObj
, texImage
);
2272 ctx
->NewState
|= _NEW_TEXTURE
;
2278 _mesa_TexSubImage3D( GLenum target
, GLint level
,
2279 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2280 GLsizei width
, GLsizei height
, GLsizei depth
,
2281 GLenum format
, GLenum type
,
2282 const GLvoid
*pixels
)
2284 struct gl_texture_unit
*texUnit
;
2285 struct gl_texture_object
*texObj
;
2286 struct gl_texture_image
*texImage
;
2287 GET_CURRENT_CONTEXT(ctx
);
2288 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2290 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2291 _mesa_update_state(ctx
);
2293 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2294 width
, height
, depth
, format
, type
)) {
2295 return; /* error was detected */
2298 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2299 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2300 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2303 if (width
== 0 || height
== 0 || height
== 0 || !pixels
)
2304 return; /* no-op, not an error */
2306 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2307 xoffset
+= texImage
->Border
;
2308 yoffset
+= texImage
->Border
;
2309 zoffset
+= texImage
->Border
;
2311 ASSERT(ctx
->Driver
.TexSubImage3D
);
2312 (*ctx
->Driver
.TexSubImage3D
)(ctx
, target
, level
,
2313 xoffset
, yoffset
, zoffset
,
2314 width
, height
, depth
,
2315 format
, type
, pixels
,
2316 &ctx
->Unpack
, texObj
, texImage
);
2317 ctx
->NewState
|= _NEW_TEXTURE
;
2323 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
2324 GLenum internalFormat
,
2326 GLsizei width
, GLint border
)
2328 struct gl_texture_unit
*texUnit
;
2329 struct gl_texture_object
*texObj
;
2330 struct gl_texture_image
*texImage
;
2331 GLsizei postConvWidth
= width
;
2332 GET_CURRENT_CONTEXT(ctx
);
2333 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2335 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2336 _mesa_update_state(ctx
);
2338 if (is_color_format(internalFormat
)) {
2339 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2342 if (copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
2343 postConvWidth
, 1, border
))
2346 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2347 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2348 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2350 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D");
2353 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2354 /* free the old texture data */
2355 MESA_PBUFFER_FREE(texImage
->Data
);
2357 texImage
->Data
= NULL
;
2359 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2360 _mesa_init_teximage_fields(ctx
, target
, texImage
, postConvWidth
, 1, 1,
2361 border
, internalFormat
);
2364 ASSERT(ctx
->Driver
.CopyTexImage1D
);
2365 (*ctx
->Driver
.CopyTexImage1D
)(ctx
, target
, level
, internalFormat
,
2366 x
, y
, width
, border
);
2368 ASSERT(texImage
->TexFormat
);
2369 if (!texImage
->FetchTexel
) {
2370 /* If driver didn't explicitly set this, use the default */
2371 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel1D
;
2373 ASSERT(texImage
->FetchTexel
);
2376 texObj
->Complete
= GL_FALSE
;
2377 ctx
->NewState
|= _NEW_TEXTURE
;
2383 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
2384 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2387 struct gl_texture_unit
*texUnit
;
2388 struct gl_texture_object
*texObj
;
2389 struct gl_texture_image
*texImage
;
2390 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2391 GET_CURRENT_CONTEXT(ctx
);
2392 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2394 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2395 _mesa_update_state(ctx
);
2397 if (is_color_format(internalFormat
)) {
2398 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
,
2402 if (copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
2403 postConvWidth
, postConvHeight
, border
))
2406 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2407 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2408 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2410 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D");
2413 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2414 /* free the old texture data */
2415 MESA_PBUFFER_FREE(texImage
->Data
);
2417 texImage
->Data
= NULL
;
2419 clear_teximage_fields(texImage
); /* not really needed, but helpful */
2420 _mesa_init_teximage_fields(ctx
, target
, texImage
,
2421 postConvWidth
, postConvHeight
, 1,
2422 border
, internalFormat
);
2424 ASSERT(ctx
->Driver
.CopyTexImage2D
);
2425 (*ctx
->Driver
.CopyTexImage2D
)(ctx
, target
, level
, internalFormat
,
2426 x
, y
, width
, height
, border
);
2428 ASSERT(texImage
->TexFormat
);
2429 if (!texImage
->FetchTexel
) {
2430 /* If driver didn't explicitly set this, use the default */
2431 texImage
->FetchTexel
= texImage
->TexFormat
->FetchTexel2D
;
2433 ASSERT(texImage
->FetchTexel
);
2436 texObj
->Complete
= GL_FALSE
;
2437 ctx
->NewState
|= _NEW_TEXTURE
;
2443 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
2444 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
2446 struct gl_texture_unit
*texUnit
;
2447 struct gl_texture_object
*texObj
;
2448 struct gl_texture_image
*texImage
;
2449 GLsizei postConvWidth
= width
;
2450 GET_CURRENT_CONTEXT(ctx
);
2451 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2453 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2454 _mesa_update_state(ctx
);
2456 /* XXX should test internal format */
2457 _mesa_adjust_image_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2459 if (copytexsubimage_error_check(ctx
, 1, target
, level
,
2460 xoffset
, 0, 0, postConvWidth
, 1))
2463 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2464 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2465 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2468 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2469 xoffset
+= texImage
->Border
;
2471 ASSERT(ctx
->Driver
.CopyTexSubImage1D
);
2472 (*ctx
->Driver
.CopyTexSubImage1D
)(ctx
, target
, level
, xoffset
, x
, y
, width
);
2473 ctx
->NewState
|= _NEW_TEXTURE
;
2479 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
2480 GLint xoffset
, GLint yoffset
,
2481 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2483 struct gl_texture_unit
*texUnit
;
2484 struct gl_texture_object
*texObj
;
2485 struct gl_texture_image
*texImage
;
2486 GLsizei postConvWidth
= width
, postConvHeight
= height
;
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
, 2, &postConvWidth
, &postConvHeight
);
2496 if (copytexsubimage_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2497 postConvWidth
, postConvHeight
))
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
;
2507 yoffset
+= texImage
->Border
;
2509 ASSERT(ctx
->Driver
.CopyTexSubImage2D
);
2510 (*ctx
->Driver
.CopyTexSubImage2D
)(ctx
, target
, level
,
2511 xoffset
, yoffset
, x
, y
, width
, height
);
2512 ctx
->NewState
|= _NEW_TEXTURE
;
2518 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
2519 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2520 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2522 struct gl_texture_unit
*texUnit
;
2523 struct gl_texture_object
*texObj
;
2524 struct gl_texture_image
*texImage
;
2525 GLsizei postConvWidth
= width
, postConvHeight
= height
;
2526 GET_CURRENT_CONTEXT(ctx
);
2527 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2529 if (ctx
->NewState
& _IMAGE_NEW_TRANSFER_STATE
)
2530 _mesa_update_state(ctx
);
2532 /* XXX should test internal format */
2533 _mesa_adjust_image_for_convolution(ctx
, 2, &postConvWidth
, &postConvHeight
);
2535 if (copytexsubimage_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
,
2536 zoffset
, postConvWidth
, postConvHeight
))
2539 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2540 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2541 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2544 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2545 xoffset
+= texImage
->Border
;
2546 yoffset
+= texImage
->Border
;
2547 zoffset
+= texImage
->Border
;
2549 ASSERT(ctx
->Driver
.CopyTexSubImage3D
);
2550 (*ctx
->Driver
.CopyTexSubImage3D
)(ctx
, target
, level
,
2551 xoffset
, yoffset
, zoffset
,
2552 x
, y
, width
, height
);
2553 ctx
->NewState
|= _NEW_TEXTURE
;
2559 /**********************************************************************/
2560 /****** Compressed Textures ******/
2561 /**********************************************************************/
2565 * Error checking for glCompressedTexImage[123]D().
2566 * \return error code or GL_NO_ERROR.
2569 compressed_texture_error_check(GLcontext
*ctx
, GLint dimensions
,
2570 GLenum target
, GLint level
,
2571 GLenum internalFormat
, GLsizei width
,
2572 GLsizei height
, GLsizei depth
, GLint border
,
2575 GLboolean isProxy
= GL_FALSE
;
2576 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2578 if (dimensions
== 1) {
2579 /* 1D compressed textures not allowed */
2580 return GL_INVALID_ENUM
;
2582 else if (dimensions
== 2) {
2583 if (target
== GL_PROXY_TEXTURE_2D
) {
2584 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2587 else if (target
== GL_TEXTURE_2D
) {
2588 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2590 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2591 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2592 return GL_INVALID_ENUM
; /*target*/
2593 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2596 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2597 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2598 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2599 return GL_INVALID_ENUM
; /*target*/
2600 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2603 return GL_INVALID_ENUM
; /*target*/
2606 else if (dimensions
== 3) {
2607 /* 3D compressed textures not allowed */
2608 return GL_INVALID_ENUM
;
2611 maxTextureSize
= 1 << (maxLevels
- 1);
2613 if (!is_compressed_format(internalFormat
))
2614 return GL_INVALID_ENUM
;
2617 return GL_INVALID_VALUE
;
2620 * XXX We should probably use the proxy texture error check function here.
2622 if (width
< 1 || width
> maxTextureSize
||
2623 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(width
) < 0))
2624 return GL_INVALID_VALUE
;
2626 if ((height
< 1 || height
> maxTextureSize
||
2627 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(height
) < 0))
2629 return GL_INVALID_VALUE
;
2631 if ((depth
< 1 || depth
> maxTextureSize
||
2632 (!ctx
->Extensions
.ARB_texture_non_power_of_two
&& logbase2(depth
) < 0))
2634 return GL_INVALID_VALUE
;
2636 /* For cube map, width must equal height */
2637 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2638 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
&& width
!= height
)
2639 return GL_INVALID_VALUE
;
2641 if (level
< 0 || level
>= maxLevels
)
2642 return GL_INVALID_VALUE
;
2644 expectedSize
= _mesa_compressed_texture_size(ctx
, width
, height
, depth
,
2646 if (expectedSize
!= imageSize
)
2647 return GL_INVALID_VALUE
;
2654 * Error checking for glCompressedTexSubImage[123]D().
2655 * \return error code or GL_NO_ERROR.
2658 compressed_subtexture_error_check(GLcontext
*ctx
, GLint dimensions
,
2659 GLenum target
, GLint level
,
2660 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2661 GLsizei width
, GLsizei height
, GLsizei depth
,
2662 GLenum format
, GLsizei imageSize
)
2664 GLboolean isProxy
= GL_FALSE
;
2665 GLint expectedSize
, maxLevels
= 0, maxTextureSize
;
2667 if (dimensions
== 1) {
2668 /* 1D compressed textures not allowed */
2669 return GL_INVALID_ENUM
;
2671 else if (dimensions
== 2) {
2672 if (target
== GL_PROXY_TEXTURE_2D
) {
2673 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2676 else if (target
== GL_TEXTURE_2D
) {
2677 maxLevels
= ctx
->Const
.MaxTextureLevels
;
2679 else if (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
) {
2680 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2681 return GL_INVALID_ENUM
; /*target*/
2682 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2685 else if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2686 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
2687 if (!ctx
->Extensions
.ARB_texture_cube_map
)
2688 return GL_INVALID_ENUM
; /*target*/
2689 maxLevels
= ctx
->Const
.MaxCubeTextureLevels
;
2692 return GL_INVALID_ENUM
; /*target*/
2695 else if (dimensions
== 3) {
2696 /* 3D compressed textures not allowed */
2697 return GL_INVALID_ENUM
;
2700 maxTextureSize
= 1 << (maxLevels
- 1);
2702 if (!is_compressed_format(format
))
2703 return GL_INVALID_ENUM
;
2705 if (width
< 1 || width
> maxTextureSize
)
2706 return GL_INVALID_VALUE
;
2708 if ((height
< 1 || height
> maxTextureSize
)
2710 return GL_INVALID_VALUE
;
2712 if (level
< 0 || level
>= maxLevels
)
2713 return GL_INVALID_VALUE
;
2715 if ((xoffset
& 3) != 0 || (yoffset
& 3) != 0)
2716 return GL_INVALID_VALUE
;
2718 if ((width
& 3) != 0 && width
!= 2 && width
!= 1)
2719 return GL_INVALID_VALUE
;
2721 if ((height
& 3) != 0 && height
!= 2 && height
!= 1)
2722 return GL_INVALID_VALUE
;
2724 expectedSize
= _mesa_compressed_texture_size(ctx
, width
, height
, depth
,
2726 if (expectedSize
!= imageSize
)
2727 return GL_INVALID_VALUE
;
2735 _mesa_CompressedTexImage1DARB(GLenum target
, GLint level
,
2736 GLenum internalFormat
, GLsizei width
,
2737 GLint border
, GLsizei imageSize
,
2740 GET_CURRENT_CONTEXT(ctx
);
2741 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2743 if (target
== GL_TEXTURE_1D
) {
2744 struct gl_texture_unit
*texUnit
;
2745 struct gl_texture_object
*texObj
;
2746 struct gl_texture_image
*texImage
;
2747 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
2748 internalFormat
, width
, 1, 1, border
, imageSize
);
2750 _mesa_error(ctx
, error
, "glCompressedTexImage1D");
2754 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2755 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2756 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2758 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage1D");
2761 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2762 MESA_PBUFFER_FREE(texImage
->Data
);
2764 texImage
->Data
= NULL
;
2766 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
2767 border
, internalFormat
);
2769 ASSERT(ctx
->Driver
.CompressedTexImage1D
);
2770 (*ctx
->Driver
.CompressedTexImage1D
)(ctx
, target
, level
,
2771 internalFormat
, width
, border
,
2776 texObj
->Complete
= GL_FALSE
;
2777 ctx
->NewState
|= _NEW_TEXTURE
;
2779 else if (target
== GL_PROXY_TEXTURE_1D
) {
2780 /* Proxy texture: check for errors and update proxy state */
2781 GLenum error
= compressed_texture_error_check(ctx
, 1, target
, level
,
2782 internalFormat
, width
, 1, 1, border
, imageSize
);
2784 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2785 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2786 internalFormat
, GL_NONE
, GL_NONE
,
2787 width
, 1, 1, border
);
2790 /* if error, clear all proxy texture image parameters */
2791 struct gl_texture_image
*texImage
;
2792 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2794 clear_teximage_fields(texImage
);
2797 /* store the teximage parameters */
2798 struct gl_texture_unit
*texUnit
;
2799 struct gl_texture_image
*texImage
;
2800 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2801 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2802 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, 1, 1,
2803 border
, internalFormat
);
2807 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage1D(target)");
2814 _mesa_CompressedTexImage2DARB(GLenum target
, GLint level
,
2815 GLenum internalFormat
, GLsizei width
,
2816 GLsizei height
, GLint border
, GLsizei imageSize
,
2819 GET_CURRENT_CONTEXT(ctx
);
2820 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2822 if (target
== GL_TEXTURE_2D
||
2823 (ctx
->Extensions
.ARB_texture_cube_map
&&
2824 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
2825 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
2826 struct gl_texture_unit
*texUnit
;
2827 struct gl_texture_object
*texObj
;
2828 struct gl_texture_image
*texImage
;
2829 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
2830 internalFormat
, width
, height
, 1, border
, imageSize
);
2832 _mesa_error(ctx
, error
, "glCompressedTexImage2D");
2836 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2837 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2838 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2840 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
2843 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2844 MESA_PBUFFER_FREE(texImage
->Data
);
2846 texImage
->Data
= NULL
;
2848 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2849 border
, internalFormat
);
2851 ASSERT(ctx
->Driver
.CompressedTexImage2D
);
2852 (*ctx
->Driver
.CompressedTexImage2D
)(ctx
, target
, level
,
2853 internalFormat
, width
, height
,
2854 border
, imageSize
, data
,
2858 texObj
->Complete
= GL_FALSE
;
2859 ctx
->NewState
|= _NEW_TEXTURE
;
2861 else if (target
== GL_PROXY_TEXTURE_2D
||
2862 (target
== GL_PROXY_TEXTURE_CUBE_MAP_ARB
&&
2863 ctx
->Extensions
.ARB_texture_cube_map
)) {
2864 /* Proxy texture: check for errors and update proxy state */
2865 GLenum error
= compressed_texture_error_check(ctx
, 2, target
, level
,
2866 internalFormat
, width
, height
, 1, border
, imageSize
);
2868 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2869 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2870 internalFormat
, GL_NONE
, GL_NONE
,
2871 width
, height
, 1, border
);
2874 /* if error, clear all proxy texture image parameters */
2875 struct gl_texture_image
*texImage
;
2876 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2878 clear_teximage_fields(texImage
);
2881 /* store the teximage parameters */
2882 struct gl_texture_unit
*texUnit
;
2883 struct gl_texture_image
*texImage
;
2884 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2885 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2886 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, 1,
2887 border
, internalFormat
);
2891 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(target)");
2898 _mesa_CompressedTexImage3DARB(GLenum target
, GLint level
,
2899 GLenum internalFormat
, GLsizei width
,
2900 GLsizei height
, GLsizei depth
, GLint border
,
2901 GLsizei imageSize
, const GLvoid
*data
)
2903 GET_CURRENT_CONTEXT(ctx
);
2904 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2906 if (target
== GL_TEXTURE_3D
) {
2907 struct gl_texture_unit
*texUnit
;
2908 struct gl_texture_object
*texObj
;
2909 struct gl_texture_image
*texImage
;
2910 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
2911 internalFormat
, width
, height
, depth
, border
, imageSize
);
2913 _mesa_error(ctx
, error
, "glCompressedTexImage3D");
2917 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2918 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2919 texImage
= _mesa_get_tex_image(ctx
, texUnit
, target
, level
);
2921 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage3D");
2924 else if (texImage
->Data
&& !texImage
->IsClientData
) {
2925 MESA_PBUFFER_FREE(texImage
->Data
);
2927 texImage
->Data
= NULL
;
2929 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
, depth
,
2930 border
, internalFormat
);
2932 ASSERT(ctx
->Driver
.CompressedTexImage3D
);
2933 (*ctx
->Driver
.CompressedTexImage3D
)(ctx
, target
, level
,
2935 width
, height
, depth
,
2936 border
, imageSize
, data
,
2940 texObj
->Complete
= GL_FALSE
;
2941 ctx
->NewState
|= _NEW_TEXTURE
;
2943 else if (target
== GL_PROXY_TEXTURE_3D
) {
2944 /* Proxy texture: check for errors and update proxy state */
2945 GLenum error
= compressed_texture_error_check(ctx
, 3, target
, level
,
2946 internalFormat
, width
, height
, depth
, border
, imageSize
);
2948 ASSERT(ctx
->Driver
.TestProxyTexImage
);
2949 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2950 internalFormat
, GL_NONE
, GL_NONE
,
2951 width
, height
, depth
, border
);
2954 /* if error, clear all proxy texture image parameters */
2955 struct gl_texture_image
*texImage
;
2956 texImage
= _mesa_get_proxy_tex_image(ctx
, target
, level
);
2958 clear_teximage_fields(texImage
);
2961 /* store the teximage parameters */
2962 struct gl_texture_unit
*texUnit
;
2963 struct gl_texture_image
*texImage
;
2964 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2965 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2966 _mesa_init_teximage_fields(ctx
, target
, texImage
, width
, height
,
2967 depth
, border
, internalFormat
);
2971 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage3D(target)");
2978 _mesa_CompressedTexSubImage1DARB(GLenum target
, GLint level
, GLint xoffset
,
2979 GLsizei width
, GLenum format
,
2980 GLsizei imageSize
, const GLvoid
*data
)
2982 struct gl_texture_unit
*texUnit
;
2983 struct gl_texture_object
*texObj
;
2984 struct gl_texture_image
*texImage
;
2986 GET_CURRENT_CONTEXT(ctx
);
2987 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
2989 error
= compressed_subtexture_error_check(ctx
, 1, target
, level
,
2990 xoffset
, 0, 0, width
, 1, 1, format
, imageSize
);
2992 _mesa_error(ctx
, error
, "glCompressedTexSubImage1D");
2996 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2997 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2998 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3001 if ((GLint
) format
!= texImage
->IntFormat
) {
3002 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3003 "glCompressedTexSubImage1D(format)");
3007 if ((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) {
3008 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage1D(width)");
3012 if (width
== 0 || !data
)
3013 return; /* no-op, not an error */
3015 if (ctx
->Driver
.CompressedTexSubImage1D
) {
3016 (*ctx
->Driver
.CompressedTexSubImage1D
)(ctx
, target
, level
,
3018 format
, imageSize
, data
,
3021 ctx
->NewState
|= _NEW_TEXTURE
;
3026 _mesa_CompressedTexSubImage2DARB(GLenum target
, GLint level
, GLint xoffset
,
3027 GLint yoffset
, GLsizei width
, GLsizei height
,
3028 GLenum format
, GLsizei imageSize
,
3031 struct gl_texture_unit
*texUnit
;
3032 struct gl_texture_object
*texObj
;
3033 struct gl_texture_image
*texImage
;
3035 GET_CURRENT_CONTEXT(ctx
);
3036 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3038 error
= compressed_subtexture_error_check(ctx
, 2, target
, level
,
3039 xoffset
, yoffset
, 0, width
, height
, 1, format
, imageSize
);
3041 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3045 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3046 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3047 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3050 if ((GLint
) format
!= texImage
->IntFormat
) {
3051 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3052 "glCompressedTexSubImage2D(format)");
3056 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3057 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
)) {
3058 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage2D(size)");
3062 if (width
== 0 || height
== 0 || !data
)
3063 return; /* no-op, not an error */
3065 if (ctx
->Driver
.CompressedTexSubImage2D
) {
3066 (*ctx
->Driver
.CompressedTexSubImage2D
)(ctx
, target
, level
,
3067 xoffset
, yoffset
, width
, height
,
3068 format
, imageSize
, data
,
3071 ctx
->NewState
|= _NEW_TEXTURE
;
3076 _mesa_CompressedTexSubImage3DARB(GLenum target
, GLint level
, GLint xoffset
,
3077 GLint yoffset
, GLint zoffset
, GLsizei width
,
3078 GLsizei height
, GLsizei depth
, GLenum format
,
3079 GLsizei imageSize
, const GLvoid
*data
)
3081 struct gl_texture_unit
*texUnit
;
3082 struct gl_texture_object
*texObj
;
3083 struct gl_texture_image
*texImage
;
3085 GET_CURRENT_CONTEXT(ctx
);
3086 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3088 error
= compressed_subtexture_error_check(ctx
, 3, target
, level
,
3089 xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
, imageSize
);
3091 _mesa_error(ctx
, error
, "glCompressedTexSubImage2D");
3095 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3096 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3097 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3100 if ((GLint
) format
!= texImage
->IntFormat
) {
3101 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3102 "glCompressedTexSubImage3D(format)");
3106 if (((width
== 1 || width
== 2) && (GLuint
) width
!= texImage
->Width
) ||
3107 ((height
== 1 || height
== 2) && (GLuint
) height
!= texImage
->Height
) ||
3108 ((depth
== 1 || depth
== 2) && (GLuint
) depth
!= texImage
->Depth
)) {
3109 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexSubImage3D(size)");
3113 if (width
== 0 || height
== 0 || depth
== 0 || !data
)
3114 return; /* no-op, not an error */
3116 if (ctx
->Driver
.CompressedTexSubImage3D
) {
3117 (*ctx
->Driver
.CompressedTexSubImage3D
)(ctx
, target
, level
,
3118 xoffset
, yoffset
, zoffset
,
3119 width
, height
, depth
,
3120 format
, imageSize
, data
,
3123 ctx
->NewState
|= _NEW_TEXTURE
;
3128 _mesa_GetCompressedTexImageARB(GLenum target
, GLint level
, GLvoid
*img
)
3130 const struct gl_texture_unit
*texUnit
;
3131 const struct gl_texture_object
*texObj
;
3132 struct gl_texture_image
*texImage
;
3134 GET_CURRENT_CONTEXT(ctx
);
3135 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
3137 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3138 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3140 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB");
3144 maxLevels
= _mesa_max_texture_levels(ctx
, target
);
3145 ASSERT(maxLevels
> 0); /* 0 indicates bad target, caught above */
3147 if (level
< 0 || level
>= maxLevels
) {
3148 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3152 if (is_proxy_target(target
)) {
3153 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
3157 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
3159 /* probably invalid mipmap level */
3160 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3164 if (!texImage
->IsCompressed
) {
3165 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetCompressedTexImageARB");
3172 /* just memcpy, no pixelstore or pixel transfer */
3173 MEMCPY(img
, texImage
->Data
, texImage
->CompressedSize
);