660f7ec63f5c78a46477617bce40cac79f8e5091
[mesa.git] / src / mesa / main / texutil.c
1 /* $Id: texutil.c,v 1.34 2002/10/29 20:28:53 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 *
26 * Authors:
27 * Gareth Hughes
28 */
29
30 /*
31 * Description:
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.
35 */
36
37
38 #include "glheader.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 #define DEBUG_TEXUTIL 0
50
51
52 #ifdef MESA_BIG_ENDIAN
53 #define APPEND16( a, b ) ( (a) << 16 | (b) )
54 #else
55 #define APPEND16( a, b ) ( (a) | (b) << 16 )
56 #endif
57
58
59 struct convert_info {
60 GLint xoffset, yoffset, zoffset; /* Subimage offset */
61 GLint width, height, depth; /* Subimage region */
62
63 GLint dstImageWidth, dstImageHeight; /* Dest image size */
64 /* Needed for subimage replacement */
65 GLenum format, type; /* Source (user) format and type */
66
67 const struct gl_pixelstore_attrib *unpacking;
68
69 const GLvoid *srcImage;
70 GLvoid *dstImage;
71
72 GLint index;
73 };
74
75 typedef GLboolean (*convert_func)( const struct convert_info *convert );
76
77 /* bitvalues for convert->index */
78 #define CONVERT_STRIDE_BIT 0x1
79 #define CONVERT_UNPACKING_BIT 0x2
80
81
82
83 /* =============================================================
84 * Convert to RGBA8888 textures:
85 */
86
87 #define DST_TYPE GLuint
88 #define DST_TEXELS_PER_DWORD 1
89
90 #define CONVERT_TEXEL( dst, src ) \
91 dst = PACK_COLOR_8888_LE( src[3], src[2], src[1], src[0] )
92
93 #define CONVERT_DIRECT
94
95 #define SRC_TEXEL_BYTES 4
96
97 #define TAG(x) x##_rgba8888_direct
98 #define PRESERVE_DST_TYPE
99 #include "texutil_tmp.h"
100
101
102 #define CONVERT_TEXEL( dst, src ) \
103 dst = PACK_COLOR_8888_LE( src[0], src[1], src[2], src[3] )
104
105 #define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
106
107 #define SRC_TEXEL_BYTES 4
108
109 #define TAG(x) x##_abgr8888_to_rgba8888
110 #define PRESERVE_DST_TYPE
111 #include "texutil_tmp.h"
112
113
114 #define CONVERT_TEXEL( dst, src ) \
115 dst = PACK_COLOR_8888_LE( src[0], src[1], src[2], 0xff )
116
117 #define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
118
119 #define SRC_TEXEL_BYTES 3
120
121 #define TAG(x) x##_bgr888_to_rgba8888
122 #include "texutil_tmp.h"
123
124
125 #define CONVERT_RGBA8888( name ) \
126 static GLboolean \
127 convert_##name##_rgba8888( const struct convert_info *convert ) \
128 { \
129 convert_func *tab; \
130 GLint index = convert->index; \
131 \
132 if ( convert->format == GL_ABGR_EXT && \
133 convert->type == GL_UNSIGNED_INT_8_8_8_8_REV ) \
134 { \
135 tab = name##_tab_rgba8888_direct; \
136 } \
137 else if ( convert->format == GL_RGBA && \
138 ( convert->type == GL_UNSIGNED_BYTE || \
139 convert->type == GL_UNSIGNED_INT_8_8_8_8 ) ) \
140 { \
141 tab = name##_tab_abgr8888_to_rgba8888; \
142 } \
143 else if ( convert->format == GL_RGB && \
144 convert->type == GL_UNSIGNED_BYTE ) \
145 { \
146 tab = name##_tab_bgr888_to_rgba8888; \
147 } \
148 else \
149 { \
150 /* Can't handle this source format/type combination */ \
151 return GL_FALSE; \
152 } \
153 \
154 return tab[index]( convert ); \
155 }
156
157 CONVERT_RGBA8888( texsubimage2d )
158 CONVERT_RGBA8888( texsubimage3d )
159
160
161
162 /* =============================================================
163 * Convert to ARGB8888 textures:
164 */
165
166 #define DST_TYPE GLuint
167 #define DST_TEXELS_PER_DWORD 1
168
169 #define CONVERT_TEXEL( dst, src ) \
170 dst = PACK_COLOR_8888_LE( src[3], src[2], src[1], src[0] )
171
172 #define CONVERT_DIRECT
173
174 #define SRC_TEXEL_BYTES 4
175
176 #define TAG(x) x##_argb8888_direct
177 #define PRESERVE_DST_TYPE
178 #include "texutil_tmp.h"
179
180
181 #define CONVERT_TEXEL( dst, src ) \
182 dst = PACK_COLOR_8888_LE( src[3], src[0], src[1], src[2] )
183
184 #define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
185
186 #define SRC_TEXEL_BYTES 4
187
188 #define TAG(x) x##_abgr8888_to_argb8888
189 #define PRESERVE_DST_TYPE
190 #include "texutil_tmp.h"
191
192
193 #define CONVERT_TEXEL( dst, src ) \
194 dst = PACK_COLOR_8888_LE( 0xff, src[0], src[1], src[2] )
195
196 #define CONVERT_TEXEL_DWORD( dst, src ) CONVERT_TEXEL( dst, src )
197
198 #define SRC_TEXEL_BYTES 3
199
200 #define TAG(x) x##_bgr888_to_argb8888
201 #include "texutil_tmp.h"
202
203
204 #define CONVERT_ARGB8888( name ) \
205 static GLboolean \
206 convert_##name##_argb8888( const struct convert_info *convert ) \
207 { \
208 convert_func *tab; \
209 GLint index = convert->index; \
210 \
211 if ( convert->format == GL_BGRA && \
212 convert->type == GL_UNSIGNED_INT_8_8_8_8_REV ) \
213 { \
214 tab = name##_tab_argb8888_direct; \
215 } \
216 else if ( convert->format == GL_RGBA && \
217 convert->type == GL_UNSIGNED_BYTE ) \
218 { \
219 tab = name##_tab_abgr8888_to_argb8888; \
220 } \
221 else if ( convert->format == GL_RGB && \
222 convert->type == GL_UNSIGNED_BYTE ) \
223 { \
224 tab = name##_tab_bgr888_to_argb8888; \
225 } \
226 else \
227 { \
228 /* Can't handle this source format/type combination */ \
229 return GL_FALSE; \
230 } \
231 \
232 return tab[index]( convert ); \
233 }
234
235 CONVERT_ARGB8888( texsubimage2d )
236 CONVERT_ARGB8888( texsubimage3d )
237
238
239
240 /* =============================================================
241 * Convert to RGB888 textures:
242 */
243
244 static GLboolean
245 convert_texsubimage2d_rgb888( const struct convert_info *convert )
246 {
247 /* This is a placeholder for now...
248 */
249 return GL_FALSE;
250 }
251
252 static GLboolean
253 convert_texsubimage3d_rgb888( const struct convert_info *convert )
254 {
255 /* This is a placeholder for now...
256 */
257 return GL_FALSE;
258 }
259
260
261
262 /* =============================================================
263 * Convert to RGB565 textures:
264 */
265
266 #define DST_TYPE GLushort
267 #define DST_TEXELS_PER_DWORD 2
268
269 #define CONVERT_TEXEL( dst, src ) \
270 dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
271
272 #define CONVERT_DIRECT
273
274 #define SRC_TEXEL_BYTES 2
275
276 #define TAG(x) x##_rgb565_direct
277 #define PRESERVE_DST_TYPE
278 #include "texutil_tmp.h"
279
280
281 #define CONVERT_TEXEL( dst, src ) \
282 dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
283
284 #define CONVERT_TEXEL_DWORD( dst, src ) \
285 dst = APPEND16( PACK_COLOR_565_LE( src[0], src[1], src[2] ), \
286 PACK_COLOR_565_LE( src[3], src[4], src[5] ) )
287
288 #define SRC_TEXEL_BYTES 3
289
290 #define TAG(x) x##_bgr888_to_rgb565
291 #define PRESERVE_DST_TYPE
292 #include "texutil_tmp.h"
293
294
295 #define CONVERT_TEXEL( dst, src ) \
296 dst = PACK_COLOR_565_LE( src[0], src[1], src[2] )
297
298 #define CONVERT_TEXEL_DWORD( dst, src ) \
299 dst = APPEND16( PACK_COLOR_565_LE( src[0], src[1], src[2] ), \
300 PACK_COLOR_565_LE( src[4], src[5], src[6] ) )
301
302 #define SRC_TEXEL_BYTES 4
303
304 #define TAG(x) x##_abgr8888_to_rgb565
305 #include "texutil_tmp.h"
306
307
308 #define CONVERT_RGB565( name ) \
309 static GLboolean \
310 convert_##name##_rgb565( const struct convert_info *convert ) \
311 { \
312 convert_func *tab; \
313 GLint index = convert->index; \
314 \
315 if ( convert->format == GL_RGB && \
316 convert->type == GL_UNSIGNED_SHORT_5_6_5 ) \
317 { \
318 tab = name##_tab_rgb565_direct; \
319 } \
320 else if ( convert->format == GL_RGB && \
321 convert->type == GL_UNSIGNED_BYTE ) \
322 { \
323 tab = name##_tab_bgr888_to_rgb565; \
324 } \
325 else if ( convert->format == GL_RGBA && \
326 convert->type == GL_UNSIGNED_BYTE ) \
327 { \
328 tab = name##_tab_abgr8888_to_rgb565; \
329 } \
330 else \
331 { \
332 /* Can't handle this source format/type combination */ \
333 return GL_FALSE; \
334 } \
335 \
336 return tab[index]( convert ); \
337 }
338
339 CONVERT_RGB565( texsubimage2d )
340 CONVERT_RGB565( texsubimage3d )
341
342
343
344 /* =============================================================
345 * Convert to ARGB4444 textures:
346 */
347
348 #define DST_TYPE GLushort
349 #define DST_TEXELS_PER_DWORD 2
350
351 #define CONVERT_TEXEL( dst, src ) \
352 dst = PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] )
353
354 #define CONVERT_DIRECT
355
356 #define SRC_TEXEL_BYTES 2
357
358 #define TAG(x) x##_argb4444_direct
359 #define PRESERVE_DST_TYPE
360 #include "texutil_tmp.h"
361
362
363 #define CONVERT_TEXEL( dst, src ) \
364 dst = PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] )
365
366 #define CONVERT_TEXEL_DWORD( dst, src ) \
367 dst = APPEND16( PACK_COLOR_4444_LE( src[3], src[0], src[1], src[2] ), \
368 PACK_COLOR_4444_LE( src[7], src[4], src[5], src[6] ) )
369
370 #define SRC_TEXEL_BYTES 4
371
372 #define TAG(x) x##_abgr8888_to_argb4444
373 #include "texutil_tmp.h"
374
375
376 #define CONVERT_ARGB4444( name ) \
377 static GLboolean \
378 convert_##name##_argb4444( const struct convert_info *convert ) \
379 { \
380 convert_func *tab; \
381 GLint index = convert->index; \
382 \
383 if ( convert->format == GL_BGRA && \
384 convert->type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) \
385 { \
386 tab = name##_tab_argb4444_direct; \
387 } \
388 else if ( convert->format == GL_RGBA && \
389 convert->type == GL_UNSIGNED_BYTE ) \
390 { \
391 tab = name##_tab_abgr8888_to_argb4444; \
392 } \
393 else \
394 { \
395 /* Can't handle this source format/type combination */ \
396 return GL_FALSE; \
397 } \
398 \
399 return tab[index]( convert ); \
400 }
401
402 CONVERT_ARGB4444( texsubimage2d )
403 CONVERT_ARGB4444( texsubimage3d )
404
405
406
407 /* =============================================================
408 * Convert to ARGB1555 textures:
409 */
410
411 #define DST_TYPE GLushort
412 #define DST_TEXELS_PER_DWORD 2
413
414 #define CONVERT_TEXEL( dst, src ) \
415 dst = PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] )
416
417 #define CONVERT_DIRECT
418
419 #define SRC_TEXEL_BYTES 2
420
421 #define TAG(x) x##_argb1555_direct
422 #define PRESERVE_DST_TYPE
423 #include "texutil_tmp.h"
424
425
426 #ifdef MESA_BIG_ENDIAN
427
428 #define CONVERT_TEXEL( dst, src ) \
429 { const GLushort s = *(GLushort *)src; \
430 dst = (s >> 9) | ((s & 0x1ff) << 7); }
431
432 #define CONVERT_TEXEL_DWORD( dst, src ) \
433 { const GLuint s = ((fi_type *)src)->i; \
434 dst = (((s & 0xfe00fe00) >> 9) | \
435 ((s & 0x01ff01ff) << 7)); }
436
437 #else
438
439 #define CONVERT_TEXEL( dst, src ) \
440 { const GLushort s = *(GLushort *)src; \
441 dst = (s >> 1) | ((s & 1) << 15); }
442
443 #define CONVERT_TEXEL_DWORD( dst, src ) \
444 { const GLuint s = ((fi_type *)src)->i; \
445 dst = (((s & 0xfffefffe) >> 1) | \
446 ((s & 0x00010001) << 15)); }
447
448 #endif
449
450 #define SRC_TEXEL_BYTES 2
451
452 #define TAG(x) x##_rgba5551_to_argb1555
453 #define PRESERVE_DST_TYPE
454 #include "texutil_tmp.h"
455
456
457 #define CONVERT_TEXEL( dst, src ) \
458 dst = PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] )
459
460 #define CONVERT_TEXEL_DWORD( dst, src ) \
461 dst = APPEND16( PACK_COLOR_1555_LE( src[3], src[0], src[1], src[2] ), \
462 PACK_COLOR_1555_LE( src[7], src[4], src[5], src[6] ) )
463
464 #define SRC_TEXEL_BYTES 4
465
466 #define TAG(x) x##_abgr8888_to_argb1555
467 #include "texutil_tmp.h"
468
469
470 #define CONVERT_ARGB1555( name ) \
471 static GLboolean \
472 convert_##name##_argb1555( const struct convert_info *convert ) \
473 { \
474 convert_func *tab; \
475 GLint index = convert->index; \
476 \
477 if ( convert->format == GL_BGRA && \
478 convert->type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) \
479 { \
480 tab = name##_tab_argb1555_direct; \
481 } \
482 else if ( convert->format == GL_RGBA && \
483 convert->type == GL_UNSIGNED_SHORT_5_5_5_1 ) \
484 { \
485 tab = name##_tab_rgba5551_to_argb1555; \
486 } \
487 else if ( convert->format == GL_RGBA && \
488 convert->type == GL_UNSIGNED_BYTE ) \
489 { \
490 tab = name##_tab_abgr8888_to_argb1555; \
491 } \
492 else \
493 { \
494 /* Can't handle this source format/type combination */ \
495 return GL_FALSE; \
496 } \
497 \
498 return tab[index]( convert ); \
499 }
500
501 CONVERT_ARGB1555( texsubimage2d )
502 CONVERT_ARGB1555( texsubimage3d )
503
504
505
506 /* =============================================================
507 * AL88 textures:
508 */
509
510 #define DST_TYPE GLushort
511 #define DST_TEXELS_PER_DWORD 2
512
513 #define CONVERT_TEXEL( dst, src ) \
514 dst = PACK_COLOR_88_LE( src[0], src[1] )
515
516 #define CONVERT_DIRECT
517
518 #define SRC_TEXEL_BYTES 2
519
520 #define TAG(x) x##_al88_direct
521 #define PRESERVE_DST_TYPE
522 #include "texutil_tmp.h"
523
524
525 #define CONVERT_TEXEL( dst, src ) \
526 dst = PACK_COLOR_88_LE( src[0], 0x00 )
527
528 #define CONVERT_TEXEL_DWORD( dst, src ) \
529 dst = APPEND16( PACK_COLOR_88_LE( src[0], 0x00 ), \
530 PACK_COLOR_88_LE( src[1], 0x00 ) )
531
532 #define SRC_TEXEL_BYTES 1
533
534 #define TAG(x) x##_a8_to_al88
535 #define PRESERVE_DST_TYPE
536 #include "texutil_tmp.h"
537
538
539 #define CONVERT_TEXEL( dst, src ) \
540 dst = PACK_COLOR_88_LE( 0xff, src[0] )
541
542 #define CONVERT_TEXEL_DWORD( dst, src ) \
543 dst = APPEND16( PACK_COLOR_88_LE( 0xff, src[0] ), \
544 PACK_COLOR_88_LE( 0xff, src[1] ) )
545
546 #define SRC_TEXEL_BYTES 1
547
548 #define TAG(x) x##_l8_to_al88
549 #define PRESERVE_DST_TYPE
550 #include "texutil_tmp.h"
551
552
553 #define CONVERT_TEXEL( dst, src ) \
554 dst = PACK_COLOR_88_LE( src[3], src[0] )
555
556 #define CONVERT_TEXEL_DWORD( dst, src ) \
557 dst = APPEND16( PACK_COLOR_88_LE( src[3], src[0] ), \
558 PACK_COLOR_88_LE( src[7], src[4] ) )
559
560 #define SRC_TEXEL_BYTES 4
561
562 #define TAG(x) x##_abgr8888_to_al88
563 #include "texutil_tmp.h"
564
565
566 #define CONVERT_AL88( name ) \
567 static GLboolean \
568 convert_##name##_al88( const struct convert_info *convert ) \
569 { \
570 convert_func *tab; \
571 GLint index = convert->index; \
572 \
573 if ( convert->format == GL_LUMINANCE_ALPHA && \
574 convert->type == GL_UNSIGNED_BYTE ) \
575 { \
576 tab = name##_tab_al88_direct; \
577 } \
578 else if ( convert->format == GL_ALPHA && \
579 convert->type == GL_UNSIGNED_BYTE ) \
580 { \
581 tab = name##_tab_a8_to_al88; \
582 } \
583 else if ( convert->format == GL_LUMINANCE && \
584 convert->type == GL_UNSIGNED_BYTE ) \
585 { \
586 tab = name##_tab_l8_to_al88; \
587 } \
588 else if ( convert->format == GL_RGBA && \
589 convert->type == GL_UNSIGNED_BYTE ) \
590 { \
591 tab = name##_tab_abgr8888_to_al88; \
592 } \
593 else \
594 { \
595 /* Can't handle this source format/type combination */ \
596 return GL_FALSE; \
597 } \
598 \
599 return tab[index]( convert ); \
600 }
601
602 CONVERT_AL88( texsubimage2d )
603 CONVERT_AL88( texsubimage3d )
604
605
606
607 /* =============================================================
608 * Convert to RGB332 textures:
609 */
610
611 static GLboolean
612 convert_texsubimage2d_rgb332( const struct convert_info *convert )
613 {
614 /* This is a placeholder for now...
615 */
616 return GL_FALSE;
617 }
618
619 static GLboolean
620 convert_texsubimage3d_rgb332( const struct convert_info *convert )
621 {
622 /* This is a placeholder for now...
623 */
624 return GL_FALSE;
625 }
626
627
628
629 /* =============================================================
630 * CI8 (and all other single-byte texel) textures:
631 */
632
633 #define DST_TYPE GLubyte
634 #define DST_TEXELS_PER_DWORD 4
635
636 #define CONVERT_TEXEL( dst, src ) dst = src[0]
637
638 #define CONVERT_DIRECT
639
640 #define SRC_TEXEL_BYTES 1
641
642 #define TAG(x) x##_ci8_direct
643 #include "texutil_tmp.h"
644
645
646 #define CONVERT_CI8( name ) \
647 static GLboolean \
648 convert_##name##_ci8( const struct convert_info *convert ) \
649 { \
650 convert_func *tab; \
651 GLint index = convert->index; \
652 \
653 if ( ( convert->format == GL_ALPHA || \
654 convert->format == GL_LUMINANCE || \
655 convert->format == GL_INTENSITY || \
656 convert->format == GL_COLOR_INDEX ) && \
657 convert->type == GL_UNSIGNED_BYTE ) \
658 { \
659 tab = name##_tab_ci8_direct; \
660 } \
661 else \
662 { \
663 /* Can't handle this source format/type combination */ \
664 return GL_FALSE; \
665 } \
666 \
667 return tab[index]( convert ); \
668 }
669
670 CONVERT_CI8( texsubimage2d )
671 CONVERT_CI8( texsubimage3d )
672
673
674 /* =============================================================
675 * convert to YCBCR textures:
676 */
677
678 #define DST_TYPE GLushort
679 #define DST_TEXELS_PER_DWORD 2
680
681 #define CONVERT_TEXEL( dst, src ) \
682 dst = (src[0] << 8) | src[1];
683
684 #define CONVERT_DIRECT
685
686 #define SRC_TEXEL_BYTES 2
687
688 #define TAG(x) x##_ycbcr_direct
689 #include "texutil_tmp.h"
690
691
692 #define CONVERT_YCBCR( name ) \
693 static GLboolean \
694 convert_##name##_ycbcr( const struct convert_info *convert ) \
695 { \
696 convert_func *tab; \
697 GLint index = convert->index; \
698 \
699 if (convert->format != GL_YCBCR_MESA) { \
700 /* Can't handle this source format/type combination */ \
701 return GL_FALSE; \
702 } \
703 tab = name##_tab_ycbcr_direct; \
704 \
705 return tab[index]( convert ); \
706 }
707
708 CONVERT_YCBCR( texsubimage2d )
709 CONVERT_YCBCR( texsubimage3d )
710
711
712 /* =============================================================
713 * convert to YCBCR_REV textures:
714 */
715
716 #define DST_TYPE GLushort
717 #define DST_TEXELS_PER_DWORD 2
718
719 #define CONVERT_TEXEL( dst, src ) \
720 dst = (src[1] << 8) | src[0];
721
722 #define CONVERT_DIRECT
723
724 #define SRC_TEXEL_BYTES 2
725
726 #define TAG(x) x##_ycbcr_rev_direct
727 #include "texutil_tmp.h"
728
729
730 #define CONVERT_YCBCR_REV( name ) \
731 static GLboolean \
732 convert_##name##_ycbcr_rev( const struct convert_info *convert ) \
733 { \
734 convert_func *tab; \
735 GLint index = convert->index; \
736 \
737 if (convert->format != GL_YCBCR_MESA) { \
738 /* Can't handle this source format/type combination */ \
739 return GL_FALSE; \
740 } \
741 tab = name##_tab_ycbcr_rev_direct; \
742 \
743 return tab[index]( convert ); \
744 }
745
746 CONVERT_YCBCR_REV( texsubimage2d )
747 CONVERT_YCBCR_REV( texsubimage3d )
748
749
750
751 /* =============================================================
752 * Global entry points
753 */
754
755 static convert_func convert_texsubimage2d_tab[] = {
756 convert_texsubimage2d_rgba8888,
757 convert_texsubimage2d_argb8888,
758 convert_texsubimage2d_rgb888,
759 convert_texsubimage2d_rgb565,
760 convert_texsubimage2d_argb4444,
761 convert_texsubimage2d_argb1555,
762 convert_texsubimage2d_al88,
763 convert_texsubimage2d_rgb332,
764 convert_texsubimage2d_ci8, /* These are all the same... */
765 convert_texsubimage2d_ci8,
766 convert_texsubimage2d_ci8,
767 convert_texsubimage2d_ci8,
768 convert_texsubimage2d_ycbcr,
769 convert_texsubimage2d_ycbcr_rev,
770 };
771
772 static convert_func convert_texsubimage3d_tab[] = {
773 convert_texsubimage3d_rgba8888,
774 convert_texsubimage3d_argb8888,
775 convert_texsubimage3d_rgb888,
776 convert_texsubimage3d_rgb565,
777 convert_texsubimage3d_argb4444,
778 convert_texsubimage3d_argb1555,
779 convert_texsubimage3d_al88,
780 convert_texsubimage3d_rgb332,
781 convert_texsubimage3d_ci8, /* These are all the same... */
782 convert_texsubimage3d_ci8,
783 convert_texsubimage3d_ci8,
784 convert_texsubimage3d_ci8,
785 convert_texsubimage3d_ycbcr,
786 convert_texsubimage3d_ycbcr_rev,
787 };
788
789
790 /* See if we need to care about the pixel store attributes when we're
791 * converting the texture image. This should be stored as
792 * unpacking->_SomeBoolean and updated when the values change, to avoid
793 * testing every time...
794 */
795 static INLINE GLboolean
796 convert_needs_unpacking( const struct gl_pixelstore_attrib *unpacking,
797 GLenum format, GLenum type )
798 {
799 if ( ( unpacking->Alignment == 1 ||
800 ( unpacking->Alignment == 4 && /* Pick up the common Q3A case... */
801 format == GL_RGBA && type == GL_UNSIGNED_BYTE ) ) &&
802 unpacking->RowLength == 0 &&
803 unpacking->SkipPixels == 0 &&
804 unpacking->SkipRows == 0 &&
805 unpacking->ImageHeight == 0 &&
806 unpacking->SkipImages == 0 &&
807 unpacking->SwapBytes == GL_FALSE &&
808 unpacking->LsbFirst == GL_FALSE ) {
809 return GL_FALSE;
810 } else {
811 return GL_TRUE;
812 }
813 }
814
815
816 GLboolean
817 _mesa_convert_texsubimage1d( GLint mesaFormat,
818 GLint xoffset,
819 GLint width,
820 GLenum format, GLenum type,
821 const struct gl_pixelstore_attrib *unpacking,
822 const GLvoid *srcImage, GLvoid *dstImage )
823 {
824 struct convert_info convert;
825
826 ASSERT( unpacking );
827 ASSERT( srcImage );
828 ASSERT( dstImage );
829
830 ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 );
831 ASSERT( mesaFormat <= MESA_FORMAT_YCBCR_REV );
832
833 /* Make it easier to pass all the parameters around.
834 */
835 convert.xoffset = xoffset;
836 convert.yoffset = 0;
837 convert.width = width;
838 convert.height = 1;
839 convert.format = format;
840 convert.type = type;
841 convert.unpacking = unpacking;
842 convert.srcImage = srcImage;
843 convert.dstImage = dstImage;
844
845 convert.index = 0;
846
847 if ( convert_needs_unpacking( unpacking, format, type ) )
848 convert.index |= CONVERT_UNPACKING_BIT;
849
850 ASSERT(convert.index < 4);
851
852 return convert_texsubimage2d_tab[mesaFormat]( &convert );
853 }
854
855
856 /* Convert a user's 2D image into a texture image. This basically
857 * repacks pixel data into the special texture formats used by core Mesa
858 * and the DRI drivers. This function can do full images or subimages.
859 *
860 * We return a boolean because this function may not accept some kinds
861 * of source image formats and/or types. For example, if the incoming
862 * format/type = GL_BGR, GL_UNSIGNED_INT this function probably won't
863 * be able to do the conversion.
864 *
865 * In that case, the incoming image should first be simplified to one of
866 * the "canonical" formats (GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA,
867 * GL_INTENSITY, GL_RGB, GL_RGBA) and types (GL_CHAN). We can do that
868 * with the _mesa_transfer_teximage() function. That function will also
869 * do image transfer operations such as scale/bias and convolution.
870 *
871 * Input:
872 * mesaFormat - one of the MESA_FORMAT_* values from texformat.h
873 * xoffset, yoffset - position in dest image to put data
874 * width, height - incoming image size, also size of dest region.
875 * dstImageWidth - width (row stride) of dest image in pixels
876 * format, type - incoming image format and type
877 * unpacking - describes incoming image unpacking
878 * srcImage - pointer to source image
879 * destImage - pointer to dest image
880 */
881 GLboolean
882 _mesa_convert_texsubimage2d( GLint mesaFormat, /* dest */
883 GLint xoffset, GLint yoffset,
884 GLint width, GLint height,
885 GLint destImageWidth,
886 GLenum format, GLenum type, /* source */
887 const struct gl_pixelstore_attrib *unpacking,
888 const GLvoid *srcImage, GLvoid *dstImage )
889 {
890 struct convert_info convert;
891
892 ASSERT( unpacking );
893 ASSERT( srcImage );
894 ASSERT( dstImage );
895
896 ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 );
897 ASSERT( mesaFormat <= MESA_FORMAT_YCBCR_REV );
898
899 /* Make it easier to pass all the parameters around.
900 */
901 convert.xoffset = xoffset;
902 convert.yoffset = yoffset;
903 convert.width = width;
904 convert.height = height;
905 convert.dstImageWidth = destImageWidth;
906 convert.format = format;
907 convert.type = type;
908 convert.unpacking = unpacking;
909 convert.srcImage = srcImage;
910 convert.dstImage = dstImage;
911
912 convert.index = 0;
913
914 if ( convert_needs_unpacking( unpacking, format, type ) )
915 convert.index |= CONVERT_UNPACKING_BIT;
916
917 if ( width != destImageWidth )
918 convert.index |= CONVERT_STRIDE_BIT;
919
920 return convert_texsubimage2d_tab[mesaFormat]( &convert );
921 }
922
923 GLboolean
924 _mesa_convert_texsubimage3d( GLint mesaFormat, /* dest */
925 GLint xoffset, GLint yoffset, GLint zoffset,
926 GLint width, GLint height, GLint depth,
927 GLint dstImageWidth, GLint dstImageHeight,
928 GLenum format, GLenum type, /* source */
929 const struct gl_pixelstore_attrib *unpacking,
930 const GLvoid *srcImage, GLvoid *dstImage )
931 {
932 struct convert_info convert;
933
934 ASSERT( unpacking );
935 ASSERT( srcImage );
936 ASSERT( dstImage );
937
938 ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 );
939 ASSERT( mesaFormat <= MESA_FORMAT_YCBCR_REV );
940
941 /* Make it easier to pass all the parameters around.
942 */
943 convert.xoffset = xoffset;
944 convert.yoffset = yoffset;
945 convert.zoffset = zoffset;
946 convert.width = width;
947 convert.height = height;
948 convert.depth = depth;
949 convert.dstImageWidth = dstImageWidth;
950 convert.dstImageHeight = dstImageHeight;
951 convert.format = format;
952 convert.type = type;
953 convert.unpacking = unpacking;
954 convert.srcImage = srcImage;
955 convert.dstImage = dstImage;
956
957 convert.index = 0;
958
959 if ( convert_needs_unpacking( unpacking, format, type ) )
960 convert.index |= CONVERT_UNPACKING_BIT;
961
962 if ( width != dstImageWidth || height != dstImageHeight )
963 convert.index |= CONVERT_STRIDE_BIT;
964
965 return convert_texsubimage3d_tab[mesaFormat]( &convert );
966 }
967
968
969
970 /* Nearest filtering only (for broken hardware that can't support
971 * all aspect ratios). This can be made a lot faster, but I don't
972 * really care enough...
973 */
974 void _mesa_rescale_teximage2d( GLuint bytesPerPixel, GLuint dstRowStride,
975 GLint srcWidth, GLint srcHeight,
976 GLint dstWidth, GLint dstHeight,
977 const GLvoid *srcImage, GLvoid *dstImage )
978 {
979 GLint row, col;
980
981 #define INNER_LOOP( TYPE, HOP, WOP ) \
982 for ( row = 0 ; row < dstHeight ; row++ ) { \
983 GLint srcRow = row HOP hScale; \
984 for ( col = 0 ; col < dstWidth ; col++ ) { \
985 GLint srcCol = col WOP wScale; \
986 dst[col] = src[srcRow * srcWidth + srcCol]; \
987 } \
988 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
989 } \
990
991 #define RESCALE_IMAGE( TYPE ) \
992 do { \
993 const TYPE *src = (const TYPE *)srcImage; \
994 TYPE *dst = (TYPE *)dstImage; \
995 \
996 if ( srcHeight <= dstHeight ) { \
997 const GLint hScale = dstHeight / srcHeight; \
998 if ( srcWidth <= dstWidth ) { \
999 const GLint wScale = dstWidth / srcWidth; \
1000 INNER_LOOP( TYPE, /, / ); \
1001 } \
1002 else { \
1003 const GLint wScale = srcWidth / dstWidth; \
1004 INNER_LOOP( TYPE, /, * ); \
1005 } \
1006 } \
1007 else { \
1008 const GLint hScale = srcHeight / dstHeight; \
1009 if ( srcWidth <= dstWidth ) { \
1010 const GLint wScale = dstWidth / srcWidth; \
1011 INNER_LOOP( TYPE, *, / ); \
1012 } \
1013 else { \
1014 const GLint wScale = srcWidth / dstWidth; \
1015 INNER_LOOP( TYPE, *, * ); \
1016 } \
1017 } \
1018 } while (0)
1019
1020 switch ( bytesPerPixel ) {
1021 case 4:
1022 RESCALE_IMAGE( GLuint );
1023 break;
1024
1025 case 2:
1026 RESCALE_IMAGE( GLushort );
1027 break;
1028
1029 case 1:
1030 RESCALE_IMAGE( GLubyte );
1031 break;
1032 default:
1033 _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
1034 }
1035 }