added pointer to Vincent (OpenGL ES implementation)
[mesa.git] / src / mesa / main / texutil.c
1
2 /*
3 * Mesa 3-D graphics library
4 * Version: 5.1
5 *
6 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 * Gareth Hughes
27 */
28
29 /*
30 * Description:
31 * Functions for texture image conversion. This takes care of converting
32 * typical GL_RGBA/GLubyte textures into hardware-specific formats.
33 * We can handle non-standard row strides and pixel unpacking parameters.
34 */
35
36
37 #include "glheader.h"
38 #include "colormac.h"
39 #include "context.h"
40 #include "enums.h"
41 #include "image.h"
42 #include "imports.h"
43 #include "macros.h"
44 #include "mtypes.h"
45 #include "texformat.h"
46 #include "texutil.h"
47
48
49 #if !NEWTEXSTORE
50
51
52 #define DEBUG_TEXUTIL 0
53
54
55 #ifdef MESA_BIG_ENDIAN
56 #define APPEND16( a, b ) ( (a) << 16 | (b) )
57 #else
58 #define APPEND16( a, b ) ( (a) | (b) << 16 )
59 #endif
60
61
62 struct convert_info {
63 GLint xoffset, yoffset, zoffset; /* Subimage offset */
64 GLint width, height, depth; /* Subimage region */
65
66 GLint dstImageWidth, dstImageHeight; /* Dest image size */
67 /* Needed for subimage replacement */
68 GLenum format, type; /* Source (user) format and type */
69
70 const struct gl_pixelstore_attrib *unpacking;
71
72 const GLvoid *srcImage;
73 GLvoid *dstImage;
74
75 GLint index;
76 };
77
78 typedef GLboolean (*convert_func)( const struct convert_info *convert );
79
80 /* bitvalues for convert->index */
81 #define CONVERT_STRIDE_BIT 0x1
82 #define CONVERT_UNPACKING_BIT 0x2
83
84
85
86 /* =============================================================
87 * Convert to RGBA8888 textures:
88 */
89
90 #define DST_TYPE GLuint
91 #define DST_TEXELS_PER_DWORD 1
92
93 #define CONVERT_TEXEL( dst, src ) \
94 dst = PACK_COLOR_8888_LE( src[3], src[2], src[1], src[0] )
95
96 #define CONVERT_DIRECT
97
98 #define SRC_TEXEL_BYTES 4
99
100 #define TAG(x) x##_rgba8888_direct
101 #define PRESERVE_DST_TYPE
102 #include "texutil_tmp.h"
103
104
105 #define CONVERT_TEXEL( dst, src ) \
106 dst = PACK_COLOR_8888_LE( src[0], src[1], src[2], src[3] )
107
108 #define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
109
110 #define SRC_TEXEL_BYTES 4
111
112 #define TAG(x) x##_abgr8888_to_rgba8888
113 #define PRESERVE_DST_TYPE
114 #include "texutil_tmp.h"
115
116
117 #define CONVERT_TEXEL( dst, src ) \
118 dst = PACK_COLOR_8888_LE( src[0], src[1], src[2], 0xff )
119
120 #define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
121
122 #define SRC_TEXEL_BYTES 3
123
124 #define TAG(x) x##_bgr888_to_rgba8888
125 #include "texutil_tmp.h"
126
127
128 #define CONVERT_RGBA8888( name ) \
129 static GLboolean \
130 convert_##name##_rgba8888( const struct convert_info *convert ) \
131 { \
132 convert_func *tab; \
133 GLint index = convert->index; \
134 \
135 if ( convert->format == GL_ABGR_EXT && \
136 convert->type == GL_UNSIGNED_INT_8_8_8_8_REV ) \
137 { \
138 tab = name##_tab_rgba8888_direct; \
139 } \
140 else if ( convert->format == GL_RGBA && \
141 ( convert->type == GL_UNSIGNED_BYTE || \
142 convert->type == GL_UNSIGNED_INT_8_8_8_8 ) ) \
143 { \
144 tab = name##_tab_abgr8888_to_rgba8888; \
145 } \
146 else if ( convert->format == GL_RGB && \
147 convert->type == GL_UNSIGNED_BYTE ) \
148 { \
149 tab = name##_tab_bgr888_to_rgba8888; \
150 } \
151 else \
152 { \
153 /* Can't handle this source format/type combination */ \
154 return GL_FALSE; \
155 } \
156 \
157 return tab[index]( convert ); \
158 }
159
160 CONVERT_RGBA8888( texsubimage2d )
161 CONVERT_RGBA8888( texsubimage3d )
162
163
164
165 /* =============================================================
166 * Convert to ARGB8888 textures:
167 */
168
169 #define DST_TYPE GLuint
170 #define DST_TEXELS_PER_DWORD 1
171
172 #define CONVERT_TEXEL( dst, src ) \
173 dst = PACK_COLOR_8888_LE( src[3], src[2], src[1], src[0] )
174
175 #define CONVERT_DIRECT
176
177 #define SRC_TEXEL_BYTES 4
178
179 #define TAG(x) x##_argb8888_direct
180 #define PRESERVE_DST_TYPE
181 #include "texutil_tmp.h"
182
183
184 #define CONVERT_TEXEL( dst, src ) \
185 dst = PACK_COLOR_8888_LE( src[3], src[0], src[1], src[2] )
186
187 #define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
188
189 #define SRC_TEXEL_BYTES 4
190
191 #define TAG(x) x##_abgr8888_to_argb8888
192 #define PRESERVE_DST_TYPE
193 #include "texutil_tmp.h"
194
195
196 #define CONVERT_TEXEL( dst, src ) \
197 dst = PACK_COLOR_8888_LE( 0xff, src[0], src[1], src[2] )
198
199 #define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
200
201 #define SRC_TEXEL_BYTES 3
202
203 #define TAG(x) x##_bgr888_to_argb8888
204 #include "texutil_tmp.h"
205
206
207 #define CONVERT_ARGB8888( name ) \
208 static GLboolean \
209 convert_##name##_argb8888( const struct convert_info *convert ) \
210 { \
211 convert_func *tab; \
212 GLint index = convert->index; \
213 \
214 if ( convert->format == GL_BGRA && \
215 convert->type == GL_UNSIGNED_INT_8_8_8_8_REV ) \
216 { \
217 tab = name##_tab_argb8888_direct; \
218 } \
219 else if ( convert->format == GL_RGBA && \
220 convert->type == GL_UNSIGNED_BYTE ) \
221 { \
222 tab = name##_tab_abgr8888_to_argb8888; \
223 } \
224 else if ( convert->format == GL_RGB && \
225 convert->type == GL_UNSIGNED_BYTE ) \
226 { \
227 tab = name##_tab_bgr888_to_argb8888; \
228 } \
229 else \
230 { \
231 /* Can't handle this source format/type combination */ \
232 return GL_FALSE; \
233 } \
234 \
235 return tab[index]( convert ); \
236 }
237
238 CONVERT_ARGB8888( texsubimage2d )
239 CONVERT_ARGB8888( texsubimage3d )
240
241
242
243 /* =============================================================
244 * Convert to RGB888 textures:
245 */
246
247 static GLboolean
248 convert_texsubimage2d_rgb888( const struct convert_info *convert )
249 {
250 /* This is a placeholder for now...
251 */
252 return GL_FALSE;
253 }
254
255 static GLboolean
256 convert_texsubimage3d_rgb888( const struct convert_info *convert )
257 {
258 /* This is a placeholder for now...
259 */
260 return GL_FALSE;
261 }
262
263
264
265 /* =============================================================
266 * Convert to RGB565 textures:
267 */
268
269 #define DST_TYPE GLushort
270 #define DST_TEXELS_PER_DWORD 2
271
272 #define CONVERT_TEXEL( dst, src ) \
273 dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
274
275 #define CONVERT_DIRECT
276
277 #define SRC_TEXEL_BYTES 2
278
279 #define TAG(x) x##_rgb565_direct
280 #define PRESERVE_DST_TYPE
281 #include "texutil_tmp.h"
282
283
284 #define CONVERT_TEXEL( dst, src ) \
285 dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
286
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] ) )
290
291 #define SRC_TEXEL_BYTES 3
292
293 #define TAG(x) x##_bgr888_to_rgb565
294 #define PRESERVE_DST_TYPE
295 #include "texutil_tmp.h"
296
297
298 #define CONVERT_TEXEL( dst, src ) \
299 dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
300
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] ) )
304
305 #define SRC_TEXEL_BYTES 4
306
307 #define TAG(x) x##_abgr8888_to_rgb565
308 #include "texutil_tmp.h"
309
310
311 #define CONVERT_RGB565( name ) \
312 static GLboolean \
313 convert_##name##_rgb565( const struct convert_info *convert ) \
314 { \
315 convert_func *tab; \
316 GLint index = convert->index; \
317 \
318 if ( convert->format == GL_RGB && \
319 convert->type == GL_UNSIGNED_SHORT_5_6_5 ) \
320 { \
321 tab = name##_tab_rgb565_direct; \
322 } \
323 else if ( convert->format == GL_RGB && \
324 convert->type == GL_UNSIGNED_BYTE ) \
325 { \
326 tab = name##_tab_bgr888_to_rgb565; \
327 } \
328 else if ( convert->format == GL_RGBA && \
329 convert->type == GL_UNSIGNED_BYTE ) \
330 { \
331 tab = name##_tab_abgr8888_to_rgb565; \
332 } \
333 else \
334 { \
335 /* Can't handle this source format/type combination */ \
336 return GL_FALSE; \
337 } \
338 \
339 return tab[index]( convert ); \
340 }
341
342 CONVERT_RGB565( texsubimage2d )
343 CONVERT_RGB565( texsubimage3d )
344
345
346
347 /* =============================================================
348 * Convert to ARGB4444 textures:
349 */
350
351 #define DST_TYPE GLushort
352 #define DST_TEXELS_PER_DWORD 2
353
354 #define CONVERT_TEXEL( dst, src ) \
355 dst = PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] )
356
357 #define CONVERT_DIRECT
358
359 #define SRC_TEXEL_BYTES 2
360
361 #define TAG(x) x##_argb4444_direct
362 #define PRESERVE_DST_TYPE
363 #include "texutil_tmp.h"
364
365
366 #define CONVERT_TEXEL( dst, src ) \
367 dst = PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] )
368
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] ) )
372
373 #define SRC_TEXEL_BYTES 4
374
375 #define TAG(x) x##_abgr8888_to_argb4444
376 #include "texutil_tmp.h"
377
378
379 #define CONVERT_ARGB4444( name ) \
380 static GLboolean \
381 convert_##name##_argb4444( const struct convert_info *convert ) \
382 { \
383 convert_func *tab; \
384 GLint index = convert->index; \
385 \
386 if ( convert->format == GL_BGRA && \
387 convert->type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) \
388 { \
389 tab = name##_tab_argb4444_direct; \
390 } \
391 else if ( convert->format == GL_RGBA && \
392 convert->type == GL_UNSIGNED_BYTE ) \
393 { \
394 tab = name##_tab_abgr8888_to_argb4444; \
395 } \
396 else \
397 { \
398 /* Can't handle this source format/type combination */ \
399 return GL_FALSE; \
400 } \
401 \
402 return tab[index]( convert ); \
403 }
404
405 CONVERT_ARGB4444( texsubimage2d )
406 CONVERT_ARGB4444( texsubimage3d )
407
408
409
410 /* =============================================================
411 * Convert to ARGB1555 textures:
412 */
413
414 #define DST_TYPE GLushort
415 #define DST_TEXELS_PER_DWORD 2
416
417 #define CONVERT_TEXEL( dst, src ) \
418 dst = PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] )
419
420 #define CONVERT_DIRECT
421
422 #define SRC_TEXEL_BYTES 2
423
424 #define TAG(x) x##_argb1555_direct
425 #define PRESERVE_DST_TYPE
426 #include "texutil_tmp.h"
427
428
429 #ifdef MESA_BIG_ENDIAN
430
431 #define CONVERT_TEXEL( dst, src ) \
432 { const GLushort s = *(GLushort *)src; \
433 dst = (s >> 9) | ((s & 0x1ff) << 7); }
434
435 #define CONVERT_TEXEL_DWORD( dst, src ) \
436 { const GLuint s = ((fi_type *)src)->i; \
437 dst = (((s & 0xfe00fe00) >> 9) | \
438 ((s & 0x01ff01ff) << 7)); }
439
440 #else
441
442 #define CONVERT_TEXEL( dst, src ) \
443 { const GLushort s = *(GLushort *)src; \
444 dst = (s >> 1) | ((s & 1) << 15); }
445
446 #define CONVERT_TEXEL_DWORD( dst, src ) \
447 { const GLuint s = ((fi_type *)src)->i; \
448 dst = (((s & 0xfffefffe) >> 1) | \
449 ((s & 0x00010001) << 15)); }
450
451 #endif
452
453 #define SRC_TEXEL_BYTES 2
454
455 #define TAG(x) x##_rgba5551_to_argb1555
456 #define PRESERVE_DST_TYPE
457 #include "texutil_tmp.h"
458
459
460 #define CONVERT_TEXEL( dst, src ) \
461 dst = PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] )
462
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] ) )
466
467 #define SRC_TEXEL_BYTES 4
468
469 #define TAG(x) x##_abgr8888_to_argb1555
470 #include "texutil_tmp.h"
471
472
473 #define CONVERT_ARGB1555( name ) \
474 static GLboolean \
475 convert_##name##_argb1555( const struct convert_info *convert ) \
476 { \
477 convert_func *tab; \
478 GLint index = convert->index; \
479 \
480 if ( convert->format == GL_BGRA && \
481 convert->type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) \
482 { \
483 tab = name##_tab_argb1555_direct; \
484 } \
485 else if ( convert->format == GL_RGBA && \
486 convert->type == GL_UNSIGNED_SHORT_5_5_5_1 ) \
487 { \
488 tab = name##_tab_rgba5551_to_argb1555; \
489 } \
490 else if ( convert->format == GL_RGBA && \
491 convert->type == GL_UNSIGNED_BYTE ) \
492 { \
493 tab = name##_tab_abgr8888_to_argb1555; \
494 } \
495 else \
496 { \
497 /* Can't handle this source format/type combination */ \
498 return GL_FALSE; \
499 } \
500 \
501 return tab[index]( convert ); \
502 }
503
504 CONVERT_ARGB1555( texsubimage2d )
505 CONVERT_ARGB1555( texsubimage3d )
506
507
508
509 /* =============================================================
510 * AL88 textures:
511 */
512
513 #define DST_TYPE GLushort
514 #define DST_TEXELS_PER_DWORD 2
515
516 #define CONVERT_TEXEL( dst, src ) \
517 dst = PACK_COLOR_88_LE( src[0], src[1] )
518
519 #define CONVERT_DIRECT
520
521 #define SRC_TEXEL_BYTES 2
522
523 #define TAG(x) x##_al88_direct
524 #define PRESERVE_DST_TYPE
525 #include "texutil_tmp.h"
526
527
528 #define CONVERT_TEXEL( dst, src ) \
529 dst = PACK_COLOR_88_LE( src[0], 0x00 )
530
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 ) )
534
535 #define SRC_TEXEL_BYTES 1
536
537 #define TAG(x) x##_a8_to_al88
538 #define PRESERVE_DST_TYPE
539 #include "texutil_tmp.h"
540
541
542 #define CONVERT_TEXEL( dst, src ) \
543 dst = PACK_COLOR_88_LE( 0xff, src[0] )
544
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] ) )
548
549 #define SRC_TEXEL_BYTES 1
550
551 #define TAG(x) x##_l8_to_al88
552 #define PRESERVE_DST_TYPE
553 #include "texutil_tmp.h"
554
555
556 #define CONVERT_TEXEL( dst, src ) \
557 dst = PACK_COLOR_88_LE( src[3], src[0] )
558
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] ) )
562
563 #define SRC_TEXEL_BYTES 4
564
565 #define TAG(x) x##_abgr8888_to_al88
566 #include "texutil_tmp.h"
567
568
569 #define CONVERT_AL88( name ) \
570 static GLboolean \
571 convert_##name##_al88( const struct convert_info *convert ) \
572 { \
573 convert_func *tab; \
574 GLint index = convert->index; \
575 \
576 if ( convert->format == GL_LUMINANCE_ALPHA && \
577 convert->type == GL_UNSIGNED_BYTE ) \
578 { \
579 tab = name##_tab_al88_direct; \
580 } \
581 else if ( convert->format == GL_ALPHA && \
582 convert->type == GL_UNSIGNED_BYTE ) \
583 { \
584 tab = name##_tab_a8_to_al88; \
585 } \
586 else if ( convert->format == GL_LUMINANCE && \
587 convert->type == GL_UNSIGNED_BYTE ) \
588 { \
589 tab = name##_tab_l8_to_al88; \
590 } \
591 else if ( convert->format == GL_RGBA && \
592 convert->type == GL_UNSIGNED_BYTE ) \
593 { \
594 tab = name##_tab_abgr8888_to_al88; \
595 } \
596 else \
597 { \
598 /* Can't handle this source format/type combination */ \
599 return GL_FALSE; \
600 } \
601 \
602 return tab[index]( convert ); \
603 }
604
605 CONVERT_AL88( texsubimage2d )
606 CONVERT_AL88( texsubimage3d )
607
608
609
610 /* =============================================================
611 * Convert to RGB332 textures:
612 */
613
614 static GLboolean
615 convert_texsubimage2d_rgb332( const struct convert_info *convert )
616 {
617 /* This is a placeholder for now...
618 */
619 return GL_FALSE;
620 }
621
622 static GLboolean
623 convert_texsubimage3d_rgb332( const struct convert_info *convert )
624 {
625 /* This is a placeholder for now...
626 */
627 return GL_FALSE;
628 }
629
630
631
632 /* =============================================================
633 * CI8 (and all other single-byte texel) textures:
634 */
635
636 #define DST_TYPE GLubyte
637 #define DST_TEXELS_PER_DWORD 4
638
639 #define CONVERT_TEXEL( dst, src ) dst = src[0]
640
641 #define CONVERT_DIRECT
642
643 #define SRC_TEXEL_BYTES 1
644
645 #define TAG(x) x##_ci8_direct
646 #include "texutil_tmp.h"
647
648
649 #define CONVERT_CI8( name ) \
650 static GLboolean \
651 convert_##name##_ci8( const struct convert_info *convert ) \
652 { \
653 convert_func *tab; \
654 GLint index = convert->index; \
655 \
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 ) \
661 { \
662 tab = name##_tab_ci8_direct; \
663 } \
664 else \
665 { \
666 /* Can't handle this source format/type combination */ \
667 return GL_FALSE; \
668 } \
669 \
670 return tab[index]( convert ); \
671 }
672
673 CONVERT_CI8( texsubimage2d )
674 CONVERT_CI8( texsubimage3d )
675
676
677 /* =============================================================
678 * convert to YCBCR textures:
679 */
680
681 #define DST_TYPE GLushort
682 #define DST_TEXELS_PER_DWORD 2
683
684 #define CONVERT_TEXEL( dst, src ) \
685 dst = (src[0] << 8) | src[1];
686
687 #define CONVERT_DIRECT
688
689 #define SRC_TEXEL_BYTES 2
690
691 #define TAG(x) x##_ycbcr_direct
692 #include "texutil_tmp.h"
693
694
695 #define CONVERT_YCBCR( name ) \
696 static GLboolean \
697 convert_##name##_ycbcr( const struct convert_info *convert ) \
698 { \
699 convert_func *tab; \
700 GLint index = convert->index; \
701 \
702 if (convert->format != GL_YCBCR_MESA) { \
703 /* Can't handle this source format/type combination */ \
704 return GL_FALSE; \
705 } \
706 tab = name##_tab_ycbcr_direct; \
707 \
708 return tab[index]( convert ); \
709 }
710
711 CONVERT_YCBCR( texsubimage2d )
712 CONVERT_YCBCR( texsubimage3d )
713
714
715 /* =============================================================
716 * convert to YCBCR_REV textures:
717 */
718
719 #define DST_TYPE GLushort
720 #define DST_TEXELS_PER_DWORD 2
721
722 #define CONVERT_TEXEL( dst, src ) \
723 dst = (src[1] << 8) | src[0];
724
725 #define CONVERT_DIRECT
726
727 #define SRC_TEXEL_BYTES 2
728
729 #define TAG(x) x##_ycbcr_rev_direct
730 #include "texutil_tmp.h"
731
732
733 #define CONVERT_YCBCR_REV( name ) \
734 static GLboolean \
735 convert_##name##_ycbcr_rev( const struct convert_info *convert ) \
736 { \
737 convert_func *tab; \
738 GLint index = convert->index; \
739 \
740 if (convert->format != GL_YCBCR_MESA) { \
741 /* Can't handle this source format/type combination */ \
742 return GL_FALSE; \
743 } \
744 tab = name##_tab_ycbcr_rev_direct; \
745 \
746 return tab[index]( convert ); \
747 }
748
749 CONVERT_YCBCR_REV( texsubimage2d )
750 CONVERT_YCBCR_REV( texsubimage3d )
751
752
753
754 /* =============================================================
755 * Global entry points
756 */
757
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,
773 };
774
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,
790 };
791
792
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...
797 */
798 static INLINE GLboolean
799 convert_needs_unpacking( const struct gl_pixelstore_attrib *unpacking,
800 GLenum format, GLenum type )
801 {
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 ) {
812 return GL_FALSE;
813 } else {
814 return GL_TRUE;
815 }
816 }
817
818
819 GLboolean
820 _mesa_convert_texsubimage1d( GLint mesaFormat,
821 GLint xoffset,
822 GLint width,
823 GLenum format, GLenum type,
824 const struct gl_pixelstore_attrib *unpacking,
825 const GLvoid *srcImage, GLvoid *dstImage )
826 {
827 struct convert_info convert;
828
829 ASSERT( unpacking );
830 ASSERT( srcImage );
831 ASSERT( dstImage );
832
833 ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 );
834 ASSERT( mesaFormat <= MESA_FORMAT_YCBCR_REV );
835
836 /* Make it easier to pass all the parameters around.
837 */
838 convert.xoffset = xoffset;
839 convert.yoffset = 0;
840 convert.width = width;
841 convert.height = 1;
842 convert.format = format;
843 convert.type = type;
844 convert.unpacking = unpacking;
845 convert.srcImage = srcImage;
846 convert.dstImage = dstImage;
847
848 convert.index = 0;
849
850 if ( convert_needs_unpacking( unpacking, format, type ) )
851 convert.index |= CONVERT_UNPACKING_BIT;
852
853 ASSERT(convert.index < 4);
854
855 return convert_texsubimage2d_tab[mesaFormat]( &convert );
856 }
857
858
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.
862 *
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.
867 *
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.
873 *
874 * \param
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
883 */
884 GLboolean
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 )
892 {
893 struct convert_info convert;
894
895 ASSERT( unpacking );
896 ASSERT( srcImage );
897 ASSERT( dstImage );
898
899 ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 );
900 ASSERT( mesaFormat <= MESA_FORMAT_YCBCR_REV );
901
902 /* Make it easier to pass all the parameters around.
903 */
904 convert.xoffset = xoffset;
905 convert.yoffset = yoffset;
906 convert.width = width;
907 convert.height = height;
908 convert.dstImageWidth = destImageWidth;
909 convert.format = format;
910 convert.type = type;
911 convert.unpacking = unpacking;
912 convert.srcImage = srcImage;
913 convert.dstImage = dstImage;
914
915 convert.index = 0;
916
917 if ( convert_needs_unpacking( unpacking, format, type ) )
918 convert.index |= CONVERT_UNPACKING_BIT;
919
920 if ( width != destImageWidth )
921 convert.index |= CONVERT_STRIDE_BIT;
922
923 return convert_texsubimage2d_tab[mesaFormat]( &convert );
924 }
925
926 GLboolean
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 )
934 {
935 struct convert_info convert;
936
937 ASSERT( unpacking );
938 ASSERT( srcImage );
939 ASSERT( dstImage );
940
941 ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 );
942 ASSERT( mesaFormat <= MESA_FORMAT_YCBCR_REV );
943
944 /* Make it easier to pass all the parameters around.
945 */
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;
955 convert.type = type;
956 convert.unpacking = unpacking;
957 convert.srcImage = srcImage;
958 convert.dstImage = dstImage;
959
960 convert.index = 0;
961
962 if ( convert_needs_unpacking( unpacking, format, type ) )
963 convert.index |= CONVERT_UNPACKING_BIT;
964
965 if ( width != dstImageWidth || height != dstImageHeight )
966 convert.index |= CONVERT_STRIDE_BIT;
967
968 return convert_texsubimage3d_tab[mesaFormat]( &convert );
969 }
970
971 #endif
972
973
974
975 /* Nearest filtering only (for broken hardware that can't support
976 * all aspect ratios). This can be made a lot faster, but I don't
977 * really care enough...
978 */
979 void _mesa_rescale_teximage2d( GLuint bytesPerPixel, GLuint dstRowStride,
980 GLint srcWidth, GLint srcHeight,
981 GLint dstWidth, GLint dstHeight,
982 const GLvoid *srcImage, GLvoid *dstImage )
983 {
984 GLint row, col;
985
986 #define INNER_LOOP( TYPE, HOP, WOP ) \
987 for ( row = 0 ; row < dstHeight ; row++ ) { \
988 GLint srcRow = row HOP hScale; \
989 for ( col = 0 ; col < dstWidth ; col++ ) { \
990 GLint srcCol = col WOP wScale; \
991 dst[col] = src[srcRow * srcWidth + srcCol]; \
992 } \
993 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
994 } \
995
996 #define RESCALE_IMAGE( TYPE ) \
997 do { \
998 const TYPE *src = (const TYPE *)srcImage; \
999 TYPE *dst = (TYPE *)dstImage; \
1000 \
1001 if ( srcHeight < dstHeight ) { \
1002 const GLint hScale = dstHeight / srcHeight; \
1003 if ( srcWidth < dstWidth ) { \
1004 const GLint wScale = dstWidth / srcWidth; \
1005 INNER_LOOP( TYPE, /, / ); \
1006 } \
1007 else { \
1008 const GLint wScale = srcWidth / dstWidth; \
1009 INNER_LOOP( TYPE, /, * ); \
1010 } \
1011 } \
1012 else { \
1013 const GLint hScale = srcHeight / dstHeight; \
1014 if ( srcWidth < dstWidth ) { \
1015 const GLint wScale = dstWidth / srcWidth; \
1016 INNER_LOOP( TYPE, *, / ); \
1017 } \
1018 else { \
1019 const GLint wScale = srcWidth / dstWidth; \
1020 INNER_LOOP( TYPE, *, * ); \
1021 } \
1022 } \
1023 } while (0)
1024
1025 switch ( bytesPerPixel ) {
1026 case 4:
1027 RESCALE_IMAGE( GLuint );
1028 break;
1029
1030 case 2:
1031 RESCALE_IMAGE( GLushort );
1032 break;
1033
1034 case 1:
1035 RESCALE_IMAGE( GLubyte );
1036 break;
1037 default:
1038 _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
1039 }
1040 }