1 /* $Id: teximage.c,v 1.53 2000/10/28 18:34:48 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48 * Mesa's native texture datatype is GLubyte. Native formats are
49 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
51 * Device drivers are free to implement any internal format they want.
56 static void PrintTexture(const struct gl_texture_image
*img
)
59 GLubyte
*data
= img
->Data
;
62 printf("No texture data\n");
66 switch (img
->Format
) {
73 case GL_LUMINANCE_ALPHA
:
83 gl_problem(NULL
, "error in PrintTexture\n");
88 for (i
= 0; i
< img
->Height
; i
++) {
89 for (j
= 0; j
< img
->Width
; j
++) {
91 printf("%02x ", data
[0]);
93 printf("%02x%02x ", data
[0], data
[1]);
95 printf("%02x%02x%02x ", data
[0], data
[1], data
[2]);
97 printf("%02x%02x%02x%02x ", data
[0], data
[1], data
[2], data
[3]);
108 * Compute log base 2 of n.
109 * If n isn't an exact power of two return -1.
137 * Given an internal texture format enum or 1, 2, 3, 4 return the
138 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
139 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
140 * Return -1 if invalid enum.
143 _mesa_base_tex_format( GLcontext
*ctx
, GLint format
)
146 * Ask the driver for the base format, if it doesn't
147 * know, it will return -1;
149 if (ctx
->Driver
.BaseCompressedTexFormat
) {
150 GLint ifmt
= (*ctx
->Driver
.BaseCompressedTexFormat
)(ctx
, format
);
170 case GL_LUMINANCE_ALPHA
:
171 case GL_LUMINANCE4_ALPHA4
:
172 case GL_LUMINANCE6_ALPHA2
:
173 case GL_LUMINANCE8_ALPHA8
:
174 case GL_LUMINANCE12_ALPHA4
:
175 case GL_LUMINANCE12_ALPHA12
:
176 case GL_LUMINANCE16_ALPHA16
:
177 return GL_LUMINANCE_ALPHA
;
205 case GL_COLOR_INDEX1_EXT
:
206 case GL_COLOR_INDEX2_EXT
:
207 case GL_COLOR_INDEX4_EXT
:
208 case GL_COLOR_INDEX8_EXT
:
209 case GL_COLOR_INDEX12_EXT
:
210 case GL_COLOR_INDEX16_EXT
:
211 return GL_COLOR_INDEX
;
213 return -1; /* error */
220 * Given an internal texture format enum or 1, 2, 3, 4 return the
221 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
222 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
223 * number of components for the format. Return -1 if invalid enum.
226 components_in_intformat( GLint format
)
243 case GL_LUMINANCE_ALPHA
:
244 case GL_LUMINANCE4_ALPHA4
:
245 case GL_LUMINANCE6_ALPHA2
:
246 case GL_LUMINANCE8_ALPHA8
:
247 case GL_LUMINANCE12_ALPHA4
:
248 case GL_LUMINANCE12_ALPHA12
:
249 case GL_LUMINANCE16_ALPHA16
:
278 case GL_COLOR_INDEX1_EXT
:
279 case GL_COLOR_INDEX2_EXT
:
280 case GL_COLOR_INDEX4_EXT
:
281 case GL_COLOR_INDEX8_EXT
:
282 case GL_COLOR_INDEX12_EXT
:
283 case GL_COLOR_INDEX16_EXT
:
286 return -1; /* error */
292 * Return GL_TRUE if internalFormat is a compressed format, return GL_FALSE
296 is_compressed_format(GLcontext
*ctx
, GLenum internalFormat
)
298 if (ctx
->Driver
.IsCompressedFormat
) {
299 return (*ctx
->Driver
.IsCompressedFormat
)(ctx
, internalFormat
);
307 * Examine the texImage->Format field and set the Red, Green, Blue, etc
308 * texel component sizes to default values.
309 * These fields are set only here by core Mesa but device drivers may
310 * overwritting these fields to indicate true texel resolution.
313 set_teximage_component_sizes( struct gl_texture_image
*texImage
)
315 switch (texImage
->Format
) {
317 texImage
->RedBits
= 0;
318 texImage
->GreenBits
= 0;
319 texImage
->BlueBits
= 0;
320 texImage
->AlphaBits
= 8;
321 texImage
->IntensityBits
= 0;
322 texImage
->LuminanceBits
= 0;
323 texImage
->IndexBits
= 0;
326 texImage
->RedBits
= 0;
327 texImage
->GreenBits
= 0;
328 texImage
->BlueBits
= 0;
329 texImage
->AlphaBits
= 0;
330 texImage
->IntensityBits
= 0;
331 texImage
->LuminanceBits
= 8;
332 texImage
->IndexBits
= 0;
334 case GL_LUMINANCE_ALPHA
:
335 texImage
->RedBits
= 0;
336 texImage
->GreenBits
= 0;
337 texImage
->BlueBits
= 0;
338 texImage
->AlphaBits
= 8;
339 texImage
->IntensityBits
= 0;
340 texImage
->LuminanceBits
= 8;
341 texImage
->IndexBits
= 0;
344 texImage
->RedBits
= 0;
345 texImage
->GreenBits
= 0;
346 texImage
->BlueBits
= 0;
347 texImage
->AlphaBits
= 0;
348 texImage
->IntensityBits
= 8;
349 texImage
->LuminanceBits
= 0;
350 texImage
->IndexBits
= 0;
353 texImage
->RedBits
= 8;
354 texImage
->GreenBits
= 0;
355 texImage
->BlueBits
= 0;
356 texImage
->AlphaBits
= 0;
357 texImage
->IntensityBits
= 0;
358 texImage
->LuminanceBits
= 0;
359 texImage
->IndexBits
= 0;
362 texImage
->RedBits
= 0;
363 texImage
->GreenBits
= 8;
364 texImage
->BlueBits
= 0;
365 texImage
->AlphaBits
= 0;
366 texImage
->IntensityBits
= 0;
367 texImage
->LuminanceBits
= 0;
368 texImage
->IndexBits
= 0;
371 texImage
->RedBits
= 0;
372 texImage
->GreenBits
= 0;
373 texImage
->BlueBits
= 8;
374 texImage
->AlphaBits
= 0;
375 texImage
->IntensityBits
= 0;
376 texImage
->LuminanceBits
= 0;
377 texImage
->IndexBits
= 0;
381 texImage
->RedBits
= 8;
382 texImage
->GreenBits
= 8;
383 texImage
->BlueBits
= 8;
384 texImage
->AlphaBits
= 0;
385 texImage
->IntensityBits
= 0;
386 texImage
->LuminanceBits
= 0;
387 texImage
->IndexBits
= 0;
392 texImage
->RedBits
= 8;
393 texImage
->GreenBits
= 8;
394 texImage
->BlueBits
= 8;
395 texImage
->AlphaBits
= 8;
396 texImage
->IntensityBits
= 0;
397 texImage
->LuminanceBits
= 0;
398 texImage
->IndexBits
= 0;
401 texImage
->RedBits
= 0;
402 texImage
->GreenBits
= 0;
403 texImage
->BlueBits
= 0;
404 texImage
->AlphaBits
= 0;
405 texImage
->IntensityBits
= 0;
406 texImage
->LuminanceBits
= 0;
407 texImage
->IndexBits
= 8;
410 gl_problem(NULL
, "unexpected format in set_teximage_component_sizes");
416 set_tex_image(struct gl_texture_object
*tObj
,
417 GLenum target
, GLint level
,
418 struct gl_texture_image
*texImage
)
424 tObj
->Image
[level
] = texImage
;
426 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
427 tObj
->Image
[level
] = texImage
;
429 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
430 tObj
->NegX
[level
] = texImage
;
432 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
433 tObj
->PosY
[level
] = texImage
;
435 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
436 tObj
->NegY
[level
] = texImage
;
438 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
439 tObj
->PosZ
[level
] = texImage
;
441 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
442 tObj
->NegZ
[level
] = texImage
;
445 gl_problem(NULL
, "bad target in set_tex_image()");
452 * Return new gl_texture_image struct with all fields initialized to zero.
454 struct gl_texture_image
*
455 _mesa_alloc_texture_image( void )
457 return CALLOC_STRUCT(gl_texture_image
);
463 * Initialize most fields of a gl_texture_image struct.
466 init_texture_image( GLcontext
*ctx
,
467 struct gl_texture_image
*img
,
468 GLsizei width
, GLsizei height
, GLsizei depth
,
469 GLint border
, GLenum internalFormat
)
473 img
->Format
= (GLenum
) _mesa_base_tex_format(ctx
, internalFormat
);
474 set_teximage_component_sizes( img
);
475 img
->IntFormat
= (GLenum
) internalFormat
;
476 img
->Border
= border
;
478 img
->Height
= height
;
480 img
->WidthLog2
= logbase2(width
- 2 * border
);
481 if (height
== 1) /* 1-D texture */
484 img
->HeightLog2
= logbase2(height
- 2 * border
);
485 if (depth
== 1) /* 2-D texture */
488 img
->DepthLog2
= logbase2(depth
- 2 * border
);
489 img
->Width2
= 1 << img
->WidthLog2
;
490 img
->Height2
= 1 << img
->HeightLog2
;
491 img
->Depth2
= 1 << img
->DepthLog2
;
492 img
->MaxLog2
= MAX2(img
->WidthLog2
, img
->HeightLog2
);
493 img
->IsCompressed
= is_compressed_format(ctx
, internalFormat
);
499 _mesa_free_texture_image( struct gl_texture_image
*teximage
)
501 if (teximage
->Data
) {
502 FREE( teximage
->Data
);
503 teximage
->Data
= NULL
;
511 * Return number of bytes of storage needed to store a compressed texture
512 * image. Only the driver knows for sure. If the driver can't help us,
516 _mesa_compressed_image_size(GLcontext
*ctx
,
517 GLenum internalFormat
,
523 if (ctx
->Driver
.CompressedImageSize
) {
524 return (*ctx
->Driver
.CompressedImageSize
)(ctx
, internalFormat
,
526 width
, height
, depth
);
529 /* Shouldn't this be an internal error of some sort? */
537 * Given a texture unit and a texture target, return the corresponding
540 struct gl_texture_object
*
541 _mesa_select_tex_object(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
546 return texUnit
->CurrentD
[1];
547 case GL_PROXY_TEXTURE_1D
:
548 return ctx
->Texture
.Proxy1D
;
550 return texUnit
->CurrentD
[2];
551 case GL_PROXY_TEXTURE_2D
:
552 return ctx
->Texture
.Proxy2D
;
554 return texUnit
->CurrentD
[3];
555 case GL_PROXY_TEXTURE_3D
:
556 return ctx
->Texture
.Proxy3D
;
557 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
558 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
559 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
560 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
561 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
562 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
563 return ctx
->Extensions
.HaveTextureCubeMap
564 ? texUnit
->CurrentCubeMap
: NULL
;
565 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
566 return ctx
->Extensions
.HaveTextureCubeMap
567 ? ctx
->Texture
.ProxyCubeMap
: NULL
;
569 gl_problem(NULL
, "bad target in _mesa_select_tex_object()");
576 * Return the texture image struct which corresponds to target and level
577 * for the given texture unit.
579 struct gl_texture_image
*
580 _mesa_select_tex_image(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
581 GLenum target
, GLint level
)
586 return texUnit
->CurrentD
[1]->Image
[level
];
587 case GL_PROXY_TEXTURE_1D
:
588 return ctx
->Texture
.Proxy1D
->Image
[level
];
590 return texUnit
->CurrentD
[2]->Image
[level
];
591 case GL_PROXY_TEXTURE_2D
:
592 return ctx
->Texture
.Proxy2D
->Image
[level
];
594 return texUnit
->CurrentD
[3]->Image
[level
];
595 case GL_PROXY_TEXTURE_3D
:
596 return ctx
->Texture
.Proxy3D
->Image
[level
];
597 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
598 if (ctx
->Extensions
.HaveTextureCubeMap
)
599 return texUnit
->CurrentCubeMap
->Image
[level
];
602 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
603 if (ctx
->Extensions
.HaveTextureCubeMap
)
604 return texUnit
->CurrentCubeMap
->NegX
[level
];
607 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
608 if (ctx
->Extensions
.HaveTextureCubeMap
)
609 return texUnit
->CurrentCubeMap
->PosY
[level
];
612 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
613 if (ctx
->Extensions
.HaveTextureCubeMap
)
614 return texUnit
->CurrentCubeMap
->NegY
[level
];
617 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
618 if (ctx
->Extensions
.HaveTextureCubeMap
)
619 return texUnit
->CurrentCubeMap
->PosZ
[level
];
622 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
623 if (ctx
->Extensions
.HaveTextureCubeMap
)
624 return texUnit
->CurrentCubeMap
->NegZ
[level
];
627 case GL_PROXY_TEXTURE_CUBE_MAP_ARB
:
628 if (ctx
->Extensions
.HaveTextureCubeMap
)
629 return ctx
->Texture
.ProxyCubeMap
->Image
[level
];
633 gl_problem(ctx
, "bad target in _mesa_select_tex_image()");
641 * Calling glTexImage and related functions when convolution is enabled
642 * with GL_REDUCE border mode causes some complications.
643 * The incoming image must be extra large so that the post-convolution
644 * image size is reduced to a power of two size (plus 2 * border).
645 * This function adjusts a texture width and height accordingly if
646 * convolution with GL_REDUCE is enabled.
649 adjust_texture_size_for_convolution(const GLcontext
*ctx
, GLuint dimensions
,
650 GLsizei
*width
, GLsizei
*height
)
652 if (ctx
->Pixel
.Convolution1DEnabled
654 && ctx
->Pixel
.ConvolutionBorderMode
[0] == GL_REDUCE
) {
655 *width
= *width
- (MAX2(ctx
->Convolution1D
.Width
, 1) - 1);
657 else if (ctx
->Pixel
.Convolution2DEnabled
659 && ctx
->Pixel
.ConvolutionBorderMode
[1] == GL_REDUCE
) {
660 *width
= *width
- (MAX2(ctx
->Convolution2D
.Width
, 1) - 1);
661 *height
= *height
- (MAX2(ctx
->Convolution2D
.Height
, 1) - 1);
663 else if (ctx
->Pixel
.Separable2DEnabled
665 && ctx
->Pixel
.ConvolutionBorderMode
[2] == GL_REDUCE
) {
666 *width
= *width
- (MAX2(ctx
->Separable2D
.Width
, 1) - 1);
667 *height
= *height
- (MAX2(ctx
->Separable2D
.Height
, 1) - 1);
674 * This function is used to move user image data into a texture image.
675 * We handle full texture images and subtexture images. We also take
676 * care of all image transfer operations here, including convolution.
678 * dstXoffset, dstYoffset, dstZoffset - offsets in pixels
679 * dstRowStride, dstImageStride - strides in bytes
682 fill_texture_image( GLcontext
*ctx
, GLuint dimensions
,
683 GLenum texFormat
, GLubyte
*texAddr
,
684 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
685 GLint dstXoffset
, GLint dstYoffset
, GLint dstZoffset
,
686 GLint dstRowStride
, GLint dstImageStride
,
687 GLenum srcFormat
, GLenum srcType
, const GLvoid
*srcAddr
,
688 const struct gl_pixelstore_attrib
*srcPacking
)
693 ASSERT(dimensions
>= 1 && dimensions
<= 3);
695 ASSERT(srcWidth
>= 1);
696 ASSERT(srcHeight
>= 1);
697 ASSERT(srcDepth
>= 1);
698 ASSERT(dstXoffset
>= 0);
699 ASSERT(dstYoffset
>= 0);
700 ASSERT(dstZoffset
>= 0);
701 ASSERT(dstRowStride
>= 0);
702 ASSERT(dstImageStride
>= 0);
706 texComponents
= components_in_intformat(texFormat
);
708 /* try common 2D texture cases first */
709 if (!ctx
->ImageTransferState
&& dimensions
== 2
710 && srcType
== GL_UNSIGNED_BYTE
) {
712 if (srcFormat
== texFormat
) {
713 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
714 * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy().
716 const GLubyte
*src
= (const GLubyte
*) _mesa_image_address(
717 srcPacking
, srcAddr
, srcWidth
, srcHeight
,
718 srcFormat
, srcType
, 0, 0, 0);
719 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
720 srcWidth
, srcFormat
, srcType
);
721 const GLint widthInBytes
= srcWidth
* texComponents
;
722 GLubyte
*dst
= texAddr
+ dstYoffset
* dstRowStride
723 + dstXoffset
* texComponents
* sizeof(GLubyte
);
724 if (srcRowStride
== widthInBytes
&& dstRowStride
== widthInBytes
) {
725 MEMCPY(dst
, src
, srcHeight
* widthInBytes
);
729 for (i
= 0; i
< srcHeight
; i
++) {
730 MEMCPY(dst
, src
, widthInBytes
);
735 return; /* all done */
737 else if (srcFormat
== GL_RGBA
&& texFormat
== GL_RGB
) {
738 /* commonly used by Quake */
739 const GLubyte
*src
= (const GLubyte
*) _mesa_image_address(
740 srcPacking
, srcAddr
, srcWidth
, srcHeight
,
741 srcFormat
, srcType
, 0, 0, 0);
742 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
,
743 srcWidth
, srcFormat
, srcType
);
744 GLubyte
*dst
= texAddr
+ dstYoffset
* dstRowStride
745 + dstXoffset
* texComponents
* sizeof(GLubyte
);
747 for (i
= 0; i
< srcHeight
; i
++) {
748 const GLubyte
*s
= src
;
750 for (j
= 0; j
< srcWidth
; j
++) {
752 *d
++ = *s
++; /*green*/
753 *d
++ = *s
++; /*blue*/
759 return; /* all done */
764 * General case solutions
766 if (texFormat
== GL_COLOR_INDEX
) {
767 /* color index texture */
768 const GLenum texType
= GL_UNSIGNED_BYTE
;
770 GLubyte
*dest
= texAddr
+ dstZoffset
* dstImageStride
771 + dstYoffset
* dstRowStride
772 + dstXoffset
* texComponents
* sizeof(GLubyte
);
773 for (img
= 0; img
< srcDepth
; img
++) {
774 GLubyte
*destRow
= dest
;
775 for (row
= 0; row
< srcHeight
; row
++) {
776 const GLvoid
*src
= _mesa_image_address(srcPacking
,
777 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
778 _mesa_unpack_index_span(ctx
, srcWidth
, texType
, destRow
,
779 srcType
, src
, srcPacking
,
780 ctx
->ImageTransferState
);
781 destRow
+= dstRowStride
;
783 dest
+= dstImageStride
;
787 /* regular, color texture */
788 if ((dimensions
== 1 && ctx
->Pixel
.Convolution1DEnabled
) ||
789 (dimensions
>= 2 && ctx
->Pixel
.Convolution2DEnabled
) ||
790 (dimensions
>= 2 && ctx
->Pixel
.Separable2DEnabled
)) {
792 * Fill texture image with convolution
795 GLint convWidth
= srcWidth
, convHeight
= srcHeight
;
796 GLfloat
*tmpImage
, *convImage
;
797 tmpImage
= (GLfloat
*) MALLOC(srcWidth
* srcHeight
* 4 * sizeof(GLfloat
));
799 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage");
802 convImage
= (GLfloat
*) MALLOC(srcWidth
* srcHeight
* 4 * sizeof(GLfloat
));
804 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage");
809 for (img
= 0; img
< srcDepth
; img
++) {
811 GLfloat
*dstf
= tmpImage
;
814 /* unpack and do transfer ops up to convolution */
815 for (row
= 0; row
< srcHeight
; row
++) {
816 const GLvoid
*src
= _mesa_image_address(srcPacking
,
817 srcAddr
, srcWidth
, srcHeight
,
818 srcFormat
, srcType
, img
, row
, 0);
819 _mesa_unpack_float_color_span(ctx
, srcWidth
, GL_RGBA
, dstf
,
820 srcFormat
, srcType
, src
, srcPacking
,
821 ctx
->ImageTransferState
& IMAGE_PRE_CONVOLUTION_BITS
,
823 dstf
+= srcWidth
* 4;
827 if (dimensions
== 1) {
828 ASSERT(ctx
->Pixel
.Convolution1DEnabled
);
829 _mesa_convolve_1d_image(ctx
, &convWidth
, tmpImage
, convImage
);
832 if (ctx
->Pixel
.Convolution2DEnabled
) {
833 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
834 tmpImage
, convImage
);
837 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
838 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
839 tmpImage
, convImage
);
843 /* packing and transfer ops after convolution */
845 dest
= texAddr
+ (dstZoffset
+ img
) * dstImageStride
846 + dstYoffset
* dstRowStride
;
847 for (row
= 0; row
< convHeight
; row
++) {
848 _mesa_pack_float_rgba_span(ctx
, convWidth
,
849 (const GLfloat (*)[4]) srcf
,
850 texFormat
, GL_UNSIGNED_BYTE
,
851 dest
, &_mesa_native_packing
,
852 ctx
->ImageTransferState
853 & IMAGE_POST_CONVOLUTION_BITS
);
854 srcf
+= convWidth
* 4;
855 dest
+= dstRowStride
;
867 GLubyte
*dest
= texAddr
+ dstZoffset
* dstImageStride
868 + dstYoffset
* dstRowStride
869 + dstXoffset
* texComponents
* sizeof(GLubyte
);
870 for (img
= 0; img
< srcDepth
; img
++) {
871 GLubyte
*destRow
= dest
;
872 for (row
= 0; row
< srcHeight
; row
++) {
873 const GLvoid
*srcRow
= _mesa_image_address(srcPacking
,
874 srcAddr
, srcWidth
, srcHeight
,
875 srcFormat
, srcType
, img
, row
, 0);
876 _mesa_unpack_ubyte_color_span(ctx
, srcWidth
, texFormat
, destRow
,
877 srcFormat
, srcType
, srcRow
, srcPacking
,
878 ctx
->ImageTransferState
);
879 destRow
+= dstRowStride
;
881 dest
+= dstImageStride
;
889 /* Need this to prevent an out-of-bounds memory access when using
890 * X86 optimized code.
893 # define EXTRA_BYTE 1
895 # define EXTRA_BYTE 0
901 * Called by glTexImage[123]D. Fill in a texture image with data given
902 * by the client. All pixel transfer and unpack modes are handled here.
903 * Input: dimensions (1, 2, or 3)
904 * texImage - destination texture image (we'll malloc the memory)
905 * width, height, depth - size of source image
906 * srcFormat, srcType - source image format and type
907 * pixels - source image data
908 * srcPacking - source image packing parameters
910 * NOTE: All texture image parameters should have already been error checked.
912 * NOTE: the texImage dimensions and source image dimensions must be correct
913 * with respect to convolution with border mode = reduce.
916 make_texture_image( GLcontext
*ctx
, GLuint dimensions
,
917 struct gl_texture_image
*texImage
,
918 GLint width
, GLint height
, GLint depth
,
919 GLenum srcFormat
, GLenum srcType
, const GLvoid
*pixels
,
920 const struct gl_pixelstore_attrib
*srcPacking
)
922 const GLint internalFormat
= texImage
->IntFormat
;
923 const GLint components
= components_in_intformat(internalFormat
);
924 GLint convWidth
= width
, convHeight
= height
;
926 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
) {
927 _mesa_update_image_transfer_state(ctx
);
930 if (ctx
->ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
931 adjust_texture_size_for_convolution(ctx
, dimensions
,
932 &convWidth
, &convHeight
);
935 texImage
->Data
= (GLubyte
*) MALLOC(convWidth
* convHeight
* depth
936 * components
+ EXTRA_BYTE
);
938 return; /* out of memory */
940 fill_texture_image(ctx
, dimensions
, texImage
->Format
, texImage
->Data
,
941 width
, height
, depth
, 0, 0, 0,
942 convWidth
* components
* sizeof(GLubyte
),
943 convWidth
* convHeight
* components
* sizeof(GLubyte
),
944 srcFormat
, srcType
, pixels
, srcPacking
);
950 * glTexImage[123]D can accept a NULL image pointer. In this case we
951 * create a texture image with unspecified image contents per the OpenGL
952 * spec. This function creates an empty image for the given texture image.
955 make_null_texture( struct gl_texture_image
*texImage
)
961 ASSERT(!texImage
->Data
);
963 components
= components_in_intformat(texImage
->IntFormat
);
964 numPixels
= texImage
->Width
* texImage
->Height
* texImage
->Depth
;
966 texImage
->Data
= (GLubyte
*) MALLOC( numPixels
* components
+ EXTRA_BYTE
);
969 * Let's see if anyone finds this. If glTexImage2D() is called with
970 * a NULL image pointer then load the texture image with something
971 * interesting instead of leaving it indeterminate.
973 if (texImage
->Data
) {
974 static const char message
[8][32] = {
978 " X X XXXX XXX XXXXX ",
981 " X X XXXXX XXX X X ",
985 GLubyte
*imgPtr
= texImage
->Data
;
987 for (i
= 0; i
< texImage
->Height
; i
++) {
988 GLint srcRow
= 7 - i
% 8;
989 for (j
= 0; j
< texImage
->Width
; j
++) {
990 GLint srcCol
= j
% 32;
991 GLint texel
= (message
[srcRow
][srcCol
]=='X') ? CHAN_MAX
: 70;
992 for (k
=0;k
<components
;k
++) {
993 *imgPtr
++ = (GLubyte
) texel
;
1003 * This is called when a proxy texture test fails, we set all the
1004 * image members (except DriverData) to zero.
1007 clear_proxy_teximage(struct gl_texture_image
*img
)
1016 img
->IntensityBits
= 0;
1017 img
->LuminanceBits
= 0;
1027 img
->HeightLog2
= 0;
1030 img
->IsCompressed
= 0;
1031 img
->CompressedSize
= 0;
1037 * Test glTexImage[123]D() parameters for errors.
1039 * dimensions - must be 1 or 2 or 3
1040 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1043 texture_error_check( GLcontext
*ctx
, GLenum target
,
1044 GLint level
, GLint internalFormat
,
1045 GLenum format
, GLenum type
,
1047 GLint width
, GLint height
,
1048 GLint depth
, GLint border
)
1053 if (dimensions
== 1) {
1054 isProxy
= (GLboolean
) (target
== GL_PROXY_TEXTURE_1D
);
1055 if (target
!= GL_TEXTURE_1D
&& !isProxy
) {
1056 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1060 else if (dimensions
== 2) {
1061 isProxy
= (GLboolean
) (target
== GL_PROXY_TEXTURE_2D
);
1062 if (target
!= GL_TEXTURE_2D
&& !isProxy
&&
1063 !(ctx
->Extensions
.HaveTextureCubeMap
&&
1064 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1065 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
1066 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
1070 else if (dimensions
== 3) {
1071 isProxy
= (GLboolean
) (target
== GL_PROXY_TEXTURE_3D
);
1072 if (target
!= GL_TEXTURE_3D
&& !isProxy
) {
1073 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1078 gl_problem( ctx
, "bad dims in texture_error_check" );
1083 if (border
!= 0 && border
!= 1) {
1086 sprintf(message
, "glTexImage%dD(border)", dimensions
);
1087 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1093 if (width
< 2 * border
|| width
> 2 + ctx
->Const
.MaxTextureSize
1094 || logbase2( width
- 2 * border
) < 0) {
1097 sprintf(message
, "glTexImage%dD(width)", dimensions
);
1098 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1104 if (dimensions
>= 2) {
1105 if (height
< 2 * border
|| height
> 2 + ctx
->Const
.MaxTextureSize
1106 || logbase2( height
- 2 * border
) < 0) {
1109 sprintf(message
, "glTexImage%dD(height)", dimensions
);
1110 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1116 /* For cube map, width must equal height */
1117 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1118 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1119 if (width
!= height
) {
1121 gl_error(ctx
, GL_INVALID_VALUE
, "glTexImage2D(width != height)");
1128 if (dimensions
>= 3) {
1129 if (depth
< 2 * border
|| depth
> 2 + ctx
->Const
.MaxTextureSize
1130 || logbase2( depth
- 2 * border
) < 0) {
1132 gl_error( ctx
, GL_INVALID_VALUE
, "glTexImage3D(depth)" );
1139 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
1142 sprintf(message
, "glTexImage%dD(level)", dimensions
);
1143 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1148 iformat
= _mesa_base_tex_format( ctx
, internalFormat
);
1152 sprintf(message
, "glTexImage%dD(internalFormat)", dimensions
);
1153 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1158 if (!is_compressed_format(ctx
, internalFormat
)) {
1159 if (!_mesa_is_legal_format_and_type( format
, type
)) {
1160 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1161 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1165 sprintf(message
, "glTexImage%dD(format or type)", dimensions
);
1166 gl_error(ctx
, GL_INVALID_OPERATION
, message
);
1172 /* if we get here, the parameters are OK */
1179 * Test glTexSubImage[123]D() parameters for errors.
1181 * dimensions - must be 1 or 2 or 3
1182 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1185 subtexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1186 GLenum target
, GLint level
,
1187 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1188 GLint width
, GLint height
, GLint depth
,
1189 GLenum format
, GLenum type
)
1191 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1192 struct gl_texture_image
*destTex
;
1194 if (dimensions
== 1) {
1195 if (target
!= GL_TEXTURE_1D
) {
1196 gl_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
1200 else if (dimensions
== 2) {
1201 if (ctx
->Extensions
.HaveTextureCubeMap
) {
1202 if ((target
< GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
||
1203 target
> GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) &&
1204 target
!= GL_TEXTURE_2D
) {
1205 gl_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1209 else if (target
!= GL_TEXTURE_2D
) {
1210 gl_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
1214 else if (dimensions
== 3) {
1215 if (target
!= GL_TEXTURE_3D
) {
1216 gl_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
1221 gl_problem( ctx
, "bad dims in texture_error_check" );
1225 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
1226 gl_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level)");
1232 sprintf(message
, "glTexSubImage%dD(width)", dimensions
);
1233 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1236 if (height
< 0 && dimensions
> 1) {
1238 sprintf(message
, "glTexSubImage%dD(height)", dimensions
);
1239 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1242 if (depth
< 0 && dimensions
> 2) {
1244 sprintf(message
, "glTexSubImage%dD(depth)", dimensions
);
1245 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1249 destTex
= texUnit
->CurrentD
[2]->Image
[level
];
1251 gl_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage2D");
1255 if (xoffset
< -((GLint
)destTex
->Border
)) {
1256 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage1/2/3D(xoffset)");
1259 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
1260 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage1/2/3D(xoffset+width)");
1263 if (dimensions
> 1) {
1264 if (yoffset
< -((GLint
)destTex
->Border
)) {
1265 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage2/3D(yoffset)");
1268 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
1269 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage2/3D(yoffset+height)");
1273 if (dimensions
> 2) {
1274 if (zoffset
< -((GLint
)destTex
->Border
)) {
1275 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
1278 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+destTex
->Border
)) {
1279 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
1284 if (!is_compressed_format(ctx
, destTex
->IntFormat
)) {
1285 if (!_mesa_is_legal_format_and_type(format
, type
)) {
1287 sprintf(message
, "glTexSubImage%dD(format or type)", dimensions
);
1288 gl_error(ctx
, GL_INVALID_ENUM
, message
);
1298 * Test glCopyTexImage[12]D() parameters for errors.
1299 * Input: dimensions - must be 1 or 2 or 3
1300 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1303 copytexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
1304 GLenum target
, GLint level
, GLint internalFormat
,
1305 GLint width
, GLint height
, GLint border
)
1309 if (dimensions
== 1) {
1310 if (target
!= GL_TEXTURE_1D
) {
1311 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
1315 else if (dimensions
== 2) {
1316 if (ctx
->Extensions
.HaveTextureCubeMap
) {
1317 if ((target
< GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
||
1318 target
> GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) &&
1319 target
!= GL_TEXTURE_2D
) {
1320 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1324 else if (target
!= GL_TEXTURE_2D
) {
1325 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
1331 if (border
!=0 && border
!=1) {
1333 sprintf(message
, "glCopyTexImage%dD(border)", dimensions
);
1334 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1339 if (width
< 2 * border
|| width
> 2 + ctx
->Const
.MaxTextureSize
1340 || logbase2( width
- 2 * border
) < 0) {
1342 sprintf(message
, "glCopyTexImage%dD(width)", dimensions
);
1343 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1348 if (dimensions
>= 2) {
1349 if (height
< 2 * border
|| height
> 2 + ctx
->Const
.MaxTextureSize
1350 || logbase2( height
- 2 * border
) < 0) {
1352 sprintf(message
, "glCopyTexImage%dD(height)", dimensions
);
1353 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1358 /* For cube map, width must equal height */
1359 if (target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1360 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) {
1361 if (width
!= height
) {
1362 gl_error(ctx
, GL_INVALID_VALUE
, "glCopyTexImage2D(width != height)");
1368 if (level
<0 || level
>=ctx
->Const
.MaxTextureLevels
) {
1370 sprintf(message
, "glCopyTexImage%dD(level)", dimensions
);
1371 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1375 iformat
= _mesa_base_tex_format( ctx
, internalFormat
);
1378 sprintf(message
, "glCopyTexImage%dD(internalFormat)", dimensions
);
1379 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1383 /* if we get here, the parameters are OK */
1389 copytexsubimage_error_check( GLcontext
*ctx
, GLuint dimensions
,
1390 GLenum target
, GLint level
,
1391 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1392 GLsizei width
, GLsizei height
)
1394 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1395 struct gl_texture_image
*teximage
;
1397 if (dimensions
== 1) {
1398 if (target
!= GL_TEXTURE_1D
) {
1399 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
1403 else if (dimensions
== 2) {
1404 if (ctx
->Extensions
.HaveTextureCubeMap
) {
1405 if ((target
< GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
||
1406 target
> GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
) &&
1407 target
!= GL_TEXTURE_2D
) {
1408 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1412 else if (target
!= GL_TEXTURE_2D
) {
1413 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
1417 else if (dimensions
== 3) {
1418 if (target
!= GL_TEXTURE_3D
) {
1419 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
1424 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
1426 sprintf(message
, "glCopyTexSubImage%dD(level)", dimensions
);
1427 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1433 sprintf(message
, "glCopyTexSubImage%dD(width)", dimensions
);
1434 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1437 if (dimensions
> 1 && height
< 0) {
1439 sprintf(message
, "glCopyTexSubImage%dD(height)", dimensions
);
1440 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1444 teximage
= texUnit
->CurrentD
[dimensions
]->Image
[level
];
1447 sprintf(message
, "glCopyTexSubImage%dD(undefined texture)", dimensions
);
1448 gl_error(ctx
, GL_INVALID_OPERATION
, message
);
1452 if (xoffset
< -((GLint
)teximage
->Border
)) {
1454 sprintf(message
, "glCopyTexSubImage%dD(xoffset)", dimensions
);
1455 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1458 if (xoffset
+width
> (GLint
) (teximage
->Width
+teximage
->Border
)) {
1460 sprintf(message
, "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
1461 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1464 if (dimensions
> 1) {
1465 if (yoffset
< -((GLint
)teximage
->Border
)) {
1467 sprintf(message
, "glCopyTexSubImage%dD(yoffset)", dimensions
);
1468 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1471 /* NOTE: we're adding the border here, not subtracting! */
1472 if (yoffset
+height
> (GLint
) (teximage
->Height
+teximage
->Border
)) {
1474 sprintf(message
, "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
1475 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1480 if (dimensions
> 2) {
1481 if (zoffset
< -((GLint
)teximage
->Border
)) {
1483 sprintf(message
, "glCopyTexSubImage%dD(zoffset)", dimensions
);
1484 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1487 if (zoffset
> (GLint
) (teximage
->Depth
+teximage
->Border
)) {
1489 sprintf(message
, "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
1490 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1495 /* if we get here, the parameters are OK */
1503 * Turn generic compressed formats into specific compressed format.
1504 * Some of the compressed formats we don't support, so we
1505 * fall back to the uncompressed format. (See issue 15 of
1506 * the GL_ARB_texture_compression specification.)
1509 get_specific_compressed_tex_format(GLcontext
*ctx
,
1510 GLint ifmt
, GLint numDimensions
,
1520 GLint internalFormat
= ifmt
;
1522 if (ctx
->Extensions
.HaveTextureCompression
1523 && ctx
->Driver
.SpecificCompressedTexFormat
) {
1525 * First, ask the driver for the specific format.
1526 * We do this for all formats, since we may want to
1527 * fake one compressed format for another.
1529 internalFormat
= (*ctx
->Driver
.SpecificCompressedTexFormat
)
1530 (ctx
, internalFormat
, numDimensions
,
1532 widthp
, heightp
, depthp
,
1533 borderp
, formatp
, typep
);
1537 * Now, convert any generic format left to an uncompressed
1538 * specific format. If the driver does not support compression
1539 * of the format, we must drop back to the uncompressed format.
1540 * See issue 15 of the GL_ARB_texture_compression specification.
1542 switch (internalFormat
) {
1543 case GL_COMPRESSED_ALPHA_ARB
:
1544 if (ctx
&& !ctx
->Extensions
.HaveTextureCompression
) {
1545 sprintf(message
, "glTexImage%dD(internalFormat)", numDimensions
);
1546 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1549 internalFormat
= GL_ALPHA
;
1551 case GL_COMPRESSED_LUMINANCE_ARB
:
1552 if (ctx
&& !ctx
->Extensions
.HaveTextureCompression
) {
1553 sprintf(message
, "glTexImage%dD(internalFormat)", numDimensions
);
1554 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1557 internalFormat
= GL_LUMINANCE
;
1559 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB
:
1560 if (ctx
&& !ctx
->Extensions
.HaveTextureCompression
) {
1561 sprintf(message
, "glTexImage%dD(internalFormat)", numDimensions
);
1562 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1565 internalFormat
= GL_LUMINANCE_ALPHA
;
1567 case GL_COMPRESSED_INTENSITY_ARB
:
1568 if (ctx
&& !ctx
->Extensions
.HaveTextureCompression
) {
1569 sprintf(message
, "glTexImage%dD(internalFormat)", numDimensions
);
1570 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1573 internalFormat
= GL_INTENSITY
;
1575 case GL_COMPRESSED_RGB_ARB
:
1576 if (ctx
&& !ctx
->Extensions
.HaveTextureCompression
) {
1577 sprintf(message
, "glTexImage%dD(internalFormat)", numDimensions
);
1578 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1581 internalFormat
= GL_RGB
;
1583 case GL_COMPRESSED_RGBA_ARB
:
1584 if (ctx
&& !ctx
->Extensions
.HaveTextureCompression
) {
1585 sprintf(message
, "glTexImage%dD(internalFormat)", numDimensions
);
1586 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1589 internalFormat
= GL_RGBA
;
1592 /* silence compiler warning */
1595 return internalFormat
;
1600 * Called from the API. Note that width includes the border.
1603 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalFormat
,
1604 GLsizei width
, GLint border
, GLenum format
,
1605 GLenum type
, const GLvoid
*pixels
)
1607 GLsizei postConvWidth
;
1608 GET_CURRENT_CONTEXT(ctx
);
1609 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glTexImage1D");
1611 postConvWidth
= width
;
1612 adjust_texture_size_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
1614 if (target
==GL_TEXTURE_1D
) {
1615 struct gl_texture_unit
*texUnit
;
1616 struct gl_texture_object
*texObj
;
1617 struct gl_texture_image
*texImage
;
1620 ifmt
= get_specific_compressed_tex_format(ctx
, internalFormat
, 1,
1623 &border
, &format
, &type
);
1626 * The error here is that we were sent a generic compressed
1627 * format, but the extension is not supported.
1632 internalFormat
= ifmt
;
1635 if (texture_error_check(ctx
, target
, level
, internalFormat
,
1636 format
, type
, 1, postConvWidth
, 1, 1, border
)) {
1637 return; /* error in texture image was detected */
1640 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1641 texObj
= texUnit
->CurrentD
[1];
1642 texImage
= texObj
->Image
[level
];
1645 texImage
= _mesa_alloc_texture_image();
1646 texObj
->Image
[level
] = texImage
;
1648 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
1652 else if (texImage
->Data
) {
1653 FREE(texImage
->Data
);
1654 texImage
->Data
= NULL
;
1657 /* setup the teximage struct's fields */
1658 init_texture_image(ctx
, texImage
, postConvWidth
, 1, 1, border
, internalFormat
);
1660 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
1661 _mesa_update_image_transfer_state(ctx
);
1663 /* process the texture image */
1665 GLboolean retain
= GL_TRUE
;
1666 GLboolean success
= GL_FALSE
;
1667 if (!ctx
->ImageTransferState
&& ctx
->Driver
.TexImage1D
) {
1668 /* let device driver try to use raw image */
1669 success
= (*ctx
->Driver
.TexImage1D
)( ctx
, target
, level
, format
,
1670 type
, pixels
, &ctx
->Unpack
,
1671 texObj
, texImage
, &retain
);
1673 if (retain
|| !success
) {
1674 /* make internal copy of the texture image */
1675 make_texture_image(ctx
, 1, texImage
, width
, 1, 1,
1676 format
, type
, pixels
, &ctx
->Unpack
);
1677 if (!success
&& ctx
->Driver
.TexImage1D
) {
1678 /* let device driver try to use unpacked image */
1679 (*ctx
->Driver
.TexImage1D
)( ctx
, target
, level
, texImage
->Format
,
1680 GL_UNSIGNED_BYTE
, texImage
->Data
,
1681 &_mesa_native_packing
,
1682 texObj
, texImage
, &retain
);
1685 if (!retain
&& texImage
->Data
) {
1686 FREE(texImage
->Data
);
1687 texImage
->Data
= NULL
;
1691 make_null_texture(texImage
);
1692 if (ctx
->Driver
.TexImage1D
) {
1694 (*ctx
->Driver
.TexImage1D
)( ctx
, target
, level
, texImage
->Format
,
1695 GL_UNSIGNED_BYTE
, texImage
->Data
,
1696 &_mesa_native_packing
,
1697 texObj
, texImage
, &retain
);
1702 gl_put_texobj_on_dirty_list( ctx
, texObj
);
1703 ctx
->NewState
|= NEW_TEXTURING
;
1705 else if (target
== GL_PROXY_TEXTURE_1D
) {
1706 /* Proxy texture: check for errors and update proxy state */
1707 GLenum error
= texture_error_check(ctx
, target
, level
, internalFormat
,
1708 format
, type
, 1, width
, 1, 1, border
);
1709 if (!error
&& ctx
->Driver
.TestProxyTexImage
) {
1710 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
1711 internalFormat
, format
, type
,
1712 width
, 1, 1, border
);
1715 /* if error, clear all proxy texture image parameters */
1716 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
1717 clear_proxy_teximage(ctx
->Texture
.Proxy1D
->Image
[level
]);
1721 /* if no error, update proxy texture image parameters */
1722 init_texture_image(ctx
, ctx
->Texture
.Proxy1D
->Image
[level
],
1723 width
, 1, 1, border
, internalFormat
);
1727 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1734 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalFormat
,
1735 GLsizei width
, GLsizei height
, GLint border
,
1736 GLenum format
, GLenum type
,
1737 const GLvoid
*pixels
)
1739 GLsizei postConvWidth
, postConvHeight
;
1740 GET_CURRENT_CONTEXT(ctx
);
1741 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glTexImage2D");
1743 postConvWidth
= width
;
1744 postConvHeight
= height
;
1745 adjust_texture_size_for_convolution(ctx
, 2, &postConvWidth
,&postConvHeight
);
1747 if (target
==GL_TEXTURE_2D
||
1748 (ctx
->Extensions
.HaveTextureCubeMap
&&
1749 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
1750 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
1751 struct gl_texture_unit
*texUnit
;
1752 struct gl_texture_object
*texObj
;
1753 struct gl_texture_image
*texImage
;
1756 ifmt
= get_specific_compressed_tex_format(ctx
, internalFormat
, 2,
1759 &border
, &format
, &type
);
1762 * The error here is that we were sent a generic compressed
1763 * format, but the extension is not supported.
1768 internalFormat
= ifmt
;
1771 if (texture_error_check(ctx
, target
, level
, internalFormat
,
1772 format
, type
, 2, postConvWidth
, postConvHeight
,
1774 return; /* error in texture image was detected */
1777 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1778 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
1779 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
1782 texImage
= _mesa_alloc_texture_image();
1783 set_tex_image(texObj
, target
, level
, texImage
);
1784 /*texObj->Image[level] = texImage;*/
1786 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1790 else if (texImage
->Data
) {
1791 FREE(texImage
->Data
);
1792 texImage
->Data
= NULL
;
1795 /* setup the teximage struct's fields */
1796 init_texture_image(ctx
, texImage
, postConvWidth
, postConvHeight
,
1797 1, border
, internalFormat
);
1799 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
1800 _mesa_update_image_transfer_state(ctx
);
1802 /* process the texture image */
1804 GLboolean retain
= GL_TRUE
;
1805 GLboolean success
= GL_FALSE
;
1806 if (!ctx
->ImageTransferState
&& ctx
->Driver
.TexImage2D
) {
1807 /* let device driver try to use raw image */
1808 success
= (*ctx
->Driver
.TexImage2D
)( ctx
, target
, level
, format
,
1809 type
, pixels
, &ctx
->Unpack
,
1810 texObj
, texImage
, &retain
);
1812 if (retain
|| !success
) {
1813 /* make internal copy of the texture image */
1814 make_texture_image(ctx
, 2, texImage
, width
, height
, 1,
1815 format
, type
, pixels
, &ctx
->Unpack
);
1816 if (!success
&& ctx
->Driver
.TexImage2D
) {
1817 /* let device driver try to use unpacked image */
1818 (*ctx
->Driver
.TexImage2D
)( ctx
, target
, level
, texImage
->Format
,
1819 GL_UNSIGNED_BYTE
, texImage
->Data
,
1820 &_mesa_native_packing
,
1821 texObj
, texImage
, &retain
);
1824 if (!retain
&& texImage
->Data
) {
1825 FREE(texImage
->Data
);
1826 texImage
->Data
= NULL
;
1830 make_null_texture(texImage
);
1831 if (ctx
->Driver
.TexImage2D
) {
1833 (*ctx
->Driver
.TexImage2D
)( ctx
, target
, level
, texImage
->Format
,
1834 GL_UNSIGNED_BYTE
, texImage
->Data
,
1835 &_mesa_native_packing
,
1836 texObj
, texImage
, &retain
);
1840 #define OLD_DD_TEXTURE
1841 #ifdef OLD_DD_TEXTURE
1842 /* XXX this will be removed in the future */
1843 if (ctx
->Driver
.TexImage
) {
1844 (*ctx
->Driver
.TexImage
)( ctx
, target
, texObj
, level
, internalFormat
,
1850 gl_put_texobj_on_dirty_list( ctx
, texObj
);
1851 ctx
->NewState
|= NEW_TEXTURING
;
1853 else if (target
== GL_PROXY_TEXTURE_2D
) {
1854 /* Proxy texture: check for errors and update proxy state */
1855 GLenum error
= texture_error_check(ctx
, target
, level
, internalFormat
,
1856 format
, type
, 2, width
, height
, 1, border
);
1857 if (!error
&& ctx
->Driver
.TestProxyTexImage
) {
1858 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
1859 internalFormat
, format
, type
,
1860 width
, height
, 1, border
);
1863 /* if error, clear all proxy texture image parameters */
1864 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
1865 clear_proxy_teximage(ctx
->Texture
.Proxy2D
->Image
[level
]);
1869 /* if no error, update proxy texture image parameters */
1870 init_texture_image(ctx
,
1871 ctx
->Texture
.Proxy2D
->Image
[level
],
1872 width
, height
, 1, border
, internalFormat
);
1876 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
1883 * Called by the API or display list executor.
1884 * Note that width and height include the border.
1887 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalFormat
,
1888 GLsizei width
, GLsizei height
, GLsizei depth
,
1889 GLint border
, GLenum format
, GLenum type
,
1890 const GLvoid
*pixels
)
1892 GET_CURRENT_CONTEXT(ctx
);
1893 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glTexImage3D");
1895 if (target
==GL_TEXTURE_3D_EXT
) {
1896 struct gl_texture_unit
*texUnit
;
1897 struct gl_texture_object
*texObj
;
1898 struct gl_texture_image
*texImage
;
1901 ifmt
= get_specific_compressed_tex_format(ctx
, internalFormat
, 3,
1903 &width
, &height
, &depth
,
1904 &border
, &format
, &type
);
1907 * The error here is that we were sent a generic compressed
1908 * format, but the extension is not supported.
1913 internalFormat
= ifmt
;
1916 if (texture_error_check(ctx
, target
, level
, internalFormat
,
1917 format
, type
, 3, width
, height
, depth
, border
)) {
1918 return; /* error in texture image was detected */
1921 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1922 texObj
= texUnit
->CurrentD
[3];
1923 texImage
= texObj
->Image
[level
];
1926 texImage
= _mesa_alloc_texture_image();
1927 texObj
->Image
[level
] = texImage
;
1929 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
1933 else if (texImage
->Data
) {
1934 FREE(texImage
->Data
);
1935 texImage
->Data
= NULL
;
1938 /* setup the teximage struct's fields */
1939 init_texture_image(ctx
, texImage
, width
, height
, depth
,
1940 border
, internalFormat
);
1942 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
1943 _mesa_update_image_transfer_state(ctx
);
1945 /* process the texture image */
1947 GLboolean retain
= GL_TRUE
;
1948 GLboolean success
= GL_FALSE
;
1949 if (!ctx
->ImageTransferState
&& ctx
->Driver
.TexImage3D
) {
1950 /* let device driver try to use raw image */
1951 success
= (*ctx
->Driver
.TexImage3D
)( ctx
, target
, level
, format
,
1952 type
, pixels
, &ctx
->Unpack
,
1953 texObj
, texImage
, &retain
);
1955 if (retain
|| !success
) {
1956 /* make internal copy of the texture image */
1957 make_texture_image(ctx
, 3, texImage
, width
, height
, depth
,
1958 format
, type
, pixels
, &ctx
->Unpack
);
1959 if (!success
&& ctx
->Driver
.TexImage3D
) {
1960 /* let device driver try to use unpacked image */
1961 (*ctx
->Driver
.TexImage3D
)( ctx
, target
, level
, texImage
->Format
,
1962 GL_UNSIGNED_BYTE
, texImage
->Data
,
1963 &_mesa_native_packing
,
1964 texObj
, texImage
, &retain
);
1967 if (!retain
&& texImage
->Data
) {
1968 FREE(texImage
->Data
);
1969 texImage
->Data
= NULL
;
1973 make_null_texture(texImage
);
1974 if (ctx
->Driver
.TexImage3D
) {
1976 (*ctx
->Driver
.TexImage3D
)( ctx
, target
, level
, texImage
->Format
,
1977 GL_UNSIGNED_BYTE
, texImage
->Data
,
1978 &_mesa_native_packing
,
1979 texObj
, texImage
, &retain
);
1984 gl_put_texobj_on_dirty_list( ctx
, texObj
);
1985 ctx
->NewState
|= NEW_TEXTURING
;
1987 else if (target
== GL_PROXY_TEXTURE_3D
) {
1988 /* Proxy texture: check for errors and update proxy state */
1989 GLenum error
= texture_error_check(ctx
, target
, level
, internalFormat
,
1990 format
, type
, 3, width
, height
, depth
, border
);
1991 if (!error
&& ctx
->Driver
.TestProxyTexImage
) {
1992 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
1993 internalFormat
, format
, type
,
1994 width
, height
, depth
, border
);
1997 /* if error, clear all proxy texture image parameters */
1998 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
1999 clear_proxy_teximage(ctx
->Texture
.Proxy3D
->Image
[level
]);
2003 /* if no error, update proxy texture image parameters */
2004 init_texture_image(ctx
, ctx
->Texture
.Proxy3D
->Image
[level
],
2005 width
, height
, depth
, border
, internalFormat
);
2009 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
2016 _mesa_TexImage3DEXT( GLenum target
, GLint level
, GLenum internalFormat
,
2017 GLsizei width
, GLsizei height
, GLsizei depth
,
2018 GLint border
, GLenum format
, GLenum type
,
2019 const GLvoid
*pixels
)
2021 _mesa_TexImage3D(target
, level
, (GLint
) internalFormat
, width
, height
,
2022 depth
, border
, format
, type
, pixels
);
2027 * Fetch a texture image from the device driver.
2028 * Store the results in the given texture object at the given mipmap level.
2031 _mesa_get_teximage_from_driver( GLcontext
*ctx
, GLenum target
, GLint level
,
2032 const struct gl_texture_object
*texObj
)
2035 GLenum imgFormat
, imgType
;
2036 GLboolean freeImage
;
2037 struct gl_texture_image
*texImage
;
2038 GLint destComponents
, numPixels
, srcBytesPerTexel
;
2040 if (!ctx
->Driver
.GetTexImage
)
2043 image
= (*ctx
->Driver
.GetTexImage
)( ctx
, target
, level
, texObj
,
2044 &imgFormat
, &imgType
, &freeImage
);
2048 texImage
= texObj
->Image
[level
];
2053 destComponents
= components_in_intformat(texImage
->Format
);
2054 assert(destComponents
> 0);
2055 numPixels
= texImage
->Width
* texImage
->Height
* texImage
->Depth
;
2056 assert(numPixels
> 0);
2057 srcBytesPerTexel
= _mesa_bytes_per_pixel(imgFormat
, imgType
);
2058 assert(srcBytesPerTexel
> 0);
2060 if (!texImage
->Data
) {
2061 /* Allocate memory for the texture image data */
2062 texImage
->Data
= (GLubyte
*) MALLOC(numPixels
* destComponents
+ EXTRA_BYTE
);
2065 if (imgFormat
== texImage
->Format
&& imgType
== GL_UNSIGNED_BYTE
) {
2066 /* We got lucky! The driver's format and type match Mesa's format. */
2067 if (texImage
->Data
) {
2068 MEMCPY(texImage
->Data
, image
, numPixels
* destComponents
);
2072 /* Convert the texture image from the driver's format to Mesa's
2075 const GLint width
= texImage
->Width
;
2076 const GLint height
= texImage
->Height
;
2077 const GLint depth
= texImage
->Depth
;
2078 const GLint destBytesPerRow
= width
* destComponents
* sizeof(GLchan
);
2079 const GLint srcBytesPerRow
= width
* srcBytesPerTexel
;
2080 const GLenum dstType
= GL_UNSIGNED_BYTE
;
2081 const GLenum dstFormat
= texImage
->Format
;
2082 const GLubyte
*srcPtr
= (const GLubyte
*) image
;
2083 GLubyte
*destPtr
= texImage
->Data
;
2085 if (texImage
->Format
== GL_COLOR_INDEX
) {
2086 /* color index texture */
2088 assert(imgFormat
== GL_COLOR_INDEX
);
2089 for (img
= 0; img
< depth
; img
++) {
2090 for (row
= 0; row
< height
; row
++) {
2091 _mesa_unpack_index_span(ctx
, width
, dstType
, destPtr
,
2092 imgType
, srcPtr
, &_mesa_native_packing
, GL_FALSE
);
2093 destPtr
+= destBytesPerRow
;
2094 srcPtr
+= srcBytesPerRow
;
2101 for (img
= 0; img
< depth
; img
++) {
2102 for (row
= 0; row
< height
; row
++) {
2103 _mesa_unpack_ubyte_color_span(ctx
, width
, dstFormat
, destPtr
,
2104 imgFormat
, imgType
, srcPtr
, &_mesa_native_packing
, GL_FALSE
);
2105 destPtr
+= destBytesPerRow
;
2106 srcPtr
+= srcBytesPerRow
;
2118 * Get all the mipmap images for a texture object from the device driver.
2119 * Actually, only get mipmap images if we're using a mipmap filter.
2122 _mesa_get_teximages_from_driver(GLcontext
*ctx
,
2123 struct gl_texture_object
*texObj
)
2125 if (ctx
->Driver
.GetTexImage
) {
2126 static const GLenum targets
[] = {
2130 GL_TEXTURE_CUBE_MAP_ARB
,
2131 GL_TEXTURE_CUBE_MAP_ARB
,
2132 GL_TEXTURE_CUBE_MAP_ARB
2134 GLboolean needLambda
= (texObj
->MinFilter
!= texObj
->MagFilter
);
2135 GLenum target
= targets
[texObj
->Dimensions
- 1];
2138 /* Get images for all mipmap levels. We might not need them
2139 * all but this is easier. We're on a (slow) software path
2142 for (level
= 0; level
<= texObj
->P
; level
++) {
2143 struct gl_texture_image
*texImg
= texObj
->Image
[level
];
2144 if (texImg
&& !texImg
->Data
) {
2145 _mesa_get_teximage_from_driver(ctx
, target
, level
, texObj
);
2147 return GL_FALSE
; /* out of memory */
2152 GLint level
= texObj
->BaseLevel
;
2153 struct gl_texture_image
*texImg
= texObj
->Image
[level
];
2154 if (texImg
&& !texImg
->Data
) {
2155 _mesa_get_teximage_from_driver(ctx
, target
, level
, texObj
);
2157 return GL_FALSE
; /* out of memory */
2168 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
2169 GLenum type
, GLvoid
*pixels
)
2171 GET_CURRENT_CONTEXT(ctx
);
2172 const struct gl_texture_unit
*texUnit
;
2173 const struct gl_texture_object
*texObj
;
2174 struct gl_texture_image
*texImage
;
2175 GLboolean discardImage
;
2177 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetTexImage");
2179 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
2180 gl_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
2184 if (_mesa_sizeof_type(type
) <= 0) {
2185 gl_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
2189 if (_mesa_components_in_format(format
) <= 0) {
2190 gl_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
2197 texUnit
= &(ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
]);
2198 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2199 texImage
= _mesa_select_tex_image(ctx
, texUnit
, target
, level
);
2200 if (!texObj
|| !texImage
||
2201 target
== GL_PROXY_TEXTURE_1D
||
2202 target
== GL_PROXY_TEXTURE_2D
||
2203 target
== GL_PROXY_TEXTURE_3D
) {
2204 gl_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)");
2209 /* invalid mipmap level */
2213 if (!texImage
->Data
) {
2214 /* try to get the texture image from the device driver */
2215 _mesa_get_teximage_from_driver(ctx
, target
, level
, texObj
);
2216 discardImage
= GL_TRUE
;
2219 discardImage
= GL_FALSE
;
2222 if (texImage
->Data
) {
2223 GLint width
= texImage
->Width
;
2224 GLint height
= texImage
->Height
;
2225 GLint depth
= texImage
->Depth
;
2228 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
2229 _mesa_update_image_transfer_state(ctx
);
2231 if (ctx
->ImageTransferState
& IMAGE_CONVOLUTION_BIT
) {
2232 /* convert texture image to GL_RGBA, GL_FLOAT */
2233 GLfloat
*tmpImage
, *convImage
;
2234 const GLint comps
= components_in_intformat(texImage
->Format
);
2236 tmpImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
2238 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glGetTexImage");
2241 convImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
2244 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glGetTexImage");
2248 for (img
= 0; img
< depth
; img
++) {
2249 GLint convWidth
, convHeight
;
2251 /* convert to GL_RGBA */
2252 for (row
= 0; row
< height
; row
++) {
2253 const GLubyte
*src
= texImage
->Data
2254 + (img
* height
+ row
) * width
* comps
;
2255 GLfloat
*dst
= tmpImage
+ row
* width
* 4;
2256 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
, dst
,
2257 texImage
->Format
, GL_UNSIGNED_BYTE
,
2258 src
, &_mesa_native_packing
,
2259 ctx
->ImageTransferState
& IMAGE_PRE_CONVOLUTION_BITS
,
2264 convHeight
= height
;
2267 if (target
== GL_TEXTURE_1D
) {
2268 if (ctx
->Pixel
.Convolution1DEnabled
) {
2269 _mesa_convolve_1d_image(ctx
, &convWidth
, tmpImage
, convImage
);
2273 if (ctx
->Pixel
.Convolution2DEnabled
) {
2274 _mesa_convolve_2d_image(ctx
, &convWidth
, &convHeight
,
2275 tmpImage
, convImage
);
2277 else if (ctx
->Pixel
.Separable2DEnabled
) {
2278 _mesa_convolve_sep_image(ctx
, &convWidth
, &convHeight
,
2279 tmpImage
, convImage
);
2283 /* pack convolved image */
2284 for (row
= 0; row
< convHeight
; row
++) {
2285 const GLfloat
*src
= convImage
+ row
* convWidth
* 4;
2286 GLvoid
*dest
= _mesa_image_address(&ctx
->Pack
, pixels
,
2287 convWidth
, convHeight
,
2288 format
, type
, img
, row
, 0);
2289 _mesa_pack_float_rgba_span(ctx
, convWidth
,
2290 (const GLfloat(*)[4]) src
,
2291 format
, type
, dest
, &ctx
->Pack
,
2292 ctx
->ImageTransferState
& IMAGE_POST_CONVOLUTION_BITS
);
2300 /* no convolution */
2301 for (img
= 0; img
< depth
; img
++) {
2302 for (row
= 0; row
< height
; row
++) {
2303 /* compute destination address in client memory */
2304 GLvoid
*dest
= _mesa_image_address( &ctx
->Unpack
, pixels
,
2305 width
, height
, format
, type
, img
, row
, 0);
2307 if (texImage
->Format
== GL_RGBA
) {
2309 const GLubyte
*src
= texImage
->Data
2310 + (img
* height
+ row
) * width
* 4;
2311 _mesa_pack_rgba_span( ctx
, width
, (CONST
GLubyte (*)[4]) src
,
2312 format
, type
, dest
, &ctx
->Pack
,
2313 ctx
->ImageTransferState
);
2316 /* general case: convert row to RGBA format */
2317 GLubyte rgba
[MAX_WIDTH
][4];
2320 switch (texImage
->Format
) {
2322 src
= texImage
->Data
+ row
* width
* sizeof(GLubyte
);
2323 for (i
= 0; i
< width
; i
++) {
2324 rgba
[i
][RCOMP
] = CHAN_MAX
;
2325 rgba
[i
][GCOMP
] = CHAN_MAX
;
2326 rgba
[i
][BCOMP
] = CHAN_MAX
;
2327 rgba
[i
][ACOMP
] = src
[i
];
2331 src
= texImage
->Data
+ row
* width
* sizeof(GLubyte
);
2332 for (i
= 0; i
< width
; i
++) {
2333 rgba
[i
][RCOMP
] = src
[i
];
2334 rgba
[i
][GCOMP
] = src
[i
];
2335 rgba
[i
][BCOMP
] = src
[i
];
2336 rgba
[i
][ACOMP
] = CHAN_MAX
;
2339 case GL_LUMINANCE_ALPHA
:
2340 src
= texImage
->Data
+ row
* 2 * width
* sizeof(GLubyte
);
2341 for (i
= 0; i
< width
; i
++) {
2342 rgba
[i
][RCOMP
] = src
[i
*2+0];
2343 rgba
[i
][GCOMP
] = src
[i
*2+0];
2344 rgba
[i
][BCOMP
] = src
[i
*2+0];
2345 rgba
[i
][ACOMP
] = src
[i
*2+1];
2349 src
= texImage
->Data
+ row
* width
* sizeof(GLubyte
);
2350 for (i
= 0; i
< width
; i
++) {
2351 rgba
[i
][RCOMP
] = src
[i
];
2352 rgba
[i
][GCOMP
] = src
[i
];
2353 rgba
[i
][BCOMP
] = src
[i
];
2354 rgba
[i
][ACOMP
] = CHAN_MAX
;
2358 src
= texImage
->Data
+ row
* 3 * width
* sizeof(GLubyte
);
2359 for (i
= 0; i
< width
; i
++) {
2360 rgba
[i
][RCOMP
] = src
[i
*3+0];
2361 rgba
[i
][GCOMP
] = src
[i
*3+1];
2362 rgba
[i
][BCOMP
] = src
[i
*3+2];
2363 rgba
[i
][ACOMP
] = CHAN_MAX
;
2366 case GL_COLOR_INDEX
:
2367 gl_problem( ctx
, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
2371 gl_problem( ctx
, "bad format in gl_GetTexImage" );
2373 _mesa_pack_rgba_span( ctx
, width
, (const GLubyte (*)[4])rgba
,
2374 format
, type
, dest
, &ctx
->Pack
,
2375 ctx
->ImageTransferState
);
2381 /* if we got the teximage from the device driver we'll discard it now */
2383 FREE(texImage
->Data
);
2384 texImage
->Data
= NULL
;
2392 _mesa_TexSubImage1D( GLenum target
, GLint level
,
2393 GLint xoffset
, GLsizei width
,
2394 GLenum format
, GLenum type
,
2395 const GLvoid
*pixels
)
2397 GET_CURRENT_CONTEXT(ctx
);
2398 struct gl_texture_unit
*texUnit
;
2399 struct gl_texture_object
*texObj
;
2400 struct gl_texture_image
*texImage
;
2401 GLboolean success
= GL_FALSE
;
2402 GLsizei postConvWidth
;
2404 postConvWidth
= width
;
2405 adjust_texture_size_for_convolution(ctx
, 1, &postConvWidth
, NULL
);
2407 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
2408 postConvWidth
, 1, 1, format
, type
)) {
2409 return; /* error was detected */
2412 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2413 texObj
= texUnit
->CurrentD
[1];
2414 texImage
= texObj
->Image
[level
];
2417 if (width
== 0 || !pixels
)
2418 return; /* no-op, not an error */
2420 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
2421 _mesa_update_image_transfer_state(ctx
);
2423 if (!ctx
->ImageTransferState
&& ctx
->Driver
.TexSubImage1D
) {
2424 success
= (*ctx
->Driver
.TexSubImage1D
)( ctx
, target
, level
, xoffset
,
2425 width
, format
, type
, pixels
,
2426 &ctx
->Unpack
, texObj
, texImage
);
2429 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
2430 GLboolean retain
= GL_TRUE
;
2431 if (!texImage
->Data
) {
2432 _mesa_get_teximage_from_driver( ctx
, target
, level
, texObj
);
2433 if (!texImage
->Data
) {
2434 make_null_texture(texImage
);
2436 if (!texImage
->Data
)
2437 return; /* we're really out of luck! */
2440 fill_texture_image(ctx
, 1, texImage
->Format
, texImage
->Data
,
2441 width
, 1, 1, xoffset
, 0, 0, /* size and offsets */
2443 format
, type
, pixels
, &ctx
->Unpack
);
2445 if (ctx
->Driver
.TexImage1D
) {
2446 (*ctx
->Driver
.TexImage1D
)( ctx
, target
, level
, texImage
->Format
,
2447 GL_UNSIGNED_BYTE
, texImage
->Data
,
2448 &_mesa_native_packing
, texObj
, texImage
,
2452 if (!retain
&& texImage
->Data
) {
2453 FREE(texImage
->Data
);
2454 texImage
->Data
= NULL
;
2461 _mesa_TexSubImage2D( GLenum target
, GLint level
,
2462 GLint xoffset
, GLint yoffset
,
2463 GLsizei width
, GLsizei height
,
2464 GLenum format
, GLenum type
,
2465 const GLvoid
*pixels
)
2467 GET_CURRENT_CONTEXT(ctx
);
2468 struct gl_texture_unit
*texUnit
;
2469 struct gl_texture_object
*texObj
;
2470 struct gl_texture_image
*texImage
;
2471 GLboolean success
= GL_FALSE
;
2472 GLsizei postConvWidth
, postConvHeight
;
2474 postConvWidth
= width
;
2475 postConvHeight
= height
;
2476 adjust_texture_size_for_convolution(ctx
, 2, &postConvWidth
,&postConvHeight
);
2478 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
2479 postConvWidth
, postConvHeight
, 1, format
, type
)) {
2480 return; /* error was detected */
2483 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2484 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
2485 texImage
= texObj
->Image
[level
];
2488 if (width
== 0 || height
== 0 || !pixels
)
2489 return; /* no-op, not an error */
2491 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
2492 _mesa_update_image_transfer_state(ctx
);
2494 if (!ctx
->ImageTransferState
&& ctx
->Driver
.TexSubImage2D
) {
2495 success
= (*ctx
->Driver
.TexSubImage2D
)( ctx
, target
, level
, xoffset
,
2496 yoffset
, width
, height
, format
, type
,
2497 pixels
, &ctx
->Unpack
, texObj
, texImage
);
2500 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
2501 const GLint texComps
= components_in_intformat(texImage
->Format
);
2502 const GLint texRowStride
= texImage
->Width
* texComps
* sizeof(GLubyte
);
2503 GLboolean retain
= GL_TRUE
;
2505 if (!texImage
->Data
) {
2506 _mesa_get_teximage_from_driver( ctx
, target
, level
, texObj
);
2507 if (!texImage
->Data
) {
2508 make_null_texture(texImage
);
2510 if (!texImage
->Data
)
2511 return; /* we're really out of luck! */
2514 fill_texture_image(ctx
, 2, texImage
->Format
, texImage
->Data
,
2515 width
, height
, 1, xoffset
, yoffset
, 0,
2517 format
, type
, pixels
, &ctx
->Unpack
);
2519 if (ctx
->Driver
.TexImage2D
) {
2520 (*ctx
->Driver
.TexImage2D
)(ctx
, target
, level
, texImage
->Format
,
2521 GL_UNSIGNED_BYTE
, texImage
->Data
,
2522 &_mesa_native_packing
, texObj
, texImage
,
2526 if (!retain
&& texImage
->Data
) {
2527 FREE(texImage
->Data
);
2528 texImage
->Data
= NULL
;
2531 #ifdef OLD_DD_TEXTURE
2532 /* XXX this will be removed in the future */
2533 if (ctx
->Driver
.TexSubImage
) {
2534 (*ctx
->Driver
.TexSubImage
)(ctx
, target
, texObj
, level
,
2535 xoffset
, yoffset
, width
, height
,
2536 texImage
->IntFormat
, texImage
);
2538 else if (ctx
->Driver
.TexImage
) {
2539 (*ctx
->Driver
.TexImage
)(ctx
, GL_TEXTURE_2D
, texObj
,
2540 level
, texImage
->IntFormat
, texImage
);
2549 _mesa_TexSubImage3D( GLenum target
, GLint level
,
2550 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2551 GLsizei width
, GLsizei height
, GLsizei depth
,
2552 GLenum format
, GLenum type
,
2553 const GLvoid
*pixels
)
2555 GET_CURRENT_CONTEXT(ctx
);
2556 struct gl_texture_unit
*texUnit
;
2557 struct gl_texture_object
*texObj
;
2558 struct gl_texture_image
*texImage
;
2559 GLboolean success
= GL_FALSE
;
2561 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
2562 width
, height
, depth
, format
, type
)) {
2563 return; /* error was detected */
2566 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2567 texObj
= texUnit
->CurrentD
[3];
2568 texImage
= texObj
->Image
[level
];
2571 if (width
== 0 || height
== 0 || height
== 0 || !pixels
)
2572 return; /* no-op, not an error */
2574 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
2575 _mesa_update_image_transfer_state(ctx
);
2577 if (!ctx
->ImageTransferState
&& ctx
->Driver
.TexSubImage3D
) {
2578 success
= (*ctx
->Driver
.TexSubImage3D
)( ctx
, target
, level
, xoffset
,
2579 yoffset
, zoffset
, width
, height
, depth
, format
,
2580 type
, pixels
, &ctx
->Unpack
, texObj
, texImage
);
2583 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
2584 const GLint texComps
= components_in_intformat(texImage
->Format
);
2585 const GLint texRowStride
= texImage
->Width
* texComps
* sizeof(GLubyte
);
2586 const GLint texImgStride
= texRowStride
* texImage
->Height
;
2587 GLboolean retain
= GL_TRUE
;
2589 if (!texImage
->Data
) {
2590 _mesa_get_teximage_from_driver( ctx
, target
, level
, texObj
);
2591 if (!texImage
->Data
) {
2592 make_null_texture(texImage
);
2594 if (!texImage
->Data
)
2595 return; /* we're really out of luck! */
2598 fill_texture_image(ctx
, 3, texImage
->Format
, texImage
->Data
,
2599 width
, height
, depth
, xoffset
, yoffset
, zoffset
,
2600 texRowStride
, texImgStride
,
2601 format
, type
, pixels
, &ctx
->Unpack
);
2603 if (ctx
->Driver
.TexImage3D
) {
2604 (*ctx
->Driver
.TexImage3D
)(ctx
, target
, level
, texImage
->Format
,
2605 GL_UNSIGNED_BYTE
, texImage
->Data
,
2606 &_mesa_native_packing
, texObj
, texImage
,
2610 if (!retain
&& texImage
->Data
) {
2611 FREE(texImage
->Data
);
2612 texImage
->Data
= NULL
;
2620 * Read an RGBA image from the frame buffer.
2621 * This is used by glCopyTex[Sub]Image[12]D().
2622 * Input: ctx - the context
2623 * x, y - lower left corner
2624 * width, height - size of region to read
2625 * Return: pointer to block of GL_RGBA, GLubyte data.
2628 read_color_image( GLcontext
*ctx
, GLint x
, GLint y
,
2629 GLsizei width
, GLsizei height
)
2632 GLubyte
*image
, *dst
;
2634 image
= (GLubyte
*) MALLOC(width
* height
* 4 * sizeof(GLubyte
));
2638 /* Select buffer to read from */
2639 (*ctx
->Driver
.SetReadBuffer
)( ctx
, ctx
->ReadBuffer
,
2640 ctx
->Pixel
.DriverReadBuffer
);
2643 stride
= width
* 4 * sizeof(GLubyte
);
2644 for (i
= 0; i
< height
; i
++) {
2645 gl_read_rgba_span( ctx
, ctx
->ReadBuffer
, width
, x
, y
+ i
,
2646 (GLubyte (*)[4]) dst
);
2650 /* Read from draw buffer (the default) */
2651 (*ctx
->Driver
.SetReadBuffer
)( ctx
, ctx
->DrawBuffer
,
2652 ctx
->Color
.DriverDrawBuffer
);
2660 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
2661 GLenum internalFormat
,
2663 GLsizei width
, GLint border
)
2665 GET_CURRENT_CONTEXT(ctx
);
2666 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexImage1D");
2668 if (copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
2672 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
2673 _mesa_update_image_transfer_state(ctx
);
2675 if (ctx
->ImageTransferState
|| !ctx
->Driver
.CopyTexImage1D
2676 || !(*ctx
->Driver
.CopyTexImage1D
)(ctx
, target
, level
,
2677 internalFormat
, x
, y
, width
, border
)) {
2678 struct gl_pixelstore_attrib unpackSave
;
2680 /* get image from framebuffer */
2681 GLubyte
*image
= read_color_image( ctx
, x
, y
, width
, 1 );
2683 gl_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D" );
2687 /* call glTexImage1D to redefine the texture */
2688 unpackSave
= ctx
->Unpack
;
2689 ctx
->Unpack
= _mesa_native_packing
;
2690 (*ctx
->Exec
->TexImage1D
)( target
, level
, internalFormat
, width
,
2691 border
, GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
2692 ctx
->Unpack
= unpackSave
;
2701 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
2702 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2705 GET_CURRENT_CONTEXT(ctx
);
2706 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexImage2D");
2708 if (copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
2709 width
, height
, border
))
2712 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
2713 _mesa_update_image_transfer_state(ctx
);
2715 if (ctx
->ImageTransferState
|| !ctx
->Driver
.CopyTexImage2D
2716 || !(*ctx
->Driver
.CopyTexImage2D
)(ctx
, target
, level
,
2717 internalFormat
, x
, y
, width
, height
, border
)) {
2718 struct gl_pixelstore_attrib unpackSave
;
2720 /* get image from framebuffer */
2721 GLubyte
*image
= read_color_image( ctx
, x
, y
, width
, height
);
2723 gl_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D" );
2727 /* call glTexImage2D to redefine the texture */
2728 unpackSave
= ctx
->Unpack
;
2729 ctx
->Unpack
= _mesa_native_packing
;
2730 (ctx
->Exec
->TexImage2D
)( target
, level
, internalFormat
, width
,
2731 height
, border
, GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
2732 ctx
->Unpack
= unpackSave
;
2741 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
2742 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
2744 GET_CURRENT_CONTEXT(ctx
);
2745 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexSubImage1D");
2747 if (copytexsubimage_error_check(ctx
, 1, target
, level
,
2748 xoffset
, 0, 0, width
, 1))
2751 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
2752 _mesa_update_image_transfer_state(ctx
);
2754 if (ctx
->ImageTransferState
|| !ctx
->Driver
.CopyTexSubImage1D
2755 || !(*ctx
->Driver
.CopyTexSubImage1D
)(ctx
, target
, level
,
2756 xoffset
, x
, y
, width
)) {
2757 struct gl_texture_unit
*texUnit
;
2758 struct gl_texture_image
*teximage
;
2759 struct gl_pixelstore_attrib unpackSave
;
2762 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2763 teximage
= texUnit
->CurrentD
[1]->Image
[level
];
2766 /* get image from frame buffer */
2767 image
= read_color_image(ctx
, x
, y
, width
, 1);
2769 gl_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D" );
2773 /* now call glTexSubImage1D to do the real work */
2774 unpackSave
= ctx
->Unpack
;
2775 ctx
->Unpack
= _mesa_native_packing
;
2776 _mesa_TexSubImage1D(target
, level
, xoffset
, width
,
2777 GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
2778 ctx
->Unpack
= unpackSave
;
2787 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
2788 GLint xoffset
, GLint yoffset
,
2789 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2791 GET_CURRENT_CONTEXT(ctx
);
2792 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexSubImage2D");
2794 if (copytexsubimage_error_check(ctx
, 2, target
, level
,
2795 xoffset
, yoffset
, 0, width
, height
))
2798 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
2799 _mesa_update_image_transfer_state(ctx
);
2801 if (ctx
->ImageTransferState
|| !ctx
->Driver
.CopyTexSubImage2D
2802 || !(*ctx
->Driver
.CopyTexSubImage2D
)(ctx
, target
, level
,
2803 xoffset
, yoffset
, x
, y
, width
, height
)) {
2804 struct gl_texture_unit
*texUnit
;
2805 struct gl_texture_image
*teximage
;
2806 struct gl_pixelstore_attrib unpackSave
;
2809 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2810 teximage
= texUnit
->CurrentD
[2]->Image
[level
];
2813 /* get image from frame buffer */
2814 image
= read_color_image(ctx
, x
, y
, width
, height
);
2816 gl_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D" );
2820 /* now call glTexSubImage2D to do the real work */
2821 unpackSave
= ctx
->Unpack
;
2822 ctx
->Unpack
= _mesa_native_packing
;
2823 _mesa_TexSubImage2D(target
, level
, xoffset
, yoffset
, width
, height
,
2824 GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
2825 ctx
->Unpack
= unpackSave
;
2834 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
2835 GLint xoffset
, GLint yoffset
, GLint zoffset
,
2836 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
2838 GET_CURRENT_CONTEXT(ctx
);
2839 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexSubImage3D");
2841 if (copytexsubimage_error_check(ctx
, 3, target
, level
,
2842 xoffset
, yoffset
, zoffset
, width
, height
))
2845 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
2846 _mesa_update_image_transfer_state(ctx
);
2848 if (ctx
->ImageTransferState
|| !ctx
->Driver
.CopyTexSubImage3D
2849 || !(*ctx
->Driver
.CopyTexSubImage3D
)(ctx
, target
, level
,
2850 xoffset
, yoffset
, zoffset
, x
, y
, width
, height
)) {
2851 struct gl_texture_unit
*texUnit
;
2852 struct gl_texture_image
*teximage
;
2853 struct gl_pixelstore_attrib unpackSave
;
2856 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2857 teximage
= texUnit
->CurrentD
[3]->Image
[level
];
2860 /* get image from frame buffer */
2861 image
= read_color_image(ctx
, x
, y
, width
, height
);
2863 gl_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D" );
2867 /* now call glTexSubImage2D to do the real work */
2868 unpackSave
= ctx
->Unpack
;
2869 ctx
->Unpack
= _mesa_native_packing
;
2870 _mesa_TexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
,
2871 width
, height
, 1, GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
2872 ctx
->Unpack
= unpackSave
;
2881 _mesa_CompressedTexImage1DARB(GLenum target
, GLint level
,
2882 GLenum internalFormat
, GLsizei width
,
2883 GLint border
, GLsizei imageSize
,
2886 GET_CURRENT_CONTEXT(ctx
);
2887 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCompressedTexImage1DARB");
2889 switch (internalFormat
) {
2890 case GL_COMPRESSED_ALPHA_ARB
:
2891 case GL_COMPRESSED_LUMINANCE_ARB
:
2892 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB
:
2893 case GL_COMPRESSED_INTENSITY_ARB
:
2894 case GL_COMPRESSED_RGB_ARB
:
2895 case GL_COMPRESSED_RGBA_ARB
:
2896 gl_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage1DARB");
2899 /* silence compiler warning */
2903 if (target
== GL_TEXTURE_1D
) {
2904 struct gl_texture_unit
*texUnit
;
2905 struct gl_texture_object
*texObj
;
2906 struct gl_texture_image
*texImage
;
2907 GLsizei computedImageSize
;
2909 if (texture_error_check(ctx
, target
, level
, internalFormat
,
2910 GL_NONE
, GL_NONE
, 1, width
, 1, 1, border
)) {
2911 return; /* error in texture image was detected */
2914 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
2915 texObj
= texUnit
->CurrentD
[1];
2916 texImage
= texObj
->Image
[level
];
2919 texImage
= _mesa_alloc_texture_image();
2920 texObj
->Image
[level
] = texImage
;
2922 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage1DARB");
2926 else if (texImage
->Data
) {
2927 FREE(texImage
->Data
);
2928 texImage
->Data
= NULL
;
2931 /* setup the teximage struct's fields */
2932 init_texture_image(ctx
, texImage
, width
, 1, 1,
2933 border
, internalFormat
);
2935 /* process the texture image */
2937 GLboolean retain
= GL_TRUE
;
2938 GLboolean success
= GL_FALSE
;
2939 if (ctx
->Driver
.CompressedTexImage1D
) {
2940 success
= (*ctx
->Driver
.CompressedTexImage1D
)(ctx
, target
, level
,
2941 imageSize
, data
, texObj
, texImage
, &retain
);
2943 if (retain
|| !success
) {
2944 /* make internal copy of the texture image */
2945 computedImageSize
= _mesa_compressed_image_size(ctx
,
2951 if (computedImageSize
!= imageSize
) {
2952 gl_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexImage1DARB(imageSize)");
2955 texImage
->Data
= MALLOC(computedImageSize
);
2956 if (texImage
->Data
) {
2957 MEMCPY(texImage
->Data
, data
, computedImageSize
);
2960 if (!retain
&& texImage
->Data
) {
2961 FREE(texImage
->Data
);
2962 texImage
->Data
= NULL
;
2966 make_null_texture(texImage
);
2967 if (ctx
->Driver
.CompressedTexImage1D
) {
2969 (*ctx
->Driver
.CompressedTexImage1D
)(ctx
, target
, level
, 0,
2970 texImage
->Data
, texObj
,
2976 gl_put_texobj_on_dirty_list( ctx
, texObj
);
2977 ctx
->NewState
|= NEW_TEXTURING
;
2979 else if (target
== GL_PROXY_TEXTURE_1D
) {
2980 /* Proxy texture: check for errors and update proxy state */
2981 GLenum error
= texture_error_check(ctx
, target
, level
, internalFormat
,
2982 GL_NONE
, GL_NONE
, 1, width
, 1, 1, border
);
2983 if (!error
&& ctx
->Driver
.TestProxyTexImage
) {
2984 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
2985 internalFormat
, GL_NONE
, GL_NONE
,
2986 width
, 1, 1, border
);
2989 /* if error, clear all proxy texture image parameters */
2990 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
2991 clear_proxy_teximage(ctx
->Texture
.Proxy1D
->Image
[level
]);
2995 /* if no error, update proxy texture image parameters */
2996 init_texture_image(ctx
, ctx
->Texture
.Proxy1D
->Image
[level
],
2997 width
, 1, 1, border
, internalFormat
);
3001 gl_error( ctx
, GL_INVALID_ENUM
, "glCompressedTexImage1DARB(target)" );
3008 _mesa_CompressedTexImage2DARB(GLenum target
, GLint level
,
3009 GLenum internalFormat
, GLsizei width
,
3010 GLsizei height
, GLint border
, GLsizei imageSize
,
3013 GET_CURRENT_CONTEXT(ctx
);
3014 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCompressedTexImage2DARB");
3016 switch (internalFormat
) {
3017 case GL_COMPRESSED_ALPHA_ARB
:
3018 case GL_COMPRESSED_LUMINANCE_ARB
:
3019 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB
:
3020 case GL_COMPRESSED_INTENSITY_ARB
:
3021 case GL_COMPRESSED_RGB_ARB
:
3022 case GL_COMPRESSED_RGBA_ARB
:
3023 gl_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2DARB");
3026 /* silence compiler warning */
3030 if (target
==GL_TEXTURE_2D
||
3031 (ctx
->Extensions
.HaveTextureCubeMap
&&
3032 target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
&&
3033 target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
)) {
3034 struct gl_texture_unit
*texUnit
;
3035 struct gl_texture_object
*texObj
;
3036 struct gl_texture_image
*texImage
;
3037 GLsizei computedImageSize
;
3039 if (texture_error_check(ctx
, target
, level
, internalFormat
,
3040 GL_NONE
, GL_NONE
, 1, width
, height
, 1, border
)) {
3041 return; /* error in texture image was detected */
3044 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3045 texObj
= texUnit
->CurrentD
[2];
3046 texImage
= texObj
->Image
[level
];
3049 texImage
= _mesa_alloc_texture_image();
3050 texObj
->Image
[level
] = texImage
;
3052 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2DARB");
3056 else if (texImage
->Data
) {
3057 FREE(texImage
->Data
);
3058 texImage
->Data
= NULL
;
3061 /* setup the teximage struct's fields */
3062 init_texture_image(ctx
, texImage
, width
, height
, 1, border
, internalFormat
);
3064 /* process the texture image */
3066 GLboolean retain
= GL_TRUE
;
3067 GLboolean success
= GL_FALSE
;
3068 if (ctx
->Driver
.CompressedTexImage2D
) {
3069 success
= (*ctx
->Driver
.CompressedTexImage2D
)( ctx
,
3078 if (retain
|| !success
) {
3079 /* make internal copy of the texture image */
3080 computedImageSize
= _mesa_compressed_image_size(ctx
,
3086 if (computedImageSize
!= imageSize
) {
3087 gl_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexImage2DARB(imageSize)");
3090 texImage
->Data
= MALLOC(computedImageSize
);
3091 if (texImage
->Data
) {
3092 MEMCPY(texImage
->Data
, data
, computedImageSize
);
3095 if (!retain
&& texImage
->Data
) {
3096 FREE(texImage
->Data
);
3097 texImage
->Data
= NULL
;
3101 make_null_texture(texImage
);
3102 if (ctx
->Driver
.CompressedTexImage2D
) {
3104 (*ctx
->Driver
.CompressedTexImage2D
)( ctx
, target
, level
, 0,
3105 texImage
->Data
, texObj
,
3111 gl_put_texobj_on_dirty_list( ctx
, texObj
);
3112 ctx
->NewState
|= NEW_TEXTURING
;
3114 else if (target
== GL_PROXY_TEXTURE_2D
) {
3115 /* Proxy texture: check for errors and update proxy state */
3116 GLenum error
= texture_error_check(ctx
, target
, level
, internalFormat
,
3117 GL_NONE
, GL_NONE
, 2, width
, height
, 1, border
);
3118 if (!error
&& ctx
->Driver
.TestProxyTexImage
) {
3119 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3120 internalFormat
, GL_NONE
, GL_NONE
,
3121 width
, height
, 1, border
);
3124 /* if error, clear all proxy texture image parameters */
3125 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
3126 clear_proxy_teximage(ctx
->Texture
.Proxy2D
->Image
[level
]);
3130 /* if no error, update proxy texture image parameters */
3131 init_texture_image(ctx
, ctx
->Texture
.Proxy2D
->Image
[level
],
3132 width
, 1, 1, border
, internalFormat
);
3136 gl_error( ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2DARB(target)" );
3143 _mesa_CompressedTexImage3DARB(GLenum target
, GLint level
,
3144 GLenum internalFormat
, GLsizei width
,
3145 GLsizei height
, GLsizei depth
, GLint border
,
3146 GLsizei imageSize
, const GLvoid
*data
)
3148 GET_CURRENT_CONTEXT(ctx
);
3149 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCompressedTexImage3DARB");
3151 switch (internalFormat
) {
3152 case GL_COMPRESSED_ALPHA_ARB
:
3153 case GL_COMPRESSED_LUMINANCE_ARB
:
3154 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB
:
3155 case GL_COMPRESSED_INTENSITY_ARB
:
3156 case GL_COMPRESSED_RGB_ARB
:
3157 case GL_COMPRESSED_RGBA_ARB
:
3158 gl_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage3DARB");
3161 /* silence compiler warning */
3165 if (target
== GL_TEXTURE_3D
) {
3166 struct gl_texture_unit
*texUnit
;
3167 struct gl_texture_object
*texObj
;
3168 struct gl_texture_image
*texImage
;
3169 GLsizei computedImageSize
;
3171 if (texture_error_check(ctx
, target
, level
, internalFormat
,
3172 GL_NONE
, GL_NONE
, 1, width
, height
, depth
, border
)) {
3173 return; /* error in texture image was detected */
3176 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3177 texObj
= texUnit
->CurrentD
[3];
3178 texImage
= texObj
->Image
[level
];
3181 texImage
= _mesa_alloc_texture_image();
3182 texObj
->Image
[level
] = texImage
;
3184 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage3DARB");
3188 else if (texImage
->Data
) {
3189 FREE(texImage
->Data
);
3190 texImage
->Data
= NULL
;
3193 /* setup the teximage struct's fields */
3194 init_texture_image(ctx
, texImage
, width
, height
, depth
,
3195 border
, internalFormat
);
3197 /* process the texture image */
3199 GLboolean retain
= GL_TRUE
;
3200 GLboolean success
= GL_FALSE
;
3201 if (ctx
->Driver
.CompressedTexImage3D
) {
3202 success
= (*ctx
->Driver
.CompressedTexImage3D
)(ctx
, target
, level
,
3207 if (retain
|| !success
) {
3208 /* make internal copy of the texture image */
3209 computedImageSize
= _mesa_compressed_image_size(ctx
,
3215 if (computedImageSize
!= imageSize
) {
3216 gl_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexImage3DARB(imageSize)");
3219 texImage
->Data
= MALLOC(computedImageSize
);
3220 if (texImage
->Data
) {
3221 MEMCPY(texImage
->Data
, data
, computedImageSize
);
3224 if (!retain
&& texImage
->Data
) {
3225 FREE(texImage
->Data
);
3226 texImage
->Data
= NULL
;
3230 make_null_texture(texImage
);
3231 if (ctx
->Driver
.CompressedTexImage3D
) {
3233 (*ctx
->Driver
.CompressedTexImage3D
)( ctx
, target
, level
, 0,
3234 texImage
->Data
, texObj
,
3240 gl_put_texobj_on_dirty_list( ctx
, texObj
);
3241 ctx
->NewState
|= NEW_TEXTURING
;
3243 else if (target
== GL_PROXY_TEXTURE_3D
) {
3244 /* Proxy texture: check for errors and update proxy state */
3245 GLenum error
= texture_error_check(ctx
, target
, level
, internalFormat
,
3246 GL_NONE
, GL_NONE
, 1, width
, height
, depth
, border
);
3247 if (!error
&& ctx
->Driver
.TestProxyTexImage
) {
3248 error
= !(*ctx
->Driver
.TestProxyTexImage
)(ctx
, target
, level
,
3249 internalFormat
, GL_NONE
, GL_NONE
,
3250 width
, height
, depth
, border
);
3253 /* if error, clear all proxy texture image parameters */
3254 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
3255 clear_proxy_teximage(ctx
->Texture
.Proxy3D
->Image
[level
]);
3259 /* if no error, update proxy texture image parameters */
3260 init_texture_image(ctx
, ctx
->Texture
.Proxy3D
->Image
[level
],
3261 width
, 1, 1, border
, internalFormat
);
3265 gl_error( ctx
, GL_INVALID_ENUM
, "glCompressedTexImage3DARB(target)" );
3272 _mesa_CompressedTexSubImage1DARB(GLenum target
, GLint level
, GLint xoffset
,
3273 GLsizei width
, GLenum format
,
3274 GLsizei imageSize
, const GLvoid
*data
)
3276 GET_CURRENT_CONTEXT(ctx
);
3277 struct gl_texture_unit
*texUnit
;
3278 struct gl_texture_object
*texObj
;
3279 struct gl_texture_image
*texImage
;
3280 GLboolean success
= GL_FALSE
;
3282 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
3283 width
, 1, 1, format
, GL_NONE
)) {
3284 return; /* error was detected */
3287 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3288 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3289 texImage
= texObj
->Image
[level
];
3292 if (width
== 0 || !data
)
3293 return; /* no-op, not an error */
3295 if (ctx
->Driver
.CompressedTexSubImage1D
) {
3296 success
= (*ctx
->Driver
.CompressedTexSubImage1D
)(ctx
, target
, level
,
3297 xoffset
, width
, format
, imageSize
, data
, texObj
, texImage
);
3300 /* XXX what else can we do? */
3301 gl_problem(ctx
, "glCompressedTexSubImage1DARB failed!");
3308 _mesa_CompressedTexSubImage2DARB(GLenum target
, GLint level
, GLint xoffset
,
3309 GLint yoffset
, GLsizei width
, GLsizei height
,
3310 GLenum format
, GLsizei imageSize
,
3313 GET_CURRENT_CONTEXT(ctx
);
3314 struct gl_texture_unit
*texUnit
;
3315 struct gl_texture_object
*texObj
;
3316 struct gl_texture_image
*texImage
;
3317 GLboolean success
= GL_FALSE
;
3319 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
3320 width
, height
, 1, format
, GL_NONE
)) {
3321 return; /* error was detected */
3324 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3325 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3326 texImage
= texObj
->Image
[level
];
3329 if (width
== 0 || height
== 0 || !data
)
3330 return; /* no-op, not an error */
3332 if (ctx
->Driver
.CompressedTexSubImage2D
) {
3333 success
= (*ctx
->Driver
.CompressedTexSubImage2D
)(ctx
, target
, level
,
3334 xoffset
, yoffset
, width
, height
, format
,
3335 imageSize
, data
, texObj
, texImage
);
3338 /* XXX what else can we do? */
3339 gl_problem(ctx
, "glCompressedTexSubImage2DARB failed!");
3346 _mesa_CompressedTexSubImage3DARB(GLenum target
, GLint level
, GLint xoffset
,
3347 GLint yoffset
, GLint zoffset
, GLsizei width
,
3348 GLsizei height
, GLsizei depth
, GLenum format
,
3349 GLsizei imageSize
, const GLvoid
*data
)
3351 GET_CURRENT_CONTEXT(ctx
);
3352 struct gl_texture_unit
*texUnit
;
3353 struct gl_texture_object
*texObj
;
3354 struct gl_texture_image
*texImage
;
3355 GLboolean success
= GL_FALSE
;
3357 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
3358 width
, height
, depth
, format
, GL_NONE
)) {
3359 return; /* error was detected */
3362 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
3363 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
3364 texImage
= texObj
->Image
[level
];
3367 if (width
== 0 || height
== 0 || depth
== 0 || !data
)
3368 return; /* no-op, not an error */
3370 if (ctx
->Driver
.CompressedTexSubImage3D
) {
3371 success
= (*ctx
->Driver
.CompressedTexSubImage3D
)(ctx
, target
, level
,
3372 xoffset
, yoffset
, zoffset
, width
, height
, depth
,
3373 format
, imageSize
, data
, texObj
, texImage
);
3376 /* XXX what else can we do? */
3377 gl_problem(ctx
, "glCompressedTexSubImage3DARB failed!");
3384 _mesa_GetCompressedTexImageARB(GLenum target
, GLint level
, GLvoid
*img
)
3386 GET_CURRENT_CONTEXT(ctx
);
3387 const struct gl_texture_object
*texObj
;
3388 struct gl_texture_image
*texImage
;
3390 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetCompressedTexImageARB");
3392 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
3393 gl_error( ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)" );
3399 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentD
[1];
3400 texImage
= texObj
->Image
[level
];
3403 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentD
[2];
3404 texImage
= texObj
->Image
[level
];
3406 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
3407 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentCubeMap
;
3408 texImage
= texObj
->Image
[level
];
3410 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
3411 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentCubeMap
;
3412 texImage
= texObj
->NegX
[level
];
3414 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
3415 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentCubeMap
;
3416 texImage
= texObj
->PosY
[level
];
3418 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
3419 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentCubeMap
;
3420 texImage
= texObj
->NegY
[level
];
3422 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
3423 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentCubeMap
;
3424 texImage
= texObj
->PosZ
[level
];
3426 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
3427 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentCubeMap
;
3428 texImage
= texObj
->NegZ
[level
];
3431 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentD
[3];
3432 texImage
= texObj
->Image
[level
];
3435 gl_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
3440 /* invalid mipmap level */
3441 gl_error(ctx
, GL_INVALID_VALUE
, "glGetCompressedTexImageARB(level)");
3445 if (!texImage
->IsCompressed
) {
3446 gl_error(ctx
, GL_INVALID_OPERATION
, "glGetCompressedTexImageARB");
3453 if (ctx
->Driver
.GetCompressedTexImage
) {
3454 (*ctx
->Driver
.GetCompressedTexImage
)(ctx
, target
, level
, img
, texObj
,
3458 gl_problem(ctx
, "Driver doesn't implement GetCompressedTexImage");