root/OpenSceneGraph/trunk/src/osgPlugins/xine/video_out_rgb.c @ 6607

Revision 6607, 71.6 kB (checked in by robert, 8 years ago)

Added first cut a Xine support

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * Copyright (C) 2000-2003 the xine project and Claudio "KLaN" Ciccani
3 *
4 * This file is part of xine, a free video player.
5 *
6 * xine is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * xine is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
19 *
20 *
21 * video_out_rgb.c, general purpose rgb video output xine driver
22 *                      by Claudio "KLaN" Ciccani <klan82@cheapnet.it>
23 *
24 * ...someway based on video_ou_xshm.c
25 *
26 *
27 * NOTE: this driver is not able to display videos itself;
28 *       however it can be used in every graphics environment
29 *       and not only for playback (either video processing,
30 *       frame dumping ... what you want)
31 *
32 *
33 *  TODO: a good scaling function, hue, saturation,
34 *        contrast, applying effects and many more
35 *        (eg. SSE2 support, if someone buy me a new procesor).
36 *
37 */
38
39#include <stdio.h>
40#include <stdlib.h>
41#include <stdint.h>
42#include <string.h>
43#include <pthread.h>
44
45#include <fcntl.h>
46#include <unistd.h>
47
48#include "xine.h"
49#include "xine/xine_internal.h"
50#include "xine/xineutils.h"
51#include "xine/video_out.h"
52#include "video_out_rgb.h"
53
54
55#define THIS  "video_out_rgb"
56
57static int s_debugMessages = 0;
58
59#define EVAL(exp) \
60{\
61        if(!(exp))\
62        {\
63                fprintf(stderr, THIS ": <\"" #exp "\"> evaluation failed !!\n");\
64                fflush(stderr);\
65                goto FAILURE;\
66        }\
67}
68
69#define CHECK(exp) \
70{\
71        if(!(exp))\
72        {\
73                fprintf(stderr, THIS ": <\"" #exp "\"> check failed !!\n");\
74                fflush(stderr);\
75        }\
76}
77
78#define release(ptr) \
79{\
80        if(ptr) free(ptr);\
81        ptr = NULL;\
82}
83
84#ifdef __cplusplus
85extern "C" {
86#endif
87
88static inline void
89clear(void* dest, uint32_t size)
90{
91#ifdef COMPILE_ASSEMBLY
92        __asm__ __volatile__(
93
94                "xorl %%eax, %%eax\n\t"
95                "movl %1, %%ecx\n\t"
96                "rep; stosl\n\t"
97                "movl %2, %%ecx\n\t"
98                "rep; stosb\n\t"
99               
100                : "=&D" (dest)
101                : "r" (size >> 2), "r" (size & 3), "0" (dest)
102                : "eax", "ecx");
103#endif
104}
105
106#ifdef DEBUG
107
108static inline uint64_t rdtsc()
109{
110        uint64_t t;
111       
112        __asm__ __volatile__(
113                ".byte 0x0f, 0x31\n\t"
114                : "=A" (t));
115       
116        return(t);
117}
118
119#endif /* DEBUG */
120
121
122
123/*
124 * I'm using this formula for colorspace conversion:
125 *
126 *      R = Y + (1.420705 * U)
127 *      G = Y - (0.698001 * U) - (0.337633 * V)
128 *      B = Y + (1.732446 * V)
129 *
130 * First YUV chunks are converted and put into a
131 * rgb_planar_t structure, then packed into the
132 * specified RGB pixel format.
133 * I'm using this method because I need RGB levels to
134 * be separated for effects stuff (currently only
135 * selecting levels).
136 *
137 */
138
139
140/* floating point factors; used by 3DNow and SSE */
141static const float fp_factors[] =
142{
143        1.420705, 1.420705,
144        0.698001, 0.698001,
145        0.337633, 0.337633,
146        1.732446, 1.732446
147};
148
149
150/* used by MMX;
151 * each factor is multiplied by 2^14 and rounded
152 */
153static const int16_t wd_factors[] =
154{
155        0x4000,  23277, 0x4000,  23277,
156        0x4000,  28384, 0x4000,  28384,
157         11436,   5532,  11436,   5532
158};
159
160
161/* used by normal C function;
162 * each factor is multiplied by 2^16 and rounded
163 */
164static const int32_t dw_factors[] =
165{
166         93107,
167         45744,
168         22127,
169        113538,
170};
171
172
173/* used by 3DNow for rounding values */
174static const float round[] =
175{
176        0.555555,
177        0.555555
178};
179
180static const uint32_t lsub[] =
181{
182        128, 128
183};
184
185static const uint32_t lmask[] =
186{
187        0xff, 0xff
188};
189
190static const uint16_t wmask[] =
191{
192        0xff, 0xff,
193        0xff, 0xff
194};
195
196
197
198#ifdef COMPILE_ASSEMBLY
199
200static void
201__3dnow_convert_yuy2(uint8_t* yuv[], rgb_planar_t* rgb,
202                         uint32_t pitches[], uint32_t width, uint32_t height)
203{
204        uint8_t* yuv_data = yuv[0];
205        uint8_t* r_buffer = rgb->r;
206        uint8_t* g_buffer = rgb->g;
207        uint8_t* b_buffer = rgb->b;
208        uint32_t samples = (width * height) >> 2; /* 4 pixels at once */
209
210
211        __asm__ __volatile__("femms\n\t");
212
213        while(samples--)
214        {
215                __asm__ __volatile__(
216
217                        "prefetch 192(%0)\n\t"
218
219                        "movq (%0), %%mm1\n\t" /* mm1 = [v2 y3 u2 y2 v0 y1 u0 y0] */
220
221                        "movq %%mm1, %%mm3\n\t" /* mm3 = [v2 y3 u2 y2 v0 y1 u0 y0] */
222                        "pand (%1), %%mm3\n\t" /*  mm3 = [0 y3 0 y2 0 y1 0 y0] */
223
224                        "movq %%mm1, %%mm2\n\t" /* mm2 = [v2 y3 u2 y2 v0 y1 u0 y0] */
225                        "psrld $8, %%mm2\n\t" /* mm2 = [0 v2 y3 u2 0 v0 y1 u0] */
226                        "pand (%2), %%mm2\n\t" /* mm2 = [0 0 0 u2 0 0 0 u0] */
227                        "psubd (%3), %%mm2\n\t" /* mm2 = [u2 - 128 | u2 - 128] */
228                        "pi2fd %%mm2, %%mm2\n\t"
229
230                        "psrld $24, %%mm1\n\t" /* mm1 = [0 0 0 v2 0 0 0 v0] */
231                        "psubd (%3), %%mm1\n\t" /* mm1 = [v2 - 128 | v0 - 128] */
232                        "pi2fd %%mm1, %%mm1\n\t"
233
234                        "addl $8, %0\n\t"
235
236                        : "=&r" (yuv_data)
237                        : "r" (wmask), "r" (lmask), "r" (lsub), "0" (yuv_data)
238                        : "memory");
239
240
241                __asm__ __volatile__(
242
243                        "prefetchw 320(%0)\n\t"
244
245                        "movq %%mm1, %%mm0\n\t" /* mm0 = [v2 | v0] */
246                        "pfmul (%3), %%mm0\n\t" /* mm0 = [v2 * 1.420705 | v0 * 1.420705] */
247                        "pfadd (%4), %%mm0\n\t" /* rounded */
248                        "pf2id %%mm0, %%mm0\n\t"
249                        "packssdw %%mm0, %%mm0\n\t" /* mm0 = [v2 * 1.420705 | v0 * 1.420705 | ...] */
250                        "punpckhwd %%mm0, %%mm0\n\t" /* mm0 = [v2 * 1.420705 | v2 * 1.420705 |
251                                                                v0 * 1.420705 | v0 * 1.420705] */
252                        "paddw %%mm3, %%mm0\n\t" /* mm0 = [0 r3 0 r2 0 r1 0 r0] */
253                        "packuswb %%mm0, %%mm0\n\t" /* mm0 = [r3 r2 r1 r0 r3 r2 r1 r0] */
254                        "movd %%mm0, (%0)\n\t"
255
256                        "prefetchw 320(%2)\n\t"
257
258                        "movq %%mm2, %%mm0\n\t" /* mm0 = [u2 | u0] */
259                        "pfmul 24(%3), %%mm0\n\t" /* mm0 = [u2 * 1.732446 | u0 * 1.732446] */
260                        "pfadd (%4), %%mm0\n\t" /* rounded */
261                        "pf2id %%mm0, %%mm0\n\t"
262                        "packssdw %%mm0, %%mm0\n\t" /* mm0 = [u2 * 1.732446 | u0 * 1.732446 | ...] */
263                        "punpckhwd %%mm0, %%mm0\n\t" /* mm0 = [u2 * 1.732446 | u2 * 1.732446 |
264                                                                u0 * 1.732446 | u0 * 1.732446] */
265                        "paddw %%mm3, %%mm0\n\t" /* mm0 = [0 b3 0 b2 0 b1 0 b0] */
266                        "packuswb %%mm0, %%mm0\n\t" /* mm0 = [b3 b2 b1 b0 b3 b2 b1 b0] */
267                        "movd %%mm0, (%2)\n\t"
268
269                        "prefetchw 320(%1)\n\t"
270
271                        "pfmul 8(%3), %%mm1\n\t" /* mm1 = [v2 * 0.698001 | v0 * 0.698001] */
272                        "pfmul 16(%3), %%mm2\n\t" /* mm2 = [u2 * 0.337633 | u0 * 0.337633] */
273                        "pfadd %%mm1, %%mm2\n\t" /* mm2 = [(v2 * 0.698001) + (u2 * 0.337633) | ...] */
274                        "pfadd (%4), %%mm2\n\t" /* rounded */
275                        "pf2id %%mm2, %%mm2\n\t"
276                        "packssdw %%mm2, %%mm2\n\t" /* mm2 = [(v2 * 0.698001) + (u2 * 0.337633) |
277                                                                (v0 * 0.698001) + (u0 * 0.337633)| ...] */
278                        "punpckhwd %%mm2, %%mm2\n\t" /* mm2 = [(v2 * 0.698001) + (u2 * 0.337633) |
279                                                                (v2 * 0.698001) + (u2 * 0.337633)| ...] */
280                        "psubw %%mm2, %%mm3\n\t" /* mm3 = [0 g3 0 g2 0 g1 0 g0] */
281                        "packuswb %%mm3, %%mm3\n\t" /* mm3 = [g3 g2 g1 g0 g3 g2 g1 g0] */
282                        "movd %%mm3, (%1)\n\t"
283
284                        "addl $4, %0\n\t"
285                        "addl $4, %1\n\t"
286                        "addl $4, %2\n\t"
287
288                        : "=&r" (r_buffer), "=&r" (g_buffer), "=&r" (b_buffer)
289                        : "r" (fp_factors), "r" (round),
290                          "0" (r_buffer), "1" (g_buffer), "2" (b_buffer)
291                        : "memory");
292
293        }
294
295        __asm__ __volatile__("femms\n\t");
296}
297
298
299static void
300__3dnow_convert_yv12(uint8_t* yuv[], rgb_planar_t* rgb,
301                         uint32_t pitches[], uint32_t width, uint32_t height)
302{
303        uint8_t* y_data = yuv[0];
304        uint8_t* u_data = yuv[1];
305        uint8_t* v_data = yuv[2];
306        uint8_t* r_buffer = rgb->r;
307        uint8_t* g_buffer = rgb->g;
308        uint8_t* b_buffer = rgb->b;
309        uint32_t line_size = width >> 2; /* 4 pixels at once */
310        uint32_t samples   = line_size * (height >> 1);
311
312
313        __asm__ __volatile__(
314                "femms\n\t"
315                "pxor %%mm7, %%mm7\n\t"
316                ::: "memory");
317
318        while(samples--)
319        {
320                __asm__ __volatile__(
321
322                        "prefetch 192(%0)\n\t"
323                        "prefetch 192(%1)\n\t"
324                        "prefetch 192(%2)\n\t"
325                        "prefetch 192(%3)\n\t"
326
327                        "movd (%0), %%mm6\n\t" /* mm6 = [0 0 0 0 y03 y02 y01 y00] */
328                        "movd (%1), %%mm5\n\t" /* mm5 = [0 0 0 0 y13 y12 y11 y10] */
329                        "movd (%2), %%mm1\n\t" /* mm1 = [0 0 0 0 u12 u8 u4 u0] */
330                        "movd (%3), %%mm0\n\t" /* mm0 = [0 0 0 0 v12 v8 v4 v0] */
331
332                        "punpcklbw %%mm7, %%mm6\n\t" /* mm6 = [0 y03 0 y02 0 y01 0 y00] */
333                        "punpcklbw %%mm7, %%mm5\n\t" /* mm5 = [0 y13 0 y12 0 y11 0 y10] */
334
335                        "punpcklbw %%mm7, %%mm1\n\t" /* mm1 = [0 u12 0 u8 0 u4 0 u0] */
336                        "punpcklwd %%mm7, %%mm1\n\t" /* mm1 = [0 0 0 u4 0 0 0 u0] */
337                        "psubd (%4), %%mm1\n\t" /* mm1 = [u4 - 128 | u0 - 128] */
338                        "pi2fd %%mm1, %%mm1\n\t"
339
340                        "punpcklbw %%mm7, %%mm0\n\t" /* mm0 = [0 v12 0 v8 0 v4 0 v0] */
341                        "punpcklwd %%mm7, %%mm0\n\t" /* mm0 = [0 0 0 v4 0 0 0 v0] */
342                        "psubd (%4), %%mm0\n\t" /* mm0 = [v4 - 128 | v0 - 128] */
343                        "pi2fd %%mm0, %%mm0\n\t"
344
345                        :: "r" (y_data), "r" (y_data + pitches[0]),
346                           "r" (u_data), "r" (v_data), "r" (lsub)
347                        : "memory");
348
349
350                __asm__ __volatile__(
351
352                        "movq %%mm0, %%mm3\n\t" /* mm3 = [v4 | v0] */
353                        "pfmul (%0), %%mm3\n\t" /* mm3 = [v4 * 1.420705 | v0 * 1.420705] */
354                        "pfadd (%1), %%mm3\n\t" /* rounded */
355                        "pf2id %%mm3, %%mm3\n\t"
356                        "packssdw %%mm3, %%mm3\n\t" /* mm3 = [v4 * 1.420705 | v0 * 1.420705 | ...] */
357                        "punpckhwd %%mm3, %%mm3\n\t" /* mm3 = [v4 * 1.420705 | v4 * 1.420705 |
358                                                                v0 * 1.420705 | v0 * 1.420705] */
359
360                        "movq %%mm1, %%mm2\n\t" /* mm2 = [u4 | u0] */
361                        "pfmul 24(%0), %%mm2\n\t" /* mm2 = [u4 * 1.732446 | u0 * 1.732446] */
362                        "pfadd (%1), %%mm2\n\t" /* rounded */
363                        "pf2id %%mm2, %%mm2\n\t"
364                        "packssdw %%mm2, %%mm2\n\t" /* mm2 = [u4 * 1.732446 | u0 * 1.732446 | ...] */
365                        "punpckhwd %%mm2, %%mm2\n\t" /* mm2 = [u4 * 1.732446 | u4 * 1.732446 |
366                                                                u0 * 1.732446 | u0 * 1.732446] */
367
368                        "pfmul 8(%0), %%mm0\n\t" /* mm0 = [v4 * 0.698001 | v0 * 0.698001] */
369                        "pfmul 16(%0), %%mm1\n\t" /* mm1 = [u4 * 0.337633 | u0 * 0.337633] */
370                        "pfadd %%mm0, %%mm1\n\t" /* mm1 = [(v4 * 0.698001) + (u4 * 0.337633) | ...] */
371                        "pfadd (%1), %%mm1\n\t" /* rounded */
372                        "pf2id %%mm1, %%mm1\n\t"
373                        "packssdw %%mm1, %%mm1\n\t" /* mm1 = [(v4 * 0.698001) + (u4 * 0.337633) |
374                                                                (v0 * 0.698001) + (u0 * 0.337633)| ...] */
375                        "punpckhwd %%mm1, %%mm1\n\t" /* mm1 = [(v4 * 0.698001) + (u4 * 0.337633) |
376                                                                (v4 * 0.698001) + (u4 * 0.337633)| ...] */
377
378                        :: "r" (fp_factors), "r" (round)
379                        : "memory");
380
381
382                __asm__ __volatile__(
383
384                        "prefetchw 320(%0)\n\t"
385
386                        "movq %%mm6, %%mm0\n\t"
387                        "paddw %%mm3, %%mm0\n\t" /* mm0 = [0 r03 0 r02 0 r01 0 r00] */
388                        "packuswb %%mm0, %%mm0\n\t" /* mm0 = [r03 r02 r01 r00 r03 r02 r01 r00] */
389                        "movd %%mm0, (%0)\n\t"
390                        "paddw %%mm5, %%mm3\n\t" /* mm3 = [0 r13 0 r12 0 r11 0 r10] */
391                        "packuswb %%mm3, %%mm3\n\t" /* mm3 = [r13 r12 r11 r10 r13 r12 r11 r10] */
392                        "movd %%mm3, (%1)\n\t"
393
394                        "addl $4, %0\n\t"
395
396                        : "=&r" (r_buffer)
397                        : "r" (r_buffer + width), "0" (r_buffer)
398                        : "memory");
399
400
401                __asm__ __volatile__(
402
403                        "prefetchw 320(%0)\n\t"
404
405                        "movq %%mm6, %%mm0\n\t"
406                        "paddw %%mm2, %%mm0\n\t" /* mm0 = [0 b03 0 b02 0 b01 0 b00] */
407                        "packuswb %%mm0, %%mm0\n\t" /* mm0 = [b03 b02 b01 b00 b03 b02 b01 b00] */
408                        "movd %%mm0, (%0)\n\t"
409                        "paddw %%mm5, %%mm2\n\t" /* mm2 = [0 b13 0 b12 0 b11 0 b10] */
410                        "packuswb %%mm2, %%mm2\n\t" /* mm2 = [b13 b12 b11 b10 b13 b12 b11 b10] */
411                        "movd %%mm2, (%1)\n\t"
412
413                        "addl $4, %0\n\t"
414
415                        : "=&r" (b_buffer)
416                        : "r" (b_buffer + width), "0" (b_buffer)
417                        : "memory");
418
419
420                __asm__ __volatile__(
421
422                        "prefetchw 320(%0)\n\t"
423
424                        "psubw %%mm1, %%mm6\n\t" /* mm6 = [0 g03 0 g02 0 g01 0 g00] */
425                        "packuswb %%mm6, %%mm6\n\t" /* mm6 = [g03 g02 g01 g00 g03 g02 g01 g00] */
426                        "movd %%mm6, (%0)\n\t"
427                        "psubw %%mm1, %%mm5\n\t" /* mm5 = [0 g13 0 g12 0 g11 0 g10] */
428                        "packuswb %%mm5, %%mm5\n\t" /* mm5 = [g13 g12 g11 g10 g13 g12 g11 g10] */
429                        "movd %%mm5, (%1)\n\t"
430
431                        "addl $4, %0\n\t"
432
433                        : "=&r" (g_buffer)
434                        : "r" (g_buffer + width), "0" (g_buffer)
435                        : "memory");
436
437
438                y_data += 4;
439                u_data += 2;
440                v_data += 2;
441
442                if(!(--line_size))
443                {
444                        line_size = width >> 2;
445                        y_data   += pitches[0];
446                        r_buffer += width;
447                        g_buffer += width;
448                        b_buffer += width;
449                }
450        }
451
452        __asm__ __volatile__("femms\n\t");
453}
454
455
456
457/* packed floats operations are slower with SSE;
458 * therefore I process only 2 pixels at once in both functions
459 */
460
461static void
462__sse_convert_yuy2(uint8_t* yuv[], rgb_planar_t* rgb,
463                        uint32_t pitches[], uint32_t width, uint32_t height)
464{
465        uint8_t* yuv_data = yuv[0];
466        uint8_t* r_buffer = rgb->r;
467        uint8_t* g_buffer = rgb->g;
468        uint8_t* b_buffer = rgb->b;
469        uint32_t samples = (width * height) >> 1;
470
471
472
473        __asm__ __volatile__(
474                "pxor %%mm7, %%mm7\n\t"
475                "movss   (%0), %%xmm7\n\t"
476                "movss  8(%0), %%xmm6\n\t"
477                "movss 16(%0), %%xmm5\n\t"
478                "movss 24(%0), %%xmm4\n\t"
479                :: "r" (fp_factors)
480                : "memory");
481
482        while(samples--)
483        {
484                __asm__ __volatile__(
485
486                        "prefetchnta 192(%0)\n\t"
487
488                        "movd (%0), %%mm3\n\t" /* mm3 = [0 0 0 0 v0 y1 u0 y0] */
489                        "punpcklwd %%mm7, %%mm3\n\t" /* mm3 = [0 0 v0 y1 0 0 u0 y0] */
490                        "pand (%1), %%mm3\n\t" /* mm3 = [0 0 0 y1 0 0 0 y0] */
491
492                        "movzbl 1(%0), %%eax\n\t" /* eax = u0 */
493                        "subl $128, %%eax\n\t" /* eax = u0 - 128 */
494                        "cvtsi2ss %%eax, %%xmm2\n\t" /* xmm2 = [0 | 0 | 0 | u0 - 128] */
495
496                        "movzbl 3(%0), %%eax\n\t" /* eax = v0 */
497                        "subl $128, %%eax\n\t" /* eax = v0 - 128 */
498                        "cvtsi2ss %%eax, %%xmm1\n\t" /* xmm1 = [0 | 0 | 0 | v0 - 128] */
499
500                        "addl $4, %0\n\t"
501
502                        : "=&r" (yuv_data)
503                        : "r" (lmask), "0" (yuv_data)
504                        : "eax");
505
506
507                __asm__ __volatile__(
508
509                        "prefetchnta 320(%0)\n\t"
510
511                        "movss %%xmm1, %%xmm0\n\t" /* xmm0 = [0 | 0 | 0 | v0] */
512                        "mulss %%xmm7, %%xmm0\n\t" /* xmm0 = [0 | 0 | 0 | v0 * 1.420705] */
513                        "cvtps2pi %%xmm0, %%mm0\n\t" /* mm0 = [0 | v0 * 1.420705] */
514                        "punpckldq %%mm0, %%mm0\n\t" /* mm0 = [v0 * 1.420705 | v0 * 1.420705] */
515                        "paddd %%mm3, %%mm0\n\t" /* mm0 = [r1 | r0] */
516                        "packssdw %%mm0, %%mm0\n\t" /* mm0 = [0 r1 0 r0 0 r1 0 r0] */
517                        "packuswb %%mm0, %%mm0\n\t" /* mm0 = [r1 r0 r1 r0 r1 r0 r1 r0] */
518                        "movd %%mm0, (%0)\n\t"
519
520                        "prefetchnta 320(%2)\n\t"
521
522                        "movss %%xmm2, %%xmm0\n\t" /* xmm0 = [0 | 0 | 0 | u0] */
523                        "mulss %%xmm4, %%xmm0\n\t" /* xmm0 = [0 | 0 | 0 | u0 * 1.732446] */
524                        "cvtps2pi %%xmm0, %%mm0\n\t" /* mm0 = [0 | u0 * 1.732446] */
525                        "punpckldq %%mm0, %%mm0\n\t" /* mm0 = [u0 * 1.732446 | u0 * 1.732446] */
526                        "paddd %%mm3, %%mm0\n\t" /* mm0 = [b1 | b0] */
527                        "packssdw %%mm0, %%mm0\n\t" /* mm0 = [0 b1 0 b0 0 b1 0 b0] */
528                        "packuswb %%mm0, %%mm0\n\t" /* mm0 = [b1 b0 b1 b0 b1 b0 b1 b0] */
529                        "movd %%mm0, (%2)\n\t"
530
531                        "prefetchnta 320(%1)\n\t"
532
533                        "mulss %%xmm6, %%xmm1\n\t" /* xmm1 = [0 | 0 | 0 | v0 * 0.698001] */
534                        "mulss %%xmm5, %%xmm2\n\t" /* xmm2 = [0 | 0 | 0 | u0 * 0.337633] */
535                        "addss %%xmm2, %%xmm1\n\t" /* xmm1 = [0 | 0 | 0 | (v0 * 0.698001) + (u0 * 0.337633)] */
536                        "cvtps2pi %%xmm1, %%mm0\n\t" /* mm0 = [0 | (v0 * 0.698001) + (u0 * 0.337633)] */
537                        "punpckldq %%mm0, %%mm0\n\t" /* mm0 = [(v0 * 0.698001) + (u0 * 0.337633) |
538                                                                (v0 * 0.698001) + (u0 * 0.337633)] */
539                        "psubd %%mm0, %%mm3\n\t" /* mm3 = [g1 | g0] */
540                        "packssdw %%mm3, %%mm3\n\t" /* mm3 = [0 g1 0 g0 0 g1 0 g0] */
541                        "packuswb %%mm3, %%mm3\n\t" /* mm3 = [g1 g0 g1 g0 g1 g0 g1 g0] */
542                        "movd %%mm3, (%1)\n\t"
543
544                        "addl $2, %0\n\t"
545                        "addl $2, %1\n\t"
546                        "addl $2, %2\n\t"
547
548                        : "=&r" (r_buffer), "=&r" (g_buffer), "=&r" (b_buffer)
549                        : "0" (r_buffer), "1" (g_buffer), "2" (b_buffer)
550                        : "memory");
551        }
552
553
554        __asm__ __volatile__("emms\n\t");
555
556}
557
558
559static void
560__sse_convert_yv12(uint8_t* yuv[], rgb_planar_t* rgb,
561                         uint32_t pitches[], uint32_t width, uint32_t height)
562{
563        uint8_t* y_data = yuv[0];
564        uint8_t* u_data = yuv[1];
565        uint8_t* v_data = yuv[2];
566        uint8_t* r_buffer = rgb->r;
567        uint8_t* g_buffer = rgb->g;
568        uint8_t* b_buffer = rgb->b;
569        uint32_t line_size = width >> 1;
570        uint32_t samples   = line_size * (height >> 1);
571
572
573        __asm__ __volatile__(
574                "pxor %%mm7, %%mm7\n\t"
575                "movss   (%0), %%xmm7\n\t"
576                "movss  8(%0), %%xmm6\n\t"
577                "movss 16(%0), %%xmm5\n\t"
578                "movss 24(%0), %%xmm4\n\t"
579                :: "r" (fp_factors)
580                : "memory");
581
582        while(samples--)
583        {
584                __asm__ __volatile__(
585
586                        "prefetchnta 192(%0)\n\t"
587                        "prefetchnta 192(%1)\n\t"
588                        "prefetchnta 192(%2)\n\t"
589                        "prefetchnta 192(%3)\n\t"
590
591                        "movd (%0), %%mm3\n\t" /* mm3 = [0 0 0 0 y03 y02 y01 y00] */
592                        "punpcklbw %%mm7, %%mm3\n\t" /* mm6 = [0 y03 0 y02 0 y01 0 y00] */
593                        "movd (%1), %%mm2\n\t" /* mm2 = [0 0 0 0 y13 y12 y11 y10] */
594                        "punpcklbw %%mm7, %%mm2\n\t" /* mm2 = [0 y13 0 y12 0 y11 0 y10] */
595                        "punpckldq %%mm2, %%mm3\n\t" /* mm3 = [0 y11 0 y10 0 y01 0 y00] */
596
597                        "movzbl (%2), %%eax\n\t" /* eax = u0 */
598                        "subl $128, %%eax\n\t" /* eax = u0 - 128 */
599                        "cvtsi2ss %%eax, %%xmm1\n\t" /* xmm1 = [0 | 0 | 0 | u0 - 128] */
600
601                        "movzbl (%3), %%eax\n\t" /* eax = v0 */
602                        "subl $128, %%eax\n\t" /* eax = v0 - 128 */
603                        "cvtsi2ss %%eax, %%xmm0\n\t" /* xmm0 = [0 | 0 | 0 | v0 - 128] */
604
605                        :: "r" (y_data), "r" (y_data + pitches[0]),
606                           "r" (u_data), "r" (v_data)
607                        : "eax");
608
609
610                __asm__ __volatile__(
611
612                        "prefetchnta 320(%0)\n\t"
613
614                        "movss %%xmm0, %%xmm3\n\t" /* xmm3 = [0 | 0 | 0 | v0] */
615                        "mulss %%xmm7, %%xmm3\n\t" /* xmm3 = [0 | 0 | 0 | v0 * 1.420705] */
616                        "cvtps2pi %%xmm3, %%mm0\n\t" /* mm0 = [0 | v0 * 1.420705] */
617                        "punpckldq %%mm0, %%mm0\n\t" /* mm0 = [v0 * 1.420705 | v0 * 1.420705] */
618                        "packssdw %%mm0, %%mm0\n\t" /* mm0 = [v0 * 1.420705 | v0 * 1.420705 | ...] */
619                        "paddw %%mm3, %%mm0\n\t" /* mm0 = [0 r11 0 r10 0 r01 0 r00] */
620                        "packuswb %%mm0, %%mm0\n\t" /* mm0 =  [r11 r10 r01 r00 r11 r10 r01 r00] */
621                        "movd %%mm0, (%0)\n\t"
622                        "psrld $16, %%mm0\n\t" /* mm0 = [0 0 r11 r10 0 0 r11 r10] */
623                        "movd %%mm0, (%1)\n\t"
624
625                        "addl $2, %0\n\t"
626
627                        : "=&r" (r_buffer)
628                        : "r" (r_buffer + width), "0" (r_buffer)
629                        : "memory");
630
631
632                __asm__ __volatile__(
633
634                        "prefetchnta 320(%0)\n\t"
635
636                        "movss %%xmm1, %%xmm3\n\t" /* xmm3 = [0 | 0 | 0 | u0] */
637                        "mulss %%xmm4, %%xmm3\n\t" /* xmm3 = [0 | 0 | 0 | u0 * 1.732446] */
638                        "cvtps2pi %%xmm3, %%mm0\n\t" /* mm0 = [0 | u0 * 1.732446] */
639                        "punpckldq %%mm0, %%mm0\n\t" /* mm0 = [u0 * 1.732446 | u0 * 1.732446] */
640                        "packssdw %%mm0, %%mm0\n\t" /* mm0 = [u0 * 1.732446 | u0 * 1.732446 | ...] */
641                        "paddw %%mm3, %%mm0\n\t" /* mm0 = [0 b11 0 b10 0 b01 0 b00] */
642                        "packuswb %%mm0, %%mm0\n\t" /* mm0 = [b11 b10 b01 b00 b11 b10 b01 b00] */
643                        "movd %%mm0, (%0)\n\t"
644                        "psrld $16, %%mm0\n\t" /* mm0 = [0 0 b11 b10 0 0 b11 b10] */
645                        "movd %%mm0, (%1)\n\t"
646
647                        "addl $2, %0\n\t"
648
649                        : "=&r" (b_buffer)
650                        : "r" (b_buffer + width), "0" (b_buffer)
651                        : "memory");
652
653
654                __asm__ __volatile__(
655
656                        "prefetchnta 320(%0)\n\t"
657
658                        "mulss %%xmm6, %%xmm0\n\t" /* xmm0 = [0 | 0 | 0 | (v0 * 0.698001)] */
659                        "mulss %%xmm5, %%xmm1\n\t" /* xmm1 = [0 | 0 | 0 | (u0 * 0.337633)] */
660                        "addss %%xmm1, %%xmm0\n\t" /* xmm0 = [0 | 0 | 0 | (v0 * 0.698001) + (u0 * 0.337633)] */
661                        "cvtps2pi %%xmm0, %%mm0\n\t" /* mm0 = [0 | (v0 * 0.698001) + (u0 * 0.337633)] */
662                        "punpckldq %%mm0, %%mm0\n\t" /* mm0 = [(v0 * 0.698001) + (u0 * 0.337633) | ...] */
663                        "packssdw %%mm0, %%mm0\n\t" /* mm0 = [(short) (v0 * 0.698001) + (u0 * 0.337633) / ..] */
664                        "psubw %%mm0, %%mm3\n\t" /* mm3 = [0 g11 0 g10 0 g01 0 g00] */
665                        "packuswb %%mm3, %%mm3\n\t" /* mm3 = [g11 g10 g01 g00 g11 g10 g01 g00] */
666                        "movd %%mm3, (%0)\n\t"
667                        "psrld $16, %%mm3\n\t" /* mm3 = [0 0 g11 g10 0 0 g11 g10] */
668                        "movd %%mm3, (%1)\n\t"
669
670                        "addl $2, %0\n\t"
671
672                        : "=&r" (g_buffer)
673                        : "r" (g_buffer + width), "0" (g_buffer)
674                        : "memory");
675
676
677                y_data += 2;
678                u_data++;
679                v_data++;
680
681                if(!(--line_size))
682                {
683                        line_size = width >> 1;
684                        y_data   += pitches[0];
685                        r_buffer += width;
686                        g_buffer += width;
687                        b_buffer += width;
688                }
689        }
690
691        __asm__ __volatile__("emms\n\t");
692}
693
694
695
696static void
697__mmx_convert_yuy2(uint8_t* yuv[], rgb_planar_t* rgb,
698                        uint32_t pitches[], uint32_t width, uint32_t height)
699{
700        uint8_t* yuv_data = yuv[0];
701        uint8_t* r_buffer = rgb->r;
702        uint8_t* g_buffer = rgb->g;
703        uint8_t* b_buffer = rgb->b;
704        uint32_t samples = (width * height) >> 2; /* 4 pixels at once */
705
706
707        while(samples--)
708        {
709                __asm__ __volatile__(
710
711                        "movq (%0), %%mm0\n\t" /* mm1 = [v2 y3 u2 y2 v0 y1 u0 y0] */
712
713                        "movq %%mm0, %%mm3\n\t" /* mm3 = [v2 y3 u2 y2 v0 y1 u0 y0] */
714                        "pand (%1), %%mm3\n\t" /* mm3 = [0 0 0 y2 0 0 0 y0] */
715                        "movq %%mm0, %%mm2\n\t" /* mm2 = [v2 y3 u2 y2 v0 y1 u0 y0] */
716                        "psrld $16, %%mm2\n\t" /* mm2 = [0 0 v2 y3 0 0 v0 y1] */
717                        "pand (%1), %%mm2\n\t" /* mm2 = [0 0 0 y3 0 0 0 y1] */
718
719                        "movq %%mm0, %%mm1\n\t" /* mm1 = [v2 y3 u2 y2 v0 y1 u0 y0] */
720                        "psrld $8, %%mm1\n\t" /* mm1 = [0 v2 y3 u2 0 v0 y1 u0] */
721                        "pand (%1), %%mm1\n\t" /* mm1 = [0 0 0 u2 0 0 0 u0] */
722                        "psubd (%2), %%mm1\n\t" /* mm1 = [u2 - 128 | u0 - 128] */
723                        "packssdw %%mm1, %%mm1\n\t" /* mm1 = [0 u2 0 u0 0 u2 0 u0] */
724
725                        "psrld $24, %%mm0\n\t" /* mm0 = [0 0 0 v2 0 0 0 v0] */
726                        "psubd (%2), %%mm0\n\t" /* mm0 = [v2 - 128 | v0 - 128] */
727                        "packssdw %%mm0, %%mm0\n\t" /* mm0 = [0 u2 0 u0 0 u2 0 u0] */
728
729                        "addl $8, %0\n\t"
730
731                        : "=&r" (yuv_data)
732                        : "r" (lmask), "r" (lsub), "0" (yuv_data)
733                        : "memory");
734
735
736                __asm__ __volatile__(
737
738                        "packssdw %%mm3, %%mm4\n\t" /* mm4 = [? ? ? ? 0 y2 0 y0] */
739                        "punpckhwd %%mm0, %%mm4\n\t" /* mm4 = [0 v2 0 y2 0 v0 0 y0] */
740                        "pmaddwd (%3), %%mm4\n\t" /* mm4 = [r2 << 14 | r0 << 14] */
741                        "psrad $14,%%mm4\n\t" /* mm4 = [0 0 0 r2 0 0 0 r0] */
742                        "packssdw %%mm4, %%mm4\n\t" /* mm4 = [0 r2 0 r0 0 r2 0 r0] */
743                        "packssdw %%mm2, %%mm5\n\t" /* mm5 = [? ? ? ? 0 y3 0 y1] */
744                        "punpckhwd %%mm0, %%mm5\n\t" /* mm5 = [0 v2 0 y3 0 v0 0 y1] */
745                        "pmaddwd (%3), %%mm5\n\t" /* mm5 = [r3 << 14| r1 << 14] */
746                        "psrad $14, %%mm5\n\t" /* mm5 = [0 0 0 r3 0 0 0 r1] */
747                        "packssdw %%mm5, %%mm5\n\t" /* mm5 = [0 r3 0 r1 0 r3 0 r1] */
748                        "punpckhwd %%mm5, %%mm4\n\t" /* mm4 = [0 r3 0 r2 0 r1 0 r0] */
749                        "packuswb %%mm4, %%mm4\n\t" /* mm4 = [r3 r2 r1 r0 r3 r2 r1 r0] */
750                        "movd %%mm4, (%0)\n\t"
751
752                        "packssdw %%mm3, %%mm4\n\t" /* mm4 = [? ? ? ? 0 y2 0 y0] */
753                        "punpckhwd %%mm1, %%mm4\n\t" /* mm4 = [0 u2 0 y2 0 u0 0 y0] */
754                        "pmaddwd 8(%3), %%mm4\n\t" /* mm4 = [b2 << 14 | b0 << 14] */
755                        "psrad $14, %%mm4\n\t" /* mm4 = [0 0 0 b2 0 0 0 b0] */
756                        "packssdw %%mm4, %%mm4\n\t" /* mm4 = [0 b2 0 b0 0 b2 0 b0] */
757                        "packssdw %%mm2, %%mm5\n\t" /* mm5 = [? ? ? ? 0 y3 0 y1] */
758                        "punpckhwd %%mm1, %%mm5\n\t" /* mm5 = [0 u2 0 y3 0 u0 0 y1] */
759                        "pmaddwd 8(%3), %%mm5\n\t" /* mm5 = [b3 << 14 | b1 << 14] */
760                        "psrad $14, %%mm5\n\t" /* mm5 = [0 0 0 b3 0 0 0 b1] */
761                        "packssdw %%mm5, %%mm5\n\t" /* mm5 = [0 b3 0 b1 0 b3 0 b1] */
762                        "punpckhwd %%mm5, %%mm4\n\t" /* mm4 = [0 b3 0 b2 0 b1 0 b0] */
763                        "packuswb %%mm4, %%mm4\n\t" /* mm4 = [b3 b2 b1 b0 b3 b2 b1 b0] */
764                        "movd %%mm4, (%2)\n\t"
765
766                        "punpckhwd %%mm1, %%mm0\n\t" /* mm0 = [0 u2 0 v2 0 u0 0 v0] */
767                        "pmaddwd 16(%3), %%mm0\n\t" /* mm0 = [(u2 * 5532) + (v2 * 11436) | ...] */
768                        "pslld $14, %%mm3\n\t"
769                        "psubd %%mm0, %%mm3\n\t" /* mm3 = [g2 << 14 | g0 << 14] */
770                        "psrad $14, %%mm3\n\t" /* mm3 = [0 0 0 g2 0 0 0 g0] */
771                        "packssdw %%mm3, %%mm3\n\t" /* mm3 = [0 g2 0 g0 0 g2 0 g0] */
772                        "pslld $14, %%mm2\n\t"
773                        "psubd %%mm0, %%mm2\n\t" /* mm2 = [g3 << 14 | g1 << 14] */
774                        "psrad $14, %%mm2\n\t" /* mm2 = [0 0 0 g3 0 0 0 g1] */
775                        "packssdw %%mm2, %%mm2\n\t" /* mm2 = [0 g3 0 g1 0 g3 0 g1] */
776                        "punpckhwd %%mm2, %%mm3\n\t" /* mm3 = [0 g3 0 g2 0 g1 0 g0] */
777                        "packuswb %%mm3, %%mm3\n\t" /* mm3 = [g3 g2 g1 g0 g3 g2 g1 g0] */
778                        "movd %%mm3, (%1)\n\t"
779
780                        "addl $4, %0\n\t"
781                        "addl $4, %1\n\t"
782                        "addl $4, %2\n\t"
783
784                        : "=&r" (r_buffer), "=&r" (g_buffer), "=&r" (b_buffer)
785                        : "r" (wd_factors), "0" (r_buffer), "1" (g_buffer), "2" (b_buffer)
786                        : "memory");
787        }
788
789
790        __asm__ __volatile__("emms\n\t");
791
792}
793
794
795static void
796__mmx_convert_yv12(uint8_t* yuv[], rgb_planar_t* rgb,
797                         uint32_t pitches[], uint32_t width, uint32_t height)
798{
799        static const uint16_t wsub[] =
800        {
801                128, 128,
802                128, 128
803        };
804        uint8_t* y_data = yuv[0];
805        uint8_t* u_data = yuv[1];
806        uint8_t* v_data = yuv[2];
807        uint8_t* r_buffer = rgb->r;
808        uint8_t* g_buffer = rgb->g;
809        uint8_t* b_buffer = rgb->b;
810        uint32_t line_size = width >> 1; /* 2 pixels at once */
811        uint32_t samples   = line_size * (height >> 1);
812
813
814        __asm__ __volatile__(
815                "pxor %%mm7, %%mm7\n\t"
816                ::: "memory");
817
818        while(samples--)
819        {
820                __asm__ __volatile__(
821
822                        "movd (%0), %%mm3\n\t" /* mm3 = [0 0 0 0 y03 y02 y01 y00] */
823                        "movd (%1), %%mm2\n\t" /* mm2 = [0 0 0 0 y13 y12 y11 y10] */
824                        "movd (%2), %%mm1\n\t" /* mm1 = [0 0 0 0 u12 u8 u4 u0] */
825                        "movd (%3), %%mm0\n\t" /* mm0 = [0 0 0 0 v12 v8 v4 v0] */
826
827                        "punpcklbw %%mm7, %%mm3\n\t" /* mm3 = [0 y03 0 y02 0 y01 0 y00] */
828                        "punpcklbw %%mm7, %%mm2\n\t" /* mm2 = [0 y13 0 y12 0 y11 0 y10] */
829
830                        "punpckldq %%mm1, %%mm1\n\t" /* mm1 = [u12 u8 u4 u0 u12 u8 u4 u0] */
831                        "pand (%5), %%mm1\n\t" /* mm1 = [0 0 0 u0 0 0 0 u0] */
832                        "packssdw %%mm1, %%mm1\n\t" /* mm1 = [0 u0 0 u0 0 u0 0 u0] */
833                        "psubw (%4), %%mm1\n\t" /* mm1 = [u0 -128 | u0 -128 | ...] */
834
835                        "punpckldq %%mm0, %%mm0\n\t" /* mm0 = [v12 v8 v4 v0 v12 v8 v4 v0] */
836                        "pand (%5), %%mm0\n\t" /* mm1 = [0 0 0 v0 0 0 0 v0] */
837                        "packssdw %%mm0, %%mm0\n\t" /* mm1 = [0 v0 0 v0 0 v0 0 v0] */
838                        "psubw (%4), %%mm0\n\t" /* mm1 = [v0 -128 | v0 -128 | ...] */
839
840                        :: "r" (y_data), "r" (y_data + pitches[0]),
841                           "r" (u_data), "r" (v_data), "r" (wsub), "r" (lmask)
842                        : "memory");
843
844
845                __asm__ __volatile__(
846
847                        "movq %%mm3, %%mm4\n\t"
848                        "punpcklwd %%mm0, %%mm4\n\t" /* mm4 = [0 v0 0 y01 0 v0 0 y00] */
849                        "pmaddwd (%2), %%mm4\n\t" /* mm4 = [r01 << 14 | r00 << 14] */
850                        "psrad $14, %%mm4\n\t" /* mm4 = [r01 | r00] */
851                        "movq %%mm2, %%mm5\n\t"
852                        "punpcklwd %%mm0, %%mm5\n\t" /* mm5 = [0 v0 0 y11 0 v0 0 y10] */
853                        "pmaddwd (%2), %%mm5\n\t" /* mm5 = [r11 << 14 | r10 << 14] */
854                        "psrad $14, %%mm5\n\t" /* mm5 = [r11 | r10] */
855                        "packssdw %%mm5, %%mm4\n\t" /* mm4 = [r11 | r10 | r01 | r00] */
856                        "packuswb %%mm4, %%mm4\n\t" /* mm4 = [r11 r10 r01 r00 r11 r10 r01 r00] */
857                        "movd %%mm4, (%0)\n\t"
858                        "psrld $16, %%mm4\n\t" /* mm4 = [0 0 r11 r10 0 0 r11 r10] */
859                        "movd %%mm4, (%1)\n\t"
860                        "addl $2, %0\n\t"
861
862                        : "=&r" (r_buffer)
863                        : "r" (r_buffer + width), "r" (wd_factors), "0" (r_buffer)
864                        : "memory");
865
866
867                __asm__ __volatile__(
868
869                        "movq %%mm3, %%mm4\n\t"
870                        "punpcklwd %%mm1, %%mm4\n\t" /* mm4 = [0 u0 0 y01 0 u0 0 y00] */
871                        "pmaddwd 8(%2), %%mm4\n\t" /* mm4 = [b01 << 14 | b00 << 14] */
872                        "psrad $14, %%mm4\n\t" /* mm4 = [b01 | b00] */
873                        "movq %%mm2, %%mm5\n\t"
874                        "punpckhwd %%mm1, %%mm5\n\t" /* mm5 = [0 u0 0 y11 0 u0 0 y10] */
875                        "pmaddwd 8(%2), %%mm5\n\t" /* mm5 = [b11 << 14 | b10 << 14] */
876                        "psrad $14, %%mm5\n\t" /* mm5 = [b11 | b10] */
877                        "packssdw %%mm5, %%mm4\n\t" /* mm4 = [b11 | b10 | b01 | b00] */
878                        "packuswb %%mm4, %%mm4\n\t" /* mm4 = [b11 b10 b01 b00 r11 b10 b01 b00] */
879                        "movd %%mm4, (%0)\n\t"
880                        "psrld $16, %%mm4\n\t" /* mm4 = [0 0 b11 b10 0 0 b11 b10] */
881                        "movd %%mm4, (%1)\n\t"
882                        "addl $2, %0\n\t"
883
884                        : "=&r" (b_buffer)
885                        : "r" (b_buffer + width), "r" (wd_factors), "0" (b_buffer)
886                        : "memory");
887
888
889                __asm__ __volatile__(
890
891                        "punpcklwd %%mm1, %%mm0\n\t" /* mm0 = [0 u0 0 v0 0 u0 0 v0] */
892                        "pmaddwd 16(%2), %%mm0\n\t" /* mm0 = [(u0 * 5532) + (v0 * 11436) | ...] */
893                        "punpcklwd %%mm7, %%mm3\n\t" /* mm3 = [0 0 0 y01 0 0 0 y00] */
894                        "pslld $14, %%mm3\n\t" /* mm3 = [y01 << 14 | y00 << 14] */
895                        "psubd %%mm0, %%mm3\n\t" /* mm3 = [g01 << 14 | g00 << 14] */
896                        "psrad $14, %%mm3\n\t" /* mm3 = [g01 | g00] */
897                        "punpcklwd %%mm7, %%mm2\n\t" /* mm2 = [0 0 0 y11 0 0 0 y10] */
898                        "pslld $14, %%mm2\n\t" /* mm2 = [y11 << 14 | y10 << 14] */
899                        "psubd %%mm0, %%mm2\n\t" /* mm2 = [g11 << 14 | g10 << 14] */
900                        "psrad $14, %%mm2\n\t" /* mm2 = [g11 | g10] */
901                        "packssdw %%mm2, %%mm3\n\t" /* mm3 = [g11 | g10 | g01 | g00] */
902                        "packuswb %%mm3, %%mm3\n\t" /* mm3 = [g11 g10 g01 g00 g11 g10 g01 g00] */
903                        "movd %%mm3, (%0)\n\t"
904                        "psrld $16, %%mm3\n\t" /* mm3 = [0 0 g11 g10 0 0 g11 g10] */
905                        "movd %%mm3, (%1)\n\t"
906                        "addl $2, %0\n\t"
907
908                        : "=&r" (g_buffer)
909                        : "r" (g_buffer + width), "r" (wd_factors), "0" (g_buffer)
910                        : "memory");
911
912
913                y_data += 2;
914                u_data++;
915                v_data++;
916
917                if(!(--line_size))
918                {
919                        line_size = width >> 1;
920                        y_data   += pitches[0];
921                        r_buffer += width;
922                        g_buffer += width;
923                        b_buffer += width;
924                }
925        }
926
927        __asm__ __volatile__("emms\n\t");
928}
929
930#endif
931
932
933#define range(x)  ((x < 0) ? 0 : ((x > 0xff) ? 0xff : x))
934
935static void
936__dummy_convert_yuy2(uint8_t* yuv[], rgb_planar_t* rgb,
937                         uint32_t pitches[], uint32_t width, uint32_t height)
938{
939        uint8_t* yuv_data = yuv[0];
940        uint8_t* r_buffer = rgb->r;
941        uint8_t* g_buffer = rgb->g;
942        uint8_t* b_buffer = rgb->b;
943        uint32_t samples = (width * height) >> 1; /* 2 pixels at once */
944
945
946        while(samples--)
947        {
948                int u, y, v, y2;
949                int m1, m2, m3, m4;
950                int r, g, b;
951
952                y  = *(yuv_data)     << 16;
953                u  = *(yuv_data + 1) - 128;
954                y2 = *(yuv_data + 2) << 16;
955                v  = *(yuv_data + 3) - 128;
956
957                m1 = v * dw_factors[0];
958                m2 = v * dw_factors[1];
959                m3 = u * dw_factors[2];
960                m4 = u * dw_factors[3];
961
962                r = (int) (y + m1) >> 16;
963                g = (int) (y - m2 - m3) >> 16;
964                b = (int) (y + m4) >> 16;
965
966                *(r_buffer) = range(r);
967                *(g_buffer) = range(g);
968                *(b_buffer) = range(b);
969
970                r = (int) (y2 + m1) >> 16;
971                g = (int) (y2 - m2 - m3) >> 16;
972                b = (int) (y2 + m4) >> 16;
973
974                *(r_buffer + 1) = range(r);
975                *(g_buffer + 1) = range(g);
976                *(b_buffer + 1) = range(b);
977
978                yuv_data += 4;
979                r_buffer += 2;
980                g_buffer += 2;
981                b_buffer += 2;
982        }
983
984}
985
986
987static void
988__dummy_convert_yv12(uint8_t* yuv[], rgb_planar_t* rgb,
989                         uint32_t pitches[], uint32_t width, uint32_t height)
990{
991        uint8_t* y_data = yuv[0];
992        uint8_t* u_data = yuv[1];
993        uint8_t* v_data = yuv[2];
994        uint8_t* r_buffer = rgb->r;
995        uint8_t* g_buffer = rgb->g;
996        uint8_t* b_buffer = rgb->b;
997        uint32_t line_size = width >> 1; /* 2 pixels at once */
998        uint32_t samples   = line_size * (height >> 1);
999
1000
1001        while(samples--)
1002        {
1003                int y, u, v;
1004                int m1, m2, m3, m4;
1005                int r, g, b;
1006
1007                u  = *(u_data++) - 128;
1008                v  = *(v_data++) - 128;
1009
1010                m1 = v * dw_factors[0];
1011                m2 = v * dw_factors[1];
1012                m3 = u * dw_factors[2];
1013                m4 = u * dw_factors[3];
1014
1015                y = *(y_data) << 16;
1016
1017                r = (int) (y + m1) >> 16;
1018                g = (int) (y - m2 - m3) >> 16;
1019                b = (int) (y + m4) >> 16;
1020
1021                *(r_buffer) = range(r);
1022                *(g_buffer) = range(g);
1023                *(b_buffer) = range(b);
1024
1025                y = *(y_data + 1) << 16;
1026
1027                r = (int) (y + m1) >> 16;
1028                g = (int) (y - m2 - m3) >> 16;
1029                b = (int) (y + m4) >> 16;
1030
1031                *(r_buffer + 1) = range(r);
1032                *(g_buffer + 1) = range(g);
1033                *(b_buffer + 1) = range(b);
1034
1035                y = *(y_data + pitches[0]) << 16;
1036
1037                r = (int) (y + m1) >> 16;
1038                g = (int) (y - m2 - m3) >> 16;
1039                b = (int) (y + m4) >> 16;
1040
1041                *(r_buffer + width) = range(r);
1042                *(g_buffer + width) = range(g);
1043                *(b_buffer + width) = range(b);
1044
1045                y = *(y_data + pitches[0] + 1) << 16;
1046
1047                r = (int) (y + m1) >> 16;
1048                g = (int) (y - m2 - m3) >> 16;
1049                b = (int) (y + m4) >> 16;
1050
1051                *(r_buffer + width + 1) = range(r);
1052                *(g_buffer + width + 1) = range(g);
1053                *(b_buffer + width + 1) = range(b);
1054
1055                y_data   += 2;
1056                r_buffer += 2;
1057                g_buffer += 2;
1058                b_buffer += 2;
1059
1060                if(!(--line_size))
1061                {
1062                        line_size = width >> 1;
1063                        y_data   += pitches[0];
1064                        r_buffer += width;
1065                        g_buffer += width;
1066                        b_buffer += width;
1067                }
1068        }
1069
1070}
1071
1072
1073
1074static const rgbout_converter_t convert_methods[] =
1075{
1076/*        <name>   <accel>      <convert yuy2>        <convert yv12>    */
1077        {    NULL,        0, __dummy_convert_yuy2, __dummy_convert_yv12},
1078#ifdef COMPILE_ASSEMBLY
1079        {   "MMX",   MM_MMX,   __mmx_convert_yuy2,   __mmx_convert_yv12},
1080        {   "SSE",   MM_SSE,   __sse_convert_yuy2,   __sse_convert_yv12},
1081        {"3DNow!", MM_3DNOW, __3dnow_convert_yuy2, __3dnow_convert_yv12}
1082#endif
1083/* currently 3DNow is the best function, therefore it's preferred on AMD cpus */
1084};
1085
1086
1087
1088
1089
1090
1091static void
1092__pack_argb(rgb_planar_t* data, void* dest,
1093                uint32_t pixels, uint32_t accel)
1094{
1095        static const uint32_t alpha[] =
1096        {
1097                0xffffffff,
1098                0xffffffff
1099        };
1100        uint8_t* buffer = (uint8_t*) dest;
1101        uint8_t* r_data = data->r;
1102        uint8_t* g_data = data->g;
1103        uint8_t* b_data = data->b;
1104        uint32_t rest = pixels;
1105
1106#ifdef COMPILE_ASSEMBLY
1107
1108        if((accel & MM_MMXEXT) == MM_MMXEXT)
1109        {
1110                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1111                rest = pixels & 3; /* pixels - (n * 4) */
1112
1113
1114                __asm__ __volatile__(
1115                        "por (%0), %%mm3\n\t"
1116                        :: "r" (alpha)
1117                        : "memory");
1118
1119                while(n--)
1120                {
1121                        __asm__ __volatile__(
1122
1123                                "prefetchw 320(%3)\n\t"
1124
1125                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1126                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1127                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1128
1129                                "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [ff r3 ff r2 ff r1 ff r0] */
1130                                "punpcklbw %%mm1, %%mm2\n\t" /* mm2 = [g3 b3 g2 b2 g1 b1 g0 b0] */
1131
1132                                "movq %%mm2, %%mm4\n\t" /* mm2 = [g3 b3 g2 b2 g1 b1 g0 b0] */
1133                                "punpcklwd %%mm0, %%mm4\n\t" /* mm4 = [ff r1 g1 b1 ff r0 g0 b0] */
1134                                "movntq %%mm4, (%3)\n\t"
1135
1136                                "punpckhwd %%mm0, %%mm2\n\t" /* mm2 = [ff r3 g3 b3 ff r2 g2 b2] */
1137                                "movntq %%mm2, 8(%3)\n\t"
1138
1139                                "addl $4, %0\n\t"
1140                                "addl $4, %1\n\t"
1141                                "addl $4, %2\n\t"
1142                                "addl $16, %3\n\t"
1143
1144                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1145                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1146                                : "memory");
1147                }
1148
1149                __asm__ __volatile__("sfence; emms\n\t");
1150
1151        }
1152        else if((accel & MM_MMX) == MM_MMX)
1153        {
1154                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1155                rest = pixels & 3; /* pixels - (n * 4) */
1156
1157
1158                __asm__ __volatile__(
1159                        "por (%0), %%mm3\n\t"
1160                        :: "r" (alpha)
1161                        : "memory");
1162
1163                while(n--)
1164                {
1165                        __asm__ __volatile__(
1166
1167                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1168                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1169                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1170
1171                                "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [ff r3 ff r2 ff r1 ff r0] */
1172                                "punpcklbw %%mm1, %%mm2\n\t" /* mm2 = [g3 b3 g2 b2 g1 b1 g0 b0] */
1173
1174                                "movq %%mm2, %%mm4\n\t" /* mm2 = [g3 b3 g2 b2 g1 b1 g0 b0] */
1175                                "punpcklwd %%mm0, %%mm4\n\t" /* mm4 = [ff r1 g1 b1 ff r0 g0 b0] */
1176                                "movq %%mm4, (%3)\n\t"
1177
1178                                "punpckhwd %%mm0, %%mm2\n\t" /* mm2 = [ff r3 g3 b3 ff r2 g2 b2] */
1179                                "movq %%mm2, 8(%3)\n\t"
1180
1181                                "addl $4, %0\n\t"
1182                                "addl $4, %1\n\t"
1183                                "addl $4, %2\n\t"
1184                                "addl $16, %3\n\t"
1185
1186                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1187                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1188                                : "memory");
1189                }
1190
1191                __asm__ __volatile__("emms\n\t");
1192
1193        }
1194#endif
1195
1196        while(rest--)
1197        {
1198                *(buffer)     = *(b_data++);
1199                *(buffer + 1) = *(g_data++);
1200                *(buffer + 2) = *(r_data++);
1201                *(buffer + 3) = 0xff;
1202
1203                buffer += 4;
1204        }
1205
1206}
1207
1208
1209static void
1210__pack_argb1555(rgb_planar_t* data, void* dest,
1211                uint32_t pixels, uint32_t accel)
1212{
1213        static const uint16_t alpha[] =
1214        {
1215                0x8000,
1216                0x8000,
1217                0x8000,
1218                0x8000
1219        };
1220        uint16_t* buffer = (uint16_t*) dest;
1221        uint8_t* r_data = data->r;
1222        uint8_t* g_data = data->g;
1223        uint8_t* b_data = data->b;
1224        int32_t rest = pixels;
1225
1226#ifdef COMPILE_ASSEMBLY
1227
1228        if((accel & MM_MMXEXT) == MM_MMXEXT)
1229        {
1230                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1231                rest = pixels & 3; /* pixels - (n * 4) */
1232
1233
1234                __asm__ __volatile__(
1235                        "pxor %%mm3, %%mm3\n\t"
1236                        "movq (%0), %%mm4\n\t"
1237                        :: "r" (alpha)
1238                        : "memory");
1239
1240                while(n--)
1241                {
1242                        __asm__ __volatile__(
1243
1244                                "prefetchw 320(%3)\n\t"
1245
1246                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1247                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1248                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1249
1250                                "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [0 r3 0 r2 0 r1 0 r0] */
1251                                "punpcklbw %%mm3, %%mm1\n\t" /* mm1 = [0 g3 0 g2 0 g1 0 g0] */
1252                                "punpcklbw %%mm3, %%mm2\n\t" /* mm2 = [0 b3 0 b2 0 b1 0 b0] */
1253
1254                                "psrlw $3, %%mm0\n\t" /* word = [00000000 000rrrrr] */
1255                                "psrlw $3, %%mm1\n\t" /* word = [00000000 000ggggg] */
1256                                "psrlw $3, %%mm2\n\t" /* word = [00000000 000bbbbb] */
1257
1258                                "psllw $10, %%mm0\n\t" /* word = [0rrrrr00 00000000] */
1259                                "psllw $5,  %%mm1\n\t" /* word = [000000gg ggg00000] */
1260                                "por %%mm2, %%mm1\n\t" /* word = [000000gg gggbbbbb] */
1261                                "por %%mm1, %%mm0\n\t" /* word = [0rrrrrgg gggbbbbb] */
1262                                "por %%mm4, %%mm0\n\t" /* word = [1rrrrrgg gggbbbbb] */
1263
1264                                "movntq %%mm0, (%3)\n\t"
1265
1266                                "addl $4, %0\n\t"
1267                                "addl $4, %1\n\t"
1268                                "addl $4, %2\n\t"
1269                                "addl $8, %3\n\t"
1270
1271                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1272                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1273                                : "memory");
1274
1275                }
1276
1277                __asm__ __volatile__("sfence; emms\n\t");
1278
1279        }
1280        else if((accel & MM_MMX) == MM_MMX)
1281        {
1282                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1283                rest = pixels & 3; /* pixels - (n * 4) */
1284
1285
1286                __asm__ __volatile__(
1287                        "pxor %%mm3, %%mm3\n\t"
1288                        "movq (%0), %%mm4\n\t"
1289                        :: "r" (alpha)
1290                        : "memory");
1291
1292                while(n--)
1293                {
1294                        __asm__ __volatile__(
1295
1296                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1297                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1298                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1299
1300                                "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [0 r3 0 r2 0 r1 0 r0] */
1301                                "punpcklbw %%mm3, %%mm1\n\t" /* mm1 = [0 g3 0 g2 0 g1 0 g0] */
1302                                "punpcklbw %%mm3, %%mm2\n\t" /* mm2 = [0 b3 0 b2 0 b1 0 b0] */
1303
1304                                "psrlw $3, %%mm0\n\t" /* word = [00000000 000rrrrr] */
1305                                "psrlw $3, %%mm1\n\t" /* word = [00000000 000ggggg] */
1306                                "psrlw $3, %%mm2\n\t" /* word = [00000000 000bbbbb] */
1307
1308                                "psllw $10, %%mm0\n\t" /* word = [0rrrrr00 00000000] */
1309                                "psllw $5,  %%mm1\n\t" /* word = [000000gg ggg00000] */
1310                                "por %%mm2, %%mm1\n\t" /* word = [000000gg gggbbbbb] */
1311                                "por %%mm1, %%mm0\n\t" /* word = [0rrrrrgg gggbbbbb] */
1312                                "por %%mm4, %%mm0\n\t" /* word = [arrrrrgg gggbbbbb] */
1313
1314                                "movq %%mm0, (%3)\n\t"
1315
1316                                "addl $4, %0\n\t"
1317                                "addl $4, %1\n\t"
1318                                "addl $4, %2\n\t"
1319                                "addl $8, %3\n\t"
1320
1321                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1322                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1323                                : "memory");
1324
1325                }
1326
1327                __asm__ __volatile__("emms\n\t");
1328
1329        }
1330
1331#endif
1332        while(rest--)
1333        {
1334                uint16_t r5, g5, b5;
1335
1336                r5 = *(r_data++) >> 3;
1337                g5 = *(g_data++) >> 3;
1338                b5 = *(b_data++) >> 3;
1339
1340                *(buffer++) = (alpha[0] | (r5 << 10) | (g5 << 5) | b5);
1341        }
1342
1343}
1344
1345
1346static void
1347__pack_rgb32(rgb_planar_t* data, void* dest,
1348                uint32_t pixels, uint32_t accel)
1349{
1350        uint8_t* buffer = (uint8_t*) dest;
1351        uint8_t* r_data = data->r;
1352        uint8_t* g_data = data->g;
1353        uint8_t* b_data = data->b;
1354        uint32_t rest = pixels;
1355
1356#ifdef COMPILE_ASSEMBLY
1357
1358        if((accel & MM_MMXEXT) == MM_MMXEXT)
1359        {
1360                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1361                rest = pixels & 3; /* pixels - (n * 4) */
1362
1363
1364                __asm__ __volatile__(
1365                        "pxor %%mm3, %%mm3\n\t"
1366                        ::: "memory");
1367
1368                while(n--)
1369                {
1370                        __asm__ __volatile__(
1371
1372                                "prefetchw 320(%0)\n\t"
1373
1374                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1375                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1376                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1377
1378                                "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [0 r3 0 r2 0 r1 0 r0] */
1379                                "punpcklbw %%mm1, %%mm2\n\t" /* mm2 = [g3 b3 g2 b2 g1 b1 g0 b0] */
1380
1381                                "movq %%mm2, %%mm4\n\t" /* mm2 = [g3 b3 g2 b2 g1 b1 g0 b0] */
1382                                "punpcklwd %%mm0, %%mm4\n\t" /* mm4 = [0 r1 g1 b1 0 r0 g0 b0] */
1383                                "movntq %%mm4, (%3)\n\t"
1384
1385                                "punpckhwd %%mm0, %%mm2\n\t" /* mm2 = [0 r3 g3 b3 0 r2 g2 b2] */
1386                                "movntq %%mm2, 8(%3)\n\t"
1387
1388                                "addl  $4, %0\n\t"
1389                                "addl  $4, %1\n\t"
1390                                "addl  $4, %2\n\t"
1391                                "addl $16, %3\n\t"
1392
1393                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1394                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1395                                : "memory");
1396                }
1397
1398                __asm__ __volatile__("sfence; emms\n\t");
1399
1400        }
1401        else if((accel & MM_MMX) == MM_MMX)
1402        {
1403                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1404                rest = pixels & 3; /* pixels - (n * 4) */
1405
1406
1407                __asm__ __volatile__(
1408                        "pxor %%mm3, %%mm3\n\t"
1409                        ::: "memory");
1410
1411                while(n--)
1412                {
1413                        __asm__ __volatile__(
1414
1415                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1416                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1417                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1418
1419                                "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [0 r3 0 r2 0 r1 0 r0] */
1420                                "punpcklbw %%mm1, %%mm2\n\t" /* mm2 = [g3 b3 g2 b2 g1 b1 g0 b0] */
1421
1422                                "movq %%mm2, %%mm4\n\t" /* mm2 = [g3 b3 g2 b2 g1 b1 g0 b0] */
1423                                "punpcklwd %%mm0, %%mm4\n\t" /* mm4 = [0 r1 g1 b1 0 r0 g0 b0] */
1424                                "movq %%mm4, (%3)\n\t"
1425
1426                                "punpckhwd %%mm0, %%mm2\n\t" /* mm2 = [0 r3 g3 b3 0 r2 g2 b2] */
1427                                "movq %%mm2, 8(%3)\n\t"
1428
1429                                "addl $4, %0\n\t"
1430                                "addl $4, %1\n\t"
1431                                "addl $4, %2\n\t"
1432                                "addl $16, %3\n\t"
1433
1434                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1435                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1436                                : "memory");
1437                }
1438
1439                __asm__ __volatile__("emms\n\t");
1440        }
1441#endif
1442
1443        while(rest--)
1444        {
1445                *(buffer)     = *(b_data++);
1446                *(buffer + 1) = *(g_data++);
1447                *(buffer + 2) = *(r_data++);
1448
1449                buffer += 4;
1450        }
1451
1452}
1453
1454
1455static void
1456__pack_rgb24(rgb_planar_t* data, void* dest,
1457                uint32_t pixels, uint32_t accel)
1458{
1459        uint8_t* buffer = (uint8_t*) dest;
1460        uint8_t* r_data = data->r;
1461        uint8_t* g_data = data->g;
1462        uint8_t* b_data = data->b;
1463        uint32_t rest = pixels;
1464
1465
1466/* MMXEXT doesn't speed up here */
1467#ifdef COMPILE_ASSEMBLY
1468
1469        if((accel & MM_MMX) == MM_MMX)
1470        {
1471                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1472                rest = pixels & 3; /* pixels - (n * 4) */
1473
1474
1475                __asm__ __volatile__(
1476                        "pxor %%mm3, %%mm3\n\t"
1477                        ::: "memory");
1478
1479                while(n--)
1480                {
1481                        __asm__ __volatile__(
1482
1483                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1484                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1485                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1486
1487                                "punpcklbw %%mm1, %%mm2\n\t" /* mm1 = [g3 b3 g2 b2 g1 b1 g0 b0] */
1488                                "punpcklbw %%mm3, %%mm0\n\t" /* mm3 = [0 r3 0 r2 0 r1 0 r0] */
1489
1490                                "movq %%mm2, %%mm4\n\t" /* mm4 = [g3 b3 g2 b2 g1 b1 g0 b0] */
1491                                "punpcklwd %%mm0, %%mm4\n\t" /* mm4 = [0 r1 g1 b1 0 r0 g0 b0] */
1492                                "movd %%mm4, (%3)\n\t"
1493                                "punpckhdq %%mm4, %%mm4\n\t" /* mm4 = [0 r1 g1 b1 0 r1 g1 b1] */
1494                                "movd %%mm4, 3(%3)\n\t"
1495
1496                                "punpckhwd %%mm0, %%mm2\n\t" /* mm2 = [0 r3 g3 b3 0 r2 g2 b2] */
1497                                "movd %%mm2, 6(%3)\n\t"
1498                                "punpckhdq %%mm2, %%mm2\n\t" /* mm2 = [0 r3 g3 b3 0 r3 g3 b3] */
1499                                "movd %%mm2, 9(%3)\n\t"
1500
1501                                "addl $4, %0\n\t"
1502                                "addl $4, %1\n\t"
1503                                "addl $4, %2\n\t"
1504                                "addl $12, %3\n\t"
1505
1506                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1507                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1508                                : "memory");
1509
1510                }
1511
1512                __asm__ __volatile__("emms\n\t");
1513
1514        }
1515#endif
1516
1517        while(rest--)
1518        {
1519                *(buffer)     = *(b_data++);
1520                *(buffer + 1) = *(g_data++);
1521                *(buffer + 2) = *(r_data++);
1522
1523                buffer += 3;
1524        }
1525
1526}
1527
1528
1529static void
1530__pack_rgb16(rgb_planar_t* data, void* dest,
1531                uint32_t pixels, uint32_t accel)
1532{
1533        uint16_t* buffer = (uint16_t*) dest;
1534        uint8_t* r_data = data->r;
1535        uint8_t* g_data = data->g;
1536        uint8_t* b_data = data->b;
1537        uint32_t rest = pixels;
1538
1539#ifdef COMPILE_ASSEMBLY
1540
1541        if((accel & MM_MMXEXT) == MM_MMXEXT)
1542        {
1543                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1544                rest = pixels & 3; /* pixels - (n * 4) */
1545
1546
1547                __asm__ __volatile__(
1548                        "pxor %%mm3, %%mm3\n\t"
1549                        ::: "memory");
1550
1551                while(n--)
1552                {
1553                        __asm__ __volatile__(
1554
1555                                "prefetchw 320(%3)\n\t"
1556
1557                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1558                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1559                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1560
1561                                "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [0 r3 0 r2 0 r1 0 r0] */
1562                                "punpcklbw %%mm3, %%mm1\n\t" /* mm1 = [0 g3 0 g2 0 g1 0 g0] */
1563                                "punpcklbw %%mm3, %%mm2\n\t" /* mm2 = [0 b3 0 b2 0 b1 0 b0] */
1564
1565                                "psrlw $3, %%mm0\n\t" /* word = [00000000 000rrrrr] */
1566                                "psrlw $2, %%mm1\n\t" /* word = [00000000 00gggggg] */
1567                                "psrlw $3, %%mm2\n\t" /* word = [00000000 000bbbbb] */
1568
1569                                "psllw $11, %%mm0\n\t" /* word = [rrrrr000 00000000] */
1570                                "psllw $5,  %%mm1\n\t" /* word = [00000ggg ggg00000] */
1571                                "por %%mm2, %%mm1\n\t" /* word = [00000ggg gggbbbbb] */
1572                                "por %%mm1, %%mm0\n\t" /* word = [rrrrrggg gggbbbbb] */
1573
1574                                "movntq %%mm0, (%3)\n\t"
1575
1576                                "addl $4, %0\n\t"
1577                                "addl $4, %1\n\t"
1578                                "addl $4, %2\n\t"
1579                                "addl $8, %3\n\t"
1580
1581                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1582                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1583                                : "memory");
1584                        }
1585
1586                __asm__ __volatile__("sfence; emms\n\t");
1587
1588        }
1589        else if((accel & MM_MMX) == MM_MMX)
1590        {
1591                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1592                rest = pixels & 3; /* pixels - (n * 4) */
1593
1594
1595                __asm__ __volatile__(
1596                        "pxor %%mm3, %%mm3\n\t"
1597                        ::: "memory");
1598
1599                while(n--)
1600                {
1601                        __asm__ __volatile__(
1602
1603                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1604                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1605                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1606
1607                                "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [0 r3 0 r2 0 r1 0 r0] */
1608                                "punpcklbw %%mm3, %%mm1\n\t" /* mm1 = [0 g3 0 g2 0 g1 0 g0] */
1609                                "punpcklbw %%mm3, %%mm2\n\t" /* mm2 = [0 b3 0 b2 0 b1 0 b0] */
1610
1611                                "psrlw $3, %%mm0\n\t" /* word = [00000000 000rrrrr] */
1612                                "psrlw $2, %%mm1\n\t" /* word = [00000000 00gggggg] */
1613                                "psrlw $3, %%mm2\n\t" /* word = [00000000 000bbbbb] */
1614
1615                                "psllw $11, %%mm0\n\t" /* word = [rrrrr000 00000000] */
1616                                "psllw $5,  %%mm1\n\t" /* word = [00000ggg ggg00000] */
1617                                "por %%mm2, %%mm1\n\t" /* word = [00000ggg gggbbbbb] */
1618                                "por %%mm1, %%mm0\n\t" /* word = [rrrrrggg gggbbbbb] */
1619
1620                                "movq %%mm0, (%3)\n\t"
1621
1622                                "addl $4, %0\n\t"
1623                                "addl $4, %1\n\t"
1624                                "addl $4, %2\n\t"
1625                                "addl $8, %3\n\t"
1626
1627                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1628                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1629                                : "memory");
1630                        }
1631
1632                __asm__ __volatile__("emms\n\t");
1633
1634        }
1635#endif
1636
1637        while(rest--)
1638        {
1639                uint16_t r16, g16, b16;
1640
1641                r16 = *(r_data++) >> 3;
1642                g16 = *(g_data++) >> 2;
1643                b16 = *(b_data++) >> 3;
1644
1645                *(buffer++) = ((r16 << 11) | (g16 << 5) | b16);
1646        }
1647
1648}
1649
1650
1651static void
1652__pack_bgra(rgb_planar_t* data, void* dest,
1653                 uint32_t pixels, uint32_t accel)
1654{
1655        static const uint32_t alpha[] =
1656        {
1657                0xffffffff,
1658                0xffffffff
1659        };
1660        uint8_t* buffer = (uint8_t*) dest;
1661        uint8_t* r_data = data->r;
1662        uint8_t* g_data = data->g;
1663        uint8_t* b_data = data->b;
1664        uint32_t rest = pixels;
1665
1666
1667#ifdef COMPILE_ASSEMBLY
1668        if((accel & MM_MMXEXT) == MM_MMXEXT)
1669        {
1670                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1671                rest = pixels & 3; /* pixels - (n * 4) */
1672
1673
1674                while(n--)
1675                {
1676                        __asm__ __volatile__(
1677
1678                                "prefetchw 320(%3)\n\t"
1679
1680                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1681                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1682                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1683
1684                                "por (%4), %%mm3\n\t" /* mm3 = [ff ff ff ff ff ff ff ff] */
1685                                "punpcklbw %%mm0, %%mm3\n\t" /* mm3 = [r3 ff r2 ff r1 ff r0 ff] */
1686                                "punpcklbw %%mm2, %%mm1\n\t" /* mm1 = [b3 g3 b2 g2 b1 g1 b0 g0] */
1687
1688                                "movq %%mm3, %%mm4\n\t" /* mm4 = [r3 ff r2 ff r1 ff r0 ff] */
1689                                "punpcklwd %%mm1, %%mm4\n\t" /* mm4 = [b1 g1 r1 ff b1 g1 r1 ff] */
1690                                "movntq %%mm4, (%3)\n\t"
1691
1692                                "punpckhwd %%mm1, %%mm3\n\t" /* mm3 = [b3 g3 r3 ff b2 g2 r2 ff] */
1693                                "movntq %%mm0, 8(%3)\n\t"
1694
1695                                "addl $4, %0\n\t"
1696                                "addl $4, %1\n\t"
1697                                "addl $4, %2\n\t"
1698                                "addl $16, %3\n\t"
1699
1700                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1701                                : "r" (alpha), "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1702                                : "memory");
1703                }
1704
1705                __asm__ __volatile__("sfence; emms\n\t");
1706
1707        }
1708        else if((accel & MM_MMX) == MM_MMX)
1709        {
1710                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1711                rest = pixels & 3; /* pixels - (n * 4) */
1712
1713
1714                while(n--)
1715                {
1716                        __asm__ __volatile__(
1717
1718                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1719                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1720                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1721
1722                                "por (%4), %%mm3\n\t" /* mm3 = [ff ff ff ff ff ff ff ff] */
1723                                "punpcklbw %%mm0, %%mm3\n\t" /* mm3 = [r3 ff r2 ff r1 ff r0 ff] */
1724                                "punpcklbw %%mm2, %%mm1\n\t" /* mm1 = [b3 g3 b2 g2 b1 g1 b0 g0] */
1725
1726                                "movq %%mm3, %%mm4\n\t" /* mm4 = [r3 ff r2 ff r1 ff r0 ff] */
1727                                "punpcklwd %%mm1, %%mm4\n\t" /* mm4 = [b1 g1 r1 ff b1 g1 r1 ff] */
1728                                "movq %%mm4, (%3)\n\t"
1729
1730                                "punpckhwd %%mm1, %%mm3\n\t" /* mm3 = [b3 g3 r3 ff b2 g2 r2 ff] */
1731                                "movq %%mm0, 8(%3)\n\t"
1732
1733                                "addl $4, %0\n\t"
1734                                "addl $4, %1\n\t"
1735                                "addl $4, %2\n\t"
1736                                "addl $16, %3\n\t"
1737
1738                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1739                                : "r" (alpha), "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1740                                : "memory");
1741                }
1742
1743                __asm__ __volatile__("emms\n\t");
1744
1745        }
1746
1747#endif
1748        while(rest--)
1749        {
1750                *(buffer)     = 0xff;
1751                *(buffer + 1) = *(r_data++);
1752                *(buffer + 2) = *(g_data++);
1753                *(buffer + 3) = *(b_data++);
1754
1755                buffer += 4;
1756        }
1757
1758}
1759
1760
1761static void
1762__pack_bgra5551(rgb_planar_t* data, void* dest,
1763                 uint32_t pixels, uint32_t accel)
1764{
1765        static const uint16_t alpha[] =
1766        {
1767                1, 1, 1, 1
1768        };
1769        uint16_t* buffer = (uint16_t*) dest;
1770        uint8_t* r_data = data->r;
1771        uint8_t* g_data = data->g;
1772        uint8_t* b_data = data->b;
1773        uint32_t rest = pixels;
1774
1775
1776#ifdef COMPILE_ASSEMBLY
1777        if((accel & MM_MMXEXT) == MM_MMXEXT)
1778        {
1779                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1780                rest = pixels & 3; /* pixels - (n * 4) */
1781
1782
1783                __asm__ __volatile__(
1784                        "pxor %%mm3, %%mm3\n\t"
1785                        ::: "memory");
1786
1787                while(n--)
1788                {
1789                        __asm__ __volatile__(
1790
1791                                "prefetchw 320(%3)\n\t"
1792
1793                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1794                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1795                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1796
1797                                "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [0 r3 0 r2 0 r1 0 r0] */
1798                                "punpcklbw %%mm3, %%mm1\n\t" /* mm1 = [0 g3 0 g2 0 g1 0 g0] */
1799                                "punpcklbw %%mm3, %%mm2\n\t" /* mm2 = [0 b3 0 b2 0 b1 0 b0] */
1800
1801                                "psrlw $2, %%mm0\n\t" /* word = [00000000 00rrrrrr] */
1802                                "psrlw $3, %%mm1\n\t" /* word = [00000000 000ggggg] */
1803                                "psrlw $3, %%mm2\n\t" /* word = [00000000 000bbbbb] */
1804
1805                                "psllw $11, %%mm2\n\t" /* word = [bbbbb000 00000000] */
1806                                "psllw $6, %%mm1\n\t"  /* word = [00000ggg gg000000] */
1807                                "por (%4), %%mm0\n\t"  /* word = [00000000 00rrrrra] */
1808                                "por %%mm2, %%mm1\n\t" /* word = [bbbbbggg gg000000] */
1809                                "por %%mm1, %%mm0\n\t" /* word = [bbbbbggg ggrrrrra] */
1810
1811                                "movntq %%mm0, (%3)\n\t"
1812
1813                                "addl $4, %0\n\t"
1814                                "addl $4, %1\n\t"
1815                                "addl $4, %2\n\t"
1816                                "addl $8, %3\n\t"
1817
1818                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1819                                : "r" (alpha), "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1820                                : "memory");
1821                }
1822
1823                __asm__ __volatile__("sfence; emms\n\t");
1824
1825        }
1826        else if((accel & MM_MMX) == MM_MMX)
1827        {
1828                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1829                rest = pixels & 3; /* pixels - (n * 4) */
1830
1831
1832                __asm__ __volatile__(
1833                        "pxor %%mm3, %%mm3\n\t"
1834                        ::: "memory");
1835
1836                while(n--)
1837                {
1838                        __asm__ __volatile__(
1839
1840                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1841                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1842                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1843
1844                                "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [0 r3 0 r2 0 r1 0 r0] */
1845                                "punpcklbw %%mm3, %%mm1\n\t" /* mm1 = [0 g3 0 g2 0 g1 0 g0] */
1846                                "punpcklbw %%mm3, %%mm2\n\t" /* mm2 = [0 b3 0 b2 0 b1 0 b0] */
1847
1848                                "psrlw $2, %%mm0\n\t" /* word = [00000000 00rrrrrr] */
1849                                "psrlw $3, %%mm1\n\t" /* word = [00000000 000ggggg] */
1850                                "psrlw $3, %%mm2\n\t" /* word = [00000000 000bbbbb] */
1851
1852                                "psllw $11, %%mm2\n\t" /* word = [bbbbb000 00000000] */
1853                                "psllw $6, %%mm1\n\t"  /* word = [00000ggg gg000000] */
1854                                "por (%4), %%mm0\n\t"  /* word = [00000000 00rrrrra] */
1855                                "por %%mm2, %%mm1\n\t" /* word = [bbbbbggg gg000000] */
1856                                "por %%mm1, %%mm0\n\t" /* word = [bbbbbggg ggrrrrra] */
1857
1858                                "movq %%mm0, (%3)\n\t"
1859
1860                                "addl $4, %0\n\t"
1861                                "addl $4, %1\n\t"
1862                                "addl $4, %2\n\t"
1863                                "addl $8, %3\n\t"
1864
1865                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1866                                : "r" (alpha), "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1867                                : "memory");
1868                }
1869
1870                __asm__ __volatile__("emms\n\t");
1871
1872        }
1873#endif
1874
1875        while(rest--)
1876        {
1877                uint16_t r5, g5, b5;
1878
1879                r5 = *(r_data++) >> 2;
1880                g5 = *(g_data++) >> 3;
1881                b5 = *(b_data++) >> 3;
1882
1883                *(buffer++) = ((b5 << 11) | (g5 << 6) | r5 | 1);
1884        }
1885
1886}
1887
1888
1889static void
1890__pack_bgr32(rgb_planar_t* data, void* dest,
1891                 uint32_t pixels, uint32_t accel)
1892{
1893        uint8_t* buffer = (uint8_t*) dest;
1894        uint8_t* r_data = data->r;
1895        uint8_t* g_data = data->g;
1896        uint8_t* b_data = data->b;
1897        uint32_t rest = pixels;
1898
1899#ifdef COMPILE_ASSEMBLY
1900
1901        if((accel & MM_MMXEXT) == MM_MMXEXT)
1902        {
1903                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1904                rest = pixels & 3; /* pixels - (n * 4) */
1905
1906
1907                __asm__ __volatile__(
1908                        "pxor %%mm3, %%mm3\n\t"
1909                        ::: "memory");
1910
1911                while(n--)
1912                {
1913                        __asm__ __volatile__(
1914
1915                                "prefetchw 320(%0)\n\t"
1916
1917                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1918                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1919                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1920
1921                                "punpcklbw %%mm1, %%mm0\n\t" /* mm0 = [g3 r3 g2 r2 g1 r1 g0 r0] */
1922                                "punpcklbw %%mm3, %%mm2\n\t" /* mm2 = [b3 0 b2 0 b1 0 b0 0] */
1923
1924                                "movq %%mm0, %%mm4\n\t" /* mm4 = [g3 r3 g2 r2 g1 r1 g0 r0] */
1925                                "punpcklwd %%mm2, %%mm4\n\t" /* mm4 = [0 b1 g1 r1 0 b0 g0 r0] */
1926                                "movntq %%mm4, (%3)\n\t"
1927
1928                                "punpckhwd %%mm2, %%mm0\n\t" /* mm0 = [0 b3 g3 r3 0 b2 g2 r2] */
1929                                "movntq %%mm0, 8(%3)\n\t"
1930
1931                                "addl $4, %0\n\t"
1932                                "addl $4, %1\n\t"
1933                                "addl $4, %2\n\t"
1934                                "addl $16, %3\n\t"
1935
1936                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1937                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1938                                : "memory");
1939                }
1940
1941                __asm__ __volatile__("sfence; emms\n\t");
1942
1943        }
1944        else if((accel & MM_MMX) == MM_MMX)
1945        {
1946                uint32_t n = pixels >> 2; /* (width * height) / 4 */
1947                rest = pixels & 3; /* pixels - (n * 4) */
1948
1949
1950                __asm__ __volatile__(
1951                        "pxor %%mm3, %%mm3\n\t"
1952                        ::: "memory");
1953
1954                while(n--)
1955                {
1956                        __asm__ __volatile__(
1957
1958                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
1959                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
1960                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
1961
1962                                "punpcklbw %%mm1, %%mm0\n\t" /* mm0 = [g3 r3 g2 r2 g1 r1 g0 r0] */
1963                                "punpcklbw %%mm3, %%mm2\n\t" /* mm2 = [b3 0 b2 0 b1 0 b0 0] */
1964
1965                                "movq %%mm0, %%mm4\n\t" /* mm4 = [g3 r3 g2 r2 g1 r1 g0 r0] */
1966                                "punpcklwd %%mm2, %%mm4\n\t" /* mm4 = [0 b1 g1 r1 0 b0 g0 r0] */
1967                                "movq %%mm4, (%3)\n\t"
1968
1969                                "punpckhwd %%mm2, %%mm0\n\t" /* mm0 = [0 b3 g3 r3 0 b2 g2 r2] */
1970                                "movq %%mm0, 8(%3)\n\t"
1971
1972                                "addl $4, %0\n\t"
1973                                "addl $4, %1\n\t"
1974                                "addl $4, %2\n\t"
1975                                "addl $16, %3\n\t"
1976
1977                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
1978                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
1979                                : "memory");
1980                }
1981
1982                __asm__ __volatile__("emms\n\t");
1983
1984        }
1985#endif
1986
1987        while(rest--)
1988        {
1989                *(buffer)     = *(r_data++);
1990                *(buffer + 1) = *(g_data++);
1991                *(buffer + 2) = *(b_data++);
1992
1993                buffer += 4;
1994        }
1995
1996}
1997
1998
1999static void
2000__pack_bgr24(rgb_planar_t* data, void* dest,
2001                 uint32_t pixels, uint32_t accel)
2002{
2003        uint8_t* buffer = (uint8_t*) dest;
2004        uint8_t* r_data = data->r;
2005        uint8_t* g_data = data->g;
2006        uint8_t* b_data = data->b;
2007        uint32_t rest = pixels;
2008
2009
2010/* MMXEXT doesn't speed up here */
2011
2012#ifdef COMPILE_ASSEMBLY
2013        if((accel & MM_MMX) == MM_MMX)
2014        {
2015                uint32_t n = pixels >> 2; /* (width * height) / 4 */
2016                rest = pixels & 3; /* pixels - (n * 4) */
2017
2018
2019                __asm__ __volatile__(
2020                        "pxor %%mm3, %%mm3\n\t"
2021                        ::: "memory");
2022
2023                while(n--)
2024                {
2025                        __asm__ __volatile__(
2026
2027                                "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */
2028                                "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */
2029                                "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */
2030
2031                                "punpcklbw %%mm1, %%mm0\n\t" /* mm1 = [g3 r3 g2 r2 g1 r1 g0 r0] */
2032                                "punpcklbw %%mm3, %%mm2\n\t" /* mm3 = [0 b3 0 b2 0 b1 0 b0] */
2033
2034                                "movq %%mm0, %%mm4\n\t" /* mm4 = [g3 r3 g2 r2 g1 r1 g0 r0] */
2035                                "punpcklwd %%mm2, %%mm4\n\t" /* mm4 = [0 b1 g1 r1 0 b0 g0 r0] */
2036                                "movd %%mm4, (%3)\n\t"
2037                                "punpckhdq %%mm4, %%mm4\n\t" /* mm4 = [0 b1 g1 r1 0 b1 g1 r1] */
2038                                "movd %%mm4, 3(%3)\n\t"
2039
2040                                "punpckhwd %%mm2, %%mm0\n\t" /* mm2 = [0 b3 g3 r3 0 b2 g2 r2] */
2041                                "movd %%mm0, 6(%3)\n\t"
2042                                "punpckhdq %%mm0, %%mm0\n\t" /* mm2 = [0 b3 g3 r3 0 b3 g3 r3] */
2043                                "movd %%mm0, 9(%3)\n\t"
2044
2045                                "addl $4, %0\n\t"
2046                                "addl $4, %1\n\t"
2047                                "addl $4, %2\n\t"
2048                                "addl $12, %3\n\t"
2049
2050                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
2051                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
2052                                : "memory");
2053                }
2054
2055                __asm__ __volatile__("emms\n\t");
2056
2057        }
2058#endif
2059
2060
2061        while(rest--)
2062        {
2063                *(buffer)     = *(r_data++);
2064                *(buffer + 1) = *(g_data++);
2065                *(buffer + 2) = *(b_data++);
2066
2067                buffer += 3;
2068        }
2069
2070}
2071
2072
2073static void
2074__pack_bgr16(rgb_planar_t* data, void* dest,
2075                 uint32_t pixels, uint32_t accel)
2076{
2077        uint16_t* buffer = (uint16_t*) dest;
2078        uint8_t* r_data = data->r;
2079        uint8_t* g_data = data->g;
2080        uint8_t* b_data = data->b;
2081        uint32_t rest = pixels;
2082
2083
2084#ifdef COMPILE_ASSEMBLY
2085        if((accel & MM_MMXEXT) == MM_MMXEXT)
2086        {
2087                uint32_t n = pixels >> 2; /* (width * height) / 4 */
2088                rest = pixels & 3; /* pixels - (n * 4) */
2089
2090
2091                __asm__ __volatile__(
2092                        "pxor %%mm3, %%mm3\n\t"
2093                        ::: "memory");
2094
2095                while(n--)
2096                {
2097                        __asm__ __volatile__(
2098
2099                                "prefetchw 320(%0)\n\t"
2100
2101                                "movd (%0), %%mm0\n\t"  /* mm0 = [0 | r3r2r1r0] */
2102                                "movd (%1), %%mm1\n\t"  /* mm1 = [0 | g3g2g1g0] */
2103                                "movd (%2), %%mm2\n\t"  /* mm2 = [0 | b3b2b1b0] */
2104
2105                                "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [0 r3 0 r2 0 r1 0 r0] */
2106                                "punpcklbw %%mm3, %%mm1\n\t" /* mm1 = [0 g3 0 g2 0 g1 0 g0] */
2107                                "punpcklbw %%mm3, %%mm2\n\t" /* mm2 = [0 b3 0 b2 0 b1 0 b0] */
2108
2109                                "psrlw $3, %%mm0\n\t" /* word = [00000000 000rrrrr] */
2110                                "psrlw $2, %%mm1\n\t" /* word = [00000000 00gggggg] */
2111                                "psrlw $3, %%mm2\n\t" /* word = [00000000 000bbbbb] */
2112
2113                                "psllw $11, %%mm2\n\t" /* word = [bbbbb000 00000000] */
2114                                "psllw $5,  %%mm1\n\t" /* word = [00000ggg ggg00000] */
2115                                "por %%mm2, %%mm1\n\t" /* word = [bbbbbggg ggg00000] */
2116                                "por %%mm1, %%mm0\n\t" /* word = [bbbbbggg gggrrrrr] */
2117
2118                                "movntq %%mm0, (%3)\n\t"
2119
2120                                "addl $4, %0\n\t"
2121                                "addl $4, %1\n\t"
2122                                "addl $4, %2\n\t"
2123                                "addl $8, %3\n\t"
2124
2125                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
2126                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
2127                                : "memory");
2128                }
2129
2130                __asm__ __volatile__("sfence; emms\n\t");
2131
2132        }
2133        else if((accel & MM_MMX) == MM_MMX)
2134        {
2135                uint32_t n = pixels >> 2; /* (width * height) / 4 */
2136                rest = pixels & 3; /* pixels - (n * 4) */
2137
2138
2139                __asm__ __volatile__(
2140                        "pxor %%mm3, %%mm3\n\t"
2141                        ::: "memory");
2142
2143                while(n--)
2144                {
2145                        __asm__ __volatile__(
2146
2147                                "movd (%0), %%mm0\n\t"  /* mm0 = [0 | r3r2r1r0] */
2148                                "movd (%1), %%mm1\n\t"  /* mm1 = [0 | g3g2g1g0] */
2149                                "movd (%2), %%mm2\n\t"  /* mm2 = [0 | b3b2b1b0] */
2150
2151                                "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [0 r3 0 r2 0 r1 0 r0] */
2152                                "punpcklbw %%mm3, %%mm1\n\t" /* mm1 = [0 g3 0 g2 0 g1 0 g0] */
2153                                "punpcklbw %%mm3, %%mm2\n\t" /* mm2 = [0 b3 0 b2 0 b1 0 b0] */
2154
2155                                "psrlw $3, %%mm0\n\t" /* word = [00000000 000rrrrr] */
2156                                "psrlw $2, %%mm1\n\t" /* word = [00000000 00gggggg] */
2157                                "psrlw $3, %%mm2\n\t" /* word = [00000000 000bbbbb] */
2158
2159                                "psllw $11, %%mm2\n\t" /* word = [bbbbb000 00000000] */
2160                                "psllw $5,  %%mm1\n\t" /* word = [00000ggg ggg00000] */
2161                                "por %%mm2, %%mm1\n\t" /* word = [bbbbbggg ggg00000] */
2162                                "por %%mm1, %%mm0\n\t" /* word = [bbbbbggg gggrrrrr] */
2163
2164                                "movq %%mm0, (%3)\n\t"
2165
2166                                "addl $4, %0\n\t"
2167                                "addl $4, %1\n\t"
2168                                "addl $4, %2\n\t"
2169                                "addl $8, %3\n\t"
2170
2171                                : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer)
2172                                : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer)
2173                                : "memory");
2174                }
2175
2176                __asm__ __volatile__("emms\n\t");
2177
2178        }
2179#endif
2180
2181
2182        while(rest--)
2183        {
2184                uint16_t r16, g16, b16;
2185
2186                r16 = *(r_data++) >> 3;
2187                g16 = *(g_data++) >> 2;
2188                b16 = *(b_data++) >> 3;
2189
2190                *(buffer++) = ((b16 << 11) | (g16 << 5) | r16);
2191        }
2192
2193}
2194
2195
2196
2197static const rgbout_packer_t pack_methods[] =
2198{
2199/*      name / pixel id / pixel size / scratch / function */
2200        {    "ARGB",     PX_ARGB, 4, 0,     __pack_argb},
2201        {"ARGB1555", PX_ARGB1555, 2, 0, __pack_argb1555},
2202        {   "RGB32",    PX_RGB32, 4, 0,    __pack_rgb32},
2203        {   "RGB24",    PX_RGB24, 3, 1,    __pack_rgb24},
2204        {   "RGB16",    PX_RGB16, 2, 0,    __pack_rgb16},
2205        {    "BGRA",     PX_BGRA, 4, 0,     __pack_bgra},
2206        {"BGRA5551", PX_BGRA5551, 2, 0, __pack_bgra5551},
2207        {   "BGR32",    PX_BGR32, 4, 0,    __pack_bgr32},
2208        {   "BGR24",    PX_BGR24, 3, 1,    __pack_bgr24},
2209        {   "BGR26",    PX_BGR16, 2, 0,    __pack_bgr16}
2210};
2211
2212
2213
2214
2215
2216
2217static uint32_t
2218rgbout_get_capabilities(vo_driver_t* vo_driver)
2219{
2220        return(VO_CAP_YV12 | VO_CAP_YUY2);
2221}
2222
2223
2224static void
2225rgbout_frame_field(vo_frame_t* vo_frame, int flags)
2226{
2227        /* nothing */
2228}
2229
2230
2231static void
2232rgbout_frame_dispose(vo_frame_t* vo_frame)
2233{
2234        rgbout_frame_t* frame = (rgbout_frame_t*) vo_frame;
2235
2236        EVAL(vo_frame != NULL)
2237
2238        release(frame->chunk[0]);
2239        release(frame->chunk[1]);
2240        release(frame->chunk[2]);
2241        free(frame);
2242
2243FAILURE:
2244        return;
2245}
2246
2247
2248static vo_frame_t*
2249rgbout_alloc_frame(vo_driver_t* vo_driver)
2250{
2251        rgbout_driver_t* this = (rgbout_driver_t*) vo_driver;
2252        rgbout_frame_t* frame = NULL;
2253
2254        EVAL(vo_driver != NULL);
2255
2256        EVAL(frame = (rgbout_frame_t*) malloc(sizeof(rgbout_frame_t)));
2257        clear(frame, sizeof(rgbout_frame_t));
2258        this->frame = frame;
2259
2260        pthread_mutex_init(&(frame->vo_frame.mutex), NULL);
2261
2262        frame->vo_frame.proc_slice = NULL;
2263        frame->vo_frame.proc_frame = NULL;
2264        frame->vo_frame.field      = rgbout_frame_field;
2265        frame->vo_frame.dispose    = rgbout_frame_dispose;
2266        frame->vo_frame.driver     = vo_driver;
2267
2268        if(this->frame_width && this->frame_height)
2269                frame->pixels = (this->frame_width * this->frame_height);
2270
2271        return((vo_frame_t*) frame);
2272
2273FAILURE:
2274        return(NULL);
2275}
2276
2277
2278static void
2279rgbout_update_frame_format(vo_driver_t* vo_driver, vo_frame_t* vo_frame,
2280                uint32_t width, uint32_t height, double ratio,
2281                int format, int flags)
2282{
2283        rgbout_driver_t* this = (rgbout_driver_t*) vo_driver;
2284        rgbout_frame_t* frame = (rgbout_frame_t*) vo_frame;
2285        static int told = 0;
2286
2287
2288        EVAL(vo_driver != NULL);
2289        EVAL(vo_frame  != NULL);
2290        CHECK(width  != 0);
2291        CHECK(height != 0);
2292
2293        frame->width  = width + (width & 1); /* if odd, round to next even number */
2294        frame->height = height + (height & 1); /* if odd, round to next even number */
2295        frame->pixels = frame->width * frame->height;
2296        frame->ratio  = ratio;
2297        frame->format = format;
2298
2299        this->lastframe_width  = this->frame_width;
2300        this->lastframe_height = this->frame_height;
2301        this->frame_width      = frame->width;
2302        this->frame_height     = frame->height;
2303
2304        release(frame->chunk[0]);
2305        release(frame->chunk[1]);
2306        release(frame->chunk[2]);
2307
2308CHECK_FRAME:
2309        switch(frame->format)
2310        {
2311                case XINE_IMGFMT_YV12:
2312                {
2313                        if(!(told))
2314                        {
2315                                if (s_debugMessages) fprintf(stderr, THIS ": yuv format is YV12\n");
2316                                told = 1;
2317                        }
2318                       
2319                        this->convert = convert_methods[this->cm].convert_yv12;
2320                        frame->vo_frame.pitches[0] = (frame->width > 7) ? frame->width : 8;
2321                        frame->vo_frame.pitches[1] = (frame->width > 15) ? (frame->width >> 1) : 8;
2322                        frame->vo_frame.pitches[2] = frame->vo_frame.pitches[1];
2323                        frame->vo_frame.base[0] = (uint8_t*) xine_xmalloc_aligned(16,
2324                                                                frame->vo_frame.pitches[0] * frame->height,
2325                                                                &(frame->chunk[0]));
2326                        frame->vo_frame.base[1] = (uint8_t*) xine_xmalloc_aligned(16,
2327                                                                frame->vo_frame.pitches[1] * (frame->height >> 1),
2328                                                                &(frame->chunk[1]));
2329                        frame->vo_frame.base[2] = (uint8_t*) xine_xmalloc_aligned(16,
2330                                                                frame->vo_frame.pitches[2] * (frame->height >> 1),
2331                                                                &(frame->chunk[2]));
2332                }
2333                break;
2334
2335                case XINE_IMGFMT_YUY2:
2336                {
2337                        if(!(told))
2338                        {
2339                                if (s_debugMessages) fprintf(stderr, THIS ": yuv format is YUY2\n");
2340                                told = 1;
2341                        }
2342                       
2343                        this->convert = convert_methods[this->cm].convert_yuy2;
2344                        frame->vo_frame.pitches[0] = (frame->width > 3) ? (frame->width << 1) : 8;
2345                        frame->vo_frame.pitches[1] = 0;
2346                        frame->vo_frame.pitches[2] = 0;
2347                        frame->vo_frame.base[0] = (uint8_t*) xine_xmalloc_aligned(16,
2348                                                                frame->vo_frame.pitches[0] * frame->height,
2349                                                                &(frame->chunk[0]));
2350                        frame->vo_frame.base[1] = NULL;
2351                        frame->vo_frame.base[2] = NULL;
2352                }
2353                break;
2354
2355                default:
2356                {
2357                        if(!(told))
2358                        {
2359                                if (s_debugMessages) fprintf(stderr, THIS
2360                                        ": unknown yuv format [%#x], assuming YV12\n",
2361                                        frame->format);
2362                                told = 1;
2363                        }
2364
2365                        frame->format = XINE_IMGFMT_YV12;
2366                        goto CHECK_FRAME;
2367                }
2368                break;
2369        }
2370
2371
2372        if(this->frame_width != this->lastframe_width ||
2373                this->frame_height != this->lastframe_height)
2374        {
2375                release(this->buffer.r);
2376                release(this->buffer.g);
2377                release(this->buffer.b);
2378                release(this->outbuffer);
2379        }
2380
2381/* some malloc call can fail;
2382 * therefore always check each buffer
2383 */
2384        if(!(this->buffer.r))
2385                this->buffer.r  = (uint8_t*) xine_xmalloc(frame->pixels + 4);
2386
2387        if(!(this->buffer.g))
2388                this->buffer.g  = (uint8_t*) xine_xmalloc(frame->pixels + 4);
2389
2390        if(!(this->buffer.b))
2391                this->buffer.b  = (uint8_t*) xine_xmalloc(frame->pixels + 4);
2392
2393        if(!(this->outbuffer))
2394        {
2395                uint32_t outbuffer_size = (frame->pixels * pack_methods[this->pm].pixelsize)
2396                                           + pack_methods[this->pm].scratch;
2397                EVAL(this->outbuffer = xine_xmalloc(outbuffer_size));
2398                clear(this->outbuffer, outbuffer_size);
2399        }
2400
2401
2402FAILURE:
2403        return;
2404}
2405
2406
2407/* the only public callback, currently */
2408static int
2409rgbout_update_visual(vo_driver_t* vo_driver,
2410                        rgbout_visual_info_t* new_visual)
2411{
2412        rgbout_driver_t* this = (rgbout_driver_t*) vo_driver;
2413        uint32_t i    = 0;
2414        uint8_t found = 0;
2415        uint32_t pm   = 0;
2416
2417        EVAL(vo_driver  != NULL);
2418        EVAL(new_visual != NULL);
2419        EVAL(new_visual->callback != NULL);
2420
2421        for(; i < (sizeof(pack_methods) / sizeof(rgbout_packer_t)); i++)
2422        {
2423                if(pack_methods[i].id == new_visual->format)
2424                {
2425                        found = 1;
2426                        pm = i;
2427
2428                        if(pack_methods[pm].pixelsize != pack_methods[this->pm].pixelsize ||
2429                           pack_methods[pm].scratch > pack_methods[this->pm].scratch)
2430                        {
2431                                release(this->outbuffer);
2432                        }
2433
2434                        break;
2435                }
2436        }
2437
2438        if(!(found))
2439        {
2440                if (s_debugMessages) fprintf(stderr, THIS ": unknown pixel format [%i]\n",
2441                                new_visual->format);
2442                goto FAILURE;
2443        }
2444
2445        this->pm     = pm;
2446        this->pack   = pack_methods[pm].pack;
2447        this->levels = new_visual->levels;
2448        this->render = new_visual->callback;
2449
2450        return(1);
2451
2452FAILURE:
2453        return(0);
2454}
2455
2456
2457static void
2458rgbout_display_frame(vo_driver_t* vo_driver, vo_frame_t* vo_frame)
2459{
2460        rgbout_driver_t* this = (rgbout_driver_t*) vo_driver;
2461        rgbout_frame_t* frame = (rgbout_frame_t*) vo_frame;
2462#ifdef DEBUG
2463        static int skip_frames = 2; /* start speed test at frame n+1 */
2464        static int test_frames = 3; /* test for n frames */
2465#endif
2466       
2467
2468        EVAL(vo_driver != NULL);
2469        EVAL(vo_frame  != NULL);
2470        EVAL(this->buffer.r  != NULL);
2471        EVAL(this->buffer.g  != NULL);
2472        EVAL(this->buffer.b  != NULL);
2473        EVAL(this->outbuffer != NULL);
2474
2475        switch(frame->format)
2476        {
2477                case XINE_IMGFMT_YV12:
2478                {
2479                        EVAL(frame->vo_frame.base[0] != NULL);
2480                        EVAL(frame->vo_frame.base[1] != NULL);
2481                        EVAL(frame->vo_frame.base[2] != NULL);
2482                }
2483                break;
2484
2485                case XINE_IMGFMT_YUY2:
2486                {
2487                        EVAL(frame->vo_frame.base[0] != NULL);
2488                }
2489                break;
2490        }
2491
2492#ifdef DEBUG
2493       
2494        if(test_frames && skip_frames < 1)
2495        {
2496                uint64_t t;
2497
2498                t = rdtsc();
2499                this->convert(frame->vo_frame.base, &(this->buffer),
2500                                frame->vo_frame.pitches, frame->width, frame->height);
2501                t = rdtsc() - t;
2502                fprintf(stderr, THIS ": [ %lli nanosec.] %s conversion speed test\n",
2503                                t, (convert_methods[this->cm].name)
2504                                    ? convert_methods[this->cm].name : "C");
2505
2506                if(!(this->levels & PXLEVEL_R))
2507                        clear(this->buffer.r, frame->pixels);
2508                if(!(this->levels & PXLEVEL_G))
2509                        clear(this->buffer.g, frame->pixels);
2510                if(!(this->levels & PXLEVEL_B))
2511                        clear(this->buffer.b, frame->pixels);
2512
2513                t = rdtsc();
2514                this->pack(&(this->buffer), this->outbuffer, frame->pixels, this->accel);
2515                t = rdtsc() - t;
2516                fprintf(stderr, THIS ": [ %lli nanosec.] %s packing speed test\n",
2517                                t, pack_methods[this->pm].name);
2518               
2519                test_frames--;
2520        }
2521        else
2522        {
2523                this->convert(frame->vo_frame.base, &(this->buffer),
2524                                frame->vo_frame.pitches, frame->width, frame->height);
2525
2526                if(!(this->levels & PXLEVEL_R))
2527                        clear(this->buffer.r, frame->pixels);
2528                if(!(this->levels & PXLEVEL_G))
2529                        clear(this->buffer.g, frame->pixels);
2530                if(!(this->levels & PXLEVEL_B))
2531                        clear(this->buffer.b, frame->pixels);
2532                                       
2533                this->pack(&(this->buffer), this->outbuffer, frame->pixels, this->accel);
2534        }
2535
2536        skip_frames--;
2537       
2538#else /* ! DEBUG */
2539       
2540        this->convert(frame->vo_frame.base, &(this->buffer),
2541                                frame->vo_frame.pitches, frame->width, frame->height);
2542
2543        if(!(this->levels & PXLEVEL_R))
2544                clear(this->buffer.r, frame->pixels);
2545        if(!(this->levels & PXLEVEL_G))
2546                clear(this->buffer.g, frame->pixels);
2547        if(!(this->levels & PXLEVEL_B))
2548                clear(this->buffer.b, frame->pixels);
2549
2550        this->pack(&(this->buffer), this->outbuffer, frame->pixels, this->accel);
2551
2552#endif /* DEBUG */
2553
2554        this->render(frame->width, frame->height, this->outbuffer, this->user_data);
2555
2556FAILURE:
2557        frame->vo_frame.free(&(frame->vo_frame));
2558}
2559
2560
2561static int
2562rgbout_get_property(vo_driver_t* vo_driver, int property)
2563{
2564        return(0);
2565}
2566
2567
2568static int
2569rgbout_set_property(vo_driver_t* vo_driver, int property, int value)
2570{
2571        return(0);
2572}
2573
2574
2575static void
2576rgbout_get_property_min_max(vo_driver_t* vo_driver,
2577                        int property, int *min, int *max)
2578{
2579        *(min) = 0;
2580        *(max) = 0;
2581}
2582
2583
2584static int
2585rgbout_gui_data_exchange(vo_driver_t* vo_driver,
2586                                int data_type, void *data)
2587{
2588        fprintf(stderr, THIS ": data exchange not implemented, yet\n");
2589        return(0);
2590}
2591
2592
2593static int
2594rgbout_redraw_needed(vo_driver_t* vo_driver)
2595{
2596        /* not needed */
2597        return(0);
2598}
2599
2600
2601static void
2602rgbout_dispose(vo_driver_t* vo_driver)
2603{
2604        rgbout_driver_t* this = (rgbout_driver_t*) vo_driver;
2605
2606        EVAL(vo_driver != NULL);
2607
2608        release(this->buffer.r);
2609        release(this->buffer.g);
2610        release(this->buffer.b);
2611        release(this->outbuffer);
2612        free(this);
2613
2614FAILURE:
2615        return;
2616}
2617
2618
2619static vo_driver_t*
2620open_plugin(video_driver_class_t* vo_class, const void *vo_visual)
2621{
2622        rgbout_visual_info_t* visual = (rgbout_visual_info_t*) vo_visual;
2623        rgbout_driver_t* this        = NULL;
2624
2625        EVAL(vo_class  != NULL);
2626        EVAL(vo_visual != NULL);
2627        EVAL(visual->callback != NULL);
2628
2629        EVAL(this = (rgbout_driver_t*) malloc(sizeof(rgbout_driver_t)));
2630        clear(this, sizeof(rgbout_driver_t));
2631
2632        this->vo_driver.get_capabilities     = rgbout_get_capabilities;
2633        this->vo_driver.alloc_frame          = rgbout_alloc_frame;
2634        this->vo_driver.update_frame_format  = rgbout_update_frame_format;
2635        this->vo_driver.overlay_begin        = NULL;
2636        this->vo_driver.overlay_blend        = NULL;
2637        this->vo_driver.overlay_end          = NULL;
2638        this->vo_driver.display_frame        = rgbout_display_frame;
2639        this->vo_driver.get_property         = rgbout_get_property;
2640        this->vo_driver.set_property         = rgbout_set_property;
2641        this->vo_driver.get_property_min_max = rgbout_get_property_min_max;
2642        this->vo_driver.gui_data_exchange    = rgbout_gui_data_exchange;
2643        this->vo_driver.redraw_needed        = rgbout_redraw_needed;
2644        this->vo_driver.dispose              = rgbout_dispose;
2645        this->update_visual                  = rgbout_update_visual;
2646
2647
2648        this->accel = xine_mm_accel();
2649       
2650        // from Ruben,
2651        // disable MMXEXT since its causing a crash at present under P4's.
2652        this->accel &= ~MM_MMXEXT;
2653
2654        {
2655                uint32_t i = (sizeof(convert_methods) /
2656                                 sizeof(rgbout_converter_t));
2657
2658                while(i--)
2659                {
2660                        if((this->accel & convert_methods[i].required_accel) ==
2661                                convert_methods[i].required_accel)
2662                        {
2663                                this->cm      = i;
2664                                this->convert = convert_methods[i].convert_yv12; /* default */
2665
2666                                if(convert_methods[i].name)
2667                                {
2668                                        if (s_debugMessages) fprintf(stderr, THIS
2669                                                ": using %s acceleration\n",
2670                                                convert_methods[i].name);
2671                                }
2672
2673                                break;
2674                        }
2675                }
2676
2677                if(!(this->convert))
2678                        this->convert = convert_methods[0].convert_yv12;
2679        }
2680       
2681        this->levels = visual->levels;
2682
2683        if(this->levels & ~(PXLEVEL_ALL))
2684        {
2685                if (s_debugMessages) fprintf(stderr, THIS ": wrong levels flag [%#x], assuming PXLEVEL_ALL\n",
2686                                visual->levels);
2687                this->levels = PXLEVEL_ALL;
2688        }
2689
2690        this->user_data = visual->user_data;
2691        this->render = visual->callback;
2692
2693        {
2694                uint32_t i = 0;
2695
2696                for(; i < (sizeof(pack_methods) / sizeof(rgbout_packer_t)); i++)
2697                {
2698                        if(pack_methods[i].id == visual->format)
2699                        {
2700                                this->pm   = i;
2701                                this->pack = pack_methods[i].pack;
2702
2703                                if(pack_methods[i].name)
2704                                {
2705                                        if (s_debugMessages) fprintf(stderr, THIS
2706                                                ": packing pixels in %s format\n",
2707                                                pack_methods[i].name);
2708                                }
2709
2710                                break;
2711                        }
2712                }
2713
2714                if(!(this->pack))
2715                {
2716                        if (s_debugMessages) fprintf(stderr, THIS
2717                                ": unknown rgb pixel format [%i]\n", visual->format);
2718                        goto FAILURE;
2719                }
2720        }
2721
2722        return(&(this->vo_driver));
2723
2724FAILURE:
2725        release(this);
2726        return(NULL);
2727}
2728
2729
2730static char*
2731get_identifier(video_driver_class_t* vo_class)
2732{
2733        return("RGBout");
2734}
2735
2736
2737static char*
2738get_description(video_driver_class_t* vo_class)
2739{
2740        return("General purpose RGB video output plugin.");
2741}
2742
2743
2744static void
2745dispose_class(video_driver_class_t* vo_class)
2746{
2747        rgbout_class_t* rgb_class = (rgbout_class_t*) vo_class;
2748
2749        EVAL(vo_class != NULL);
2750
2751        free(rgb_class);
2752
2753FAILURE:
2754        return;
2755}
2756
2757
2758static void*
2759init_class(xine_t* xine, void* vo_visual)
2760{
2761        rgbout_class_t* rgb_class = NULL;
2762
2763        EVAL(xine != NULL);
2764        EVAL(vo_visual != NULL);
2765
2766        EVAL(rgb_class = (rgbout_class_t*) malloc(sizeof(rgbout_class_t)));
2767        clear(rgb_class, sizeof(rgbout_class_t));
2768
2769        rgb_class->driver_class.open_plugin     = open_plugin;
2770        rgb_class->driver_class.get_identifier  = get_identifier;
2771        rgb_class->driver_class.get_description = get_description;
2772        rgb_class->driver_class.dispose         = dispose_class;
2773
2774        return(rgb_class);
2775
2776FAILURE:
2777        release(rgb_class);
2778        return(NULL);
2779}
2780
2781
2782
2783static vo_info_t vo_info_rgbout =
2784{
2785        8,
2786        XINE_VISUAL_TYPE_RGBOUT
2787};
2788
2789
2790plugin_info_t xine_plugin_info[] =
2791{
2792  /* type, API, "name", version, special_info, init_function */
2793  { PLUGIN_VIDEO_OUT, 20, "rgb", XINE_VERSION_CODE, &vo_info_rgbout, init_class},
2794  { PLUGIN_VIDEO_OUT, 21, "rgb", XINE_VERSION_CODE, &vo_info_rgbout, init_class},
2795  { PLUGIN_NONE, 0, "", 0, NULL, NULL}
2796};
2797
2798void register_rgbout_plugin(xine_t *self)
2799{
2800     xine_register_plugins(self, xine_plugin_info);
2801}
2802
2803#ifdef __cplusplus
2804}
2805#endif
Note: See TracBrowser for help on using the browser.