This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_yuv_sw.c
1348 lines (1191 loc) · 41.8 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2009 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
11
12
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Lesser General Public License for more details.
14
15
16
17
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/* This code was derived from code carrying the following copyright notices:
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
* Copyright (c) 1995 Erik Corry
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
* SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
* THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#include "SDL_video.h"
87
#include "SDL_cpuinfo.h"
88
89
90
#include "SDL_yuv_sw_c.h"
91
92
struct SDL_SW_YUVTexture
{
93
Uint32 format;
94
Uint32 target_format;
95
int w, h;
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
Uint8 *pixels;
int *colortab;
Uint32 *rgb_2_pix;
void (*Display1X) (int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod);
void (*Display2X) (int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod);
/* These are just so we don't have to allocate them separately */
Uint16 pitches[3];
Uint8 *planes[3];
/* This is a temporary surface in case we have to stretch copy */
SDL_Surface *stretch;
SDL_Surface *display;
115
116
117
118
};
/* The colorspace conversion functions */
119
#if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES
120
extern void Color565DitherYV12MMX1X(int *colortab, Uint32 * rgb_2_pix,
121
122
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
123
124
125
126
127
128
129
130
131
132
133
134
int rows, int cols, int mod);
extern void ColorRGBDitherYV12MMX1X(int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod);
#endif
static void
Color16DitherYV12Mod1X(int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod)
135
{
136
137
138
unsigned short *row1;
unsigned short *row2;
unsigned char *lum2;
139
140
141
142
143
144
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
145
row1 = (unsigned short *) out;
146
147
148
149
150
151
row2 = row1 + cols + mod;
lum2 = lum + cols;
mod += cols + mod;
y = rows / 2;
152
while (y--) {
153
x = cols_2;
154
while (x--) {
155
156
register int L;
157
158
159
160
161
162
cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
+ colortab[*cb + 2 * 256];
cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
++cr;
++cb;
163
164
L = *lum++;
165
166
167
*row1++ = (unsigned short) (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] |
rgb_2_pix[L + cb_b]);
168
169
L = *lum++;
170
171
172
*row1++ = (unsigned short) (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] |
rgb_2_pix[L + cb_b]);
173
174
175
176
177
/* Now, do second row. */
L = *lum2++;
178
179
180
*row2++ = (unsigned short) (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] |
rgb_2_pix[L + cb_b]);
181
182
L = *lum2++;
183
184
185
*row2++ = (unsigned short) (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] |
rgb_2_pix[L + cb_b]);
186
187
188
189
190
191
192
}
/*
* These values are at the start of the next line, (due
* to the ++'s above),but they need to be at the start
* of the line after that.
*/
193
lum += cols;
194
195
196
197
198
199
lum2 += cols;
row1 += mod;
row2 += mod;
}
}
200
201
202
203
204
static void
Color24DitherYV12Mod1X(int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod)
205
206
{
unsigned int value;
207
208
209
unsigned char *row1;
unsigned char *row2;
unsigned char *lum2;
210
211
212
213
214
215
216
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
row1 = out;
217
row2 = row1 + cols * 3 + mod * 3;
218
219
220
221
222
223
lum2 = lum + cols;
mod += cols + mod;
mod *= 3;
y = rows / 2;
224
while (y--) {
225
x = cols_2;
226
while (x--) {
227
228
register int L;
229
230
231
232
233
234
cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
+ colortab[*cb + 2 * 256];
cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
++cr;
++cb;
235
236
L = *lum++;
237
238
239
240
value = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
*row1++ = (value) & 0xFF;
*row1++ = (value >> 8) & 0xFF;
241
242
243
*row1++ = (value >> 16) & 0xFF;
L = *lum++;
244
245
246
247
value = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
*row1++ = (value) & 0xFF;
*row1++ = (value >> 8) & 0xFF;
248
249
250
251
252
253
*row1++ = (value >> 16) & 0xFF;
/* Now, do second row. */
L = *lum2++;
254
255
256
257
value = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
*row2++ = (value) & 0xFF;
*row2++ = (value >> 8) & 0xFF;
258
259
260
*row2++ = (value >> 16) & 0xFF;
L = *lum2++;
261
262
263
264
value = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
*row2++ = (value) & 0xFF;
*row2++ = (value >> 8) & 0xFF;
265
266
267
268
269
270
271
272
*row2++ = (value >> 16) & 0xFF;
}
/*
* These values are at the start of the next line, (due
* to the ++'s above),but they need to be at the start
* of the line after that.
*/
273
lum += cols;
274
275
276
277
278
279
lum2 += cols;
row1 += mod;
row2 += mod;
}
}
280
281
282
283
284
static void
Color32DitherYV12Mod1X(int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod)
285
{
286
287
288
unsigned int *row1;
unsigned int *row2;
unsigned char *lum2;
289
290
291
292
293
294
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
295
row1 = (unsigned int *) out;
296
297
298
299
300
301
row2 = row1 + cols + mod;
lum2 = lum + cols;
mod += cols + mod;
y = rows / 2;
302
while (y--) {
303
x = cols_2;
304
while (x--) {
305
306
register int L;
307
308
309
310
311
312
cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
+ colortab[*cb + 2 * 256];
cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
++cr;
++cb;
313
314
L = *lum++;
315
316
*row1++ = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
317
318
L = *lum++;
319
320
*row1++ = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
321
322
323
324
325
/* Now, do second row. */
L = *lum2++;
326
327
*row2++ = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
328
329
L = *lum2++;
330
331
*row2++ = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
332
333
334
335
336
337
338
}
/*
* These values are at the start of the next line, (due
* to the ++'s above),but they need to be at the start
* of the line after that.
*/
339
lum += cols;
340
341
342
343
344
345
346
347
348
349
350
lum2 += cols;
row1 += mod;
row2 += mod;
}
}
/*
* In this function I make use of a nasty trick. The tables have the lower
* 16 bits replicated in the upper 16. This means I can write ints and get
* the horisontal doubling for free (almost).
*/
351
352
353
354
355
static void
Color16DitherYV12Mod2X(int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod)
356
{
357
358
359
360
unsigned int *row1 = (unsigned int *) out;
const int next_row = cols + (mod / 2);
unsigned int *row2 = row1 + 2 * next_row;
unsigned char *lum2;
361
362
363
364
365
366
367
368
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
lum2 = lum + cols;
369
mod = (next_row * 3) + (mod / 2);
370
371
y = rows / 2;
372
while (y--) {
373
x = cols_2;
374
while (x--) {
375
376
register int L;
377
378
379
380
381
382
cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
+ colortab[*cb + 2 * 256];
cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
++cr;
++cb;
383
384
L = *lum++;
385
386
387
row1[0] = row1[next_row] = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] |
rgb_2_pix[L + cb_b]);
388
389
390
row1++;
L = *lum++;
391
392
393
row1[0] = row1[next_row] = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] |
rgb_2_pix[L + cb_b]);
394
395
396
397
398
399
row1++;
/* Now, do second row. */
L = *lum2++;
400
401
402
row2[0] = row2[next_row] = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] |
rgb_2_pix[L + cb_b]);
403
404
405
row2++;
L = *lum2++;
406
407
408
row2[0] = row2[next_row] = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] |
rgb_2_pix[L + cb_b]);
409
410
411
412
413
414
415
416
row2++;
}
/*
* These values are at the start of the next line, (due
* to the ++'s above),but they need to be at the start
* of the line after that.
*/
417
lum += cols;
418
419
420
421
422
423
lum2 += cols;
row1 += mod;
row2 += mod;
}
}
424
425
426
427
428
static void
Color24DitherYV12Mod2X(int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod)
429
430
{
unsigned int value;
431
432
433
434
unsigned char *row1 = out;
const int next_row = (cols * 2 + mod) * 3;
unsigned char *row2 = row1 + 2 * next_row;
unsigned char *lum2;
435
436
437
438
439
440
441
442
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
lum2 = lum + cols;
443
mod = next_row * 3 + mod * 3;
444
445
y = rows / 2;
446
while (y--) {
447
x = cols_2;
448
while (x--) {
449
450
register int L;
451
452
453
454
455
456
cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
+ colortab[*cb + 2 * 256];
cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
++cr;
++cb;
457
458
L = *lum++;
459
460
461
462
463
464
465
466
467
value = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
row1[0 + 0] = row1[3 + 0] = row1[next_row + 0] =
row1[next_row + 3 + 0] = (value) & 0xFF;
row1[0 + 1] = row1[3 + 1] = row1[next_row + 1] =
row1[next_row + 3 + 1] = (value >> 8) & 0xFF;
row1[0 + 2] = row1[3 + 2] = row1[next_row + 2] =
row1[next_row + 3 + 2] = (value >> 16) & 0xFF;
row1 += 2 * 3;
468
469
L = *lum++;
470
471
472
473
474
475
476
477
478
value = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
row1[0 + 0] = row1[3 + 0] = row1[next_row + 0] =
row1[next_row + 3 + 0] = (value) & 0xFF;
row1[0 + 1] = row1[3 + 1] = row1[next_row + 1] =
row1[next_row + 3 + 1] = (value >> 8) & 0xFF;
row1[0 + 2] = row1[3 + 2] = row1[next_row + 2] =
row1[next_row + 3 + 2] = (value >> 16) & 0xFF;
row1 += 2 * 3;
479
480
481
482
483
/* Now, do second row. */
L = *lum2++;
484
485
486
487
488
489
490
491
492
value = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
row2[0 + 0] = row2[3 + 0] = row2[next_row + 0] =
row2[next_row + 3 + 0] = (value) & 0xFF;
row2[0 + 1] = row2[3 + 1] = row2[next_row + 1] =
row2[next_row + 3 + 1] = (value >> 8) & 0xFF;
row2[0 + 2] = row2[3 + 2] = row2[next_row + 2] =
row2[next_row + 3 + 2] = (value >> 16) & 0xFF;
row2 += 2 * 3;
493
494
L = *lum2++;
495
496
497
498
499
500
501
502
503
value = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
row2[0 + 0] = row2[3 + 0] = row2[next_row + 0] =
row2[next_row + 3 + 0] = (value) & 0xFF;
row2[0 + 1] = row2[3 + 1] = row2[next_row + 1] =
row2[next_row + 3 + 1] = (value >> 8) & 0xFF;
row2[0 + 2] = row2[3 + 2] = row2[next_row + 2] =
row2[next_row + 3 + 2] = (value >> 16) & 0xFF;
row2 += 2 * 3;
504
505
506
507
508
509
510
}
/*
* These values are at the start of the next line, (due
* to the ++'s above),but they need to be at the start
* of the line after that.
*/
511
lum += cols;
512
513
514
515
516
517
lum2 += cols;
row1 += mod;
row2 += mod;
}
}
518
519
520
521
522
static void
Color32DitherYV12Mod2X(int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod)
523
{
524
525
526
527
unsigned int *row1 = (unsigned int *) out;
const int next_row = cols * 2 + mod;
unsigned int *row2 = row1 + 2 * next_row;
unsigned char *lum2;
528
529
530
531
532
533
534
535
536
537
538
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
lum2 = lum + cols;
mod = (next_row * 3) + mod;
y = rows / 2;
539
while (y--) {
540
x = cols_2;
541
while (x--) {
542
543
register int L;
544
545
546
547
548
549
cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
+ colortab[*cb + 2 * 256];
cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
++cr;
++cb;
550
551
L = *lum++;
552
553
554
row1[0] = row1[1] = row1[next_row] = row1[next_row + 1] =
(rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
555
556
557
row1 += 2;
L = *lum++;
558
559
560
row1[0] = row1[1] = row1[next_row] = row1[next_row + 1] =
(rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
561
562
563
564
565
566
row1 += 2;
/* Now, do second row. */
L = *lum2++;
567
568
569
row2[0] = row2[1] = row2[next_row] = row2[next_row + 1] =
(rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
570
571
572
row2 += 2;
L = *lum2++;
573
574
575
row2[0] = row2[1] = row2[next_row] = row2[next_row + 1] =
(rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
576
577
578
579
580
581
582
583
row2 += 2;
}
/*
* These values are at the start of the next line, (due
* to the ++'s above),but they need to be at the start
* of the line after that.
*/
584
lum += cols;
585
586
587
588
589
590
lum2 += cols;
row1 += mod;
row2 += mod;
}
}
591
592
593
594
595
static void
Color16DitherYUY2Mod1X(int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod)
596
{
597
unsigned short *row;
598
599
600
601
602
603
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
604
row = (unsigned short *) out;
605
606
y = rows;
607
while (y--) {
608
x = cols_2;
609
while (x--) {
610
611
register int L;
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
+ colortab[*cb + 2 * 256];
cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
cr += 4;
cb += 4;
L = *lum;
lum += 2;
*row++ = (unsigned short) (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] |
rgb_2_pix[L + cb_b]);
L = *lum;
lum += 2;
*row++ = (unsigned short) (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] |
rgb_2_pix[L + cb_b]);
630
631
632
633
634
635
636
}
row += mod;
}
}
637
638
639
640
641
static void
Color24DitherYUY2Mod1X(int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod)
642
643
{
unsigned int value;
644
unsigned char *row;
645
646
647
648
649
650
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
651
row = (unsigned char *) out;
652
653
mod *= 3;
y = rows;
654
while (y--) {
655
x = cols_2;
656
while (x--) {
657
658
register int L;
659
660
661
662
663
664
665
666
667
668
669
670
671
cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
+ colortab[*cb + 2 * 256];
cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
cr += 4;
cb += 4;
L = *lum;
lum += 2;
value = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
*row++ = (value) & 0xFF;
*row++ = (value >> 8) & 0xFF;
672
673
*row++ = (value >> 16) & 0xFF;
674
675
676
677
678
679
L = *lum;
lum += 2;
value = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
*row++ = (value) & 0xFF;
*row++ = (value >> 8) & 0xFF;
680
681
682
683
684
685
686
*row++ = (value >> 16) & 0xFF;
}
row += mod;
}
}
687
688
689
690
691
static void
Color32DitherYUY2Mod1X(int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod)
692
{
693
unsigned int *row;
694
695
696
697
698
699
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
700
row = (unsigned int *) out;
701
y = rows;
702
while (y--) {
703
x = cols_2;
704
while (x--) {
705
706
register int L;
707
708
709
710
711
712
cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
+ colortab[*cb + 2 * 256];
cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
cr += 4;
cb += 4;
713
714
715
716
717
L = *lum;
lum += 2;
*row++ = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
718
719
720
721
722
L = *lum;
lum += 2;
*row++ = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
723
724
725
726
727
728
729
730
731
732
733
734
}
row += mod;
}
}
/*
* In this function I make use of a nasty trick. The tables have the lower
* 16 bits replicated in the upper 16. This means I can write ints and get
* the horisontal doubling for free (almost).
*/
735
736
737
738
739
static void
Color16DitherYUY2Mod2X(int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod)
740
{
741
742
unsigned int *row = (unsigned int *) out;
const int next_row = cols + (mod / 2);
743
744
745
746
747
748
749
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
y = rows;
750
while (y--) {
751
x = cols_2;
752
while (x--) {
753
754
register int L;
755
756
757
758
759
760
761
762
763
764
765
766
cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
+ colortab[*cb + 2 * 256];
cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
cr += 4;
cb += 4;
L = *lum;
lum += 2;
row[0] = row[next_row] = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] |
rgb_2_pix[L + cb_b]);
767
768
row++;
769
770
771
772
773
L = *lum;
lum += 2;
row[0] = row[next_row] = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] |
rgb_2_pix[L + cb_b]);
774
775
776
777
778
779
780
row++;
}
row += next_row;
}
}
781
782
783
784
785
static void
Color24DitherYUY2Mod2X(int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod)
786
787
{
unsigned int value;
788
789
unsigned char *row = out;
const int next_row = (cols * 2 + mod) * 3;
790
791
792
793
794
795
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
y = rows;
796
while (y--) {
797
x = cols_2;
798
while (x--) {
799
800
register int L;
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
+ colortab[*cb + 2 * 256];
cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
cr += 4;
cb += 4;
L = *lum;
lum += 2;
value = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
row[0 + 0] = row[3 + 0] = row[next_row + 0] =
row[next_row + 3 + 0] = (value) & 0xFF;
row[0 + 1] = row[3 + 1] = row[next_row + 1] =
row[next_row + 3 + 1] = (value >> 8) & 0xFF;
row[0 + 2] = row[3 + 2] = row[next_row + 2] =
row[next_row + 3 + 2] = (value >> 16) & 0xFF;
row += 2 * 3;
L = *lum;
lum += 2;
value = (rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
row[0 + 0] = row[3 + 0] = row[next_row + 0] =
row[next_row + 3 + 0] = (value) & 0xFF;
row[0 + 1] = row[3 + 1] = row[next_row + 1] =
row[next_row + 3 + 1] = (value >> 8) & 0xFF;
row[0 + 2] = row[3 + 2] = row[next_row + 2] =
row[next_row + 3 + 2] = (value >> 16) & 0xFF;
row += 2 * 3;
831
832
833
834
835
836
}
row += next_row;
}
}
837
838
839
840
841
static void
Color32DitherYUY2Mod2X(int *colortab, Uint32 * rgb_2_pix,
unsigned char *lum, unsigned char *cr,
unsigned char *cb, unsigned char *out,
int rows, int cols, int mod)
842
{
843
844
unsigned int *row = (unsigned int *) out;
const int next_row = cols * 2 + mod;
845
846
847
848
849
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
850
mod += mod;
851
y = rows;
852
while (y--) {
853
x = cols_2;
854
while (x--) {
855
856
register int L;
857
858
859
860
861
862
863
864
865
866
867
868
cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256]
+ colortab[*cb + 2 * 256];
cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
cr += 4;
cb += 4;
L = *lum;
lum += 2;
row[0] = row[1] = row[next_row] = row[next_row + 1] =
(rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
869
870
row += 2;
871
872
873
874
875
L = *lum;
lum += 2;
row[0] = row[1] = row[next_row] = row[next_row + 1] =
(rgb_2_pix[L + cr_r] |
rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
876
877
878
879
880
881
882
883
884
885
886
887
888
row += 2;
}
row += next_row;
}
}
/*
* How many 1 bits are there in the Uint32.
* Low performance, do not call often.
*/
889
890
static int
number_of_bits_set(Uint32 a)
891
{
892
893
894
895
896
if (!a)
return 0;
if (a & 1)
return 1 + number_of_bits_set(a >> 1);
return (number_of_bits_set(a >> 1));
897
898
899
900
901
902
}
/*
* How many 0 bits are there at least significant end of Uint32.
* Low performance, do not call often.
*/
903
904
static int
free_bits_at_bottom(Uint32 a)
905
{
906
907
908
909
910
911
/* assume char is 8 bits */
if (!a)
return sizeof(Uint32) * 8;
if (((Sint32) a) & 1l)
return 0;
return 1 + free_bits_at_bottom(a >> 1);
912
913
}
914
915
static int
SDL_SW_SetupYUVDisplay(SDL_SW_YUVTexture * swdata, Uint32 target_format)
916
{
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
Uint32 *r_2_pix_alloc;
Uint32 *g_2_pix_alloc;
Uint32 *b_2_pix_alloc;
int i;
int bpp;
Uint32 Rmask, Gmask, Bmask, Amask;
if (!SDL_PixelFormatEnumToMasks
(target_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask) || bpp < 15) {
SDL_SetError("Unsupported YUV destination format");
return -1;
}
swdata->target_format = target_format;
r_2_pix_alloc = &swdata->rgb_2_pix[0 * 768];
g_2_pix_alloc = &swdata->rgb_2_pix[1 * 768];
b_2_pix_alloc = &swdata->rgb_2_pix[2 * 768];
/*
* Set up entries 0-255 in rgb-to-pixel value tables.
*/
for (i = 0; i < 256; ++i) {
r_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Rmask));
r_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Rmask);
941
r_2_pix_alloc[i + 256] |= Amask;
942
943
g_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Gmask));
g_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Gmask);
944
g_2_pix_alloc[i + 256] |= Amask;
945
946
b_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Bmask));
b_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Bmask);
947
b_2_pix_alloc[i + 256] |= Amask;
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
}
/*
* If we have 16-bit output depth, then we double the value
* in the top word. This means that we can write out both
* pixels in the pixel doubling mode with one op. It is
* harmless in the normal case as storing a 32-bit value
* through a short pointer will lose the top bits anyway.
*/
if (SDL_BYTESPERPIXEL(target_format) == 2) {
for (i = 0; i < 256; ++i) {
r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16;
g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16;
b_2_pix_alloc[i + 256] |= (b_2_pix_alloc[i + 256]) << 16;
}
}
/*
* Spread out the values we have to the rest of the array so that
* we do not need to check for overflow.
*/
for (i = 0; i < 256; ++i) {
r_2_pix_alloc[i] = r_2_pix_alloc[256];
r_2_pix_alloc[i + 512] = r_2_pix_alloc[511];
g_2_pix_alloc[i] = g_2_pix_alloc[256];
g_2_pix_alloc[i + 512] = g_2_pix_alloc[511];
b_2_pix_alloc[i] = b_2_pix_alloc[256];
b_2_pix_alloc[i + 512] = b_2_pix_alloc[511];
}
/* You have chosen wisely... */
979
switch (swdata->format) {
980
981
case SDL_PIXELFORMAT_YV12:
case SDL_PIXELFORMAT_IYUV:
982
if (SDL_BYTESPERPIXEL(target_format) == 2) {
983
#if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES
984
985
/* inline assembly functions */
if (SDL_HasMMX() && (Rmask == 0xF800) &&
986
(Gmask == 0x07E0) && (Bmask == 0x001F)
987
&& (swdata->w & 15) == 0) {
988
/*printf("Using MMX 16-bit 565 dither\n");*/
989
990
swdata->Display1X = Color565DitherYV12MMX1X;
} else {
991
/*printf("Using C 16-bit dither\n");*/
992
993
swdata->Display1X = Color16DitherYV12Mod1X;
}
994
#else
995
swdata->Display1X = Color16DitherYV12Mod1X;
996
#endif
997
998
999
1000
swdata->Display2X = Color16DitherYV12Mod2X;
}
if (SDL_BYTESPERPIXEL(target_format) == 3) {
swdata->Display1X = Color24DitherYV12Mod1X;