diff options
Diffstat (limited to 'apps/plugins/sdl/src/video/SDL_yuv_sw.c')
-rw-r--r-- | apps/plugins/sdl/src/video/SDL_yuv_sw.c | 1299 |
1 files changed, 1299 insertions, 0 deletions
diff --git a/apps/plugins/sdl/src/video/SDL_yuv_sw.c b/apps/plugins/sdl/src/video/SDL_yuv_sw.c new file mode 100644 index 0000000000..c555ce06c2 --- /dev/null +++ b/apps/plugins/sdl/src/video/SDL_yuv_sw.c | |||
@@ -0,0 +1,1299 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 video overlay 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_stretch_c.h" | ||
89 | #include "SDL_yuvfuncs.h" | ||
90 | #include "SDL_yuv_sw_c.h" | ||
91 | |||
92 | /* The functions used to manipulate software video overlays */ | ||
93 | static struct private_yuvhwfuncs sw_yuvfuncs = { | ||
94 | SDL_LockYUV_SW, | ||
95 | SDL_UnlockYUV_SW, | ||
96 | SDL_DisplayYUV_SW, | ||
97 | SDL_FreeYUV_SW | ||
98 | }; | ||
99 | |||
100 | /* RGB conversion lookup tables */ | ||
101 | struct private_yuvhwdata { | ||
102 | SDL_Surface *stretch; | ||
103 | SDL_Surface *display; | ||
104 | Uint8 *pixels; | ||
105 | int *colortab; | ||
106 | Uint32 *rgb_2_pix; | ||
107 | void (*Display1X)(int *colortab, Uint32 *rgb_2_pix, | ||
108 | unsigned char *lum, unsigned char *cr, | ||
109 | unsigned char *cb, unsigned char *out, | ||
110 | int rows, int cols, int mod ); | ||
111 | void (*Display2X)(int *colortab, Uint32 *rgb_2_pix, | ||
112 | unsigned char *lum, unsigned char *cr, | ||
113 | unsigned char *cb, unsigned char *out, | ||
114 | int rows, int cols, int mod ); | ||
115 | |||
116 | /* These are just so we don't have to allocate them separately */ | ||
117 | Uint16 pitches[3]; | ||
118 | Uint8 *planes[3]; | ||
119 | }; | ||
120 | |||
121 | |||
122 | /* The colorspace conversion functions */ | ||
123 | |||
124 | #if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES | ||
125 | extern void Color565DitherYV12MMX1X( 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 ); | ||
129 | extern void ColorRGBDitherYV12MMX1X( int *colortab, Uint32 *rgb_2_pix, | ||
130 | unsigned char *lum, unsigned char *cr, | ||
131 | unsigned char *cb, unsigned char *out, | ||
132 | int rows, int cols, int mod ); | ||
133 | #endif | ||
134 | |||
135 | static void Color16DitherYV12Mod1X( int *colortab, Uint32 *rgb_2_pix, | ||
136 | unsigned char *lum, unsigned char *cr, | ||
137 | unsigned char *cb, unsigned char *out, | ||
138 | int rows, int cols, int mod ) | ||
139 | { | ||
140 | unsigned short* row1; | ||
141 | unsigned short* row2; | ||
142 | unsigned char* lum2; | ||
143 | int x, y; | ||
144 | int cr_r; | ||
145 | int crb_g; | ||
146 | int cb_b; | ||
147 | int cols_2 = cols / 2; | ||
148 | |||
149 | row1 = (unsigned short*) out; | ||
150 | row2 = row1 + cols + mod; | ||
151 | lum2 = lum + cols; | ||
152 | |||
153 | mod += cols + mod; | ||
154 | |||
155 | y = rows / 2; | ||
156 | while( y-- ) | ||
157 | { | ||
158 | x = cols_2; | ||
159 | while( x-- ) | ||
160 | { | ||
161 | register int L; | ||
162 | |||
163 | cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; | ||
164 | crb_g = 1*768+256 + colortab[ *cr + 1*256 ] | ||
165 | + colortab[ *cb + 2*256 ]; | ||
166 | cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; | ||
167 | ++cr; ++cb; | ||
168 | |||
169 | L = *lum++; | ||
170 | *row1++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | | ||
171 | rgb_2_pix[ L + crb_g ] | | ||
172 | rgb_2_pix[ L + cb_b ]); | ||
173 | |||
174 | L = *lum++; | ||
175 | *row1++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | | ||
176 | rgb_2_pix[ L + crb_g ] | | ||
177 | rgb_2_pix[ L + cb_b ]); | ||
178 | |||
179 | |||
180 | /* Now, do second row. */ | ||
181 | |||
182 | L = *lum2++; | ||
183 | *row2++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | | ||
184 | rgb_2_pix[ L + crb_g ] | | ||
185 | rgb_2_pix[ L + cb_b ]); | ||
186 | |||
187 | L = *lum2++; | ||
188 | *row2++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | | ||
189 | rgb_2_pix[ L + crb_g ] | | ||
190 | rgb_2_pix[ L + cb_b ]); | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * These values are at the start of the next line, (due | ||
195 | * to the ++'s above),but they need to be at the start | ||
196 | * of the line after that. | ||
197 | */ | ||
198 | lum += cols; | ||
199 | lum2 += cols; | ||
200 | row1 += mod; | ||
201 | row2 += mod; | ||
202 | } | ||
203 | } | ||
204 | |||
205 | static void Color24DitherYV12Mod1X( int *colortab, Uint32 *rgb_2_pix, | ||
206 | unsigned char *lum, unsigned char *cr, | ||
207 | unsigned char *cb, unsigned char *out, | ||
208 | int rows, int cols, int mod ) | ||
209 | { | ||
210 | unsigned int value; | ||
211 | unsigned char* row1; | ||
212 | unsigned char* row2; | ||
213 | unsigned char* lum2; | ||
214 | int x, y; | ||
215 | int cr_r; | ||
216 | int crb_g; | ||
217 | int cb_b; | ||
218 | int cols_2 = cols / 2; | ||
219 | |||
220 | row1 = out; | ||
221 | row2 = row1 + cols*3 + mod*3; | ||
222 | lum2 = lum + cols; | ||
223 | |||
224 | mod += cols + mod; | ||
225 | mod *= 3; | ||
226 | |||
227 | y = rows / 2; | ||
228 | while( y-- ) | ||
229 | { | ||
230 | x = cols_2; | ||
231 | while( x-- ) | ||
232 | { | ||
233 | register int L; | ||
234 | |||
235 | cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; | ||
236 | crb_g = 1*768+256 + colortab[ *cr + 1*256 ] | ||
237 | + colortab[ *cb + 2*256 ]; | ||
238 | cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; | ||
239 | ++cr; ++cb; | ||
240 | |||
241 | L = *lum++; | ||
242 | value = (rgb_2_pix[ L + cr_r ] | | ||
243 | rgb_2_pix[ L + crb_g ] | | ||
244 | rgb_2_pix[ L + cb_b ]); | ||
245 | *row1++ = (value ) & 0xFF; | ||
246 | *row1++ = (value >> 8) & 0xFF; | ||
247 | *row1++ = (value >> 16) & 0xFF; | ||
248 | |||
249 | L = *lum++; | ||
250 | value = (rgb_2_pix[ L + cr_r ] | | ||
251 | rgb_2_pix[ L + crb_g ] | | ||
252 | rgb_2_pix[ L + cb_b ]); | ||
253 | *row1++ = (value ) & 0xFF; | ||
254 | *row1++ = (value >> 8) & 0xFF; | ||
255 | *row1++ = (value >> 16) & 0xFF; | ||
256 | |||
257 | |||
258 | /* Now, do second row. */ | ||
259 | |||
260 | L = *lum2++; | ||
261 | value = (rgb_2_pix[ L + cr_r ] | | ||
262 | rgb_2_pix[ L + crb_g ] | | ||
263 | rgb_2_pix[ L + cb_b ]); | ||
264 | *row2++ = (value ) & 0xFF; | ||
265 | *row2++ = (value >> 8) & 0xFF; | ||
266 | *row2++ = (value >> 16) & 0xFF; | ||
267 | |||
268 | L = *lum2++; | ||
269 | value = (rgb_2_pix[ L + cr_r ] | | ||
270 | rgb_2_pix[ L + crb_g ] | | ||
271 | rgb_2_pix[ L + cb_b ]); | ||
272 | *row2++ = (value ) & 0xFF; | ||
273 | *row2++ = (value >> 8) & 0xFF; | ||
274 | *row2++ = (value >> 16) & 0xFF; | ||
275 | } | ||
276 | |||
277 | /* | ||
278 | * These values are at the start of the next line, (due | ||
279 | * to the ++'s above),but they need to be at the start | ||
280 | * of the line after that. | ||
281 | */ | ||
282 | lum += cols; | ||
283 | lum2 += cols; | ||
284 | row1 += mod; | ||
285 | row2 += mod; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | static void Color32DitherYV12Mod1X( int *colortab, Uint32 *rgb_2_pix, | ||
290 | unsigned char *lum, unsigned char *cr, | ||
291 | unsigned char *cb, unsigned char *out, | ||
292 | int rows, int cols, int mod ) | ||
293 | { | ||
294 | unsigned int* row1; | ||
295 | unsigned int* row2; | ||
296 | unsigned char* lum2; | ||
297 | int x, y; | ||
298 | int cr_r; | ||
299 | int crb_g; | ||
300 | int cb_b; | ||
301 | int cols_2 = cols / 2; | ||
302 | |||
303 | row1 = (unsigned int*) out; | ||
304 | row2 = row1 + cols + mod; | ||
305 | lum2 = lum + cols; | ||
306 | |||
307 | mod += cols + mod; | ||
308 | |||
309 | y = rows / 2; | ||
310 | while( y-- ) | ||
311 | { | ||
312 | x = cols_2; | ||
313 | while( x-- ) | ||
314 | { | ||
315 | register int L; | ||
316 | |||
317 | cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; | ||
318 | crb_g = 1*768+256 + colortab[ *cr + 1*256 ] | ||
319 | + colortab[ *cb + 2*256 ]; | ||
320 | cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; | ||
321 | ++cr; ++cb; | ||
322 | |||
323 | L = *lum++; | ||
324 | *row1++ = (rgb_2_pix[ L + cr_r ] | | ||
325 | rgb_2_pix[ L + crb_g ] | | ||
326 | rgb_2_pix[ L + cb_b ]); | ||
327 | |||
328 | L = *lum++; | ||
329 | *row1++ = (rgb_2_pix[ L + cr_r ] | | ||
330 | rgb_2_pix[ L + crb_g ] | | ||
331 | rgb_2_pix[ L + cb_b ]); | ||
332 | |||
333 | |||
334 | /* Now, do second row. */ | ||
335 | |||
336 | L = *lum2++; | ||
337 | *row2++ = (rgb_2_pix[ L + cr_r ] | | ||
338 | rgb_2_pix[ L + crb_g ] | | ||
339 | rgb_2_pix[ L + cb_b ]); | ||
340 | |||
341 | L = *lum2++; | ||
342 | *row2++ = (rgb_2_pix[ L + cr_r ] | | ||
343 | rgb_2_pix[ L + crb_g ] | | ||
344 | rgb_2_pix[ L + cb_b ]); | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | * These values are at the start of the next line, (due | ||
349 | * to the ++'s above),but they need to be at the start | ||
350 | * of the line after that. | ||
351 | */ | ||
352 | lum += cols; | ||
353 | lum2 += cols; | ||
354 | row1 += mod; | ||
355 | row2 += mod; | ||
356 | } | ||
357 | } | ||
358 | |||
359 | /* | ||
360 | * In this function I make use of a nasty trick. The tables have the lower | ||
361 | * 16 bits replicated in the upper 16. This means I can write ints and get | ||
362 | * the horisontal doubling for free (almost). | ||
363 | */ | ||
364 | static void Color16DitherYV12Mod2X( int *colortab, Uint32 *rgb_2_pix, | ||
365 | unsigned char *lum, unsigned char *cr, | ||
366 | unsigned char *cb, unsigned char *out, | ||
367 | int rows, int cols, int mod ) | ||
368 | { | ||
369 | unsigned int* row1 = (unsigned int*) out; | ||
370 | const int next_row = cols+(mod/2); | ||
371 | unsigned int* row2 = row1 + 2*next_row; | ||
372 | unsigned char* lum2; | ||
373 | int x, y; | ||
374 | int cr_r; | ||
375 | int crb_g; | ||
376 | int cb_b; | ||
377 | int cols_2 = cols / 2; | ||
378 | |||
379 | lum2 = lum + cols; | ||
380 | |||
381 | mod = (next_row * 3) + (mod/2); | ||
382 | |||
383 | y = rows / 2; | ||
384 | while( y-- ) | ||
385 | { | ||
386 | x = cols_2; | ||
387 | while( x-- ) | ||
388 | { | ||
389 | register int L; | ||
390 | |||
391 | cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; | ||
392 | crb_g = 1*768+256 + colortab[ *cr + 1*256 ] | ||
393 | + colortab[ *cb + 2*256 ]; | ||
394 | cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; | ||
395 | ++cr; ++cb; | ||
396 | |||
397 | L = *lum++; | ||
398 | row1[0] = row1[next_row] = (rgb_2_pix[ L + cr_r ] | | ||
399 | rgb_2_pix[ L + crb_g ] | | ||
400 | rgb_2_pix[ L + cb_b ]); | ||
401 | row1++; | ||
402 | |||
403 | L = *lum++; | ||
404 | row1[0] = row1[next_row] = (rgb_2_pix[ L + cr_r ] | | ||
405 | rgb_2_pix[ L + crb_g ] | | ||
406 | rgb_2_pix[ L + cb_b ]); | ||
407 | row1++; | ||
408 | |||
409 | |||
410 | /* Now, do second row. */ | ||
411 | |||
412 | L = *lum2++; | ||
413 | row2[0] = row2[next_row] = (rgb_2_pix[ L + cr_r ] | | ||
414 | rgb_2_pix[ L + crb_g ] | | ||
415 | rgb_2_pix[ L + cb_b ]); | ||
416 | row2++; | ||
417 | |||
418 | L = *lum2++; | ||
419 | row2[0] = row2[next_row] = (rgb_2_pix[ L + cr_r ] | | ||
420 | rgb_2_pix[ L + crb_g ] | | ||
421 | rgb_2_pix[ L + cb_b ]); | ||
422 | row2++; | ||
423 | } | ||
424 | |||
425 | /* | ||
426 | * These values are at the start of the next line, (due | ||
427 | * to the ++'s above),but they need to be at the start | ||
428 | * of the line after that. | ||
429 | */ | ||
430 | lum += cols; | ||
431 | lum2 += cols; | ||
432 | row1 += mod; | ||
433 | row2 += mod; | ||
434 | } | ||
435 | } | ||
436 | |||
437 | static void Color24DitherYV12Mod2X( int *colortab, Uint32 *rgb_2_pix, | ||
438 | unsigned char *lum, unsigned char *cr, | ||
439 | unsigned char *cb, unsigned char *out, | ||
440 | int rows, int cols, int mod ) | ||
441 | { | ||
442 | unsigned int value; | ||
443 | unsigned char* row1 = out; | ||
444 | const int next_row = (cols*2 + mod) * 3; | ||
445 | unsigned char* row2 = row1 + 2*next_row; | ||
446 | unsigned char* lum2; | ||
447 | int x, y; | ||
448 | int cr_r; | ||
449 | int crb_g; | ||
450 | int cb_b; | ||
451 | int cols_2 = cols / 2; | ||
452 | |||
453 | lum2 = lum + cols; | ||
454 | |||
455 | mod = next_row*3 + mod*3; | ||
456 | |||
457 | y = rows / 2; | ||
458 | while( y-- ) | ||
459 | { | ||
460 | x = cols_2; | ||
461 | while( x-- ) | ||
462 | { | ||
463 | register int L; | ||
464 | |||
465 | cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; | ||
466 | crb_g = 1*768+256 + colortab[ *cr + 1*256 ] | ||
467 | + colortab[ *cb + 2*256 ]; | ||
468 | cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; | ||
469 | ++cr; ++cb; | ||
470 | |||
471 | L = *lum++; | ||
472 | value = (rgb_2_pix[ L + cr_r ] | | ||
473 | rgb_2_pix[ L + crb_g ] | | ||
474 | rgb_2_pix[ L + cb_b ]); | ||
475 | row1[0+0] = row1[3+0] = row1[next_row+0] = row1[next_row+3+0] = | ||
476 | (value ) & 0xFF; | ||
477 | row1[0+1] = row1[3+1] = row1[next_row+1] = row1[next_row+3+1] = | ||
478 | (value >> 8) & 0xFF; | ||
479 | row1[0+2] = row1[3+2] = row1[next_row+2] = row1[next_row+3+2] = | ||
480 | (value >> 16) & 0xFF; | ||
481 | row1 += 2*3; | ||
482 | |||
483 | L = *lum++; | ||
484 | value = (rgb_2_pix[ L + cr_r ] | | ||
485 | rgb_2_pix[ L + crb_g ] | | ||
486 | rgb_2_pix[ L + cb_b ]); | ||
487 | row1[0+0] = row1[3+0] = row1[next_row+0] = row1[next_row+3+0] = | ||
488 | (value ) & 0xFF; | ||
489 | row1[0+1] = row1[3+1] = row1[next_row+1] = row1[next_row+3+1] = | ||
490 | (value >> 8) & 0xFF; | ||
491 | row1[0+2] = row1[3+2] = row1[next_row+2] = row1[next_row+3+2] = | ||
492 | (value >> 16) & 0xFF; | ||
493 | row1 += 2*3; | ||
494 | |||
495 | |||
496 | /* Now, do second row. */ | ||
497 | |||
498 | L = *lum2++; | ||
499 | value = (rgb_2_pix[ L + cr_r ] | | ||
500 | rgb_2_pix[ L + crb_g ] | | ||
501 | rgb_2_pix[ L + cb_b ]); | ||
502 | row2[0+0] = row2[3+0] = row2[next_row+0] = row2[next_row+3+0] = | ||
503 | (value ) & 0xFF; | ||
504 | row2[0+1] = row2[3+1] = row2[next_row+1] = row2[next_row+3+1] = | ||
505 | (value >> 8) & 0xFF; | ||
506 | row2[0+2] = row2[3+2] = row2[next_row+2] = row2[next_row+3+2] = | ||
507 | (value >> 16) & 0xFF; | ||
508 | row2 += 2*3; | ||
509 | |||
510 | L = *lum2++; | ||
511 | value = (rgb_2_pix[ L + cr_r ] | | ||
512 | rgb_2_pix[ L + crb_g ] | | ||
513 | rgb_2_pix[ L + cb_b ]); | ||
514 | row2[0+0] = row2[3+0] = row2[next_row+0] = row2[next_row+3+0] = | ||
515 | (value ) & 0xFF; | ||
516 | row2[0+1] = row2[3+1] = row2[next_row+1] = row2[next_row+3+1] = | ||
517 | (value >> 8) & 0xFF; | ||
518 | row2[0+2] = row2[3+2] = row2[next_row+2] = row2[next_row+3+2] = | ||
519 | (value >> 16) & 0xFF; | ||
520 | row2 += 2*3; | ||
521 | } | ||
522 | |||
523 | /* | ||
524 | * These values are at the start of the next line, (due | ||
525 | * to the ++'s above),but they need to be at the start | ||
526 | * of the line after that. | ||
527 | */ | ||
528 | lum += cols; | ||
529 | lum2 += cols; | ||
530 | row1 += mod; | ||
531 | row2 += mod; | ||
532 | } | ||
533 | } | ||
534 | |||
535 | static void Color32DitherYV12Mod2X( int *colortab, Uint32 *rgb_2_pix, | ||
536 | unsigned char *lum, unsigned char *cr, | ||
537 | unsigned char *cb, unsigned char *out, | ||
538 | int rows, int cols, int mod ) | ||
539 | { | ||
540 | unsigned int* row1 = (unsigned int*) out; | ||
541 | const int next_row = cols*2+mod; | ||
542 | unsigned int* row2 = row1 + 2*next_row; | ||
543 | unsigned char* lum2; | ||
544 | int x, y; | ||
545 | int cr_r; | ||
546 | int crb_g; | ||
547 | int cb_b; | ||
548 | int cols_2 = cols / 2; | ||
549 | |||
550 | lum2 = lum + cols; | ||
551 | |||
552 | mod = (next_row * 3) + mod; | ||
553 | |||
554 | y = rows / 2; | ||
555 | while( y-- ) | ||
556 | { | ||
557 | x = cols_2; | ||
558 | while( x-- ) | ||
559 | { | ||
560 | register int L; | ||
561 | |||
562 | cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; | ||
563 | crb_g = 1*768+256 + colortab[ *cr + 1*256 ] | ||
564 | + colortab[ *cb + 2*256 ]; | ||
565 | cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; | ||
566 | ++cr; ++cb; | ||
567 | |||
568 | L = *lum++; | ||
569 | row1[0] = row1[1] = row1[next_row] = row1[next_row+1] = | ||
570 | (rgb_2_pix[ L + cr_r ] | | ||
571 | rgb_2_pix[ L + crb_g ] | | ||
572 | rgb_2_pix[ L + cb_b ]); | ||
573 | row1 += 2; | ||
574 | |||
575 | L = *lum++; | ||
576 | row1[0] = row1[1] = row1[next_row] = row1[next_row+1] = | ||
577 | (rgb_2_pix[ L + cr_r ] | | ||
578 | rgb_2_pix[ L + crb_g ] | | ||
579 | rgb_2_pix[ L + cb_b ]); | ||
580 | row1 += 2; | ||
581 | |||
582 | |||
583 | /* Now, do second row. */ | ||
584 | |||
585 | L = *lum2++; | ||
586 | row2[0] = row2[1] = row2[next_row] = row2[next_row+1] = | ||
587 | (rgb_2_pix[ L + cr_r ] | | ||
588 | rgb_2_pix[ L + crb_g ] | | ||
589 | rgb_2_pix[ L + cb_b ]); | ||
590 | row2 += 2; | ||
591 | |||
592 | L = *lum2++; | ||
593 | row2[0] = row2[1] = row2[next_row] = row2[next_row+1] = | ||
594 | (rgb_2_pix[ L + cr_r ] | | ||
595 | rgb_2_pix[ L + crb_g ] | | ||
596 | rgb_2_pix[ L + cb_b ]); | ||
597 | row2 += 2; | ||
598 | } | ||
599 | |||
600 | /* | ||
601 | * These values are at the start of the next line, (due | ||
602 | * to the ++'s above),but they need to be at the start | ||
603 | * of the line after that. | ||
604 | */ | ||
605 | lum += cols; | ||
606 | lum2 += cols; | ||
607 | row1 += mod; | ||
608 | row2 += mod; | ||
609 | } | ||
610 | } | ||
611 | |||
612 | static void Color16DitherYUY2Mod1X( 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 short* row; | ||
618 | int x, y; | ||
619 | int cr_r; | ||
620 | int crb_g; | ||
621 | int cb_b; | ||
622 | int cols_2 = cols / 2; | ||
623 | |||
624 | row = (unsigned short*) out; | ||
625 | |||
626 | y = rows; | ||
627 | while( y-- ) | ||
628 | { | ||
629 | x = cols_2; | ||
630 | while( x-- ) | ||
631 | { | ||
632 | register int L; | ||
633 | |||
634 | cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; | ||
635 | crb_g = 1*768+256 + colortab[ *cr + 1*256 ] | ||
636 | + colortab[ *cb + 2*256 ]; | ||
637 | cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; | ||
638 | cr += 4; cb += 4; | ||
639 | |||
640 | L = *lum; lum += 2; | ||
641 | *row++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | | ||
642 | rgb_2_pix[ L + crb_g ] | | ||
643 | rgb_2_pix[ L + cb_b ]); | ||
644 | |||
645 | L = *lum; lum += 2; | ||
646 | *row++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | | ||
647 | rgb_2_pix[ L + crb_g ] | | ||
648 | rgb_2_pix[ L + cb_b ]); | ||
649 | |||
650 | } | ||
651 | |||
652 | row += mod; | ||
653 | } | ||
654 | } | ||
655 | |||
656 | static void Color24DitherYUY2Mod1X( int *colortab, Uint32 *rgb_2_pix, | ||
657 | unsigned char *lum, unsigned char *cr, | ||
658 | unsigned char *cb, unsigned char *out, | ||
659 | int rows, int cols, int mod ) | ||
660 | { | ||
661 | unsigned int value; | ||
662 | unsigned char* row; | ||
663 | int x, y; | ||
664 | int cr_r; | ||
665 | int crb_g; | ||
666 | int cb_b; | ||
667 | int cols_2 = cols / 2; | ||
668 | |||
669 | row = (unsigned char*) out; | ||
670 | mod *= 3; | ||
671 | y = rows; | ||
672 | while( y-- ) | ||
673 | { | ||
674 | x = cols_2; | ||
675 | while( x-- ) | ||
676 | { | ||
677 | register int L; | ||
678 | |||
679 | cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; | ||
680 | crb_g = 1*768+256 + colortab[ *cr + 1*256 ] | ||
681 | + colortab[ *cb + 2*256 ]; | ||
682 | cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; | ||
683 | cr += 4; cb += 4; | ||
684 | |||
685 | L = *lum; lum += 2; | ||
686 | value = (rgb_2_pix[ L + cr_r ] | | ||
687 | rgb_2_pix[ L + crb_g ] | | ||
688 | rgb_2_pix[ L + cb_b ]); | ||
689 | *row++ = (value ) & 0xFF; | ||
690 | *row++ = (value >> 8) & 0xFF; | ||
691 | *row++ = (value >> 16) & 0xFF; | ||
692 | |||
693 | L = *lum; lum += 2; | ||
694 | value = (rgb_2_pix[ L + cr_r ] | | ||
695 | rgb_2_pix[ L + crb_g ] | | ||
696 | rgb_2_pix[ L + cb_b ]); | ||
697 | *row++ = (value ) & 0xFF; | ||
698 | *row++ = (value >> 8) & 0xFF; | ||
699 | *row++ = (value >> 16) & 0xFF; | ||
700 | |||
701 | } | ||
702 | row += mod; | ||
703 | } | ||
704 | } | ||
705 | |||
706 | static void Color32DitherYUY2Mod1X( int *colortab, Uint32 *rgb_2_pix, | ||
707 | unsigned char *lum, unsigned char *cr, | ||
708 | unsigned char *cb, unsigned char *out, | ||
709 | int rows, int cols, int mod ) | ||
710 | { | ||
711 | unsigned int* row; | ||
712 | int x, y; | ||
713 | int cr_r; | ||
714 | int crb_g; | ||
715 | int cb_b; | ||
716 | int cols_2 = cols / 2; | ||
717 | |||
718 | row = (unsigned int*) out; | ||
719 | y = rows; | ||
720 | while( y-- ) | ||
721 | { | ||
722 | x = cols_2; | ||
723 | while( x-- ) | ||
724 | { | ||
725 | register int L; | ||
726 | |||
727 | cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; | ||
728 | crb_g = 1*768+256 + colortab[ *cr + 1*256 ] | ||
729 | + colortab[ *cb + 2*256 ]; | ||
730 | cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; | ||
731 | cr += 4; cb += 4; | ||
732 | |||
733 | L = *lum; lum += 2; | ||
734 | *row++ = (rgb_2_pix[ L + cr_r ] | | ||
735 | rgb_2_pix[ L + crb_g ] | | ||
736 | rgb_2_pix[ L + cb_b ]); | ||
737 | |||
738 | L = *lum; lum += 2; | ||
739 | *row++ = (rgb_2_pix[ L + cr_r ] | | ||
740 | rgb_2_pix[ L + crb_g ] | | ||
741 | rgb_2_pix[ L + cb_b ]); | ||
742 | |||
743 | |||
744 | } | ||
745 | row += mod; | ||
746 | } | ||
747 | } | ||
748 | |||
749 | /* | ||
750 | * In this function I make use of a nasty trick. The tables have the lower | ||
751 | * 16 bits replicated in the upper 16. This means I can write ints and get | ||
752 | * the horisontal doubling for free (almost). | ||
753 | */ | ||
754 | static void Color16DitherYUY2Mod2X( int *colortab, Uint32 *rgb_2_pix, | ||
755 | unsigned char *lum, unsigned char *cr, | ||
756 | unsigned char *cb, unsigned char *out, | ||
757 | int rows, int cols, int mod ) | ||
758 | { | ||
759 | unsigned int* row = (unsigned int*) out; | ||
760 | const int next_row = cols+(mod/2); | ||
761 | int x, y; | ||
762 | int cr_r; | ||
763 | int crb_g; | ||
764 | int cb_b; | ||
765 | int cols_2 = cols / 2; | ||
766 | |||
767 | y = rows; | ||
768 | while( y-- ) | ||
769 | { | ||
770 | x = cols_2; | ||
771 | while( x-- ) | ||
772 | { | ||
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; cb += 4; | ||
780 | |||
781 | L = *lum; lum += 2; | ||
782 | row[0] = row[next_row] = (rgb_2_pix[ L + cr_r ] | | ||
783 | rgb_2_pix[ L + crb_g ] | | ||
784 | rgb_2_pix[ L + cb_b ]); | ||
785 | row++; | ||
786 | |||
787 | L = *lum; lum += 2; | ||
788 | row[0] = row[next_row] = (rgb_2_pix[ L + cr_r ] | | ||
789 | rgb_2_pix[ L + crb_g ] | | ||
790 | rgb_2_pix[ L + cb_b ]); | ||
791 | row++; | ||
792 | |||
793 | } | ||
794 | row += next_row; | ||
795 | } | ||
796 | } | ||
797 | |||
798 | static void Color24DitherYUY2Mod2X( int *colortab, Uint32 *rgb_2_pix, | ||
799 | unsigned char *lum, unsigned char *cr, | ||
800 | unsigned char *cb, unsigned char *out, | ||
801 | int rows, int cols, int mod ) | ||
802 | { | ||
803 | unsigned int value; | ||
804 | unsigned char* row = out; | ||
805 | const int next_row = (cols*2 + mod) * 3; | ||
806 | int x, y; | ||
807 | int cr_r; | ||
808 | int crb_g; | ||
809 | int cb_b; | ||
810 | int cols_2 = cols / 2; | ||
811 | y = rows; | ||
812 | while( y-- ) | ||
813 | { | ||
814 | x = cols_2; | ||
815 | while( x-- ) | ||
816 | { | ||
817 | register int L; | ||
818 | |||
819 | cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; | ||
820 | crb_g = 1*768+256 + colortab[ *cr + 1*256 ] | ||
821 | + colortab[ *cb + 2*256 ]; | ||
822 | cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; | ||
823 | cr += 4; cb += 4; | ||
824 | |||
825 | L = *lum; lum += 2; | ||
826 | value = (rgb_2_pix[ L + cr_r ] | | ||
827 | rgb_2_pix[ L + crb_g ] | | ||
828 | rgb_2_pix[ L + cb_b ]); | ||
829 | row[0+0] = row[3+0] = row[next_row+0] = row[next_row+3+0] = | ||
830 | (value ) & 0xFF; | ||
831 | row[0+1] = row[3+1] = row[next_row+1] = row[next_row+3+1] = | ||
832 | (value >> 8) & 0xFF; | ||
833 | row[0+2] = row[3+2] = row[next_row+2] = row[next_row+3+2] = | ||
834 | (value >> 16) & 0xFF; | ||
835 | row += 2*3; | ||
836 | |||
837 | L = *lum; lum += 2; | ||
838 | value = (rgb_2_pix[ L + cr_r ] | | ||
839 | rgb_2_pix[ L + crb_g ] | | ||
840 | rgb_2_pix[ L + cb_b ]); | ||
841 | row[0+0] = row[3+0] = row[next_row+0] = row[next_row+3+0] = | ||
842 | (value ) & 0xFF; | ||
843 | row[0+1] = row[3+1] = row[next_row+1] = row[next_row+3+1] = | ||
844 | (value >> 8) & 0xFF; | ||
845 | row[0+2] = row[3+2] = row[next_row+2] = row[next_row+3+2] = | ||
846 | (value >> 16) & 0xFF; | ||
847 | row += 2*3; | ||
848 | |||
849 | } | ||
850 | row += next_row; | ||
851 | } | ||
852 | } | ||
853 | |||
854 | static void Color32DitherYUY2Mod2X( int *colortab, Uint32 *rgb_2_pix, | ||
855 | unsigned char *lum, unsigned char *cr, | ||
856 | unsigned char *cb, unsigned char *out, | ||
857 | int rows, int cols, int mod ) | ||
858 | { | ||
859 | unsigned int* row = (unsigned int*) out; | ||
860 | const int next_row = cols*2+mod; | ||
861 | int x, y; | ||
862 | int cr_r; | ||
863 | int crb_g; | ||
864 | int cb_b; | ||
865 | int cols_2 = cols / 2; | ||
866 | mod+=mod; | ||
867 | y = rows; | ||
868 | while( y-- ) | ||
869 | { | ||
870 | x = cols_2; | ||
871 | while( x-- ) | ||
872 | { | ||
873 | register int L; | ||
874 | |||
875 | cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; | ||
876 | crb_g = 1*768+256 + colortab[ *cr + 1*256 ] | ||
877 | + colortab[ *cb + 2*256 ]; | ||
878 | cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; | ||
879 | cr += 4; cb += 4; | ||
880 | |||
881 | L = *lum; lum += 2; | ||
882 | row[0] = row[1] = row[next_row] = row[next_row+1] = | ||
883 | (rgb_2_pix[ L + cr_r ] | | ||
884 | rgb_2_pix[ L + crb_g ] | | ||
885 | rgb_2_pix[ L + cb_b ]); | ||
886 | row += 2; | ||
887 | |||
888 | L = *lum; lum += 2; | ||
889 | row[0] = row[1] = row[next_row] = row[next_row+1] = | ||
890 | (rgb_2_pix[ L + cr_r ] | | ||
891 | rgb_2_pix[ L + crb_g ] | | ||
892 | rgb_2_pix[ L + cb_b ]); | ||
893 | row += 2; | ||
894 | |||
895 | |||
896 | } | ||
897 | |||
898 | row += next_row; | ||
899 | } | ||
900 | } | ||
901 | |||
902 | /* | ||
903 | * How many 1 bits are there in the Uint32. | ||
904 | * Low performance, do not call often. | ||
905 | */ | ||
906 | static int number_of_bits_set( Uint32 a ) | ||
907 | { | ||
908 | if(!a) return 0; | ||
909 | if(a & 1) return 1 + number_of_bits_set(a >> 1); | ||
910 | return(number_of_bits_set(a >> 1)); | ||
911 | } | ||
912 | |||
913 | /* | ||
914 | * How many 0 bits are there at least significant end of Uint32. | ||
915 | * Low performance, do not call often. | ||
916 | */ | ||
917 | static int free_bits_at_bottom( Uint32 a ) | ||
918 | { | ||
919 | /* assume char is 8 bits */ | ||
920 | if(!a) return sizeof(Uint32) * 8; | ||
921 | if(((Sint32)a) & 1l) return 0; | ||
922 | return 1 + free_bits_at_bottom ( a >> 1); | ||
923 | } | ||
924 | |||
925 | |||
926 | SDL_Overlay *SDL_CreateYUV_SW(_THIS, int width, int height, Uint32 format, SDL_Surface *display) | ||
927 | { | ||
928 | SDL_Overlay *overlay; | ||
929 | struct private_yuvhwdata *swdata; | ||
930 | int *Cr_r_tab; | ||
931 | int *Cr_g_tab; | ||
932 | int *Cb_g_tab; | ||
933 | int *Cb_b_tab; | ||
934 | Uint32 *r_2_pix_alloc; | ||
935 | Uint32 *g_2_pix_alloc; | ||
936 | Uint32 *b_2_pix_alloc; | ||
937 | int i; | ||
938 | int CR, CB; | ||
939 | Uint32 Rmask, Gmask, Bmask; | ||
940 | |||
941 | /* Only RGB packed pixel conversion supported */ | ||
942 | if ( (display->format->BytesPerPixel != 2) && | ||
943 | (display->format->BytesPerPixel != 3) && | ||
944 | (display->format->BytesPerPixel != 4) ) { | ||
945 | SDL_SetError("Can't use YUV data on non 16/24/32 bit surfaces"); | ||
946 | return(NULL); | ||
947 | } | ||
948 | |||
949 | /* Verify that we support the format */ | ||
950 | switch (format) { | ||
951 | case SDL_YV12_OVERLAY: | ||
952 | case SDL_IYUV_OVERLAY: | ||
953 | case SDL_YUY2_OVERLAY: | ||
954 | case SDL_UYVY_OVERLAY: | ||
955 | case SDL_YVYU_OVERLAY: | ||
956 | break; | ||
957 | default: | ||
958 | SDL_SetError("Unsupported YUV format"); | ||
959 | return(NULL); | ||
960 | } | ||
961 | |||
962 | /* Create the overlay structure */ | ||
963 | overlay = (SDL_Overlay *)SDL_malloc(sizeof *overlay); | ||
964 | if ( overlay == NULL ) { | ||
965 | SDL_OutOfMemory(); | ||
966 | return(NULL); | ||
967 | } | ||
968 | SDL_memset(overlay, 0, (sizeof *overlay)); | ||
969 | |||
970 | /* Fill in the basic members */ | ||
971 | overlay->format = format; | ||
972 | overlay->w = width; | ||
973 | overlay->h = height; | ||
974 | |||
975 | /* Set up the YUV surface function structure */ | ||
976 | overlay->hwfuncs = &sw_yuvfuncs; | ||
977 | |||
978 | /* Create the pixel data and lookup tables */ | ||
979 | swdata = (struct private_yuvhwdata *)SDL_malloc(sizeof *swdata); | ||
980 | overlay->hwdata = swdata; | ||
981 | if ( swdata == NULL ) { | ||
982 | SDL_OutOfMemory(); | ||
983 | SDL_FreeYUVOverlay(overlay); | ||
984 | return(NULL); | ||
985 | } | ||
986 | swdata->stretch = NULL; | ||
987 | swdata->display = display; | ||
988 | swdata->pixels = (Uint8 *) SDL_malloc(width*height*2); | ||
989 | swdata->colortab = (int *)SDL_malloc(4*256*sizeof(int)); | ||
990 | Cr_r_tab = &swdata->colortab[0*256]; | ||
991 | Cr_g_tab = &swdata->colortab[1*256]; | ||
992 | Cb_g_tab = &swdata->colortab[2*256]; | ||
993 | Cb_b_tab = &swdata->colortab[3*256]; | ||
994 | swdata->rgb_2_pix = (Uint32 *)SDL_malloc(3*768*sizeof(Uint32)); | ||
995 | r_2_pix_alloc = &swdata->rgb_2_pix[0*768]; | ||
996 | g_2_pix_alloc = &swdata->rgb_2_pix[1*768]; | ||
997 | b_2_pix_alloc = &swdata->rgb_2_pix[2*768]; | ||
998 | if ( ! swdata->pixels || ! swdata->colortab || ! swdata->rgb_2_pix ) { | ||
999 | SDL_OutOfMemory(); | ||
1000 | SDL_FreeYUVOverlay(overlay); | ||
1001 | return(NULL); | ||
1002 | } | ||
1003 | |||
1004 | /* Generate the tables for the display surface */ | ||
1005 | for (i=0; i<256; i++) { | ||
1006 | /* Gamma correction (luminescence table) and chroma correction | ||
1007 | would be done here. See the Berkeley mpeg_play sources. | ||
1008 | */ | ||
1009 | CB = CR = (i-128); | ||
1010 | Cr_r_tab[i] = (int) ( (0.419/0.299) * CR); | ||
1011 | Cr_g_tab[i] = (int) (-(0.299/0.419) * CR); | ||
1012 | Cb_g_tab[i] = (int) (-(0.114/0.331) * CB); | ||
1013 | Cb_b_tab[i] = (int) ( (0.587/0.331) * CB); | ||
1014 | } | ||
1015 | |||
1016 | /* | ||
1017 | * Set up entries 0-255 in rgb-to-pixel value tables. | ||
1018 | */ | ||
1019 | Rmask = display->format->Rmask; | ||
1020 | Gmask = display->format->Gmask; | ||
1021 | Bmask = display->format->Bmask; | ||
1022 | for ( i=0; i<256; ++i ) { | ||
1023 | r_2_pix_alloc[i+256] = i >> (8 - number_of_bits_set(Rmask)); | ||
1024 | r_2_pix_alloc[i+256] <<= free_bits_at_bottom(Rmask); | ||
1025 | g_2_pix_alloc[i+256] = i >> (8 - number_of_bits_set(Gmask)); | ||
1026 | g_2_pix_alloc[i+256] <<= free_bits_at_bottom(Gmask); | ||
1027 | b_2_pix_alloc[i+256] = i >> (8 - number_of_bits_set(Bmask)); | ||
1028 | b_2_pix_alloc[i+256] <<= free_bits_at_bottom(Bmask); | ||
1029 | } | ||
1030 | |||
1031 | /* | ||
1032 | * If we have 16-bit output depth, then we double the value | ||
1033 | * in the top word. This means that we can write out both | ||
1034 | * pixels in the pixel doubling mode with one op. It is | ||
1035 | * harmless in the normal case as storing a 32-bit value | ||
1036 | * through a short pointer will lose the top bits anyway. | ||
1037 | */ | ||
1038 | if( display->format->BytesPerPixel == 2 ) { | ||
1039 | for ( i=0; i<256; ++i ) { | ||
1040 | r_2_pix_alloc[i+256] |= (r_2_pix_alloc[i+256]) << 16; | ||
1041 | g_2_pix_alloc[i+256] |= (g_2_pix_alloc[i+256]) << 16; | ||
1042 | b_2_pix_alloc[i+256] |= (b_2_pix_alloc[i+256]) << 16; | ||
1043 | } | ||
1044 | } | ||
1045 | |||
1046 | /* | ||
1047 | * Spread out the values we have to the rest of the array so that | ||
1048 | * we do not need to check for overflow. | ||
1049 | */ | ||
1050 | for ( i=0; i<256; ++i ) { | ||
1051 | r_2_pix_alloc[i] = r_2_pix_alloc[256]; | ||
1052 | r_2_pix_alloc[i+512] = r_2_pix_alloc[511]; | ||
1053 | g_2_pix_alloc[i] = g_2_pix_alloc[256]; | ||
1054 | g_2_pix_alloc[i+512] = g_2_pix_alloc[511]; | ||
1055 | b_2_pix_alloc[i] = b_2_pix_alloc[256]; | ||
1056 | b_2_pix_alloc[i+512] = b_2_pix_alloc[511]; | ||
1057 | } | ||
1058 | |||
1059 | /* You have chosen wisely... */ | ||
1060 | switch (format) { | ||
1061 | case SDL_YV12_OVERLAY: | ||
1062 | case SDL_IYUV_OVERLAY: | ||
1063 | if ( display->format->BytesPerPixel == 2 ) { | ||
1064 | #if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES | ||
1065 | /* inline assembly functions */ | ||
1066 | if ( SDL_HasMMX() && (Rmask == 0xF800) && | ||
1067 | (Gmask == 0x07E0) && | ||
1068 | (Bmask == 0x001F) && | ||
1069 | (width & 15) == 0) { | ||
1070 | /*printf("Using MMX 16-bit 565 dither\n");*/ | ||
1071 | swdata->Display1X = Color565DitherYV12MMX1X; | ||
1072 | } else { | ||
1073 | /*printf("Using C 16-bit dither\n");*/ | ||
1074 | swdata->Display1X = Color16DitherYV12Mod1X; | ||
1075 | } | ||
1076 | #else | ||
1077 | swdata->Display1X = Color16DitherYV12Mod1X; | ||
1078 | #endif | ||
1079 | swdata->Display2X = Color16DitherYV12Mod2X; | ||
1080 | } | ||
1081 | if ( display->format->BytesPerPixel == 3 ) { | ||
1082 | swdata->Display1X = Color24DitherYV12Mod1X; | ||
1083 | swdata->Display2X = Color24DitherYV12Mod2X; | ||
1084 | } | ||
1085 | if ( display->format->BytesPerPixel == 4 ) { | ||
1086 | #if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES | ||
1087 | /* inline assembly functions */ | ||
1088 | if ( SDL_HasMMX() && (Rmask == 0x00FF0000) && | ||
1089 | (Gmask == 0x0000FF00) && | ||
1090 | (Bmask == 0x000000FF) && | ||
1091 | (width & 15) == 0) { | ||
1092 | /*printf("Using MMX 32-bit dither\n");*/ | ||
1093 | swdata->Display1X = ColorRGBDitherYV12MMX1X; | ||
1094 | } else { | ||
1095 | /*printf("Using C 32-bit dither\n");*/ | ||
1096 | swdata->Display1X = Color32DitherYV12Mod1X; | ||
1097 | } | ||
1098 | #else | ||
1099 | swdata->Display1X = Color32DitherYV12Mod1X; | ||
1100 | #endif | ||
1101 | swdata->Display2X = Color32DitherYV12Mod2X; | ||
1102 | } | ||
1103 | break; | ||
1104 | case SDL_YUY2_OVERLAY: | ||
1105 | case SDL_UYVY_OVERLAY: | ||
1106 | case SDL_YVYU_OVERLAY: | ||
1107 | if ( display->format->BytesPerPixel == 2 ) { | ||
1108 | swdata->Display1X = Color16DitherYUY2Mod1X; | ||
1109 | swdata->Display2X = Color16DitherYUY2Mod2X; | ||
1110 | } | ||
1111 | if ( display->format->BytesPerPixel == 3 ) { | ||
1112 | swdata->Display1X = Color24DitherYUY2Mod1X; | ||
1113 | swdata->Display2X = Color24DitherYUY2Mod2X; | ||
1114 | } | ||
1115 | if ( display->format->BytesPerPixel == 4 ) { | ||
1116 | swdata->Display1X = Color32DitherYUY2Mod1X; | ||
1117 | swdata->Display2X = Color32DitherYUY2Mod2X; | ||
1118 | } | ||
1119 | break; | ||
1120 | default: | ||
1121 | /* We should never get here (caught above) */ | ||
1122 | break; | ||
1123 | } | ||
1124 | |||
1125 | /* Find the pitch and offset values for the overlay */ | ||
1126 | overlay->pitches = swdata->pitches; | ||
1127 | overlay->pixels = swdata->planes; | ||
1128 | switch (format) { | ||
1129 | case SDL_YV12_OVERLAY: | ||
1130 | case SDL_IYUV_OVERLAY: | ||
1131 | overlay->pitches[0] = overlay->w; | ||
1132 | overlay->pitches[1] = overlay->pitches[0] / 2; | ||
1133 | overlay->pitches[2] = overlay->pitches[0] / 2; | ||
1134 | overlay->pixels[0] = swdata->pixels; | ||
1135 | overlay->pixels[1] = overlay->pixels[0] + | ||
1136 | overlay->pitches[0] * overlay->h; | ||
1137 | overlay->pixels[2] = overlay->pixels[1] + | ||
1138 | overlay->pitches[1] * overlay->h / 2; | ||
1139 | overlay->planes = 3; | ||
1140 | break; | ||
1141 | case SDL_YUY2_OVERLAY: | ||
1142 | case SDL_UYVY_OVERLAY: | ||
1143 | case SDL_YVYU_OVERLAY: | ||
1144 | overlay->pitches[0] = overlay->w*2; | ||
1145 | overlay->pixels[0] = swdata->pixels; | ||
1146 | overlay->planes = 1; | ||
1147 | break; | ||
1148 | default: | ||
1149 | /* We should never get here (caught above) */ | ||
1150 | break; | ||
1151 | } | ||
1152 | |||
1153 | /* We're all done.. */ | ||
1154 | return(overlay); | ||
1155 | } | ||
1156 | |||
1157 | int SDL_LockYUV_SW(_THIS, SDL_Overlay *overlay) | ||
1158 | { | ||
1159 | return(0); | ||
1160 | } | ||
1161 | |||
1162 | void SDL_UnlockYUV_SW(_THIS, SDL_Overlay *overlay) | ||
1163 | { | ||
1164 | return; | ||
1165 | } | ||
1166 | |||
1167 | int SDL_DisplayYUV_SW(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) | ||
1168 | { | ||
1169 | struct private_yuvhwdata *swdata; | ||
1170 | int stretch; | ||
1171 | int scale_2x; | ||
1172 | SDL_Surface *display; | ||
1173 | Uint8 *lum, *Cr, *Cb; | ||
1174 | Uint8 *dstp; | ||
1175 | int mod; | ||
1176 | |||
1177 | swdata = overlay->hwdata; | ||
1178 | stretch = 0; | ||
1179 | scale_2x = 0; | ||
1180 | if ( src->x || src->y || src->w < overlay->w || src->h < overlay->h ) { | ||
1181 | /* The source rectangle has been clipped. | ||
1182 | Using a scratch surface is easier than adding clipped | ||
1183 | source support to all the blitters, plus that would | ||
1184 | slow them down in the general unclipped case. | ||
1185 | */ | ||
1186 | stretch = 1; | ||
1187 | } else if ( (src->w != dst->w) || (src->h != dst->h) ) { | ||
1188 | if ( (dst->w == 2*src->w) && | ||
1189 | (dst->h == 2*src->h) ) { | ||
1190 | scale_2x = 1; | ||
1191 | } else { | ||
1192 | stretch = 1; | ||
1193 | } | ||
1194 | } | ||
1195 | if ( stretch ) { | ||
1196 | if ( ! swdata->stretch ) { | ||
1197 | display = swdata->display; | ||
1198 | swdata->stretch = SDL_CreateRGBSurface( | ||
1199 | SDL_SWSURFACE, | ||
1200 | overlay->w, overlay->h, | ||
1201 | display->format->BitsPerPixel, | ||
1202 | display->format->Rmask, | ||
1203 | display->format->Gmask, | ||
1204 | display->format->Bmask, 0); | ||
1205 | if ( ! swdata->stretch ) { | ||
1206 | return(-1); | ||
1207 | } | ||
1208 | } | ||
1209 | display = swdata->stretch; | ||
1210 | } else { | ||
1211 | display = swdata->display; | ||
1212 | } | ||
1213 | switch (overlay->format) { | ||
1214 | case SDL_YV12_OVERLAY: | ||
1215 | lum = overlay->pixels[0]; | ||
1216 | Cr = overlay->pixels[1]; | ||
1217 | Cb = overlay->pixels[2]; | ||
1218 | break; | ||
1219 | case SDL_IYUV_OVERLAY: | ||
1220 | lum = overlay->pixels[0]; | ||
1221 | Cr = overlay->pixels[2]; | ||
1222 | Cb = overlay->pixels[1]; | ||
1223 | break; | ||
1224 | case SDL_YUY2_OVERLAY: | ||
1225 | lum = overlay->pixels[0]; | ||
1226 | Cr = lum + 3; | ||
1227 | Cb = lum + 1; | ||
1228 | break; | ||
1229 | case SDL_UYVY_OVERLAY: | ||
1230 | lum = overlay->pixels[0]+1; | ||
1231 | Cr = lum + 1; | ||
1232 | Cb = lum - 1; | ||
1233 | break; | ||
1234 | case SDL_YVYU_OVERLAY: | ||
1235 | lum = overlay->pixels[0]; | ||
1236 | Cr = lum + 1; | ||
1237 | Cb = lum + 3; | ||
1238 | break; | ||
1239 | default: | ||
1240 | SDL_SetError("Unsupported YUV format in blit"); | ||
1241 | return(-1); | ||
1242 | } | ||
1243 | if ( SDL_MUSTLOCK(display) ) { | ||
1244 | if ( SDL_LockSurface(display) < 0 ) { | ||
1245 | return(-1); | ||
1246 | } | ||
1247 | } | ||
1248 | if ( stretch ) { | ||
1249 | dstp = (Uint8 *)swdata->stretch->pixels; | ||
1250 | } else { | ||
1251 | dstp = (Uint8 *)display->pixels | ||
1252 | + dst->x * display->format->BytesPerPixel | ||
1253 | + dst->y * display->pitch; | ||
1254 | } | ||
1255 | mod = (display->pitch / display->format->BytesPerPixel); | ||
1256 | |||
1257 | if ( scale_2x ) { | ||
1258 | mod -= (overlay->w * 2); | ||
1259 | swdata->Display2X(swdata->colortab, swdata->rgb_2_pix, | ||
1260 | lum, Cr, Cb, dstp, overlay->h, overlay->w, mod); | ||
1261 | } else { | ||
1262 | mod -= overlay->w; | ||
1263 | swdata->Display1X(swdata->colortab, swdata->rgb_2_pix, | ||
1264 | lum, Cr, Cb, dstp, overlay->h, overlay->w, mod); | ||
1265 | } | ||
1266 | if ( SDL_MUSTLOCK(display) ) { | ||
1267 | SDL_UnlockSurface(display); | ||
1268 | } | ||
1269 | if ( stretch ) { | ||
1270 | display = swdata->display; | ||
1271 | SDL_SoftStretch(swdata->stretch, src, display, dst); | ||
1272 | } | ||
1273 | SDL_UpdateRects(display, 1, dst); | ||
1274 | |||
1275 | return(0); | ||
1276 | } | ||
1277 | |||
1278 | void SDL_FreeYUV_SW(_THIS, SDL_Overlay *overlay) | ||
1279 | { | ||
1280 | struct private_yuvhwdata *swdata; | ||
1281 | |||
1282 | swdata = overlay->hwdata; | ||
1283 | if ( swdata ) { | ||
1284 | if ( swdata->stretch ) { | ||
1285 | SDL_FreeSurface(swdata->stretch); | ||
1286 | } | ||
1287 | if ( swdata->pixels ) { | ||
1288 | SDL_free(swdata->pixels); | ||
1289 | } | ||
1290 | if ( swdata->colortab ) { | ||
1291 | SDL_free(swdata->colortab); | ||
1292 | } | ||
1293 | if ( swdata->rgb_2_pix ) { | ||
1294 | SDL_free(swdata->rgb_2_pix); | ||
1295 | } | ||
1296 | SDL_free(swdata); | ||
1297 | overlay->hwdata = NULL; | ||
1298 | } | ||
1299 | } | ||