comparison src/render/SDL_yuv_sw.c @ 5159:307ccc9c135e

Made it possible to create a texture of any format, even if not supported by the renderer. This allows me to reduce the set of formats supported by the renderers to the most optimal set, for a nice speed boost.
author Sam Lantinga <slouken@libsdl.org>
date Thu, 03 Feb 2011 00:19:40 -0800
parents src/video/SDL_yuv_sw.c@f7b03b6838cb
children b530ef003506
comparison
equal deleted inserted replaced
5158:f3ebd1950442 5159:307ccc9c135e
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2010 Sam Lantinga
4
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.
9
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.
14
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
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 /* This is the software implementation of the YUV texture support */
25
26 /* This code was derived from code carrying the following copyright notices:
27
28 * Copyright (c) 1995 The Regents of the University of California.
29 * All rights reserved.
30 *
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.
35 *
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.
40 *
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.
46
47 * Copyright (c) 1995 Erik Corry
48 * All rights reserved.
49 *
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.
54 *
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.
59 *
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.
65
66 * Portions of this software Copyright (c) 1995 Brown University.
67 * All rights reserved.
68 *
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.
73 *
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.
78 *
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.
84 */
85
86 #include "SDL_video.h"
87 #include "SDL_cpuinfo.h"
88 #include "SDL_yuv_sw_c.h"
89
90
91 /* The colorspace conversion functions */
92
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);
102 #endif
103
104 static void
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)
109 {
110 unsigned short *row1;
111 unsigned short *row2;
112 unsigned char *lum2;
113 int x, y;
114 int cr_r;
115 int crb_g;
116 int cb_b;
117 int cols_2 = cols / 2;
118
119 row1 = (unsigned short *) out;
120 row2 = row1 + cols + mod;
121 lum2 = lum + cols;
122
123 mod += cols + mod;
124
125 y = rows / 2;
126 while (y--) {
127 x = cols_2;
128 while (x--) {
129 register int L;
130
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];
135 ++cr;
136 ++cb;
137
138 L = *lum++;
139 *row1++ = (unsigned short) (rgb_2_pix[L + cr_r] |
140 rgb_2_pix[L + crb_g] |
141 rgb_2_pix[L + cb_b]);
142
143 L = *lum++;
144 *row1++ = (unsigned short) (rgb_2_pix[L + cr_r] |
145 rgb_2_pix[L + crb_g] |
146 rgb_2_pix[L + cb_b]);
147
148
149 /* Now, do second row. */
150
151 L = *lum2++;
152 *row2++ = (unsigned short) (rgb_2_pix[L + cr_r] |
153 rgb_2_pix[L + crb_g] |
154 rgb_2_pix[L + cb_b]);
155
156 L = *lum2++;
157 *row2++ = (unsigned short) (rgb_2_pix[L + cr_r] |
158 rgb_2_pix[L + crb_g] |
159 rgb_2_pix[L + cb_b]);
160 }
161
162 /*
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.
166 */
167 lum += cols;
168 lum2 += cols;
169 row1 += mod;
170 row2 += mod;
171 }
172 }
173
174 static void
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)
179 {
180 unsigned int value;
181 unsigned char *row1;
182 unsigned char *row2;
183 unsigned char *lum2;
184 int x, y;
185 int cr_r;
186 int crb_g;
187 int cb_b;
188 int cols_2 = cols / 2;
189
190 row1 = out;
191 row2 = row1 + cols * 3 + mod * 3;
192 lum2 = lum + cols;
193
194 mod += cols + mod;
195 mod *= 3;
196
197 y = rows / 2;
198 while (y--) {
199 x = cols_2;
200 while (x--) {
201 register int L;
202
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];
207 ++cr;
208 ++cb;
209
210 L = *lum++;
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;
216
217 L = *lum++;
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;
223
224
225 /* Now, do second row. */
226
227 L = *lum2++;
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;
233
234 L = *lum2++;
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;
240 }
241
242 /*
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.
246 */
247 lum += cols;
248 lum2 += cols;
249 row1 += mod;
250 row2 += mod;
251 }
252 }
253
254 static void
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)
259 {
260 unsigned int *row1;
261 unsigned int *row2;
262 unsigned char *lum2;
263 int x, y;
264 int cr_r;
265 int crb_g;
266 int cb_b;
267 int cols_2 = cols / 2;
268
269 row1 = (unsigned int *) out;
270 row2 = row1 + cols + mod;
271 lum2 = lum + cols;
272
273 mod += cols + mod;
274
275 y = rows / 2;
276 while (y--) {
277 x = cols_2;
278 while (x--) {
279 register int L;
280
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];
285 ++cr;
286 ++cb;
287
288 L = *lum++;
289 *row1++ = (rgb_2_pix[L + cr_r] |
290 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
291
292 L = *lum++;
293 *row1++ = (rgb_2_pix[L + cr_r] |
294 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
295
296
297 /* Now, do second row. */
298
299 L = *lum2++;
300 *row2++ = (rgb_2_pix[L + cr_r] |
301 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
302
303 L = *lum2++;
304 *row2++ = (rgb_2_pix[L + cr_r] |
305 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
306 }
307
308 /*
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.
312 */
313 lum += cols;
314 lum2 += cols;
315 row1 += mod;
316 row2 += mod;
317 }
318 }
319
320 /*
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).
324 */
325 static void
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)
330 {
331 unsigned int *row1 = (unsigned int *) out;
332 const int next_row = cols + (mod / 2);
333 unsigned int *row2 = row1 + 2 * next_row;
334 unsigned char *lum2;
335 int x, y;
336 int cr_r;
337 int crb_g;
338 int cb_b;
339 int cols_2 = cols / 2;
340
341 lum2 = lum + cols;
342
343 mod = (next_row * 3) + (mod / 2);
344
345 y = rows / 2;
346 while (y--) {
347 x = cols_2;
348 while (x--) {
349 register int L;
350
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];
355 ++cr;
356 ++cb;
357
358 L = *lum++;
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]);
362 row1++;
363
364 L = *lum++;
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]);
368 row1++;
369
370
371 /* Now, do second row. */
372
373 L = *lum2++;
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]);
377 row2++;
378
379 L = *lum2++;
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]);
383 row2++;
384 }
385
386 /*
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.
390 */
391 lum += cols;
392 lum2 += cols;
393 row1 += mod;
394 row2 += mod;
395 }
396 }
397
398 static void
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)
403 {
404 unsigned int value;
405 unsigned char *row1 = out;
406 const int next_row = (cols * 2 + mod) * 3;
407 unsigned char *row2 = row1 + 2 * next_row;
408 unsigned char *lum2;
409 int x, y;
410 int cr_r;
411 int crb_g;
412 int cb_b;
413 int cols_2 = cols / 2;
414
415 lum2 = lum + cols;
416
417 mod = next_row * 3 + mod * 3;
418
419 y = rows / 2;
420 while (y--) {
421 x = cols_2;
422 while (x--) {
423 register int L;
424
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];
429 ++cr;
430 ++cb;
431
432 L = *lum++;
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;
441 row1 += 2 * 3;
442
443 L = *lum++;
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;
452 row1 += 2 * 3;
453
454
455 /* Now, do second row. */
456
457 L = *lum2++;
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;
466 row2 += 2 * 3;
467
468 L = *lum2++;
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;
477 row2 += 2 * 3;
478 }
479
480 /*
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.
484 */
485 lum += cols;
486 lum2 += cols;
487 row1 += mod;
488 row2 += mod;
489 }
490 }
491
492 static void
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)
497 {
498 unsigned int *row1 = (unsigned int *) out;
499 const int next_row = cols * 2 + mod;
500 unsigned int *row2 = row1 + 2 * next_row;
501 unsigned char *lum2;
502 int x, y;
503 int cr_r;
504 int crb_g;
505 int cb_b;
506 int cols_2 = cols / 2;
507
508 lum2 = lum + cols;
509
510 mod = (next_row * 3) + mod;
511
512 y = rows / 2;
513 while (y--) {
514 x = cols_2;
515 while (x--) {
516 register int L;
517
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];
522 ++cr;
523 ++cb;
524
525 L = *lum++;
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]);
529 row1 += 2;
530
531 L = *lum++;
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]);
535 row1 += 2;
536
537
538 /* Now, do second row. */
539
540 L = *lum2++;
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]);
544 row2 += 2;
545
546 L = *lum2++;
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]);
550 row2 += 2;
551 }
552
553 /*
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.
557 */
558 lum += cols;
559 lum2 += cols;
560 row1 += mod;
561 row2 += mod;
562 }
563 }
564
565 static void
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)
570 {
571 unsigned short *row;
572 int x, y;
573 int cr_r;
574 int crb_g;
575 int cb_b;
576 int cols_2 = cols / 2;
577
578 row = (unsigned short *) out;
579
580 y = rows;
581 while (y--) {
582 x = cols_2;
583 while (x--) {
584 register int L;
585
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];
590 cr += 4;
591 cb += 4;
592
593 L = *lum;
594 lum += 2;
595 *row++ = (unsigned short) (rgb_2_pix[L + cr_r] |
596 rgb_2_pix[L + crb_g] |
597 rgb_2_pix[L + cb_b]);
598
599 L = *lum;
600 lum += 2;
601 *row++ = (unsigned short) (rgb_2_pix[L + cr_r] |
602 rgb_2_pix[L + crb_g] |
603 rgb_2_pix[L + cb_b]);
604
605 }
606
607 row += mod;
608 }
609 }
610
611 static void
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)
616 {
617 unsigned int value;
618 unsigned char *row;
619 int x, y;
620 int cr_r;
621 int crb_g;
622 int cb_b;
623 int cols_2 = cols / 2;
624
625 row = (unsigned char *) out;
626 mod *= 3;
627 y = rows;
628 while (y--) {
629 x = cols_2;
630 while (x--) {
631 register int L;
632
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];
637 cr += 4;
638 cb += 4;
639
640 L = *lum;
641 lum += 2;
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;
647
648 L = *lum;
649 lum += 2;
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;
655
656 }
657 row += mod;
658 }
659 }
660
661 static void
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)
666 {
667 unsigned int *row;
668 int x, y;
669 int cr_r;
670 int crb_g;
671 int cb_b;
672 int cols_2 = cols / 2;
673
674 row = (unsigned int *) out;
675 y = rows;
676 while (y--) {
677 x = cols_2;
678 while (x--) {
679 register int L;
680
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];
685 cr += 4;
686 cb += 4;
687
688 L = *lum;
689 lum += 2;
690 *row++ = (rgb_2_pix[L + cr_r] |
691 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
692
693 L = *lum;
694 lum += 2;
695 *row++ = (rgb_2_pix[L + cr_r] |
696 rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
697
698
699 }
700 row += mod;
701 }
702 }
703
704 /*
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).
708 */
709 static void
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)
714 {
715 unsigned int *row = (unsigned int *) out;
716 const int next_row = cols + (mod / 2);
717 int x, y;
718 int cr_r;
719 int crb_g;
720 int cb_b;
721 int cols_2 = cols / 2;
722
723 y = rows;
724 while (y--) {
725 x = cols_2;
726 while (x--) {
727 register int L;
728
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];
733 cr += 4;
734 cb += 4;
735
736 L = *lum;
737 lum += 2;
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]);
741 row++;
742
743 L = *lum;
744 lum += 2;
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]);
748 row++;
749
750 }
751 row += next_row;
752 }
753 }
754
755 static void
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)
760 {
761 unsigned int value;
762 unsigned char *row = out;
763 const int next_row = (cols * 2 + mod) * 3;
764 int x, y;
765 int cr_r;
766 int crb_g;
767 int cb_b;
768 int cols_2 = cols / 2;
769 y = rows;
770 while (y--) {
771 x = cols_2;
772 while (x--) {
773 register int L;
774
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];
779 cr += 4;
780 cb += 4;
781
782 L = *lum;
783 lum += 2;
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;
792 row += 2 * 3;
793
794 L = *lum;
795 lum += 2;
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;
804 row += 2 * 3;
805
806 }
807 row += next_row;
808 }
809 }
810
811 static void
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)
816 {
817 unsigned int *row = (unsigned int *) out;
818 const int next_row = cols * 2 + mod;
819 int x, y;
820 int cr_r;
821 int crb_g;
822 int cb_b;
823 int cols_2 = cols / 2;
824 mod += mod;
825 y = rows;
826 while (y--) {
827 x = cols_2;
828 while (x--) {
829 register int L;
830
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];
835 cr += 4;
836 cb += 4;
837
838 L = *lum;
839 lum += 2;
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]);
843 row += 2;
844
845 L = *lum;
846 lum += 2;
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]);
850 row += 2;
851
852
853 }
854
855 row += next_row;
856 }
857 }
858
859 /*
860 * How many 1 bits are there in the Uint32.
861 * Low performance, do not call often.
862 */
863 static int
864 number_of_bits_set(Uint32 a)
865 {
866 if (!a)
867 return 0;
868 if (a & 1)
869 return 1 + number_of_bits_set(a >> 1);
870 return (number_of_bits_set(a >> 1));
871 }
872
873 /*
874 * How many 0 bits are there at least significant end of Uint32.
875 * Low performance, do not call often.
876 */
877 static int
878 free_bits_at_bottom(Uint32 a)
879 {
880 /* assume char is 8 bits */
881 if (!a)
882 return sizeof(Uint32) * 8;
883 if (((Sint32) a) & 1l)
884 return 0;
885 return 1 + free_bits_at_bottom(a >> 1);
886 }
887
888 static int
889 SDL_SW_SetupYUVDisplay(SDL_SW_YUVTexture * swdata, Uint32 target_format)
890 {
891 Uint32 *r_2_pix_alloc;
892 Uint32 *g_2_pix_alloc;
893 Uint32 *b_2_pix_alloc;
894 int i;
895 int bpp;
896 Uint32 Rmask, Gmask, Bmask, Amask;
897
898 if (!SDL_PixelFormatEnumToMasks
899 (target_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask) || bpp < 15) {
900 SDL_SetError("Unsupported YUV destination format");
901 return -1;
902 }
903
904 swdata->target_format = target_format;
905 r_2_pix_alloc = &swdata->rgb_2_pix[0 * 768];
906 g_2_pix_alloc = &swdata->rgb_2_pix[1 * 768];
907 b_2_pix_alloc = &swdata->rgb_2_pix[2 * 768];
908
909 /*
910 * Set up entries 0-255 in rgb-to-pixel value tables.
911 */
912 for (i = 0; i < 256; ++i) {
913 r_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Rmask));
914 r_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Rmask);
915 r_2_pix_alloc[i + 256] |= Amask;
916 g_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Gmask));
917 g_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Gmask);
918 g_2_pix_alloc[i + 256] |= Amask;
919 b_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Bmask));
920 b_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Bmask);
921 b_2_pix_alloc[i + 256] |= Amask;
922 }
923
924 /*
925 * If we have 16-bit output depth, then we double the value
926 * in the top word. This means that we can write out both
927 * pixels in the pixel doubling mode with one op. It is
928 * harmless in the normal case as storing a 32-bit value
929 * through a short pointer will lose the top bits anyway.
930 */
931 if (SDL_BYTESPERPIXEL(target_format) == 2) {
932 for (i = 0; i < 256; ++i) {
933 r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16;
934 g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16;
935 b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 16;
936 }
937 }
938
939 /*
940 * Spread out the values we have to the rest of the array so that
941 * we do not need to check for overflow.
942 */
943 for (i = 0; i < 256; ++i) {
944 r_2_pix_alloc[i] = r_2_pix_alloc[256];
945 r_2_pix_alloc[i + 512] = r_2_pix_alloc[511];
946 g_2_pix_alloc[i] = g_2_pix_alloc[256];
947 g_2_pix_alloc[i + 512] = g_2_pix_alloc[511];
948 b_2_pix_alloc[i] = b_2_pix_alloc[256];
949 b_2_pix_alloc[i + 512] = b_2_pix_alloc[511];
950 }
951
952 /* You have chosen wisely... */
953 switch (swdata->format) {
954 case SDL_PIXELFORMAT_YV12:
955 case SDL_PIXELFORMAT_IYUV:
956 if (SDL_BYTESPERPIXEL(target_format) == 2) {
957 #if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES
958 /* inline assembly functions */
959 if (SDL_HasMMX() && (Rmask == 0xF800) &&
960 (Gmask == 0x07E0) && (Bmask == 0x001F)
961 && (swdata->w & 15) == 0) {
962 /*printf("Using MMX 16-bit 565 dither\n");*/
963 swdata->Display1X = Color565DitherYV12MMX1X;
964 } else {
965 /*printf("Using C 16-bit dither\n");*/
966 swdata->Display1X = Color16DitherYV12Mod1X;
967 }
968 #else
969 swdata->Display1X = Color16DitherYV12Mod1X;
970 #endif
971 swdata->Display2X = Color16DitherYV12Mod2X;
972 }
973 if (SDL_BYTESPERPIXEL(target_format) == 3) {
974 swdata->Display1X = Color24DitherYV12Mod1X;
975 swdata->Display2X = Color24DitherYV12Mod2X;
976 }
977 if (SDL_BYTESPERPIXEL(target_format) == 4) {
978 #if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES
979 /* inline assembly functions */
980 if (SDL_HasMMX() && (Rmask == 0x00FF0000) &&
981 (Gmask == 0x0000FF00) &&
982 (Bmask == 0x000000FF) && (swdata->w & 15) == 0) {
983 /*printf("Using MMX 32-bit dither\n");*/
984 swdata->Display1X = ColorRGBDitherYV12MMX1X;
985 } else {
986 /*printf("Using C 32-bit dither\n");*/
987 swdata->Display1X = Color32DitherYV12Mod1X;
988 }
989 #else
990 swdata->Display1X = Color32DitherYV12Mod1X;
991 #endif
992 swdata->Display2X = Color32DitherYV12Mod2X;
993 }
994 break;
995 case SDL_PIXELFORMAT_YUY2:
996 case SDL_PIXELFORMAT_UYVY:
997 case SDL_PIXELFORMAT_YVYU:
998 if (SDL_BYTESPERPIXEL(target_format) == 2) {
999 swdata->Display1X = Color16DitherYUY2Mod1X;
1000 swdata->Display2X = Color16DitherYUY2Mod2X;
1001 }
1002 if (SDL_BYTESPERPIXEL(target_format) == 3) {
1003 swdata->Display1X = Color24DitherYUY2Mod1X;
1004 swdata->Display2X = Color24DitherYUY2Mod2X;
1005 }
1006 if (SDL_BYTESPERPIXEL(target_format) == 4) {
1007 swdata->Display1X = Color32DitherYUY2Mod1X;
1008 swdata->Display2X = Color32DitherYUY2Mod2X;
1009 }
1010 break;
1011 default:
1012 /* We should never get here (caught above) */
1013 break;
1014 }
1015
1016 if (swdata->display) {
1017 SDL_FreeSurface(swdata->display);
1018 swdata->display = NULL;
1019 }
1020 return 0;
1021 }
1022
1023 SDL_SW_YUVTexture *
1024 SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
1025 {
1026 SDL_SW_YUVTexture *swdata;
1027 int *Cr_r_tab;
1028 int *Cr_g_tab;
1029 int *Cb_g_tab;
1030 int *Cb_b_tab;
1031 int i;
1032 int CR, CB;
1033
1034 swdata = (SDL_SW_YUVTexture *) SDL_calloc(1, sizeof(*swdata));
1035 if (!swdata) {
1036 SDL_OutOfMemory();
1037 return NULL;
1038 }
1039
1040 switch (format) {
1041 case SDL_PIXELFORMAT_YV12:
1042 case SDL_PIXELFORMAT_IYUV:
1043 case SDL_PIXELFORMAT_YUY2:
1044 case SDL_PIXELFORMAT_UYVY:
1045 case SDL_PIXELFORMAT_YVYU:
1046 break;
1047 default:
1048 SDL_SetError("Unsupported YUV format");
1049 return NULL;
1050 }
1051
1052 swdata->format = format;
1053 swdata->target_format = SDL_PIXELFORMAT_UNKNOWN;
1054 swdata->w = w;
1055 swdata->h = h;
1056 swdata->pixels = (Uint8 *) SDL_malloc(w * h * 2);
1057 swdata->colortab = (int *) SDL_malloc(4 * 256 * sizeof(int));
1058 swdata->rgb_2_pix = (Uint32 *) SDL_malloc(3 * 768 * sizeof(Uint32));
1059 if (!swdata->pixels || !swdata->colortab || !swdata->rgb_2_pix) {
1060 SDL_OutOfMemory();
1061 SDL_SW_DestroyYUVTexture(swdata);
1062 return NULL;
1063 }
1064
1065 /* Generate the tables for the display surface */
1066 Cr_r_tab = &swdata->colortab[0 * 256];
1067 Cr_g_tab = &swdata->colortab[1 * 256];
1068 Cb_g_tab = &swdata->colortab[2 * 256];
1069 Cb_b_tab = &swdata->colortab[3 * 256];
1070 for (i = 0; i < 256; i++) {
1071 /* Gamma correction (luminescence table) and chroma correction
1072 would be done here. See the Berkeley mpeg_play sources.
1073 */
1074 CB = CR = (i - 128);
1075 Cr_r_tab[i] = (int) ((0.419 / 0.299) * CR);
1076 Cr_g_tab[i] = (int) (-(0.299 / 0.419) * CR);
1077 Cb_g_tab[i] = (int) (-(0.114 / 0.331) * CB);
1078 Cb_b_tab[i] = (int) ((0.587 / 0.331) * CB);
1079 }
1080
1081 /* Find the pitch and offset values for the overlay */
1082 switch (format) {
1083 case SDL_PIXELFORMAT_YV12:
1084 case SDL_PIXELFORMAT_IYUV:
1085 swdata->pitches[0] = w;
1086 swdata->pitches[1] = swdata->pitches[0] / 2;
1087 swdata->pitches[2] = swdata->pitches[0] / 2;
1088 swdata->planes[0] = swdata->pixels;
1089 swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h;
1090 swdata->planes[2] = swdata->planes[1] + swdata->pitches[1] * h / 2;
1091 break;
1092 case SDL_PIXELFORMAT_YUY2:
1093 case SDL_PIXELFORMAT_UYVY:
1094 case SDL_PIXELFORMAT_YVYU:
1095 swdata->pitches[0] = w * 2;
1096 swdata->planes[0] = swdata->pixels;
1097 break;
1098 default:
1099 /* We should never get here (caught above) */
1100 break;
1101 }
1102
1103 /* We're all done.. */
1104 return (swdata);
1105 }
1106
1107 int
1108 SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture * swdata, void **pixels,
1109 int *pitch)
1110 {
1111 *pixels = swdata->planes[0];
1112 *pitch = swdata->pitches[0];
1113 return 0;
1114 }
1115
1116 int
1117 SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
1118 const void *pixels, int pitch)
1119 {
1120 switch (swdata->format) {
1121 case SDL_PIXELFORMAT_YV12:
1122 case SDL_PIXELFORMAT_IYUV:
1123 if (rect
1124 && (rect->x != 0 || rect->y != 0 || rect->w != swdata->w
1125 || rect->h != swdata->h)) {
1126 SDL_SetError
1127 ("YV12 and IYUV textures only support full surface updates");
1128 return -1;
1129 }
1130 SDL_memcpy(swdata->pixels, pixels, swdata->h * swdata->w * 2);
1131 break;
1132 case SDL_PIXELFORMAT_YUY2:
1133 case SDL_PIXELFORMAT_UYVY:
1134 case SDL_PIXELFORMAT_YVYU:
1135 {
1136 Uint8 *src, *dst;
1137 int row;
1138 size_t length;
1139
1140 src = (Uint8 *) pixels;
1141 dst =
1142 swdata->planes[0] + rect->y * swdata->pitches[0] +
1143 rect->x * 2;
1144 length = rect->w * 2;
1145 for (row = 0; row < rect->h; ++row) {
1146 SDL_memcpy(dst, src, length);
1147 src += pitch;
1148 dst += swdata->pitches[0];
1149 }
1150 }
1151 break;
1152 }
1153 return 0;
1154 }
1155
1156 int
1157 SDL_SW_LockYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
1158 void **pixels, int *pitch)
1159 {
1160 switch (swdata->format) {
1161 case SDL_PIXELFORMAT_YV12:
1162 case SDL_PIXELFORMAT_IYUV:
1163 if (rect
1164 && (rect->x != 0 || rect->y != 0 || rect->w != swdata->w
1165 || rect->h != swdata->h)) {
1166 SDL_SetError
1167 ("YV12 and IYUV textures only support full surface locks");
1168 return -1;
1169 }
1170 break;
1171 }
1172
1173 *pixels = swdata->planes[0] + rect->y * swdata->pitches[0] + rect->x * 2;
1174 *pitch = swdata->pitches[0];
1175 return 0;
1176 }
1177
1178 void
1179 SDL_SW_UnlockYUVTexture(SDL_SW_YUVTexture * swdata)
1180 {
1181 }
1182
1183 int
1184 SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture * swdata, const SDL_Rect * srcrect,
1185 Uint32 target_format, int w, int h, void *pixels,
1186 int pitch)
1187 {
1188 int stretch;
1189 int scale_2x;
1190 Uint8 *lum, *Cr, *Cb;
1191 int mod;
1192
1193 /* Make sure we're set up to display in the desired format */
1194 if (target_format != swdata->target_format) {
1195 if (SDL_SW_SetupYUVDisplay(swdata, target_format) < 0) {
1196 return -1;
1197 }
1198 }
1199
1200 stretch = 0;
1201 scale_2x = 0;
1202 if (srcrect->x || srcrect->y || srcrect->w < swdata->w
1203 || srcrect->h < swdata->h) {
1204 /* The source rectangle has been clipped.
1205 Using a scratch surface is easier than adding clipped
1206 source support to all the blitters, plus that would
1207 slow them down in the general unclipped case.
1208 */
1209 stretch = 1;
1210 } else if ((srcrect->w != w) || (srcrect->h != h)) {
1211 if ((w == 2 * srcrect->w) && (h == 2 * srcrect->h)) {
1212 scale_2x = 1;
1213 } else {
1214 stretch = 1;
1215 }
1216 }
1217 if (stretch) {
1218 int bpp;
1219 Uint32 Rmask, Gmask, Bmask, Amask;
1220
1221 if (swdata->display) {
1222 swdata->display->w = w;
1223 swdata->display->h = h;
1224 swdata->display->pixels = pixels;
1225 swdata->display->pitch = pitch;
1226 } else {
1227 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
1228 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
1229 &Bmask, &Amask);
1230 swdata->display =
1231 SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask,
1232 Gmask, Bmask, Amask);
1233 if (!swdata->display) {
1234 return (-1);
1235 }
1236 }
1237 if (!swdata->stretch) {
1238 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
1239 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
1240 &Bmask, &Amask);
1241 swdata->stretch =
1242 SDL_CreateRGBSurface(0, swdata->w, swdata->h, bpp, Rmask,
1243 Gmask, Bmask, Amask);
1244 if (!swdata->stretch) {
1245 return (-1);
1246 }
1247 }
1248 pixels = swdata->stretch->pixels;
1249 pitch = swdata->stretch->pitch;
1250 }
1251 switch (swdata->format) {
1252 case SDL_PIXELFORMAT_YV12:
1253 lum = swdata->planes[0];
1254 Cr = swdata->planes[1];
1255 Cb = swdata->planes[2];
1256 break;
1257 case SDL_PIXELFORMAT_IYUV:
1258 lum = swdata->planes[0];
1259 Cr = swdata->planes[2];
1260 Cb = swdata->planes[1];
1261 break;
1262 case SDL_PIXELFORMAT_YUY2:
1263 lum = swdata->planes[0];
1264 Cr = lum + 3;
1265 Cb = lum + 1;
1266 break;
1267 case SDL_PIXELFORMAT_UYVY:
1268 lum = swdata->planes[0] + 1;
1269 Cr = lum + 1;
1270 Cb = lum - 1;
1271 break;
1272 case SDL_PIXELFORMAT_YVYU:
1273 lum = swdata->planes[0];
1274 Cr = lum + 1;
1275 Cb = lum + 3;
1276 break;
1277 default:
1278 SDL_SetError("Unsupported YUV format in copy");
1279 return (-1);
1280 }
1281 mod = (pitch / SDL_BYTESPERPIXEL(target_format));
1282
1283 if (scale_2x) {
1284 mod -= (swdata->w * 2);
1285 swdata->Display2X(swdata->colortab, swdata->rgb_2_pix,
1286 lum, Cr, Cb, pixels, swdata->h, swdata->w, mod);
1287 } else {
1288 mod -= swdata->w;
1289 swdata->Display1X(swdata->colortab, swdata->rgb_2_pix,
1290 lum, Cr, Cb, pixels, swdata->h, swdata->w, mod);
1291 }
1292 if (stretch) {
1293 SDL_Rect rect = *srcrect;
1294 SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL);
1295 }
1296 return 0;
1297 }
1298
1299 void
1300 SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture * swdata)
1301 {
1302 if (swdata) {
1303 if (swdata->pixels) {
1304 SDL_free(swdata->pixels);
1305 }
1306 if (swdata->colortab) {
1307 SDL_free(swdata->colortab);
1308 }
1309 if (swdata->rgb_2_pix) {
1310 SDL_free(swdata->rgb_2_pix);
1311 }
1312 if (swdata->stretch) {
1313 SDL_FreeSurface(swdata->stretch);
1314 }
1315 if (swdata->display) {
1316 SDL_FreeSurface(swdata->display);
1317 }
1318 SDL_free(swdata);
1319 }
1320 }
1321
1322 /* vi: set ts=4 sw=4 expandtab: */