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

Revision 10806, 71.6 kB (checked in by robert, 5 years ago)

From David Callu, "I have a Segfault with xine plugin, when I load a video, then delete the XineStreamImage?,
then reload a video and finally delete the second XineStreamImage?.

In src/osgPlugins/xine/video_out_rgb.c, many code is ASM code, and 'clear()' function is one of them.
If OSG is compiled without the flag COMPILE_ASSEMBLY (default behaviours) the clear() function is an empty
function and allocated memory is never initialized to 0. So a structure which contain pointer haven't its pointer set to NULL.
And when we need to delete this pointer, all go bad.

I join the fixed file."

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