1 /* $Id: texutil.c,v 1.16 2001/03/18 13:40:58 gareth Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 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.
27 * Gareth Hughes <gareth@valinux.com>
40 #include "texformat.h"
47 struct gl_texture_convert
{
48 GLint xoffset
, yoffset
, zoffset
; /* Subimage offset */
49 GLint width
, height
, depth
; /* Subimage region */
51 GLint imageWidth
, imageHeight
; /* Full image dimensions */
54 const struct gl_pixelstore_attrib
*packing
;
56 const GLvoid
*srcImage
;
62 typedef GLboolean (*convert_func
)( struct gl_texture_convert
*convert
);
64 #define CONVERT_STRIDE_BIT 0x1
65 #define CONVERT_PACKING_BIT 0x2
69 /* ================================================================
73 #define DST_TYPE GLuint
74 #define DST_TEXELS_PER_DWORD 1
76 #define CONVERT_TEXEL( src ) \
77 PACK_COLOR_8888( src[3], src[2], src[1], src[0] )
79 #define CONVERT_DIRECT
81 #define SRC_TEXEL_BYTES 4
83 #define TAG(x) x##_rgba8888_direct
84 #define PRESERVE_DST_TYPE
85 #include "texutil_tmp.h"
88 #define CONVERT_TEXEL( src ) \
89 PACK_COLOR_8888( src[0], src[1], src[2], src[3] )
91 #define CONVERT_TEXEL_DWORD( src ) CONVERT_TEXEL( src )
93 #define SRC_TEXEL_BYTES 4
95 #define TAG(x) x##_abgr8888_to_rgba8888
96 #define PRESERVE_DST_TYPE
97 #include "texutil_tmp.h"
100 #define CONVERT_TEXEL( src ) \
101 PACK_COLOR_8888( src[0], src[1], src[2], 0xff )
103 #define CONVERT_TEXEL_DWORD( src ) CONVERT_TEXEL( src )
105 #define SRC_TEXEL_BYTES 3
107 #define TAG(x) x##_bgr888_to_rgba8888
108 #include "texutil_tmp.h"
111 #define CONVERT_RGBA8888( name ) \
113 convert_##name##_rgba8888( struct gl_texture_convert *convert ) \
116 GLint index = convert->index; \
118 if ( convert->format == GL_ABGR_EXT && \
119 convert->type == GL_UNSIGNED_INT_8_8_8_8_REV ) \
121 tab = name##_tab_rgba8888_direct; \
123 else if ( convert->format == GL_RGBA && \
124 ( convert->type == GL_UNSIGNED_BYTE || \
125 convert->type == GL_UNSIGNED_INT_8_8_8_8 ) ) \
127 tab = name##_tab_abgr8888_to_rgba8888; \
129 else if ( convert->format == GL_RGB && \
130 convert->type == GL_UNSIGNED_BYTE ) \
132 tab = name##_tab_bgr888_to_rgba8888; \
136 /* Can't handle this source format/type combination */ \
140 return tab[index]( convert ); \
143 CONVERT_RGBA8888( texsubimage2d
)
144 CONVERT_RGBA8888( texsubimage3d
)
148 /* ================================================================
152 #define DST_TYPE GLuint
153 #define DST_TEXELS_PER_DWORD 1
155 #define CONVERT_TEXEL( src ) \
156 PACK_COLOR_8888( src[3], src[2], src[1], src[0] )
158 #define CONVERT_DIRECT
160 #define SRC_TEXEL_BYTES 4
162 #define TAG(x) x##_argb8888_direct
163 #define PRESERVE_DST_TYPE
164 #include "texutil_tmp.h"
167 #define CONVERT_TEXEL( src ) \
168 PACK_COLOR_8888( src[3], src[0], src[1], src[2] )
170 #define CONVERT_TEXEL_DWORD( src ) CONVERT_TEXEL( src )
172 #define SRC_TEXEL_BYTES 4
174 #define TAG(x) x##_abgr8888_to_argb8888
175 #define PRESERVE_DST_TYPE
176 #include "texutil_tmp.h"
179 #define CONVERT_TEXEL( src ) \
180 PACK_COLOR_8888( 0xff, src[0], src[1], src[2] )
182 #define CONVERT_TEXEL_DWORD( src ) CONVERT_TEXEL( src )
184 #define SRC_TEXEL_BYTES 3
186 #define TAG(x) x##_bgr888_to_argb8888
187 #include "texutil_tmp.h"
190 #define CONVERT_ARGB8888( name ) \
192 convert_##name##_argb8888( struct gl_texture_convert *convert ) \
195 GLint index = convert->index; \
197 if ( convert->format == GL_BGRA && \
198 convert->type == GL_UNSIGNED_INT_8_8_8_8_REV ) \
200 tab = name##_tab_argb8888_direct; \
202 else if ( convert->format == GL_RGBA && \
203 convert->type == GL_UNSIGNED_BYTE ) \
205 tab = name##_tab_abgr8888_to_argb8888; \
207 else if ( convert->format == GL_RGB && \
208 convert->type == GL_UNSIGNED_BYTE ) \
210 tab = name##_tab_bgr888_to_argb8888; \
214 /* Can't handle this source format/type combination */ \
218 return tab[index]( convert ); \
221 CONVERT_ARGB8888( texsubimage2d
)
222 CONVERT_ARGB8888( texsubimage3d
)
226 /* ================================================================
231 convert_texsubimage2d_rgb888( struct gl_texture_convert
*convert
)
233 /* This is a placeholder for now...
239 convert_texsubimage3d_rgb888( struct gl_texture_convert
*convert
)
241 /* This is a placeholder for now...
248 /* ================================================================
252 #define DST_TYPE GLushort
253 #define DST_TEXELS_PER_DWORD 2
255 #define CONVERT_TEXEL( src ) \
256 PACK_COLOR_565( src[0], src[1], src[2] )
258 #define CONVERT_DIRECT
260 #define SRC_TEXEL_BYTES 2
262 #define TAG(x) x##_rgb565_direct
263 #define PRESERVE_DST_TYPE
264 #include "texutil_tmp.h"
267 #define CONVERT_TEXEL( src ) \
268 PACK_COLOR_565( src[0], src[1], src[2] )
270 #define CONVERT_TEXEL_DWORD( src ) \
271 ((PACK_COLOR_565( src[0], src[1], src[2] )) | \
272 (PACK_COLOR_565( src[3], src[4], src[5] ) << 16))
274 #define SRC_TEXEL_BYTES 3
276 #define TAG(x) x##_bgr888_to_rgb565
277 #define PRESERVE_DST_TYPE
278 #include "texutil_tmp.h"
281 #define CONVERT_TEXEL( src ) \
282 PACK_COLOR_565( src[0], src[1], src[2] )
284 #define CONVERT_TEXEL_DWORD( src ) \
285 ((PACK_COLOR_565( src[0], src[1], src[2] )) | \
286 (PACK_COLOR_565( src[4], src[5], src[6] ) << 16))
288 #define SRC_TEXEL_BYTES 4
290 #define TAG(x) x##_abgr8888_to_rgb565
291 #include "texutil_tmp.h"
294 #define CONVERT_RGB565( name ) \
296 convert_##name##_rgb565( struct gl_texture_convert *convert ) \
299 GLint index = convert->index; \
301 if ( convert->format == GL_RGB && \
302 convert->type == GL_UNSIGNED_SHORT_5_6_5 ) \
304 tab = name##_tab_rgb565_direct; \
306 else if ( convert->format == GL_RGB && \
307 convert->type == GL_UNSIGNED_BYTE ) \
309 tab = name##_tab_bgr888_to_rgb565; \
311 else if ( convert->format == GL_RGBA && \
312 convert->type == GL_UNSIGNED_BYTE ) \
314 tab = name##_tab_abgr8888_to_rgb565; \
318 /* Can't handle this source format/type combination */ \
322 return tab[index]( convert ); \
325 CONVERT_RGB565( texsubimage2d
)
326 CONVERT_RGB565( texsubimage3d
)
330 /* ================================================================
334 #define DST_TYPE GLushort
335 #define DST_TEXELS_PER_DWORD 2
337 #define CONVERT_TEXEL( src ) \
338 PACK_COLOR_4444( src[3], src[0], src[1], src[2] )
340 #define CONVERT_DIRECT
342 #define SRC_TEXEL_BYTES 2
344 #define TAG(x) x##_argb4444_direct
345 #define PRESERVE_DST_TYPE
346 #include "texutil_tmp.h"
349 #define CONVERT_TEXEL( src ) \
350 PACK_COLOR_4444( src[3], src[0], src[1], src[2] )
352 #define CONVERT_TEXEL_DWORD( src ) \
353 ((PACK_COLOR_4444( src[3], src[0], src[1], src[2] )) | \
354 (PACK_COLOR_4444( src[7], src[4], src[5], src[6] ) << 16))
356 #define SRC_TEXEL_BYTES 4
358 #define TAG(x) x##_rgba8888_to_argb4444
359 #include "texutil_tmp.h"
362 #define CONVERT_ARGB4444( name ) \
364 convert_##name##_argb4444( struct gl_texture_convert *convert ) \
367 GLint index = convert->index; \
369 if ( convert->format == GL_BGRA && \
370 convert->type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) \
372 tab = name##_tab_argb4444_direct; \
374 else if ( convert->format == GL_RGBA && \
375 convert->type == GL_UNSIGNED_BYTE ) \
377 tab = name##_tab_rgba8888_to_argb4444; \
381 /* Can't handle this source format/type combination */ \
385 return tab[index]( convert ); \
388 CONVERT_ARGB4444( texsubimage2d
)
389 CONVERT_ARGB4444( texsubimage3d
)
393 /* ================================================================
397 #define DST_TYPE GLushort
398 #define DST_TEXELS_PER_DWORD 2
400 #define CONVERT_TEXEL( src ) \
401 PACK_COLOR_1555( src[3], src[0], src[1], src[2] )
403 #define CONVERT_DIRECT
405 #define SRC_TEXEL_BYTES 2
407 #define TAG(x) x##_argb1555_direct
408 #define PRESERVE_DST_TYPE
409 #include "texutil_tmp.h"
412 #define CONVERT_TEXEL( src ) \
413 PACK_COLOR_1555( src[3], src[0], src[1], src[2] )
415 #define CONVERT_TEXEL_DWORD( src ) \
416 ((PACK_COLOR_1555( src[3], src[0], src[1], src[2] )) | \
417 (PACK_COLOR_1555( src[7], src[4], src[5], src[6] ) << 16))
419 #define SRC_TEXEL_BYTES 4
421 #define TAG(x) x##_rgba8888_to_argb1555
422 #include "texutil_tmp.h"
425 #define CONVERT_ARGB1555( name ) \
427 convert_##name##_argb1555( struct gl_texture_convert *convert ) \
430 GLint index = convert->index; \
432 if ( convert->format == GL_BGRA && \
433 convert->type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) \
435 tab = name##_tab_argb1555_direct; \
437 else if ( convert->format == GL_RGBA && \
438 convert->type == GL_UNSIGNED_BYTE ) \
440 tab = name##_tab_rgba8888_to_argb1555; \
444 /* Can't handle this source format/type combination */ \
448 return tab[index]( convert ); \
451 CONVERT_ARGB1555( texsubimage2d
)
452 CONVERT_ARGB1555( texsubimage3d
)
456 /* ================================================================
460 #define DST_TYPE GLushort
461 #define DST_TEXELS_PER_DWORD 2
463 #define CONVERT_TEXEL( src ) \
464 PACK_COLOR_88( src[0], src[1] )
466 #define CONVERT_DIRECT
468 #define SRC_TEXEL_BYTES 2
470 #define TAG(x) x##_al88_direct
471 #define PRESERVE_DST_TYPE
472 #include "texutil_tmp.h"
475 #define CONVERT_TEXEL( src ) \
476 PACK_COLOR_88( src[0], 0x00 )
478 #define CONVERT_TEXEL_DWORD( src ) \
479 ((PACK_COLOR_88( src[0], 0x00 )) | \
480 (PACK_COLOR_88( src[1], 0x00 ) << 16))
482 #define SRC_TEXEL_BYTES 1
484 #define TAG(x) x##_a8_to_al88
485 #define PRESERVE_DST_TYPE
486 #include "texutil_tmp.h"
489 #define CONVERT_TEXEL( src ) \
490 PACK_COLOR_88( 0xff, src[0] )
492 #define CONVERT_TEXEL_DWORD( src ) \
493 ((PACK_COLOR_88( 0xff, src[0] )) | \
494 (PACK_COLOR_88( 0xff, src[1] ) << 16))
496 #define SRC_TEXEL_BYTES 1
498 #define TAG(x) x##_l8_to_al88
499 #include "texutil_tmp.h"
502 #define CONVERT_AL88( name ) \
504 convert_##name##_al88( struct gl_texture_convert *convert ) \
507 GLint index = convert->index; \
509 if ( convert->format == GL_LUMINANCE_ALPHA && \
510 convert->type == GL_UNSIGNED_BYTE ) \
512 tab = name##_tab_al88_direct; \
514 else if ( convert->format == GL_ALPHA && \
515 convert->type == GL_UNSIGNED_BYTE ) \
517 tab = name##_tab_a8_to_al88; \
519 else if ( convert->format == GL_LUMINANCE && \
520 convert->type == GL_UNSIGNED_BYTE ) \
522 tab = name##_tab_l8_to_al88; \
526 /* Can't handle this source format/type combination */ \
530 return tab[index]( convert ); \
533 CONVERT_AL88( texsubimage2d
)
534 CONVERT_AL88( texsubimage3d
)
538 /* ================================================================
543 convert_texsubimage2d_rgb332( struct gl_texture_convert
*convert
)
545 /* This is a placeholder for now...
551 convert_texsubimage3d_rgb332( struct gl_texture_convert
*convert
)
553 /* This is a placeholder for now...
560 /* ================================================================
561 * CI8 (and all other single-byte texel) textures:
564 #define DST_TYPE GLubyte
565 #define DST_TEXELS_PER_DWORD 4
567 #define CONVERT_TEXEL( src ) src[0]
569 #define CONVERT_DIRECT
571 #define SRC_TEXEL_BYTES 1
573 #define TAG(x) x##_ci8_direct
574 #include "texutil_tmp.h"
577 #define CONVERT_CI8( name ) \
579 convert_##name##_ci8( struct gl_texture_convert *convert ) \
582 GLint index = convert->index; \
584 if ( ( convert->format == GL_ALPHA || \
585 convert->format == GL_LUMINANCE || \
586 convert->format == GL_INTENSITY || \
587 convert->format == GL_COLOR_INDEX ) && \
588 convert->type == GL_UNSIGNED_BYTE ) \
590 tab = name##_tab_ci8_direct; \
594 /* Can't handle this source format/type combination */ \
598 return tab[index]( convert ); \
601 CONVERT_CI8( texsubimage2d
)
602 CONVERT_CI8( texsubimage3d
)
606 /* ================================================================
607 * Global entry points
610 static convert_func gl_convert_texsubimage2d_tab
[] = {
611 convert_texsubimage2d_rgba8888
,
612 convert_texsubimage2d_argb8888
,
613 convert_texsubimage2d_rgb888
,
614 convert_texsubimage2d_rgb565
,
615 convert_texsubimage2d_argb4444
,
616 convert_texsubimage2d_argb1555
,
617 convert_texsubimage2d_al88
,
618 convert_texsubimage2d_rgb332
,
619 convert_texsubimage2d_ci8
, /* These are all the same... */
620 convert_texsubimage2d_ci8
,
621 convert_texsubimage2d_ci8
,
622 convert_texsubimage2d_ci8
,
625 static convert_func gl_convert_texsubimage3d_tab
[] = {
626 convert_texsubimage3d_rgba8888
,
627 convert_texsubimage3d_argb8888
,
628 convert_texsubimage3d_rgb888
,
629 convert_texsubimage3d_rgb565
,
630 convert_texsubimage3d_argb4444
,
631 convert_texsubimage3d_argb1555
,
632 convert_texsubimage3d_al88
,
633 convert_texsubimage3d_rgb332
,
634 convert_texsubimage3d_ci8
, /* These are all the same... */
635 convert_texsubimage3d_ci8
,
636 convert_texsubimage3d_ci8
,
637 convert_texsubimage3d_ci8
,
641 /* See if we need to care about the pixel store attributes when we're
642 * converting the texture image. This should be stored as
643 * packing->_SomeBoolean and updated when the values change, to avoid
644 * testing every time...
646 static INLINE GLboolean
647 convert_needs_packing( const struct gl_pixelstore_attrib
*packing
,
648 GLenum format
, GLenum type
)
650 if ( ( packing
->Alignment
== 1 ||
651 ( packing
->Alignment
== 4 && /* Pick up the common Q3A case... */
652 format
== GL_RGBA
&& type
== GL_UNSIGNED_BYTE
) ) &&
653 packing
->RowLength
== 0 &&
654 packing
->SkipPixels
== 0 &&
655 packing
->SkipRows
== 0 &&
656 packing
->ImageHeight
== 0 &&
657 packing
->SkipImages
== 0 &&
658 packing
->SwapBytes
== GL_FALSE
&&
659 packing
->LsbFirst
== GL_FALSE
) {
668 _mesa_convert_texsubimage1d( GLint mesaFormat
,
671 GLenum format
, GLenum type
,
672 const struct gl_pixelstore_attrib
*packing
,
673 const GLvoid
*srcImage
, GLvoid
*dstImage
)
675 struct gl_texture_convert convert
;
681 ASSERT( mesaFormat
>= MESA_FORMAT_RGBA
);
682 ASSERT( mesaFormat
<= MESA_FORMAT_CI8
);
684 /* Make it easier to pass all the parameters around.
686 convert
.xoffset
= xoffset
;
688 convert
.width
= width
;
690 convert
.format
= format
;
692 convert
.packing
= packing
;
693 convert
.srcImage
= srcImage
;
694 convert
.dstImage
= dstImage
;
698 if ( convert_needs_packing( packing
, format
, type
) )
699 convert
.index
|= CONVERT_PACKING_BIT
;
701 return gl_convert_texsubimage2d_tab
[mesaFormat
]( &convert
);
705 _mesa_convert_texsubimage2d( GLint mesaFormat
,
706 GLint xoffset
, GLint yoffset
,
707 GLint width
, GLint height
,
709 GLenum format
, GLenum type
,
710 const struct gl_pixelstore_attrib
*packing
,
711 const GLvoid
*srcImage
, GLvoid
*dstImage
)
713 struct gl_texture_convert convert
;
719 ASSERT( mesaFormat
>= MESA_FORMAT_RGBA
);
720 ASSERT( mesaFormat
<= MESA_FORMAT_CI8
);
722 /* Make it easier to pass all the parameters around.
724 convert
.xoffset
= xoffset
;
725 convert
.yoffset
= yoffset
;
726 convert
.width
= width
;
727 convert
.height
= height
;
728 convert
.imageWidth
= imageWidth
;
729 convert
.format
= format
;
731 convert
.packing
= packing
;
732 convert
.srcImage
= srcImage
;
733 convert
.dstImage
= dstImage
;
737 if ( convert_needs_packing( packing
, format
, type
) )
738 convert
.index
|= CONVERT_PACKING_BIT
;
740 if ( width
!= imageWidth
)
741 convert
.index
|= CONVERT_STRIDE_BIT
;
743 return gl_convert_texsubimage2d_tab
[mesaFormat
]( &convert
);
747 _mesa_convert_texsubimage3d( GLint mesaFormat
,
748 GLint xoffset
, GLint yoffset
, GLint zoffset
,
749 GLint width
, GLint height
, GLint depth
,
750 GLint imageWidth
, GLint imageHeight
,
751 GLenum format
, GLenum type
,
752 const struct gl_pixelstore_attrib
*packing
,
753 const GLvoid
*srcImage
, GLvoid
*dstImage
)
755 struct gl_texture_convert convert
;
761 ASSERT( mesaFormat
>= MESA_FORMAT_RGBA
);
762 ASSERT( mesaFormat
<= MESA_FORMAT_CI8
);
764 /* Make it easier to pass all the parameters around.
766 convert
.xoffset
= xoffset
;
767 convert
.yoffset
= yoffset
;
768 convert
.zoffset
= zoffset
;
769 convert
.width
= width
;
770 convert
.height
= height
;
771 convert
.depth
= depth
;
772 convert
.imageWidth
= imageWidth
;
773 convert
.imageHeight
= imageHeight
;
774 convert
.format
= format
;
776 convert
.packing
= packing
;
777 convert
.srcImage
= srcImage
;
778 convert
.dstImage
= dstImage
;
782 if ( convert_needs_packing( packing
, format
, type
) )
783 convert
.index
|= CONVERT_PACKING_BIT
;
785 if ( width
!= imageWidth
|| height
!= imageHeight
)
786 convert
.index
|= CONVERT_STRIDE_BIT
;
788 return gl_convert_texsubimage3d_tab
[mesaFormat
]( &convert
);
793 /* Nearest filtering only (for broken hardware that can't support
794 * all aspect ratios). This can be made a lot faster, but I don't
795 * really care enough...
797 void _mesa_rescale_teximage2d( const struct gl_texture_format
*texFormat
,
798 GLint srcWidth
, GLint srcHeight
,
799 GLint dstWidth
, GLint dstHeight
,
800 const GLvoid
*srcImage
, GLvoid
*dstImage
)
804 #define INNER_LOOP( HOP, WOP ) \
805 for ( row = 0 ; row < dstHeight ; row++ ) { \
806 GLint srcRow = row HOP hScale; \
807 for ( col = 0 ; col < dstWidth ; col++ ) { \
808 GLint srcCol = col WOP wScale; \
809 *dst++ = src[srcRow * srcWidth + srcCol]; \
813 #define RESCALE_IMAGE( TYPE ) \
815 const TYPE *src = (const TYPE *)srcImage; \
816 TYPE *dst = (TYPE *)dstImage; \
818 if ( srcHeight <= dstHeight ) { \
819 const GLint hScale = dstHeight / srcHeight; \
820 if ( srcWidth <= dstWidth ) { \
821 const GLint wScale = dstWidth / srcWidth; \
822 INNER_LOOP( /, / ); \
825 const GLint wScale = srcWidth / dstWidth; \
826 INNER_LOOP( /, * ); \
830 const GLint hScale = srcHeight / dstHeight; \
831 if ( srcWidth <= dstWidth ) { \
832 const GLint wScale = dstWidth / srcWidth; \
833 INNER_LOOP( *, / ); \
836 const GLint wScale = srcWidth / dstWidth; \
837 INNER_LOOP( *, * ); \
842 switch ( texFormat
->TexelBytes
) {
844 RESCALE_IMAGE( GLuint
);
848 RESCALE_IMAGE( GLushort
);
852 RESCALE_IMAGE( GLubyte
);