Convert SDL_malloc to SDL_calloc if appropriate, slightly faster on operating systems which map the zero page for memory allocations.
OpenGL renderer in progress
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "SDL_config.h"
24 /* This is the software implementation of the YUV texture support */
26 /* This code was derived from code carrying the following copyright notices:
28 * Copyright (c) 1995 The Regents of the University of California.
29 * All rights reserved.
31 * Permission to use, copy, modify, and distribute this software and its
32 * documentation for any purpose, without fee, and without written agreement is
33 * hereby granted, provided that the above copyright notice and the following
34 * two paragraphs appear in all copies of this software.
36 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
37 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
38 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
39 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
42 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
43 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
44 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
45 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
47 * Copyright (c) 1995 Erik Corry
48 * All rights reserved.
50 * Permission to use, copy, modify, and distribute this software and its
51 * documentation for any purpose, without fee, and without written agreement is
52 * hereby granted, provided that the above copyright notice and the following
53 * two paragraphs appear in all copies of this software.
55 * IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
56 * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
57 * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED
58 * OF THE POSSIBILITY OF SUCH DAMAGE.
60 * ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
61 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
62 * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
63 * BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
64 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
66 * Portions of this software Copyright (c) 1995 Brown University.
67 * All rights reserved.
69 * Permission to use, copy, modify, and distribute this software and its
70 * documentation for any purpose, without fee, and without written agreement
71 * is hereby granted, provided that the above copyright notice and the
72 * following two paragraphs appear in all copies of this software.
74 * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
75 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
76 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
77 * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
79 * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
80 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
81 * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
82 * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
83 * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
86 #include "SDL_video.h"
87 #include "SDL_cpuinfo.h"
88 #include "SDL_stretch_c.h"
89 #include "SDL_yuv_sw_c.h"
92 struct SDL_SW_YUVTexture
100 void (*Display1X) (int *colortab, Uint32 * rgb_2_pix,
101 unsigned char *lum, unsigned char *cr,
102 unsigned char *cb, unsigned char *out,
103 int rows, int cols, int mod);
104 void (*Display2X) (int *colortab, Uint32 * rgb_2_pix,
105 unsigned char *lum, unsigned char *cr,
106 unsigned char *cb, unsigned char *out,
107 int rows, int cols, int mod);
109 /* These are just so we don't have to allocate them separately */
113 /* This is a temporary surface in case we have to stretch copy */
114 SDL_Surface *stretch;
115 SDL_Surface *display;
118 /* The colorspace conversion functions */
120 #if 0 /*defined(__GNUC__) && defined(__i386__) && SDL_ASSEMBLY_ROUTINES */
121 extern void Color565DitherYV12MMX1X(int *colortab, Uint32 * rgb_2_pix,
122 unsigned char *lum, unsigned char *cr,
123 unsigned char *cb, unsigned char *out,
124 int rows, int cols, int mod);
125 extern void ColorRGBDitherYV12MMX1X(int *colortab, Uint32 * rgb_2_pix,
126 unsigned char *lum, unsigned char *cr,
127 unsigned char *cb, unsigned char *out,
128 int rows, int cols, int mod);
132 Color16DitherYV12Mod1X(int *colortab, Uint32 * rgb_2_pix,
133 unsigned char *lum, unsigned char *cr,
134 unsigned char *cb, unsigned char *out,
135 int rows, int cols, int mod)
137 unsigned short *row1;
138 unsigned short *row2;
144 int cols_2 = cols / 2;
146 row1 = (unsigned short *) out;
147 row2 = row1 + cols + mod;
158 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
159 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
160 + colortab[*cb + 2 * 256];
161 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
166 *row1++ = (unsigned short) (rgb_2_pix[L + cr_r] |
167 rgb_2_pix[L + crb_g] |
168 rgb_2_pix[L + cb_b]);
171 *row1++ = (unsigned short) (rgb_2_pix[L + cr_r] |
172 rgb_2_pix[L + crb_g] |
173 rgb_2_pix[L + cb_b]);
176 /* Now, do second row. */
179 *row2++ = (unsigned short) (rgb_2_pix[L + cr_r] |
180 rgb_2_pix[L + crb_g] |
181 rgb_2_pix[L + cb_b]);
184 *row2++ = (unsigned short) (rgb_2_pix[L + cr_r] |
185 rgb_2_pix[L + crb_g] |
186 rgb_2_pix[L + cb_b]);
190 * These values are at the start of the next line, (due
191 * to the ++'s above),but they need to be at the start
192 * of the line after that.
202 Color24DitherYV12Mod1X(int *colortab, Uint32 * rgb_2_pix,
203 unsigned char *lum, unsigned char *cr,
204 unsigned char *cb, unsigned char *out,
205 int rows, int cols, int mod)
215 int cols_2 = cols / 2;
218 row2 = row1 + cols * 3 + mod * 3;
230 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
231 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
232 + colortab[*cb + 2 * 256];
233 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
238 value = (rgb_2_pix[L + cr_r] |
239 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
240 *row1++ = (value) & 0xFF;
241 *row1++ = (value >> 8) & 0xFF;
242 *row1++ = (value >> 16) & 0xFF;
245 value = (rgb_2_pix[L + cr_r] |
246 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
247 *row1++ = (value) & 0xFF;
248 *row1++ = (value >> 8) & 0xFF;
249 *row1++ = (value >> 16) & 0xFF;
252 /* Now, do second row. */
255 value = (rgb_2_pix[L + cr_r] |
256 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
257 *row2++ = (value) & 0xFF;
258 *row2++ = (value >> 8) & 0xFF;
259 *row2++ = (value >> 16) & 0xFF;
262 value = (rgb_2_pix[L + cr_r] |
263 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
264 *row2++ = (value) & 0xFF;
265 *row2++ = (value >> 8) & 0xFF;
266 *row2++ = (value >> 16) & 0xFF;
270 * These values are at the start of the next line, (due
271 * to the ++'s above),but they need to be at the start
272 * of the line after that.
282 Color32DitherYV12Mod1X(int *colortab, Uint32 * rgb_2_pix,
283 unsigned char *lum, unsigned char *cr,
284 unsigned char *cb, unsigned char *out,
285 int rows, int cols, int mod)
294 int cols_2 = cols / 2;
296 row1 = (unsigned int *) out;
297 row2 = row1 + cols + mod;
308 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
309 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
310 + colortab[*cb + 2 * 256];
311 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
316 *row1++ = (rgb_2_pix[L + cr_r] |
317 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
320 *row1++ = (rgb_2_pix[L + cr_r] |
321 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
324 /* Now, do second row. */
327 *row2++ = (rgb_2_pix[L + cr_r] |
328 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
331 *row2++ = (rgb_2_pix[L + cr_r] |
332 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
336 * These values are at the start of the next line, (due
337 * to the ++'s above),but they need to be at the start
338 * of the line after that.
348 * In this function I make use of a nasty trick. The tables have the lower
349 * 16 bits replicated in the upper 16. This means I can write ints and get
350 * the horisontal doubling for free (almost).
353 Color16DitherYV12Mod2X(int *colortab, Uint32 * rgb_2_pix,
354 unsigned char *lum, unsigned char *cr,
355 unsigned char *cb, unsigned char *out,
356 int rows, int cols, int mod)
358 unsigned int *row1 = (unsigned int *) out;
359 const int next_row = cols + (mod / 2);
360 unsigned int *row2 = row1 + 2 * next_row;
366 int cols_2 = cols / 2;
370 mod = (next_row * 3) + (mod / 2);
378 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
379 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
380 + colortab[*cb + 2 * 256];
381 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
386 row1[0] = row1[next_row] = (rgb_2_pix[L + cr_r] |
387 rgb_2_pix[L + crb_g] |
388 rgb_2_pix[L + cb_b]);
392 row1[0] = row1[next_row] = (rgb_2_pix[L + cr_r] |
393 rgb_2_pix[L + crb_g] |
394 rgb_2_pix[L + cb_b]);
398 /* Now, do second row. */
401 row2[0] = row2[next_row] = (rgb_2_pix[L + cr_r] |
402 rgb_2_pix[L + crb_g] |
403 rgb_2_pix[L + cb_b]);
407 row2[0] = row2[next_row] = (rgb_2_pix[L + cr_r] |
408 rgb_2_pix[L + crb_g] |
409 rgb_2_pix[L + cb_b]);
414 * These values are at the start of the next line, (due
415 * to the ++'s above),but they need to be at the start
416 * of the line after that.
426 Color24DitherYV12Mod2X(int *colortab, Uint32 * rgb_2_pix,
427 unsigned char *lum, unsigned char *cr,
428 unsigned char *cb, unsigned char *out,
429 int rows, int cols, int mod)
432 unsigned char *row1 = out;
433 const int next_row = (cols * 2 + mod) * 3;
434 unsigned char *row2 = row1 + 2 * next_row;
440 int cols_2 = cols / 2;
444 mod = next_row * 3 + mod * 3;
452 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
453 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
454 + colortab[*cb + 2 * 256];
455 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
460 value = (rgb_2_pix[L + cr_r] |
461 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
462 row1[0 + 0] = row1[3 + 0] = row1[next_row + 0] =
463 row1[next_row + 3 + 0] = (value) & 0xFF;
464 row1[0 + 1] = row1[3 + 1] = row1[next_row + 1] =
465 row1[next_row + 3 + 1] = (value >> 8) & 0xFF;
466 row1[0 + 2] = row1[3 + 2] = row1[next_row + 2] =
467 row1[next_row + 3 + 2] = (value >> 16) & 0xFF;
471 value = (rgb_2_pix[L + cr_r] |
472 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
473 row1[0 + 0] = row1[3 + 0] = row1[next_row + 0] =
474 row1[next_row + 3 + 0] = (value) & 0xFF;
475 row1[0 + 1] = row1[3 + 1] = row1[next_row + 1] =
476 row1[next_row + 3 + 1] = (value >> 8) & 0xFF;
477 row1[0 + 2] = row1[3 + 2] = row1[next_row + 2] =
478 row1[next_row + 3 + 2] = (value >> 16) & 0xFF;
482 /* Now, do second row. */
485 value = (rgb_2_pix[L + cr_r] |
486 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
487 row2[0 + 0] = row2[3 + 0] = row2[next_row + 0] =
488 row2[next_row + 3 + 0] = (value) & 0xFF;
489 row2[0 + 1] = row2[3 + 1] = row2[next_row + 1] =
490 row2[next_row + 3 + 1] = (value >> 8) & 0xFF;
491 row2[0 + 2] = row2[3 + 2] = row2[next_row + 2] =
492 row2[next_row + 3 + 2] = (value >> 16) & 0xFF;
496 value = (rgb_2_pix[L + cr_r] |
497 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
498 row2[0 + 0] = row2[3 + 0] = row2[next_row + 0] =
499 row2[next_row + 3 + 0] = (value) & 0xFF;
500 row2[0 + 1] = row2[3 + 1] = row2[next_row + 1] =
501 row2[next_row + 3 + 1] = (value >> 8) & 0xFF;
502 row2[0 + 2] = row2[3 + 2] = row2[next_row + 2] =
503 row2[next_row + 3 + 2] = (value >> 16) & 0xFF;
508 * These values are at the start of the next line, (due
509 * to the ++'s above),but they need to be at the start
510 * of the line after that.
520 Color32DitherYV12Mod2X(int *colortab, Uint32 * rgb_2_pix,
521 unsigned char *lum, unsigned char *cr,
522 unsigned char *cb, unsigned char *out,
523 int rows, int cols, int mod)
525 unsigned int *row1 = (unsigned int *) out;
526 const int next_row = cols * 2 + mod;
527 unsigned int *row2 = row1 + 2 * next_row;
533 int cols_2 = cols / 2;
537 mod = (next_row * 3) + mod;
545 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
546 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
547 + colortab[*cb + 2 * 256];
548 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
553 row1[0] = row1[1] = row1[next_row] = row1[next_row + 1] =
554 (rgb_2_pix[L + cr_r] |
555 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
559 row1[0] = row1[1] = row1[next_row] = row1[next_row + 1] =
560 (rgb_2_pix[L + cr_r] |
561 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
565 /* Now, do second row. */
568 row2[0] = row2[1] = row2[next_row] = row2[next_row + 1] =
569 (rgb_2_pix[L + cr_r] |
570 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
574 row2[0] = row2[1] = row2[next_row] = row2[next_row + 1] =
575 (rgb_2_pix[L + cr_r] |
576 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
581 * These values are at the start of the next line, (due
582 * to the ++'s above),but they need to be at the start
583 * of the line after that.
593 Color16DitherYUY2Mod1X(int *colortab, Uint32 * rgb_2_pix,
594 unsigned char *lum, unsigned char *cr,
595 unsigned char *cb, unsigned char *out,
596 int rows, int cols, int mod)
603 int cols_2 = cols / 2;
605 row = (unsigned short *) out;
613 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
614 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
615 + colortab[*cb + 2 * 256];
616 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
622 *row++ = (unsigned short) (rgb_2_pix[L + cr_r] |
623 rgb_2_pix[L + crb_g] |
624 rgb_2_pix[L + cb_b]);
628 *row++ = (unsigned short) (rgb_2_pix[L + cr_r] |
629 rgb_2_pix[L + crb_g] |
630 rgb_2_pix[L + cb_b]);
639 Color24DitherYUY2Mod1X(int *colortab, Uint32 * rgb_2_pix,
640 unsigned char *lum, unsigned char *cr,
641 unsigned char *cb, unsigned char *out,
642 int rows, int cols, int mod)
650 int cols_2 = cols / 2;
652 row = (unsigned char *) out;
660 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
661 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
662 + colortab[*cb + 2 * 256];
663 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
669 value = (rgb_2_pix[L + cr_r] |
670 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
671 *row++ = (value) & 0xFF;
672 *row++ = (value >> 8) & 0xFF;
673 *row++ = (value >> 16) & 0xFF;
677 value = (rgb_2_pix[L + cr_r] |
678 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
679 *row++ = (value) & 0xFF;
680 *row++ = (value >> 8) & 0xFF;
681 *row++ = (value >> 16) & 0xFF;
689 Color32DitherYUY2Mod1X(int *colortab, Uint32 * rgb_2_pix,
690 unsigned char *lum, unsigned char *cr,
691 unsigned char *cb, unsigned char *out,
692 int rows, int cols, int mod)
699 int cols_2 = cols / 2;
701 row = (unsigned int *) out;
708 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
709 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
710 + colortab[*cb + 2 * 256];
711 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
717 *row++ = (rgb_2_pix[L + cr_r] |
718 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
722 *row++ = (rgb_2_pix[L + cr_r] |
723 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
732 * In this function I make use of a nasty trick. The tables have the lower
733 * 16 bits replicated in the upper 16. This means I can write ints and get
734 * the horisontal doubling for free (almost).
737 Color16DitherYUY2Mod2X(int *colortab, Uint32 * rgb_2_pix,
738 unsigned char *lum, unsigned char *cr,
739 unsigned char *cb, unsigned char *out,
740 int rows, int cols, int mod)
742 unsigned int *row = (unsigned int *) out;
743 const int next_row = cols + (mod / 2);
748 int cols_2 = cols / 2;
756 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
757 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
758 + colortab[*cb + 2 * 256];
759 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
765 row[0] = row[next_row] = (rgb_2_pix[L + cr_r] |
766 rgb_2_pix[L + crb_g] |
767 rgb_2_pix[L + cb_b]);
772 row[0] = row[next_row] = (rgb_2_pix[L + cr_r] |
773 rgb_2_pix[L + crb_g] |
774 rgb_2_pix[L + cb_b]);
783 Color24DitherYUY2Mod2X(int *colortab, Uint32 * rgb_2_pix,
784 unsigned char *lum, unsigned char *cr,
785 unsigned char *cb, unsigned char *out,
786 int rows, int cols, int mod)
789 unsigned char *row = out;
790 const int next_row = (cols * 2 + mod) * 3;
795 int cols_2 = cols / 2;
802 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
803 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
804 + colortab[*cb + 2 * 256];
805 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
811 value = (rgb_2_pix[L + cr_r] |
812 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
813 row[0 + 0] = row[3 + 0] = row[next_row + 0] =
814 row[next_row + 3 + 0] = (value) & 0xFF;
815 row[0 + 1] = row[3 + 1] = row[next_row + 1] =
816 row[next_row + 3 + 1] = (value >> 8) & 0xFF;
817 row[0 + 2] = row[3 + 2] = row[next_row + 2] =
818 row[next_row + 3 + 2] = (value >> 16) & 0xFF;
823 value = (rgb_2_pix[L + cr_r] |
824 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
825 row[0 + 0] = row[3 + 0] = row[next_row + 0] =
826 row[next_row + 3 + 0] = (value) & 0xFF;
827 row[0 + 1] = row[3 + 1] = row[next_row + 1] =
828 row[next_row + 3 + 1] = (value >> 8) & 0xFF;
829 row[0 + 2] = row[3 + 2] = row[next_row + 2] =
830 row[next_row + 3 + 2] = (value >> 16) & 0xFF;
839 Color32DitherYUY2Mod2X(int *colortab, Uint32 * rgb_2_pix,
840 unsigned char *lum, unsigned char *cr,
841 unsigned char *cb, unsigned char *out,
842 int rows, int cols, int mod)
844 unsigned int *row = (unsigned int *) out;
845 const int next_row = cols * 2 + mod;
850 int cols_2 = cols / 2;
858 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
859 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
860 + colortab[*cb + 2 * 256];
861 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
867 row[0] = row[1] = row[next_row] = row[next_row + 1] =
868 (rgb_2_pix[L + cr_r] |
869 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
874 row[0] = row[1] = row[next_row] = row[next_row + 1] =
875 (rgb_2_pix[L + cr_r] |
876 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
887 * How many 1 bits are there in the Uint32.
888 * Low performance, do not call often.
891 number_of_bits_set(Uint32 a)
896 return 1 + number_of_bits_set(a >> 1);
897 return (number_of_bits_set(a >> 1));
901 * How many 0 bits are there at least significant end of Uint32.
902 * Low performance, do not call often.
905 free_bits_at_bottom(Uint32 a)
907 /* assume char is 8 bits */
909 return sizeof(Uint32) * 8;
910 if (((Sint32) a) & 1l)
912 return 1 + free_bits_at_bottom(a >> 1);
916 SDL_SW_SetupYUVDisplay(SDL_SW_YUVTexture * swdata, Uint32 target_format)
918 Uint32 *r_2_pix_alloc;
919 Uint32 *g_2_pix_alloc;
920 Uint32 *b_2_pix_alloc;
923 Uint32 Rmask, Gmask, Bmask, Amask;
925 if (!SDL_PixelFormatEnumToMasks
926 (target_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask) || bpp < 15) {
927 SDL_SetError("Unsupported YUV destination format");
931 swdata->target_format = target_format;
932 r_2_pix_alloc = &swdata->rgb_2_pix[0 * 768];
933 g_2_pix_alloc = &swdata->rgb_2_pix[1 * 768];
934 b_2_pix_alloc = &swdata->rgb_2_pix[2 * 768];
937 * Set up entries 0-255 in rgb-to-pixel value tables.
939 for (i = 0; i < 256; ++i) {
940 r_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Rmask));
941 r_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Rmask);
942 g_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Gmask));
943 g_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Gmask);
944 b_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Bmask));
945 b_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Bmask);
949 * If we have 16-bit output depth, then we double the value
950 * in the top word. This means that we can write out both
951 * pixels in the pixel doubling mode with one op. It is
952 * harmless in the normal case as storing a 32-bit value
953 * through a short pointer will lose the top bits anyway.
955 if (SDL_BYTESPERPIXEL(target_format) == 2) {
956 for (i = 0; i < 256; ++i) {
957 r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16;
958 g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16;
959 b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 16;
964 * Spread out the values we have to the rest of the array so that
965 * we do not need to check for overflow.
967 for (i = 0; i < 256; ++i) {
968 r_2_pix_alloc[i] = r_2_pix_alloc[256];
969 r_2_pix_alloc[i + 512] = r_2_pix_alloc[511];
970 g_2_pix_alloc[i] = g_2_pix_alloc[256];
971 g_2_pix_alloc[i + 512] = g_2_pix_alloc[511];
972 b_2_pix_alloc[i] = b_2_pix_alloc[256];
973 b_2_pix_alloc[i + 512] = b_2_pix_alloc[511];
976 /* You have chosen wisely... */
977 switch (swdata->texture->format) {
978 case SDL_PixelFormat_YV12:
979 case SDL_PixelFormat_IYUV:
980 if (SDL_BYTESPERPIXEL(target_format) == 2) {
981 #if 0 /*defined(__GNUC__) && defined(__i386__) && SDL_ASSEMBLY_ROUTINES */
982 /* inline assembly functions */
983 if (SDL_HasMMX() && (Rmask == 0xF800) &&
984 (Gmask == 0x07E0) && (Bmask == 0x001F) && (width & 15) == 0) {
985 /*printf("Using MMX 16-bit 565 dither\n");*/
986 swdata->Display1X = Color565DitherYV12MMX1X;
988 /*printf("Using C 16-bit dither\n");*/
989 swdata->Display1X = Color16DitherYV12Mod1X;
992 swdata->Display1X = Color16DitherYV12Mod1X;
994 swdata->Display2X = Color16DitherYV12Mod2X;
996 if (SDL_BYTESPERPIXEL(target_format) == 3) {
997 swdata->Display1X = Color24DitherYV12Mod1X;
998 swdata->Display2X = Color24DitherYV12Mod2X;
1000 if (SDL_BYTESPERPIXEL(target_format) == 4) {
1001 #if 0 /*defined(__GNUC__) && defined(__i386__) && SDL_ASSEMBLY_ROUTINES */
1002 /* inline assembly functions */
1003 if (SDL_HasMMX() && (Rmask == 0x00FF0000) &&
1004 (Gmask == 0x0000FF00) &&
1005 (Bmask == 0x000000FF) && (width & 15) == 0) {
1006 /*printf("Using MMX 32-bit dither\n");*/
1007 swdata->Display1X = ColorRGBDitherYV12MMX1X;
1009 /*printf("Using C 32-bit dither\n");*/
1010 swdata->Display1X = Color32DitherYV12Mod1X;
1013 swdata->Display1X = Color32DitherYV12Mod1X;
1015 swdata->Display2X = Color32DitherYV12Mod2X;
1018 case SDL_PixelFormat_YUY2:
1019 case SDL_PixelFormat_UYVY:
1020 case SDL_PixelFormat_YVYU:
1021 if (SDL_BYTESPERPIXEL(target_format) == 2) {
1022 swdata->Display1X = Color16DitherYUY2Mod1X;
1023 swdata->Display2X = Color16DitherYUY2Mod2X;
1025 if (SDL_BYTESPERPIXEL(target_format) == 3) {
1026 swdata->Display1X = Color24DitherYUY2Mod1X;
1027 swdata->Display2X = Color24DitherYUY2Mod2X;
1029 if (SDL_BYTESPERPIXEL(target_format) == 4) {
1030 swdata->Display1X = Color32DitherYUY2Mod1X;
1031 swdata->Display2X = Color32DitherYUY2Mod2X;
1035 /* We should never get here (caught above) */
1039 if (swdata->display) {
1040 SDL_FreeSurface(swdata->display);
1041 swdata->display = NULL;
1047 SDL_SW_CreateYUVTexture(SDL_Texture * texture)
1049 SDL_SW_YUVTexture *swdata;
1057 swdata = (SDL_SW_YUVTexture *) SDL_calloc(1, sizeof(*swdata));
1063 switch (texture->format) {
1064 case SDL_PixelFormat_YV12:
1065 case SDL_PixelFormat_IYUV:
1066 case SDL_PixelFormat_YUY2:
1067 case SDL_PixelFormat_UYVY:
1068 case SDL_PixelFormat_YVYU:
1071 SDL_SetError("Unsupported YUV format");
1075 swdata->texture = texture;
1076 swdata->target_format = SDL_PixelFormat_Unknown;
1077 swdata->pixels = (Uint8 *) SDL_malloc(texture->w * texture->h * 2);
1078 swdata->colortab = (int *) SDL_malloc(4 * 256 * sizeof(int));
1079 swdata->rgb_2_pix = (Uint32 *) SDL_malloc(3 * 768 * sizeof(Uint32));
1080 if (!swdata->pixels || !swdata->colortab || !swdata->rgb_2_pix) {
1082 SDL_SW_DestroyYUVTexture(swdata);
1086 /* Generate the tables for the display surface */
1087 Cr_r_tab = &swdata->colortab[0 * 256];
1088 Cr_g_tab = &swdata->colortab[1 * 256];
1089 Cb_g_tab = &swdata->colortab[2 * 256];
1090 Cb_b_tab = &swdata->colortab[3 * 256];
1091 for (i = 0; i < 256; i++) {
1092 /* Gamma correction (luminescence table) and chroma correction
1093 would be done here. See the Berkeley mpeg_play sources.
1095 CB = CR = (i - 128);
1096 Cr_r_tab[i] = (int) ((0.419 / 0.299) * CR);
1097 Cr_g_tab[i] = (int) (-(0.299 / 0.419) * CR);
1098 Cb_g_tab[i] = (int) (-(0.114 / 0.331) * CB);
1099 Cb_b_tab[i] = (int) ((0.587 / 0.331) * CB);
1102 /* Find the pitch and offset values for the overlay */
1103 switch (texture->format) {
1104 case SDL_PixelFormat_YV12:
1105 case SDL_PixelFormat_IYUV:
1106 swdata->pitches[0] = texture->w;
1107 swdata->pitches[1] = swdata->pitches[0] / 2;
1108 swdata->pitches[2] = swdata->pitches[0] / 2;
1109 swdata->planes[0] = swdata->pixels;
1111 swdata->planes[0] + swdata->pitches[0] * texture->h;
1113 swdata->planes[1] + swdata->pitches[1] * texture->h / 2;
1115 case SDL_PixelFormat_YUY2:
1116 case SDL_PixelFormat_UYVY:
1117 case SDL_PixelFormat_YVYU:
1118 swdata->pitches[0] = texture->w * 2;
1119 swdata->planes[0] = swdata->pixels;
1122 /* We should never get here (caught above) */
1126 /* We're all done.. */
1131 SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture * swdata, void **pixels,
1134 *pixels = swdata->planes[0];
1135 *pitch = swdata->pitches[0];
1140 SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
1141 const void *pixels, int pitch)
1143 SDL_Texture *texture = swdata->texture;
1145 switch (texture->format) {
1146 case SDL_PixelFormat_YV12:
1147 case SDL_PixelFormat_IYUV:
1149 && (rect->x != 0 || rect->y != 0 || rect->w != texture->w
1150 || rect->h != texture->h)) {
1152 ("YV12 and IYUV textures only support full surface updates");
1155 SDL_memcpy(swdata->pixels, pixels, texture->h * texture->w * 2);
1157 case SDL_PixelFormat_YUY2:
1158 case SDL_PixelFormat_UYVY:
1159 case SDL_PixelFormat_YVYU:
1165 src = (Uint8 *) pixels;
1167 swdata->planes[0] + rect->y * swdata->pitches[0] +
1169 length = rect->w * 2;
1170 for (row = 0; row < rect->h; ++row) {
1171 SDL_memcpy(dst, src, length);
1173 dst += swdata->pitches[0];
1182 SDL_SW_LockYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
1183 int markDirty, void **pixels, int *pitch)
1185 SDL_Texture *texture = swdata->texture;
1187 switch (texture->format) {
1188 case SDL_PixelFormat_YV12:
1189 case SDL_PixelFormat_IYUV:
1191 && (rect->x != 0 || rect->y != 0 || rect->w != texture->w
1192 || rect->h != texture->h)) {
1194 ("YV12 and IYUV textures only support full surface locks");
1200 *pixels = swdata->planes[0] + rect->y * swdata->pitches[0] + rect->x * 2;
1201 *pitch = swdata->pitches[0];
1206 SDL_SW_UnlockYUVTexture(SDL_SW_YUVTexture * swdata)
1211 SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture * swdata, const SDL_Rect * srcrect,
1212 Uint32 target_format, int w, int h, void *pixels,
1215 SDL_Texture *texture = swdata->texture;
1218 Uint8 *lum, *Cr, *Cb;
1221 /* Make sure we're set up to display in the desired format */
1222 if (target_format != swdata->target_format) {
1223 if (SDL_SW_SetupYUVDisplay(swdata, target_format) < 0) {
1230 if (srcrect->x || srcrect->y || srcrect->w < texture->w
1231 || srcrect->h < texture->h) {
1232 /* The source rectangle has been clipped.
1233 Using a scratch surface is easier than adding clipped
1234 source support to all the blitters, plus that would
1235 slow them down in the general unclipped case.
1238 } else if ((srcrect->w != w) || (srcrect->h != h)) {
1239 if ((w == 2 * srcrect->w) && (h == 2 * srcrect->h)) {
1247 Uint32 Rmask, Gmask, Bmask, Amask;
1249 if (swdata->display) {
1250 swdata->display->w = w;
1251 swdata->display->h = h;
1252 swdata->display->pixels = pixels;
1253 swdata->display->pitch = pitch;
1255 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
1256 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
1259 SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask,
1260 Gmask, Bmask, Amask);
1261 if (!swdata->display) {
1265 if (!swdata->stretch) {
1266 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
1267 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
1270 SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask,
1271 Gmask, Bmask, Amask);
1272 if (!swdata->stretch) {
1276 pixels = swdata->stretch->pixels;
1277 pitch = swdata->stretch->pitch;
1279 switch (texture->format) {
1280 case SDL_PixelFormat_YV12:
1281 lum = swdata->planes[0];
1282 Cr = swdata->planes[1];
1283 Cb = swdata->planes[2];
1285 case SDL_PixelFormat_IYUV:
1286 lum = swdata->planes[0];
1287 Cr = swdata->planes[2];
1288 Cb = swdata->planes[1];
1290 case SDL_PixelFormat_YUY2:
1291 lum = swdata->planes[0];
1295 case SDL_PixelFormat_UYVY:
1296 lum = swdata->planes[0] + 1;
1300 case SDL_PixelFormat_YVYU:
1301 lum = swdata->planes[0];
1306 SDL_SetError("Unsupported YUV format in copy");
1309 mod = (pitch / SDL_BYTESPERPIXEL(target_format));
1312 mod -= (texture->w * 2);
1313 swdata->Display2X(swdata->colortab, swdata->rgb_2_pix,
1314 lum, Cr, Cb, pixels, texture->h, texture->w, mod);
1317 swdata->Display1X(swdata->colortab, swdata->rgb_2_pix,
1318 lum, Cr, Cb, pixels, texture->h, texture->w, mod);
1321 SDL_Rect rect = *srcrect;
1322 SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL);
1328 SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture * swdata)
1331 if (swdata->pixels) {
1332 SDL_free(swdata->pixels);
1334 if (swdata->colortab) {
1335 SDL_free(swdata->colortab);
1337 if (swdata->rgb_2_pix) {
1338 SDL_free(swdata->rgb_2_pix);
1340 if (swdata->stretch) {
1341 SDL_FreeSurface(swdata->stretch);
1343 if (swdata->display) {
1344 SDL_FreeSurface(swdata->display);
1350 /* vi: set ts=4 sw=4 expandtab: */