2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
21 #include "../SDL_internal.h"
23 /* This is the software implementation of the YUV texture support */
25 /* This code was derived from code carrying the following copyright notices:
27 * Copyright (c) 1995 The Regents of the University of California.
28 * All rights reserved.
30 * Permission to use, copy, modify, and distribute this software and its
31 * documentation for any purpose, without fee, and without written agreement is
32 * hereby granted, provided that the above copyright notice and the following
33 * two paragraphs appear in all copies of this software.
35 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
36 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
37 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
38 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
41 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
42 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
43 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
44 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
46 * Copyright (c) 1995 Erik Corry
47 * All rights reserved.
49 * Permission to use, copy, modify, and distribute this software and its
50 * documentation for any purpose, without fee, and without written agreement is
51 * hereby granted, provided that the above copyright notice and the following
52 * two paragraphs appear in all copies of this software.
54 * IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
55 * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
56 * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED
57 * OF THE POSSIBILITY OF SUCH DAMAGE.
59 * ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
60 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
61 * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
62 * BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
63 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
65 * Portions of this software Copyright (c) 1995 Brown University.
66 * All rights reserved.
68 * Permission to use, copy, modify, and distribute this software and its
69 * documentation for any purpose, without fee, and without written agreement
70 * is hereby granted, provided that the above copyright notice and the
71 * following two paragraphs appear in all copies of this software.
73 * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
74 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
75 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
76 * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
78 * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
79 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
80 * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
81 * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
82 * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
85 #include "SDL_assert.h"
86 #include "SDL_video.h"
87 #include "SDL_cpuinfo.h"
88 #include "SDL_yuv_sw_c.h"
91 /* The colorspace conversion functions */
93 #if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES
94 extern void Color565DitherYV12MMX1X(int *colortab, Uint32 * rgb_2_pix,
95 unsigned char *lum, unsigned char *cr,
96 unsigned char *cb, unsigned char *out,
97 int rows, int cols, int mod);
98 extern void ColorRGBDitherYV12MMX1X(int *colortab, Uint32 * rgb_2_pix,
99 unsigned char *lum, unsigned char *cr,
100 unsigned char *cb, unsigned char *out,
101 int rows, int cols, int mod);
105 Color16DitherYV12Mod1X(int *colortab, Uint32 * rgb_2_pix,
106 unsigned char *lum, unsigned char *cr,
107 unsigned char *cb, unsigned char *out,
108 int rows, int cols, int mod)
110 unsigned short *row1;
111 unsigned short *row2;
117 int cols_2 = cols / 2;
119 row1 = (unsigned short *) out;
120 row2 = row1 + cols + mod;
131 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
132 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
133 + colortab[*cb + 2 * 256];
134 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
139 *row1++ = (unsigned short) (rgb_2_pix[L + cr_r] |
140 rgb_2_pix[L + crb_g] |
141 rgb_2_pix[L + cb_b]);
144 *row1++ = (unsigned short) (rgb_2_pix[L + cr_r] |
145 rgb_2_pix[L + crb_g] |
146 rgb_2_pix[L + cb_b]);
149 /* Now, do second row. */
152 *row2++ = (unsigned short) (rgb_2_pix[L + cr_r] |
153 rgb_2_pix[L + crb_g] |
154 rgb_2_pix[L + cb_b]);
157 *row2++ = (unsigned short) (rgb_2_pix[L + cr_r] |
158 rgb_2_pix[L + crb_g] |
159 rgb_2_pix[L + cb_b]);
163 * These values are at the start of the next line, (due
164 * to the ++'s above),but they need to be at the start
165 * of the line after that.
175 Color24DitherYV12Mod1X(int *colortab, Uint32 * rgb_2_pix,
176 unsigned char *lum, unsigned char *cr,
177 unsigned char *cb, unsigned char *out,
178 int rows, int cols, int mod)
188 int cols_2 = cols / 2;
191 row2 = row1 + cols * 3 + mod * 3;
203 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
204 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
205 + colortab[*cb + 2 * 256];
206 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
211 value = (rgb_2_pix[L + cr_r] |
212 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
213 *row1++ = (value) & 0xFF;
214 *row1++ = (value >> 8) & 0xFF;
215 *row1++ = (value >> 16) & 0xFF;
218 value = (rgb_2_pix[L + cr_r] |
219 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
220 *row1++ = (value) & 0xFF;
221 *row1++ = (value >> 8) & 0xFF;
222 *row1++ = (value >> 16) & 0xFF;
225 /* Now, do second row. */
228 value = (rgb_2_pix[L + cr_r] |
229 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
230 *row2++ = (value) & 0xFF;
231 *row2++ = (value >> 8) & 0xFF;
232 *row2++ = (value >> 16) & 0xFF;
235 value = (rgb_2_pix[L + cr_r] |
236 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
237 *row2++ = (value) & 0xFF;
238 *row2++ = (value >> 8) & 0xFF;
239 *row2++ = (value >> 16) & 0xFF;
243 * These values are at the start of the next line, (due
244 * to the ++'s above),but they need to be at the start
245 * of the line after that.
255 Color32DitherYV12Mod1X(int *colortab, Uint32 * rgb_2_pix,
256 unsigned char *lum, unsigned char *cr,
257 unsigned char *cb, unsigned char *out,
258 int rows, int cols, int mod)
267 int cols_2 = cols / 2;
269 row1 = (unsigned int *) out;
270 row2 = row1 + cols + mod;
281 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
282 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
283 + colortab[*cb + 2 * 256];
284 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
289 *row1++ = (rgb_2_pix[L + cr_r] |
290 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
293 *row1++ = (rgb_2_pix[L + cr_r] |
294 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
297 /* Now, do second row. */
300 *row2++ = (rgb_2_pix[L + cr_r] |
301 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
304 *row2++ = (rgb_2_pix[L + cr_r] |
305 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
309 * These values are at the start of the next line, (due
310 * to the ++'s above),but they need to be at the start
311 * of the line after that.
321 * In this function I make use of a nasty trick. The tables have the lower
322 * 16 bits replicated in the upper 16. This means I can write ints and get
323 * the horisontal doubling for free (almost).
326 Color16DitherYV12Mod2X(int *colortab, Uint32 * rgb_2_pix,
327 unsigned char *lum, unsigned char *cr,
328 unsigned char *cb, unsigned char *out,
329 int rows, int cols, int mod)
331 unsigned int *row1 = (unsigned int *) out;
332 const int next_row = cols + (mod / 2);
333 unsigned int *row2 = row1 + 2 * next_row;
339 int cols_2 = cols / 2;
343 mod = (next_row * 3) + (mod / 2);
351 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
352 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
353 + colortab[*cb + 2 * 256];
354 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
359 row1[0] = row1[next_row] = (rgb_2_pix[L + cr_r] |
360 rgb_2_pix[L + crb_g] |
361 rgb_2_pix[L + cb_b]);
365 row1[0] = row1[next_row] = (rgb_2_pix[L + cr_r] |
366 rgb_2_pix[L + crb_g] |
367 rgb_2_pix[L + cb_b]);
371 /* Now, do second row. */
374 row2[0] = row2[next_row] = (rgb_2_pix[L + cr_r] |
375 rgb_2_pix[L + crb_g] |
376 rgb_2_pix[L + cb_b]);
380 row2[0] = row2[next_row] = (rgb_2_pix[L + cr_r] |
381 rgb_2_pix[L + crb_g] |
382 rgb_2_pix[L + cb_b]);
387 * These values are at the start of the next line, (due
388 * to the ++'s above),but they need to be at the start
389 * of the line after that.
399 Color24DitherYV12Mod2X(int *colortab, Uint32 * rgb_2_pix,
400 unsigned char *lum, unsigned char *cr,
401 unsigned char *cb, unsigned char *out,
402 int rows, int cols, int mod)
405 unsigned char *row1 = out;
406 const int next_row = (cols * 2 + mod) * 3;
407 unsigned char *row2 = row1 + 2 * next_row;
413 int cols_2 = cols / 2;
417 mod = next_row * 3 + mod * 3;
425 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
426 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
427 + colortab[*cb + 2 * 256];
428 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
433 value = (rgb_2_pix[L + cr_r] |
434 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
435 row1[0 + 0] = row1[3 + 0] = row1[next_row + 0] =
436 row1[next_row + 3 + 0] = (value) & 0xFF;
437 row1[0 + 1] = row1[3 + 1] = row1[next_row + 1] =
438 row1[next_row + 3 + 1] = (value >> 8) & 0xFF;
439 row1[0 + 2] = row1[3 + 2] = row1[next_row + 2] =
440 row1[next_row + 3 + 2] = (value >> 16) & 0xFF;
444 value = (rgb_2_pix[L + cr_r] |
445 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
446 row1[0 + 0] = row1[3 + 0] = row1[next_row + 0] =
447 row1[next_row + 3 + 0] = (value) & 0xFF;
448 row1[0 + 1] = row1[3 + 1] = row1[next_row + 1] =
449 row1[next_row + 3 + 1] = (value >> 8) & 0xFF;
450 row1[0 + 2] = row1[3 + 2] = row1[next_row + 2] =
451 row1[next_row + 3 + 2] = (value >> 16) & 0xFF;
455 /* Now, do second row. */
458 value = (rgb_2_pix[L + cr_r] |
459 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
460 row2[0 + 0] = row2[3 + 0] = row2[next_row + 0] =
461 row2[next_row + 3 + 0] = (value) & 0xFF;
462 row2[0 + 1] = row2[3 + 1] = row2[next_row + 1] =
463 row2[next_row + 3 + 1] = (value >> 8) & 0xFF;
464 row2[0 + 2] = row2[3 + 2] = row2[next_row + 2] =
465 row2[next_row + 3 + 2] = (value >> 16) & 0xFF;
469 value = (rgb_2_pix[L + cr_r] |
470 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
471 row2[0 + 0] = row2[3 + 0] = row2[next_row + 0] =
472 row2[next_row + 3 + 0] = (value) & 0xFF;
473 row2[0 + 1] = row2[3 + 1] = row2[next_row + 1] =
474 row2[next_row + 3 + 1] = (value >> 8) & 0xFF;
475 row2[0 + 2] = row2[3 + 2] = row2[next_row + 2] =
476 row2[next_row + 3 + 2] = (value >> 16) & 0xFF;
481 * These values are at the start of the next line, (due
482 * to the ++'s above),but they need to be at the start
483 * of the line after that.
493 Color32DitherYV12Mod2X(int *colortab, Uint32 * rgb_2_pix,
494 unsigned char *lum, unsigned char *cr,
495 unsigned char *cb, unsigned char *out,
496 int rows, int cols, int mod)
498 unsigned int *row1 = (unsigned int *) out;
499 const int next_row = cols * 2 + mod;
500 unsigned int *row2 = row1 + 2 * next_row;
506 int cols_2 = cols / 2;
510 mod = (next_row * 3) + mod;
518 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
519 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
520 + colortab[*cb + 2 * 256];
521 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
526 row1[0] = row1[1] = row1[next_row] = row1[next_row + 1] =
527 (rgb_2_pix[L + cr_r] |
528 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
532 row1[0] = row1[1] = row1[next_row] = row1[next_row + 1] =
533 (rgb_2_pix[L + cr_r] |
534 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
538 /* Now, do second row. */
541 row2[0] = row2[1] = row2[next_row] = row2[next_row + 1] =
542 (rgb_2_pix[L + cr_r] |
543 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
547 row2[0] = row2[1] = row2[next_row] = row2[next_row + 1] =
548 (rgb_2_pix[L + cr_r] |
549 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
554 * These values are at the start of the next line, (due
555 * to the ++'s above),but they need to be at the start
556 * of the line after that.
566 Color16DitherYUY2Mod1X(int *colortab, Uint32 * rgb_2_pix,
567 unsigned char *lum, unsigned char *cr,
568 unsigned char *cb, unsigned char *out,
569 int rows, int cols, int mod)
576 int cols_2 = cols / 2;
578 row = (unsigned short *) out;
586 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
587 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
588 + colortab[*cb + 2 * 256];
589 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
595 *row++ = (unsigned short) (rgb_2_pix[L + cr_r] |
596 rgb_2_pix[L + crb_g] |
597 rgb_2_pix[L + cb_b]);
601 *row++ = (unsigned short) (rgb_2_pix[L + cr_r] |
602 rgb_2_pix[L + crb_g] |
603 rgb_2_pix[L + cb_b]);
612 Color24DitherYUY2Mod1X(int *colortab, Uint32 * rgb_2_pix,
613 unsigned char *lum, unsigned char *cr,
614 unsigned char *cb, unsigned char *out,
615 int rows, int cols, int mod)
623 int cols_2 = cols / 2;
625 row = (unsigned char *) out;
633 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
634 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
635 + colortab[*cb + 2 * 256];
636 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
642 value = (rgb_2_pix[L + cr_r] |
643 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
644 *row++ = (value) & 0xFF;
645 *row++ = (value >> 8) & 0xFF;
646 *row++ = (value >> 16) & 0xFF;
650 value = (rgb_2_pix[L + cr_r] |
651 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
652 *row++ = (value) & 0xFF;
653 *row++ = (value >> 8) & 0xFF;
654 *row++ = (value >> 16) & 0xFF;
662 Color32DitherYUY2Mod1X(int *colortab, Uint32 * rgb_2_pix,
663 unsigned char *lum, unsigned char *cr,
664 unsigned char *cb, unsigned char *out,
665 int rows, int cols, int mod)
672 int cols_2 = cols / 2;
674 row = (unsigned int *) out;
681 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
682 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
683 + colortab[*cb + 2 * 256];
684 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
690 *row++ = (rgb_2_pix[L + cr_r] |
691 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
695 *row++ = (rgb_2_pix[L + cr_r] |
696 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
705 * In this function I make use of a nasty trick. The tables have the lower
706 * 16 bits replicated in the upper 16. This means I can write ints and get
707 * the horisontal doubling for free (almost).
710 Color16DitherYUY2Mod2X(int *colortab, Uint32 * rgb_2_pix,
711 unsigned char *lum, unsigned char *cr,
712 unsigned char *cb, unsigned char *out,
713 int rows, int cols, int mod)
715 unsigned int *row = (unsigned int *) out;
716 const int next_row = cols + (mod / 2);
721 int cols_2 = cols / 2;
729 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
730 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
731 + colortab[*cb + 2 * 256];
732 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
738 row[0] = row[next_row] = (rgb_2_pix[L + cr_r] |
739 rgb_2_pix[L + crb_g] |
740 rgb_2_pix[L + cb_b]);
745 row[0] = row[next_row] = (rgb_2_pix[L + cr_r] |
746 rgb_2_pix[L + crb_g] |
747 rgb_2_pix[L + cb_b]);
756 Color24DitherYUY2Mod2X(int *colortab, Uint32 * rgb_2_pix,
757 unsigned char *lum, unsigned char *cr,
758 unsigned char *cb, unsigned char *out,
759 int rows, int cols, int mod)
762 unsigned char *row = out;
763 const int next_row = (cols * 2 + mod) * 3;
768 int cols_2 = cols / 2;
775 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
776 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
777 + colortab[*cb + 2 * 256];
778 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
784 value = (rgb_2_pix[L + cr_r] |
785 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
786 row[0 + 0] = row[3 + 0] = row[next_row + 0] =
787 row[next_row + 3 + 0] = (value) & 0xFF;
788 row[0 + 1] = row[3 + 1] = row[next_row + 1] =
789 row[next_row + 3 + 1] = (value >> 8) & 0xFF;
790 row[0 + 2] = row[3 + 2] = row[next_row + 2] =
791 row[next_row + 3 + 2] = (value >> 16) & 0xFF;
796 value = (rgb_2_pix[L + cr_r] |
797 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
798 row[0 + 0] = row[3 + 0] = row[next_row + 0] =
799 row[next_row + 3 + 0] = (value) & 0xFF;
800 row[0 + 1] = row[3 + 1] = row[next_row + 1] =
801 row[next_row + 3 + 1] = (value >> 8) & 0xFF;
802 row[0 + 2] = row[3 + 2] = row[next_row + 2] =
803 row[next_row + 3 + 2] = (value >> 16) & 0xFF;
812 Color32DitherYUY2Mod2X(int *colortab, Uint32 * rgb_2_pix,
813 unsigned char *lum, unsigned char *cr,
814 unsigned char *cb, unsigned char *out,
815 int rows, int cols, int mod)
817 unsigned int *row = (unsigned int *) out;
818 const int next_row = cols * 2 + mod;
823 int cols_2 = cols / 2;
831 cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
832 crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
833 + colortab[*cb + 2 * 256];
834 cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
840 row[0] = row[1] = row[next_row] = row[next_row + 1] =
841 (rgb_2_pix[L + cr_r] |
842 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
847 row[0] = row[1] = row[next_row] = row[next_row + 1] =
848 (rgb_2_pix[L + cr_r] |
849 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
860 * How many 1 bits are there in the Uint32.
861 * Low performance, do not call often.
864 number_of_bits_set(Uint32 a)
869 return 1 + number_of_bits_set(a >> 1);
870 return (number_of_bits_set(a >> 1));
874 * How many 0 bits are there at least significant end of Uint32.
875 * Low performance, do not call often.
878 free_bits_at_bottom(Uint32 a)
880 /* assume char is 8 bits */
882 return sizeof(Uint32) * 8;
883 if (((Sint32) a) & 1l)
885 return 1 + free_bits_at_bottom(a >> 1);
889 SDL_SW_SetupYUVDisplay(SDL_SW_YUVTexture * swdata, Uint32 target_format)
891 Uint32 *r_2_pix_alloc;
892 Uint32 *g_2_pix_alloc;
893 Uint32 *b_2_pix_alloc;
896 Uint32 Rmask, Gmask, Bmask, Amask;
898 if (!SDL_PixelFormatEnumToMasks
899 (target_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask) || bpp < 15) {
900 return SDL_SetError("Unsupported YUV destination format");
903 swdata->target_format = target_format;
904 r_2_pix_alloc = &swdata->rgb_2_pix[0 * 768];
905 g_2_pix_alloc = &swdata->rgb_2_pix[1 * 768];
906 b_2_pix_alloc = &swdata->rgb_2_pix[2 * 768];
909 * Set up entries 0-255 in rgb-to-pixel value tables.
911 for (i = 0; i < 256; ++i) {
912 r_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Rmask));
913 r_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Rmask);
914 r_2_pix_alloc[i + 256] |= Amask;
915 g_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Gmask));
916 g_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Gmask);
917 g_2_pix_alloc[i + 256] |= Amask;
918 b_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Bmask));
919 b_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Bmask);
920 b_2_pix_alloc[i + 256] |= Amask;
924 * If we have 16-bit output depth, then we double the value
925 * in the top word. This means that we can write out both
926 * pixels in the pixel doubling mode with one op. It is
927 * harmless in the normal case as storing a 32-bit value
928 * through a short pointer will lose the top bits anyway.
930 if (SDL_BYTESPERPIXEL(target_format) == 2) {
931 for (i = 0; i < 256; ++i) {
932 r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16;
933 g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16;
934 b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 16;
939 * Spread out the values we have to the rest of the array so that
940 * we do not need to check for overflow.
942 for (i = 0; i < 256; ++i) {
943 r_2_pix_alloc[i] = r_2_pix_alloc[256];
944 r_2_pix_alloc[i + 512] = r_2_pix_alloc[511];
945 g_2_pix_alloc[i] = g_2_pix_alloc[256];
946 g_2_pix_alloc[i + 512] = g_2_pix_alloc[511];
947 b_2_pix_alloc[i] = b_2_pix_alloc[256];
948 b_2_pix_alloc[i + 512] = b_2_pix_alloc[511];
951 /* You have chosen wisely... */
952 switch (swdata->format) {
953 case SDL_PIXELFORMAT_YV12:
954 case SDL_PIXELFORMAT_IYUV:
955 if (SDL_BYTESPERPIXEL(target_format) == 2) {
956 #if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES
957 /* inline assembly functions */
958 if (SDL_HasMMX() && (Rmask == 0xF800) &&
959 (Gmask == 0x07E0) && (Bmask == 0x001F)
960 && (swdata->w & 15) == 0) {
961 /* printf("Using MMX 16-bit 565 dither\n"); */
962 swdata->Display1X = Color565DitherYV12MMX1X;
964 /* printf("Using C 16-bit dither\n"); */
965 swdata->Display1X = Color16DitherYV12Mod1X;
968 swdata->Display1X = Color16DitherYV12Mod1X;
970 swdata->Display2X = Color16DitherYV12Mod2X;
972 if (SDL_BYTESPERPIXEL(target_format) == 3) {
973 swdata->Display1X = Color24DitherYV12Mod1X;
974 swdata->Display2X = Color24DitherYV12Mod2X;
976 if (SDL_BYTESPERPIXEL(target_format) == 4) {
977 #if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES
978 /* inline assembly functions */
979 if (SDL_HasMMX() && (Rmask == 0x00FF0000) &&
980 (Gmask == 0x0000FF00) &&
981 (Bmask == 0x000000FF) && (swdata->w & 15) == 0) {
982 /* printf("Using MMX 32-bit dither\n"); */
983 swdata->Display1X = ColorRGBDitherYV12MMX1X;
985 /* printf("Using C 32-bit dither\n"); */
986 swdata->Display1X = Color32DitherYV12Mod1X;
989 swdata->Display1X = Color32DitherYV12Mod1X;
991 swdata->Display2X = Color32DitherYV12Mod2X;
994 case SDL_PIXELFORMAT_YUY2:
995 case SDL_PIXELFORMAT_UYVY:
996 case SDL_PIXELFORMAT_YVYU:
997 if (SDL_BYTESPERPIXEL(target_format) == 2) {
998 swdata->Display1X = Color16DitherYUY2Mod1X;
999 swdata->Display2X = Color16DitherYUY2Mod2X;
1001 if (SDL_BYTESPERPIXEL(target_format) == 3) {
1002 swdata->Display1X = Color24DitherYUY2Mod1X;
1003 swdata->Display2X = Color24DitherYUY2Mod2X;
1005 if (SDL_BYTESPERPIXEL(target_format) == 4) {
1006 swdata->Display1X = Color32DitherYUY2Mod1X;
1007 swdata->Display2X = Color32DitherYUY2Mod2X;
1011 /* We should never get here (caught above) */
1015 SDL_FreeSurface(swdata->display);
1016 swdata->display = NULL;
1021 SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
1023 SDL_SW_YUVTexture *swdata;
1032 case SDL_PIXELFORMAT_YV12:
1033 case SDL_PIXELFORMAT_IYUV:
1034 case SDL_PIXELFORMAT_YUY2:
1035 case SDL_PIXELFORMAT_UYVY:
1036 case SDL_PIXELFORMAT_YVYU:
1039 SDL_SetError("Unsupported YUV format");
1043 swdata = (SDL_SW_YUVTexture *) SDL_calloc(1, sizeof(*swdata));
1049 swdata->format = format;
1050 swdata->target_format = SDL_PIXELFORMAT_UNKNOWN;
1053 swdata->pixels = (Uint8 *) SDL_malloc(w * h * 2);
1054 swdata->colortab = (int *) SDL_malloc(4 * 256 * sizeof(int));
1055 swdata->rgb_2_pix = (Uint32 *) SDL_malloc(3 * 768 * sizeof(Uint32));
1056 if (!swdata->pixels || !swdata->colortab || !swdata->rgb_2_pix) {
1057 SDL_SW_DestroyYUVTexture(swdata);
1062 /* Generate the tables for the display surface */
1063 Cr_r_tab = &swdata->colortab[0 * 256];
1064 Cr_g_tab = &swdata->colortab[1 * 256];
1065 Cb_g_tab = &swdata->colortab[2 * 256];
1066 Cb_b_tab = &swdata->colortab[3 * 256];
1067 for (i = 0; i < 256; i++) {
1068 /* Gamma correction (luminescence table) and chroma correction
1069 would be done here. See the Berkeley mpeg_play sources.
1071 CB = CR = (i - 128);
1072 Cr_r_tab[i] = (int) ((0.419 / 0.299) * CR);
1073 Cr_g_tab[i] = (int) (-(0.299 / 0.419) * CR);
1074 Cb_g_tab[i] = (int) (-(0.114 / 0.331) * CB);
1075 Cb_b_tab[i] = (int) ((0.587 / 0.331) * CB);
1078 /* Find the pitch and offset values for the overlay */
1080 case SDL_PIXELFORMAT_YV12:
1081 case SDL_PIXELFORMAT_IYUV:
1082 swdata->pitches[0] = w;
1083 swdata->pitches[1] = swdata->pitches[0] / 2;
1084 swdata->pitches[2] = swdata->pitches[0] / 2;
1085 swdata->planes[0] = swdata->pixels;
1086 swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h;
1087 swdata->planes[2] = swdata->planes[1] + swdata->pitches[1] * h / 2;
1089 case SDL_PIXELFORMAT_YUY2:
1090 case SDL_PIXELFORMAT_UYVY:
1091 case SDL_PIXELFORMAT_YVYU:
1092 swdata->pitches[0] = w * 2;
1093 swdata->planes[0] = swdata->pixels;
1096 SDL_assert(0 && "We should never get here (caught above)");
1100 /* We're all done.. */
1105 SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture * swdata, void **pixels,
1108 *pixels = swdata->planes[0];
1109 *pitch = swdata->pitches[0];
1114 SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
1115 const void *pixels, int pitch)
1117 switch (swdata->format) {
1118 case SDL_PIXELFORMAT_YV12:
1119 case SDL_PIXELFORMAT_IYUV:
1120 if (rect->x == 0 && rect->y == 0 &&
1121 rect->w == swdata->w && rect->h == swdata->h) {
1122 SDL_memcpy(swdata->pixels, pixels,
1123 (swdata->h * swdata->w) + (swdata->h * swdata->w) / 2);
1129 /* Copy the Y plane */
1130 src = (Uint8 *) pixels;
1131 dst = swdata->pixels + rect->y * swdata->w + rect->x;
1133 for (row = 0; row < rect->h; ++row) {
1134 SDL_memcpy(dst, src, length);
1139 /* Copy the next plane */
1140 src = (Uint8 *) pixels + rect->h * pitch;
1141 dst = swdata->pixels + swdata->h * swdata->w;
1142 dst += rect->y/2 * swdata->w/2 + rect->x/2;
1143 length = rect->w / 2;
1144 for (row = 0; row < rect->h/2; ++row) {
1145 SDL_memcpy(dst, src, length);
1150 /* Copy the next plane */
1151 src = (Uint8 *) pixels + rect->h * pitch + (rect->h * pitch) / 4;
1152 dst = swdata->pixels + swdata->h * swdata->w +
1153 (swdata->h * swdata->w) / 4;
1154 dst += rect->y/2 * swdata->w/2 + rect->x/2;
1155 length = rect->w / 2;
1156 for (row = 0; row < rect->h/2; ++row) {
1157 SDL_memcpy(dst, src, length);
1163 case SDL_PIXELFORMAT_YUY2:
1164 case SDL_PIXELFORMAT_UYVY:
1165 case SDL_PIXELFORMAT_YVYU:
1171 src = (Uint8 *) pixels;
1173 swdata->planes[0] + rect->y * swdata->pitches[0] +
1175 length = rect->w * 2;
1176 for (row = 0; row < rect->h; ++row) {
1177 SDL_memcpy(dst, src, length);
1179 dst += swdata->pitches[0];
1188 SDL_SW_UpdateYUVTexturePlanar(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
1189 const Uint8 *Yplane, int Ypitch,
1190 const Uint8 *Uplane, int Upitch,
1191 const Uint8 *Vplane, int Vpitch)
1198 /* Copy the Y plane */
1200 dst = swdata->pixels + rect->y * swdata->w + rect->x;
1202 for (row = 0; row < rect->h; ++row) {
1203 SDL_memcpy(dst, src, length);
1208 /* Copy the U plane */
1210 if (swdata->format == SDL_PIXELFORMAT_IYUV) {
1211 dst = swdata->pixels + swdata->h * swdata->w;
1213 dst = swdata->pixels + swdata->h * swdata->w +
1214 (swdata->h * swdata->w) / 4;
1216 dst += rect->y/2 * swdata->w/2 + rect->x/2;
1217 length = rect->w / 2;
1218 for (row = 0; row < rect->h/2; ++row) {
1219 SDL_memcpy(dst, src, length);
1224 /* Copy the V plane */
1226 if (swdata->format == SDL_PIXELFORMAT_YV12) {
1227 dst = swdata->pixels + swdata->h * swdata->w;
1229 dst = swdata->pixels + swdata->h * swdata->w +
1230 (swdata->h * swdata->w) / 4;
1232 dst += rect->y/2 * swdata->w/2 + rect->x/2;
1233 length = rect->w / 2;
1234 for (row = 0; row < rect->h/2; ++row) {
1235 SDL_memcpy(dst, src, length);
1243 SDL_SW_LockYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
1244 void **pixels, int *pitch)
1246 switch (swdata->format) {
1247 case SDL_PIXELFORMAT_YV12:
1248 case SDL_PIXELFORMAT_IYUV:
1250 && (rect->x != 0 || rect->y != 0 || rect->w != swdata->w
1251 || rect->h != swdata->h)) {
1253 ("YV12 and IYUV textures only support full surface locks");
1259 *pixels = swdata->planes[0] + rect->y * swdata->pitches[0] + rect->x * 2;
1261 *pixels = swdata->planes[0];
1263 *pitch = swdata->pitches[0];
1268 SDL_SW_UnlockYUVTexture(SDL_SW_YUVTexture * swdata)
1273 SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture * swdata, const SDL_Rect * srcrect,
1274 Uint32 target_format, int w, int h, void *pixels,
1277 const int targetbpp = SDL_BYTESPERPIXEL(target_format);
1280 Uint8 *lum, *Cr, *Cb;
1283 if (targetbpp == 0) {
1284 return SDL_SetError("Invalid target pixel format");
1287 /* Make sure we're set up to display in the desired format */
1288 if (target_format != swdata->target_format) {
1289 if (SDL_SW_SetupYUVDisplay(swdata, target_format) < 0) {
1296 if (srcrect->x || srcrect->y || srcrect->w < swdata->w
1297 || srcrect->h < swdata->h) {
1298 /* The source rectangle has been clipped.
1299 Using a scratch surface is easier than adding clipped
1300 source support to all the blitters, plus that would
1301 slow them down in the general unclipped case.
1304 } else if ((srcrect->w != w) || (srcrect->h != h)) {
1305 if ((w == 2 * srcrect->w) && (h == 2 * srcrect->h)) {
1313 Uint32 Rmask, Gmask, Bmask, Amask;
1315 if (swdata->display) {
1316 swdata->display->w = w;
1317 swdata->display->h = h;
1318 swdata->display->pixels = pixels;
1319 swdata->display->pitch = pitch;
1321 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
1322 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
1325 SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask,
1326 Gmask, Bmask, Amask);
1327 if (!swdata->display) {
1331 if (!swdata->stretch) {
1332 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
1333 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
1336 SDL_CreateRGBSurface(0, swdata->w, swdata->h, bpp, Rmask,
1337 Gmask, Bmask, Amask);
1338 if (!swdata->stretch) {
1342 pixels = swdata->stretch->pixels;
1343 pitch = swdata->stretch->pitch;
1345 switch (swdata->format) {
1346 case SDL_PIXELFORMAT_YV12:
1347 lum = swdata->planes[0];
1348 Cr = swdata->planes[1];
1349 Cb = swdata->planes[2];
1351 case SDL_PIXELFORMAT_IYUV:
1352 lum = swdata->planes[0];
1353 Cr = swdata->planes[2];
1354 Cb = swdata->planes[1];
1356 case SDL_PIXELFORMAT_YUY2:
1357 lum = swdata->planes[0];
1361 case SDL_PIXELFORMAT_UYVY:
1362 lum = swdata->planes[0] + 1;
1366 case SDL_PIXELFORMAT_YVYU:
1367 lum = swdata->planes[0];
1372 return SDL_SetError("Unsupported YUV format in copy");
1374 mod = (pitch / targetbpp);
1377 mod -= (swdata->w * 2);
1378 swdata->Display2X(swdata->colortab, swdata->rgb_2_pix,
1379 lum, Cr, Cb, pixels, swdata->h, swdata->w, mod);
1382 swdata->Display1X(swdata->colortab, swdata->rgb_2_pix,
1383 lum, Cr, Cb, pixels, swdata->h, swdata->w, mod);
1386 SDL_Rect rect = *srcrect;
1387 SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL);
1393 SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture * swdata)
1396 SDL_free(swdata->pixels);
1397 SDL_free(swdata->colortab);
1398 SDL_free(swdata->rgb_2_pix);
1399 SDL_FreeSurface(swdata->stretch);
1400 SDL_FreeSurface(swdata->display);
1405 /* vi: set ts=4 sw=4 expandtab: */