1 /* $Id: texutil.c,v 1.31 2002/09/21 16:51:25 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 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>
32 * Functions for texture image conversion. This takes care of converting
33 * typical GL_RGBA/GLubyte textures into hardware-specific formats.
34 * We can handle non-standard row strides and pixel unpacking parameters.
48 #include "texformat.h"
52 #define DEBUG_TEXUTIL 0
55 #ifdef MESA_BIG_ENDIAN
56 #define APPEND16( a, b ) ( (a) << 16 | (b) )
58 #define APPEND16( a, b ) ( (a) | (b) << 16 )
63 GLint xoffset
, yoffset
, zoffset
; /* Subimage offset */
64 GLint width
, height
, depth
; /* Subimage region */
66 GLint dstImageWidth
, dstImageHeight
; /* Dest image size */
67 /* Needed for subimage replacement */
68 GLenum format
, type
; /* Source (user) format and type */
70 const struct gl_pixelstore_attrib
*unpacking
;
72 const GLvoid
*srcImage
;
78 typedef GLboolean (*convert_func
)( const struct convert_info
*convert
);
80 /* bitvalues for convert->index */
81 #define CONVERT_STRIDE_BIT 0x1
82 #define CONVERT_UNPACKING_BIT 0x2
86 /* =============================================================
87 * Convert to RGBA8888 textures:
90 #define DST_TYPE GLuint
91 #define DST_TEXELS_PER_DWORD 1
93 #define CONVERT_TEXEL( dst, src ) \
94 dst = PACK_COLOR_8888_LE( src[3], src[2], src[1], src[0] )
96 #define CONVERT_DIRECT
98 #define SRC_TEXEL_BYTES 4
100 #define TAG(x) x##_rgba8888_direct
101 #define PRESERVE_DST_TYPE
102 #include "texutil_tmp.h"
105 #define CONVERT_TEXEL( dst, src ) \
106 dst = PACK_COLOR_8888_LE( src[0], src[1], src[2], src[3] )
108 #define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
110 #define SRC_TEXEL_BYTES 4
112 #define TAG(x) x##_abgr8888_to_rgba8888
113 #define PRESERVE_DST_TYPE
114 #include "texutil_tmp.h"
117 #define CONVERT_TEXEL( dst, src ) \
118 dst = PACK_COLOR_8888_LE( src[0], src[1], src[2], 0xff )
120 #define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
122 #define SRC_TEXEL_BYTES 3
124 #define TAG(x) x##_bgr888_to_rgba8888
125 #include "texutil_tmp.h"
128 #define CONVERT_RGBA8888( name ) \
130 convert_##name##_rgba8888( const struct convert_info *convert ) \
133 GLint index = convert->index; \
135 if ( convert->format == GL_ABGR_EXT && \
136 convert->type == GL_UNSIGNED_INT_8_8_8_8_REV ) \
138 tab = name##_tab_rgba8888_direct; \
140 else if ( convert->format == GL_RGBA && \
141 ( convert->type == GL_UNSIGNED_BYTE || \
142 convert->type == GL_UNSIGNED_INT_8_8_8_8 ) ) \
144 tab = name##_tab_abgr8888_to_rgba8888; \
146 else if ( convert->format == GL_RGB && \
147 convert->type == GL_UNSIGNED_BYTE ) \
149 tab = name##_tab_bgr888_to_rgba8888; \
153 /* Can't handle this source format/type combination */ \
157 return tab[index]( convert ); \
160 CONVERT_RGBA8888( texsubimage2d
)
161 CONVERT_RGBA8888( texsubimage3d
)
165 /* =============================================================
166 * Convert to ARGB8888 textures:
169 #define DST_TYPE GLuint
170 #define DST_TEXELS_PER_DWORD 1
172 #define CONVERT_TEXEL( dst, src ) \
173 dst = PACK_COLOR_8888_LE( src[3], src[2], src[1], src[0] )
175 #define CONVERT_DIRECT
177 #define SRC_TEXEL_BYTES 4
179 #define TAG(x) x##_argb8888_direct
180 #define PRESERVE_DST_TYPE
181 #include "texutil_tmp.h"
184 #define CONVERT_TEXEL( dst, src ) \
185 dst = PACK_COLOR_8888_LE( src[3], src[0], src[1], src[2] )
187 #define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
189 #define SRC_TEXEL_BYTES 4
191 #define TAG(x) x##_abgr8888_to_argb8888
192 #define PRESERVE_DST_TYPE
193 #include "texutil_tmp.h"
196 #define CONVERT_TEXEL( dst, src ) \
197 dst = PACK_COLOR_8888_LE( 0xff, src[0], src[1], src[2] )
199 #define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
201 #define SRC_TEXEL_BYTES 3
203 #define TAG(x) x##_bgr888_to_argb8888
204 #include "texutil_tmp.h"
207 #define CONVERT_ARGB8888( name ) \
209 convert_##name##_argb8888( const struct convert_info *convert ) \
212 GLint index = convert->index; \
214 if ( convert->format == GL_BGRA && \
215 convert->type == GL_UNSIGNED_INT_8_8_8_8_REV ) \
217 tab = name##_tab_argb8888_direct; \
219 else if ( convert->format == GL_RGBA && \
220 convert->type == GL_UNSIGNED_BYTE ) \
222 tab = name##_tab_abgr8888_to_argb8888; \
224 else if ( convert->format == GL_RGB && \
225 convert->type == GL_UNSIGNED_BYTE ) \
227 tab = name##_tab_bgr888_to_argb8888; \
231 /* Can't handle this source format/type combination */ \
235 return tab[index]( convert ); \
238 CONVERT_ARGB8888( texsubimage2d
)
239 CONVERT_ARGB8888( texsubimage3d
)
243 /* =============================================================
244 * Convert to RGB888 textures:
248 convert_texsubimage2d_rgb888( const struct convert_info
*convert
)
250 /* This is a placeholder for now...
256 convert_texsubimage3d_rgb888( const struct convert_info
*convert
)
258 /* This is a placeholder for now...
265 /* =============================================================
266 * Convert to RGB565 textures:
269 #define DST_TYPE GLushort
270 #define DST_TEXELS_PER_DWORD 2
272 #define CONVERT_TEXEL( dst, src ) \
273 dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
275 #define CONVERT_DIRECT
277 #define SRC_TEXEL_BYTES 2
279 #define TAG(x) x##_rgb565_direct
280 #define PRESERVE_DST_TYPE
281 #include "texutil_tmp.h"
284 #define CONVERT_TEXEL( dst, src ) \
285 dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
287 #define CONVERT_TEXEL_DWORD( dst, src ) \
288 dst = APPEND16( PACK_COLOR_565_LE( src[0], src[1], src[2] ), \
289 PACK_COLOR_565_LE( src[3], src[4], src[5] ) )
291 #define SRC_TEXEL_BYTES 3
293 #define TAG(x) x##_bgr888_to_rgb565
294 #define PRESERVE_DST_TYPE
295 #include "texutil_tmp.h"
298 #define CONVERT_TEXEL( dst, src ) \
299 dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
301 #define CONVERT_TEXEL_DWORD( dst, src ) \
302 dst = APPEND16( PACK_COLOR_565_LE( src[0], src[1], src[2] ), \
303 PACK_COLOR_565_LE( src[4], src[5], src[6] ) )
305 #define SRC_TEXEL_BYTES 4
307 #define TAG(x) x##_abgr8888_to_rgb565
308 #include "texutil_tmp.h"
311 #define CONVERT_RGB565( name ) \
313 convert_##name##_rgb565( const struct convert_info *convert ) \
316 GLint index = convert->index; \
318 if ( convert->format == GL_RGB && \
319 convert->type == GL_UNSIGNED_SHORT_5_6_5 ) \
321 tab = name##_tab_rgb565_direct; \
323 else if ( convert->format == GL_RGB && \
324 convert->type == GL_UNSIGNED_BYTE ) \
326 tab = name##_tab_bgr888_to_rgb565; \
328 else if ( convert->format == GL_RGBA && \
329 convert->type == GL_UNSIGNED_BYTE ) \
331 tab = name##_tab_abgr8888_to_rgb565; \
335 /* Can't handle this source format/type combination */ \
339 return tab[index]( convert ); \
342 CONVERT_RGB565( texsubimage2d
)
343 CONVERT_RGB565( texsubimage3d
)
347 /* =============================================================
348 * Convert to ARGB4444 textures:
351 #define DST_TYPE GLushort
352 #define DST_TEXELS_PER_DWORD 2
354 #define CONVERT_TEXEL( dst, src ) \
355 dst = PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] )
357 #define CONVERT_DIRECT
359 #define SRC_TEXEL_BYTES 2
361 #define TAG(x) x##_argb4444_direct
362 #define PRESERVE_DST_TYPE
363 #include "texutil_tmp.h"
366 #define CONVERT_TEXEL( dst, src ) \
367 dst = PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] )
369 #define CONVERT_TEXEL_DWORD( dst, src ) \
370 dst = APPEND16( PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] ), \
371 PACK_COLOR_4444_LE( src[7], src[4], src[5], src[6] ) )
373 #define SRC_TEXEL_BYTES 4
375 #define TAG(x) x##_abgr8888_to_argb4444
376 #include "texutil_tmp.h"
379 #define CONVERT_ARGB4444( name ) \
381 convert_##name##_argb4444( const struct convert_info *convert ) \
384 GLint index = convert->index; \
386 if ( convert->format == GL_BGRA && \
387 convert->type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) \
389 tab = name##_tab_argb4444_direct; \
391 else if ( convert->format == GL_RGBA && \
392 convert->type == GL_UNSIGNED_BYTE ) \
394 tab = name##_tab_abgr8888_to_argb4444; \
398 /* Can't handle this source format/type combination */ \
402 return tab[index]( convert ); \
405 CONVERT_ARGB4444( texsubimage2d
)
406 CONVERT_ARGB4444( texsubimage3d
)
410 /* =============================================================
411 * Convert to ARGB1555 textures:
414 #define DST_TYPE GLushort
415 #define DST_TEXELS_PER_DWORD 2
417 #define CONVERT_TEXEL( dst, src ) \
418 dst = PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] )
420 #define CONVERT_DIRECT
422 #define SRC_TEXEL_BYTES 2
424 #define TAG(x) x##_argb1555_direct
425 #define PRESERVE_DST_TYPE
426 #include "texutil_tmp.h"
429 #ifdef MESA_BIG_ENDIAN
431 #define CONVERT_TEXEL( dst, src ) \
432 { const GLushort s = *(GLushort *)src; \
433 dst = (s >> 9) | ((s & 0x1ff) << 7); }
435 #define CONVERT_TEXEL_DWORD( dst, src ) \
436 { const GLuint s = ((fi_type *)src)->i; \
437 dst = (((s & 0xfe00fe00) >> 9) | \
438 ((s & 0x01ff01ff) << 7)); }
442 #define CONVERT_TEXEL( dst, src ) \
443 { const GLushort s = *(GLushort *)src; \
444 dst = (s >> 1) | ((s & 1) << 15); }
446 #define CONVERT_TEXEL_DWORD( dst, src ) \
447 { const GLuint s = ((fi_type *)src)->i; \
448 dst = (((s & 0xfffefffe) >> 1) | \
449 ((s & 0x00010001) << 15)); }
453 #define SRC_TEXEL_BYTES 2
455 #define TAG(x) x##_rgba5551_to_argb1555
456 #define PRESERVE_DST_TYPE
457 #include "texutil_tmp.h"
460 #define CONVERT_TEXEL( dst, src ) \
461 dst = PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] )
463 #define CONVERT_TEXEL_DWORD( dst, src ) \
464 dst = APPEND16( PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] ), \
465 PACK_COLOR_1555_LE( src[7], src[4], src[5], src[6] ) )
467 #define SRC_TEXEL_BYTES 4
469 #define TAG(x) x##_abgr8888_to_argb1555
470 #include "texutil_tmp.h"
473 #define CONVERT_ARGB1555( name ) \
475 convert_##name##_argb1555( const struct convert_info *convert ) \
478 GLint index = convert->index; \
480 if ( convert->format == GL_BGRA && \
481 convert->type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) \
483 tab = name##_tab_argb1555_direct; \
485 else if ( convert->format == GL_RGBA && \
486 convert->type == GL_UNSIGNED_SHORT_5_5_5_1 ) \
488 tab = name##_tab_rgba5551_to_argb1555; \
490 else if ( convert->format == GL_RGBA && \
491 convert->type == GL_UNSIGNED_BYTE ) \
493 tab = name##_tab_abgr8888_to_argb1555; \
497 /* Can't handle this source format/type combination */ \
501 return tab[index]( convert ); \
504 CONVERT_ARGB1555( texsubimage2d
)
505 CONVERT_ARGB1555( texsubimage3d
)
509 /* =============================================================
513 #define DST_TYPE GLushort
514 #define DST_TEXELS_PER_DWORD 2
516 #define CONVERT_TEXEL( dst, src ) \
517 dst = PACK_COLOR_88_LE( src[0], src[1] )
519 #define CONVERT_DIRECT
521 #define SRC_TEXEL_BYTES 2
523 #define TAG(x) x##_al88_direct
524 #define PRESERVE_DST_TYPE
525 #include "texutil_tmp.h"
528 #define CONVERT_TEXEL( dst, src ) \
529 dst = PACK_COLOR_88_LE( src[0], 0x00 )
531 #define CONVERT_TEXEL_DWORD( dst, src ) \
532 dst = APPEND16( PACK_COLOR_88_LE( src[0], 0x00 ), \
533 PACK_COLOR_88_LE( src[1], 0x00 ) )
535 #define SRC_TEXEL_BYTES 1
537 #define TAG(x) x##_a8_to_al88
538 #define PRESERVE_DST_TYPE
539 #include "texutil_tmp.h"
542 #define CONVERT_TEXEL( dst, src ) \
543 dst = PACK_COLOR_88_LE( 0xff, src[0] )
545 #define CONVERT_TEXEL_DWORD( dst, src ) \
546 dst = APPEND16( PACK_COLOR_88_LE( 0xff, src[0] ), \
547 PACK_COLOR_88_LE( 0xff, src[1] ) )
549 #define SRC_TEXEL_BYTES 1
551 #define TAG(x) x##_l8_to_al88
552 #define PRESERVE_DST_TYPE
553 #include "texutil_tmp.h"
556 #define CONVERT_TEXEL( dst, src ) \
557 dst = PACK_COLOR_88_LE( src[3], src[0] )
559 #define CONVERT_TEXEL_DWORD( dst, src ) \
560 dst = APPEND16( PACK_COLOR_88_LE( src[3], src[0] ), \
561 PACK_COLOR_88_LE( src[7], src[4] ) )
563 #define SRC_TEXEL_BYTES 4
565 #define TAG(x) x##_abgr8888_to_al88
566 #include "texutil_tmp.h"
569 #define CONVERT_AL88( name ) \
571 convert_##name##_al88( const struct convert_info *convert ) \
574 GLint index = convert->index; \
576 if ( convert->format == GL_LUMINANCE_ALPHA && \
577 convert->type == GL_UNSIGNED_BYTE ) \
579 tab = name##_tab_al88_direct; \
581 else if ( convert->format == GL_ALPHA && \
582 convert->type == GL_UNSIGNED_BYTE ) \
584 tab = name##_tab_a8_to_al88; \
586 else if ( convert->format == GL_LUMINANCE && \
587 convert->type == GL_UNSIGNED_BYTE ) \
589 tab = name##_tab_l8_to_al88; \
591 else if ( convert->format == GL_RGBA && \
592 convert->type == GL_UNSIGNED_BYTE ) \
594 tab = name##_tab_abgr8888_to_al88; \
598 /* Can't handle this source format/type combination */ \
602 return tab[index]( convert ); \
605 CONVERT_AL88( texsubimage2d
)
606 CONVERT_AL88( texsubimage3d
)
610 /* =============================================================
611 * Convert to RGB332 textures:
615 convert_texsubimage2d_rgb332( const struct convert_info
*convert
)
617 /* This is a placeholder for now...
623 convert_texsubimage3d_rgb332( const struct convert_info
*convert
)
625 /* This is a placeholder for now...
632 /* =============================================================
633 * CI8 (and all other single-byte texel) textures:
636 #define DST_TYPE GLubyte
637 #define DST_TEXELS_PER_DWORD 4
639 #define CONVERT_TEXEL( dst, src ) dst = src[0]
641 #define CONVERT_DIRECT
643 #define SRC_TEXEL_BYTES 1
645 #define TAG(x) x##_ci8_direct
646 #include "texutil_tmp.h"
649 #define CONVERT_CI8( name ) \
651 convert_##name##_ci8( const struct convert_info *convert ) \
654 GLint index = convert->index; \
656 if ( ( convert->format == GL_ALPHA || \
657 convert->format == GL_LUMINANCE || \
658 convert->format == GL_INTENSITY || \
659 convert->format == GL_COLOR_INDEX ) && \
660 convert->type == GL_UNSIGNED_BYTE ) \
662 tab = name##_tab_ci8_direct; \
666 /* Can't handle this source format/type combination */ \
670 return tab[index]( convert ); \
673 CONVERT_CI8( texsubimage2d
)
674 CONVERT_CI8( texsubimage3d
)
677 /* =============================================================
678 * convert to YCBCR textures:
681 #define DST_TYPE GLushort
682 #define DST_TEXELS_PER_DWORD 2
684 #define CONVERT_TEXEL( dst, src ) \
685 dst = (src[0] << 8) | src[1];
687 #define CONVERT_DIRECT
689 #define SRC_TEXEL_BYTES 2
691 #define TAG(x) x##_ycbcr_direct
692 #include "texutil_tmp.h"
695 #define CONVERT_YCBCR( name ) \
697 convert_##name##_ycbcr( const struct convert_info *convert ) \
700 GLint index = convert->index; \
702 if (convert->format != GL_YCBCR_MESA) { \
703 /* Can't handle this source format/type combination */ \
706 tab = name##_tab_ycbcr_direct; \
708 return tab[index]( convert ); \
711 CONVERT_YCBCR( texsubimage2d
)
712 CONVERT_YCBCR( texsubimage3d
)
715 /* =============================================================
716 * convert to YCBCR_REV textures:
719 #define DST_TYPE GLushort
720 #define DST_TEXELS_PER_DWORD 2
722 #define CONVERT_TEXEL( dst, src ) \
723 dst = (src[1] << 8) | src[0];
725 #define CONVERT_DIRECT
727 #define SRC_TEXEL_BYTES 2
729 #define TAG(x) x##_ycbcr_rev_direct
730 #include "texutil_tmp.h"
733 #define CONVERT_YCBCR_REV( name ) \
735 convert_##name##_ycbcr_rev( const struct convert_info *convert ) \
738 GLint index = convert->index; \
740 if (convert->format != GL_YCBCR_MESA) { \
741 /* Can't handle this source format/type combination */ \
744 tab = name##_tab_ycbcr_rev_direct; \
746 return tab[index]( convert ); \
749 CONVERT_YCBCR_REV( texsubimage2d
)
750 CONVERT_YCBCR_REV( texsubimage3d
)
754 /* =============================================================
755 * Global entry points
758 static convert_func convert_texsubimage2d_tab
[] = {
759 convert_texsubimage2d_rgba8888
,
760 convert_texsubimage2d_argb8888
,
761 convert_texsubimage2d_rgb888
,
762 convert_texsubimage2d_rgb565
,
763 convert_texsubimage2d_argb4444
,
764 convert_texsubimage2d_argb1555
,
765 convert_texsubimage2d_al88
,
766 convert_texsubimage2d_rgb332
,
767 convert_texsubimage2d_ci8
, /* These are all the same... */
768 convert_texsubimage2d_ci8
,
769 convert_texsubimage2d_ci8
,
770 convert_texsubimage2d_ci8
,
771 convert_texsubimage2d_ycbcr
,
772 convert_texsubimage2d_ycbcr_rev
,
775 static convert_func convert_texsubimage3d_tab
[] = {
776 convert_texsubimage3d_rgba8888
,
777 convert_texsubimage3d_argb8888
,
778 convert_texsubimage3d_rgb888
,
779 convert_texsubimage3d_rgb565
,
780 convert_texsubimage3d_argb4444
,
781 convert_texsubimage3d_argb1555
,
782 convert_texsubimage3d_al88
,
783 convert_texsubimage3d_rgb332
,
784 convert_texsubimage3d_ci8
, /* These are all the same... */
785 convert_texsubimage3d_ci8
,
786 convert_texsubimage3d_ci8
,
787 convert_texsubimage3d_ci8
,
788 convert_texsubimage3d_ycbcr
,
789 convert_texsubimage3d_ycbcr_rev
,
793 /* See if we need to care about the pixel store attributes when we're
794 * converting the texture image. This should be stored as
795 * unpacking->_SomeBoolean and updated when the values change, to avoid
796 * testing every time...
798 static INLINE GLboolean
799 convert_needs_unpacking( const struct gl_pixelstore_attrib
*unpacking
,
800 GLenum format
, GLenum type
)
802 if ( ( unpacking
->Alignment
== 1 ||
803 ( unpacking
->Alignment
== 4 && /* Pick up the common Q3A case... */
804 format
== GL_RGBA
&& type
== GL_UNSIGNED_BYTE
) ) &&
805 unpacking
->RowLength
== 0 &&
806 unpacking
->SkipPixels
== 0 &&
807 unpacking
->SkipRows
== 0 &&
808 unpacking
->ImageHeight
== 0 &&
809 unpacking
->SkipImages
== 0 &&
810 unpacking
->SwapBytes
== GL_FALSE
&&
811 unpacking
->LsbFirst
== GL_FALSE
) {
820 _mesa_convert_texsubimage1d( GLint mesaFormat
,
823 GLenum format
, GLenum type
,
824 const struct gl_pixelstore_attrib
*unpacking
,
825 const GLvoid
*srcImage
, GLvoid
*dstImage
)
827 struct convert_info convert
;
833 ASSERT( mesaFormat
>= MESA_FORMAT_RGBA8888
);
834 ASSERT( mesaFormat
<= MESA_FORMAT_YCBCR_REV
);
836 /* Make it easier to pass all the parameters around.
838 convert
.xoffset
= xoffset
;
840 convert
.width
= width
;
842 convert
.format
= format
;
844 convert
.unpacking
= unpacking
;
845 convert
.srcImage
= srcImage
;
846 convert
.dstImage
= dstImage
;
850 if ( convert_needs_unpacking( unpacking
, format
, type
) )
851 convert
.index
|= CONVERT_UNPACKING_BIT
;
853 ASSERT(convert
.index
< 4);
855 return convert_texsubimage2d_tab
[mesaFormat
]( &convert
);
859 /* Convert a user's 2D image into a texture image. This basically
860 * repacks pixel data into the special texture formats used by core Mesa
861 * and the DRI drivers. This function can do full images or subimages.
863 * We return a boolean because this function may not accept some kinds
864 * of source image formats and/or types. For example, if the incoming
865 * format/type = GL_BGR, GL_UNSIGNED_INT this function probably won't
866 * be able to do the conversion.
868 * In that case, the incoming image should first be simplified to one of
869 * the "canonical" formats (GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA,
870 * GL_INTENSITY, GL_RGB, GL_RGBA) and types (GL_CHAN). We can do that
871 * with the _mesa_transfer_teximage() function. That function will also
872 * do image transfer operations such as scale/bias and convolution.
875 * mesaFormat - one of the MESA_FORMAT_* values from texformat.h
876 * xoffset, yoffset - position in dest image to put data
877 * width, height - incoming image size, also size of dest region.
878 * dstImageWidth - width (row stride) of dest image in pixels
879 * format, type - incoming image format and type
880 * unpacking - describes incoming image unpacking
881 * srcImage - pointer to source image
882 * destImage - pointer to dest image
885 _mesa_convert_texsubimage2d( GLint mesaFormat
, /* dest */
886 GLint xoffset
, GLint yoffset
,
887 GLint width
, GLint height
,
888 GLint destImageWidth
,
889 GLenum format
, GLenum type
, /* source */
890 const struct gl_pixelstore_attrib
*unpacking
,
891 const GLvoid
*srcImage
, GLvoid
*dstImage
)
893 struct convert_info convert
;
899 ASSERT( mesaFormat
>= MESA_FORMAT_RGBA8888
);
900 ASSERT( mesaFormat
<= MESA_FORMAT_YCBCR_REV
);
902 /* Make it easier to pass all the parameters around.
904 convert
.xoffset
= xoffset
;
905 convert
.yoffset
= yoffset
;
906 convert
.width
= width
;
907 convert
.height
= height
;
908 convert
.dstImageWidth
= destImageWidth
;
909 convert
.format
= format
;
911 convert
.unpacking
= unpacking
;
912 convert
.srcImage
= srcImage
;
913 convert
.dstImage
= dstImage
;
917 if ( convert_needs_unpacking( unpacking
, format
, type
) )
918 convert
.index
|= CONVERT_UNPACKING_BIT
;
920 if ( width
!= destImageWidth
)
921 convert
.index
|= CONVERT_STRIDE_BIT
;
923 return convert_texsubimage2d_tab
[mesaFormat
]( &convert
);
927 _mesa_convert_texsubimage3d( GLint mesaFormat
, /* dest */
928 GLint xoffset
, GLint yoffset
, GLint zoffset
,
929 GLint width
, GLint height
, GLint depth
,
930 GLint dstImageWidth
, GLint dstImageHeight
,
931 GLenum format
, GLenum type
, /* source */
932 const struct gl_pixelstore_attrib
*unpacking
,
933 const GLvoid
*srcImage
, GLvoid
*dstImage
)
935 struct convert_info convert
;
941 ASSERT( mesaFormat
>= MESA_FORMAT_RGBA8888
);
942 ASSERT( mesaFormat
<= MESA_FORMAT_YCBCR_REV
);
944 /* Make it easier to pass all the parameters around.
946 convert
.xoffset
= xoffset
;
947 convert
.yoffset
= yoffset
;
948 convert
.zoffset
= zoffset
;
949 convert
.width
= width
;
950 convert
.height
= height
;
951 convert
.depth
= depth
;
952 convert
.dstImageWidth
= dstImageWidth
;
953 convert
.dstImageHeight
= dstImageHeight
;
954 convert
.format
= format
;
956 convert
.unpacking
= unpacking
;
957 convert
.srcImage
= srcImage
;
958 convert
.dstImage
= dstImage
;
962 if ( convert_needs_unpacking( unpacking
, format
, type
) )
963 convert
.index
|= CONVERT_UNPACKING_BIT
;
965 if ( width
!= dstImageWidth
|| height
!= dstImageHeight
)
966 convert
.index
|= CONVERT_STRIDE_BIT
;
968 return convert_texsubimage3d_tab
[mesaFormat
]( &convert
);
973 /* Nearest filtering only (for broken hardware that can't support
974 * all aspect ratios). This can be made a lot faster, but I don't
975 * really care enough...
977 void _mesa_rescale_teximage2d( GLuint bytesPerPixel
, GLuint dstRowStride
,
978 GLint srcWidth
, GLint srcHeight
,
979 GLint dstWidth
, GLint dstHeight
,
980 const GLvoid
*srcImage
, GLvoid
*dstImage
)
984 #define INNER_LOOP( TYPE, HOP, WOP ) \
985 for ( row = 0 ; row < dstHeight ; row++ ) { \
986 GLint srcRow = row HOP hScale; \
987 for ( col = 0 ; col < dstWidth ; col++ ) { \
988 GLint srcCol = col WOP wScale; \
989 dst[col] = src[srcRow * srcWidth + srcCol]; \
991 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
994 #define RESCALE_IMAGE( TYPE ) \
996 const TYPE *src = (const TYPE *)srcImage; \
997 TYPE *dst = (TYPE *)dstImage; \
999 if ( srcHeight <= dstHeight ) { \
1000 const GLint hScale = dstHeight / srcHeight; \
1001 if ( srcWidth <= dstWidth ) { \
1002 const GLint wScale = dstWidth / srcWidth; \
1003 INNER_LOOP( TYPE, /, / ); \
1006 const GLint wScale = srcWidth / dstWidth; \
1007 INNER_LOOP( TYPE, /, * ); \
1011 const GLint hScale = srcHeight / dstHeight; \
1012 if ( srcWidth <= dstWidth ) { \
1013 const GLint wScale = dstWidth / srcWidth; \
1014 INNER_LOOP( TYPE, *, / ); \
1017 const GLint wScale = srcWidth / dstWidth; \
1018 INNER_LOOP( TYPE, *, * ); \
1023 switch ( bytesPerPixel
) {
1025 RESCALE_IMAGE( GLuint
);
1029 RESCALE_IMAGE( GLushort
);
1033 RESCALE_IMAGE( GLubyte
);
1036 _mesa_problem(NULL
,"unexpected bytes/pixel in _mesa_rescale_teximage2d");