~ubuntu-branches/ubuntu/utopic/libav/utopic

« back to all changes in this revision

Viewing changes to libswscale/rgb2rgb_template.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2011-03-20 12:09:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110320120931-nfhi9tiok27gxhw1
Tags: upstream-0.6.2
ImportĀ upstreamĀ versionĀ 0.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * software RGB to RGB converter
 
3
 * pluralize by software PAL8 to RGB converter
 
4
 *              software YUV to YUV converter
 
5
 *              software YUV to RGB converter
 
6
 * Written by Nick Kurshev.
 
7
 * palette & YUV & runtime CPU stuff by Michael (michaelni@gmx.at)
 
8
 * lot of big-endian byte order fixes by Alex Beregszaszi
 
9
 *
 
10
 * This file is part of FFmpeg.
 
11
 *
 
12
 * FFmpeg is free software; you can redistribute it and/or
 
13
 * modify it under the terms of the GNU Lesser General Public
 
14
 * License as published by the Free Software Foundation; either
 
15
 * version 2.1 of the License, or (at your option) any later version.
 
16
 *
 
17
 * FFmpeg is distributed in the hope that it will be useful,
 
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
20
 * Lesser General Public License for more details.
 
21
 *
 
22
 * You should have received a copy of the GNU Lesser General Public
 
23
 * License along with FFmpeg; if not, write to the Free Software
 
24
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
25
 */
 
26
 
 
27
#include <stddef.h>
 
28
 
 
29
#undef PREFETCH
 
30
#undef MOVNTQ
 
31
#undef EMMS
 
32
#undef SFENCE
 
33
#undef MMREG_SIZE
 
34
#undef PAVGB
 
35
 
 
36
#if HAVE_SSE2
 
37
#define MMREG_SIZE 16
 
38
#else
 
39
#define MMREG_SIZE 8
 
40
#endif
 
41
 
 
42
#if HAVE_AMD3DNOW
 
43
#define PREFETCH  "prefetch"
 
44
#define PAVGB     "pavgusb"
 
45
#elif HAVE_MMX2
 
46
#define PREFETCH "prefetchnta"
 
47
#define PAVGB     "pavgb"
 
48
#else
 
49
#define PREFETCH  " # nop"
 
50
#endif
 
51
 
 
52
#if HAVE_AMD3DNOW
 
53
/* On K6 femms is faster than emms. On K7 femms is directly mapped to emms. */
 
54
#define EMMS     "femms"
 
55
#else
 
56
#define EMMS     "emms"
 
57
#endif
 
58
 
 
59
#if HAVE_MMX2
 
60
#define MOVNTQ "movntq"
 
61
#define SFENCE "sfence"
 
62
#else
 
63
#define MOVNTQ "movq"
 
64
#define SFENCE " # nop"
 
65
#endif
 
66
 
 
67
static inline void RENAME(rgb24tobgr32)(const uint8_t *src, uint8_t *dst, long src_size)
 
68
{
 
69
    uint8_t *dest = dst;
 
70
    const uint8_t *s = src;
 
71
    const uint8_t *end;
 
72
#if HAVE_MMX
 
73
    const uint8_t *mm_end;
 
74
#endif
 
75
    end = s + src_size;
 
76
#if HAVE_MMX
 
77
    __asm__ volatile(PREFETCH"    %0"::"m"(*s):"memory");
 
78
    mm_end = end - 23;
 
79
    __asm__ volatile("movq        %0, %%mm7"::"m"(mask32a):"memory");
 
80
    while (s < mm_end) {
 
81
        __asm__ volatile(
 
82
            PREFETCH"    32%1           \n\t"
 
83
            "movd          %1, %%mm0    \n\t"
 
84
            "punpckldq    3%1, %%mm0    \n\t"
 
85
            "movd         6%1, %%mm1    \n\t"
 
86
            "punpckldq    9%1, %%mm1    \n\t"
 
87
            "movd        12%1, %%mm2    \n\t"
 
88
            "punpckldq   15%1, %%mm2    \n\t"
 
89
            "movd        18%1, %%mm3    \n\t"
 
90
            "punpckldq   21%1, %%mm3    \n\t"
 
91
            "por        %%mm7, %%mm0    \n\t"
 
92
            "por        %%mm7, %%mm1    \n\t"
 
93
            "por        %%mm7, %%mm2    \n\t"
 
94
            "por        %%mm7, %%mm3    \n\t"
 
95
            MOVNTQ"     %%mm0,   %0     \n\t"
 
96
            MOVNTQ"     %%mm1,  8%0     \n\t"
 
97
            MOVNTQ"     %%mm2, 16%0     \n\t"
 
98
            MOVNTQ"     %%mm3, 24%0"
 
99
            :"=m"(*dest)
 
100
            :"m"(*s)
 
101
            :"memory");
 
102
        dest += 32;
 
103
        s += 24;
 
104
    }
 
105
    __asm__ volatile(SFENCE:::"memory");
 
106
    __asm__ volatile(EMMS:::"memory");
 
107
#endif
 
108
    while (s < end) {
 
109
#if HAVE_BIGENDIAN
 
110
        /* RGB24 (= R,G,B) -> RGB32 (= A,B,G,R) */
 
111
        *dest++ = 255;
 
112
        *dest++ = s[2];
 
113
        *dest++ = s[1];
 
114
        *dest++ = s[0];
 
115
        s+=3;
 
116
#else
 
117
        *dest++ = *s++;
 
118
        *dest++ = *s++;
 
119
        *dest++ = *s++;
 
120
        *dest++ = 255;
 
121
#endif
 
122
    }
 
123
}
 
124
 
 
125
#define STORE_BGR24_MMX \
 
126
            "psrlq         $8, %%mm2    \n\t" \
 
127
            "psrlq         $8, %%mm3    \n\t" \
 
128
            "psrlq         $8, %%mm6    \n\t" \
 
129
            "psrlq         $8, %%mm7    \n\t" \
 
130
            "pand "MANGLE(mask24l)", %%mm0\n\t" \
 
131
            "pand "MANGLE(mask24l)", %%mm1\n\t" \
 
132
            "pand "MANGLE(mask24l)", %%mm4\n\t" \
 
133
            "pand "MANGLE(mask24l)", %%mm5\n\t" \
 
134
            "pand "MANGLE(mask24h)", %%mm2\n\t" \
 
135
            "pand "MANGLE(mask24h)", %%mm3\n\t" \
 
136
            "pand "MANGLE(mask24h)", %%mm6\n\t" \
 
137
            "pand "MANGLE(mask24h)", %%mm7\n\t" \
 
138
            "por        %%mm2, %%mm0    \n\t" \
 
139
            "por        %%mm3, %%mm1    \n\t" \
 
140
            "por        %%mm6, %%mm4    \n\t" \
 
141
            "por        %%mm7, %%mm5    \n\t" \
 
142
 \
 
143
            "movq       %%mm1, %%mm2    \n\t" \
 
144
            "movq       %%mm4, %%mm3    \n\t" \
 
145
            "psllq        $48, %%mm2    \n\t" \
 
146
            "psllq        $32, %%mm3    \n\t" \
 
147
            "pand "MANGLE(mask24hh)", %%mm2\n\t" \
 
148
            "pand "MANGLE(mask24hhh)", %%mm3\n\t" \
 
149
            "por        %%mm2, %%mm0    \n\t" \
 
150
            "psrlq        $16, %%mm1    \n\t" \
 
151
            "psrlq        $32, %%mm4    \n\t" \
 
152
            "psllq        $16, %%mm5    \n\t" \
 
153
            "por        %%mm3, %%mm1    \n\t" \
 
154
            "pand  "MANGLE(mask24hhhh)", %%mm5\n\t" \
 
155
            "por        %%mm5, %%mm4    \n\t" \
 
156
 \
 
157
            MOVNTQ"     %%mm0,   %0     \n\t" \
 
158
            MOVNTQ"     %%mm1,  8%0     \n\t" \
 
159
            MOVNTQ"     %%mm4, 16%0"
 
160
 
 
161
 
 
162
static inline void RENAME(rgb32tobgr24)(const uint8_t *src, uint8_t *dst, long src_size)
 
163
{
 
164
    uint8_t *dest = dst;
 
165
    const uint8_t *s = src;
 
166
    const uint8_t *end;
 
167
#if HAVE_MMX
 
168
    const uint8_t *mm_end;
 
169
#endif
 
170
    end = s + src_size;
 
171
#if HAVE_MMX
 
172
    __asm__ volatile(PREFETCH"    %0"::"m"(*s):"memory");
 
173
    mm_end = end - 31;
 
174
    while (s < mm_end) {
 
175
        __asm__ volatile(
 
176
            PREFETCH"    32%1           \n\t"
 
177
            "movq          %1, %%mm0    \n\t"
 
178
            "movq         8%1, %%mm1    \n\t"
 
179
            "movq        16%1, %%mm4    \n\t"
 
180
            "movq        24%1, %%mm5    \n\t"
 
181
            "movq       %%mm0, %%mm2    \n\t"
 
182
            "movq       %%mm1, %%mm3    \n\t"
 
183
            "movq       %%mm4, %%mm6    \n\t"
 
184
            "movq       %%mm5, %%mm7    \n\t"
 
185
            STORE_BGR24_MMX
 
186
            :"=m"(*dest)
 
187
            :"m"(*s)
 
188
            :"memory");
 
189
        dest += 24;
 
190
        s += 32;
 
191
    }
 
192
    __asm__ volatile(SFENCE:::"memory");
 
193
    __asm__ volatile(EMMS:::"memory");
 
194
#endif
 
195
    while (s < end) {
 
196
#if HAVE_BIGENDIAN
 
197
        /* RGB32 (= A,B,G,R) -> RGB24 (= R,G,B) */
 
198
        s++;
 
199
        dest[2] = *s++;
 
200
        dest[1] = *s++;
 
201
        dest[0] = *s++;
 
202
        dest += 3;
 
203
#else
 
204
        *dest++ = *s++;
 
205
        *dest++ = *s++;
 
206
        *dest++ = *s++;
 
207
        s++;
 
208
#endif
 
209
    }
 
210
}
 
211
 
 
212
/*
 
213
 original by Strepto/Astral
 
214
 ported to gcc & bugfixed: A'rpi
 
215
 MMX2, 3DNOW optimization by Nick Kurshev
 
216
 32-bit C version, and and&add trick by Michael Niedermayer
 
217
*/
 
218
static inline void RENAME(rgb15to16)(const uint8_t *src, uint8_t *dst, long src_size)
 
219
{
 
220
    register const uint8_t* s=src;
 
221
    register uint8_t* d=dst;
 
222
    register const uint8_t *end;
 
223
    const uint8_t *mm_end;
 
224
    end = s + src_size;
 
225
#if HAVE_MMX
 
226
    __asm__ volatile(PREFETCH"    %0"::"m"(*s));
 
227
    __asm__ volatile("movq        %0, %%mm4"::"m"(mask15s));
 
228
    mm_end = end - 15;
 
229
    while (s<mm_end) {
 
230
        __asm__ volatile(
 
231
            PREFETCH"  32%1         \n\t"
 
232
            "movq        %1, %%mm0  \n\t"
 
233
            "movq       8%1, %%mm2  \n\t"
 
234
            "movq     %%mm0, %%mm1  \n\t"
 
235
            "movq     %%mm2, %%mm3  \n\t"
 
236
            "pand     %%mm4, %%mm0  \n\t"
 
237
            "pand     %%mm4, %%mm2  \n\t"
 
238
            "paddw    %%mm1, %%mm0  \n\t"
 
239
            "paddw    %%mm3, %%mm2  \n\t"
 
240
            MOVNTQ"   %%mm0,  %0    \n\t"
 
241
            MOVNTQ"   %%mm2, 8%0"
 
242
            :"=m"(*d)
 
243
            :"m"(*s)
 
244
        );
 
245
        d+=16;
 
246
        s+=16;
 
247
    }
 
248
    __asm__ volatile(SFENCE:::"memory");
 
249
    __asm__ volatile(EMMS:::"memory");
 
250
#endif
 
251
    mm_end = end - 3;
 
252
    while (s < mm_end) {
 
253
        register unsigned x= *((const uint32_t *)s);
 
254
        *((uint32_t *)d) = (x&0x7FFF7FFF) + (x&0x7FE07FE0);
 
255
        d+=4;
 
256
        s+=4;
 
257
    }
 
258
    if (s < end) {
 
259
        register unsigned short x= *((const uint16_t *)s);
 
260
        *((uint16_t *)d) = (x&0x7FFF) + (x&0x7FE0);
 
261
    }
 
262
}
 
263
 
 
264
static inline void RENAME(rgb16to15)(const uint8_t *src, uint8_t *dst, long src_size)
 
265
{
 
266
    register const uint8_t* s=src;
 
267
    register uint8_t* d=dst;
 
268
    register const uint8_t *end;
 
269
    const uint8_t *mm_end;
 
270
    end = s + src_size;
 
271
#if HAVE_MMX
 
272
    __asm__ volatile(PREFETCH"    %0"::"m"(*s));
 
273
    __asm__ volatile("movq        %0, %%mm7"::"m"(mask15rg));
 
274
    __asm__ volatile("movq        %0, %%mm6"::"m"(mask15b));
 
275
    mm_end = end - 15;
 
276
    while (s<mm_end) {
 
277
        __asm__ volatile(
 
278
            PREFETCH"  32%1         \n\t"
 
279
            "movq        %1, %%mm0  \n\t"
 
280
            "movq       8%1, %%mm2  \n\t"
 
281
            "movq     %%mm0, %%mm1  \n\t"
 
282
            "movq     %%mm2, %%mm3  \n\t"
 
283
            "psrlq       $1, %%mm0  \n\t"
 
284
            "psrlq       $1, %%mm2  \n\t"
 
285
            "pand     %%mm7, %%mm0  \n\t"
 
286
            "pand     %%mm7, %%mm2  \n\t"
 
287
            "pand     %%mm6, %%mm1  \n\t"
 
288
            "pand     %%mm6, %%mm3  \n\t"
 
289
            "por      %%mm1, %%mm0  \n\t"
 
290
            "por      %%mm3, %%mm2  \n\t"
 
291
            MOVNTQ"   %%mm0,  %0    \n\t"
 
292
            MOVNTQ"   %%mm2, 8%0"
 
293
            :"=m"(*d)
 
294
            :"m"(*s)
 
295
        );
 
296
        d+=16;
 
297
        s+=16;
 
298
    }
 
299
    __asm__ volatile(SFENCE:::"memory");
 
300
    __asm__ volatile(EMMS:::"memory");
 
301
#endif
 
302
    mm_end = end - 3;
 
303
    while (s < mm_end) {
 
304
        register uint32_t x= *((const uint32_t*)s);
 
305
        *((uint32_t *)d) = ((x>>1)&0x7FE07FE0) | (x&0x001F001F);
 
306
        s+=4;
 
307
        d+=4;
 
308
    }
 
309
    if (s < end) {
 
310
        register uint16_t x= *((const uint16_t*)s);
 
311
        *((uint16_t *)d) = ((x>>1)&0x7FE0) | (x&0x001F);
 
312
    }
 
313
}
 
314
 
 
315
static inline void RENAME(rgb32to16)(const uint8_t *src, uint8_t *dst, long src_size)
 
316
{
 
317
    const uint8_t *s = src;
 
318
    const uint8_t *end;
 
319
#if HAVE_MMX
 
320
    const uint8_t *mm_end;
 
321
#endif
 
322
    uint16_t *d = (uint16_t *)dst;
 
323
    end = s + src_size;
 
324
#if HAVE_MMX
 
325
    mm_end = end - 15;
 
326
#if 1 //is faster only if multiplies are reasonably fast (FIXME figure out on which CPUs this is faster, on Athlon it is slightly faster)
 
327
    __asm__ volatile(
 
328
        "movq           %3, %%mm5   \n\t"
 
329
        "movq           %4, %%mm6   \n\t"
 
330
        "movq           %5, %%mm7   \n\t"
 
331
        "jmp 2f                     \n\t"
 
332
        ASMALIGN(4)
 
333
        "1:                         \n\t"
 
334
        PREFETCH"   32(%1)          \n\t"
 
335
        "movd         (%1), %%mm0   \n\t"
 
336
        "movd        4(%1), %%mm3   \n\t"
 
337
        "punpckldq   8(%1), %%mm0   \n\t"
 
338
        "punpckldq  12(%1), %%mm3   \n\t"
 
339
        "movq        %%mm0, %%mm1   \n\t"
 
340
        "movq        %%mm3, %%mm4   \n\t"
 
341
        "pand        %%mm6, %%mm0   \n\t"
 
342
        "pand        %%mm6, %%mm3   \n\t"
 
343
        "pmaddwd     %%mm7, %%mm0   \n\t"
 
344
        "pmaddwd     %%mm7, %%mm3   \n\t"
 
345
        "pand        %%mm5, %%mm1   \n\t"
 
346
        "pand        %%mm5, %%mm4   \n\t"
 
347
        "por         %%mm1, %%mm0   \n\t"
 
348
        "por         %%mm4, %%mm3   \n\t"
 
349
        "psrld          $5, %%mm0   \n\t"
 
350
        "pslld         $11, %%mm3   \n\t"
 
351
        "por         %%mm3, %%mm0   \n\t"
 
352
        MOVNTQ"      %%mm0, (%0)    \n\t"
 
353
        "add           $16,  %1     \n\t"
 
354
        "add            $8,  %0     \n\t"
 
355
        "2:                         \n\t"
 
356
        "cmp            %2,  %1     \n\t"
 
357
        " jb            1b          \n\t"
 
358
        : "+r" (d), "+r"(s)
 
359
        : "r" (mm_end), "m" (mask3216g), "m" (mask3216br), "m" (mul3216)
 
360
    );
 
361
#else
 
362
    __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
 
363
    __asm__ volatile(
 
364
        "movq    %0, %%mm7    \n\t"
 
365
        "movq    %1, %%mm6    \n\t"
 
366
        ::"m"(red_16mask),"m"(green_16mask));
 
367
    while (s < mm_end) {
 
368
        __asm__ volatile(
 
369
            PREFETCH"    32%1           \n\t"
 
370
            "movd          %1, %%mm0    \n\t"
 
371
            "movd         4%1, %%mm3    \n\t"
 
372
            "punpckldq    8%1, %%mm0    \n\t"
 
373
            "punpckldq   12%1, %%mm3    \n\t"
 
374
            "movq       %%mm0, %%mm1    \n\t"
 
375
            "movq       %%mm0, %%mm2    \n\t"
 
376
            "movq       %%mm3, %%mm4    \n\t"
 
377
            "movq       %%mm3, %%mm5    \n\t"
 
378
            "psrlq         $3, %%mm0    \n\t"
 
379
            "psrlq         $3, %%mm3    \n\t"
 
380
            "pand          %2, %%mm0    \n\t"
 
381
            "pand          %2, %%mm3    \n\t"
 
382
            "psrlq         $5, %%mm1    \n\t"
 
383
            "psrlq         $5, %%mm4    \n\t"
 
384
            "pand       %%mm6, %%mm1    \n\t"
 
385
            "pand       %%mm6, %%mm4    \n\t"
 
386
            "psrlq         $8, %%mm2    \n\t"
 
387
            "psrlq         $8, %%mm5    \n\t"
 
388
            "pand       %%mm7, %%mm2    \n\t"
 
389
            "pand       %%mm7, %%mm5    \n\t"
 
390
            "por        %%mm1, %%mm0    \n\t"
 
391
            "por        %%mm4, %%mm3    \n\t"
 
392
            "por        %%mm2, %%mm0    \n\t"
 
393
            "por        %%mm5, %%mm3    \n\t"
 
394
            "psllq        $16, %%mm3    \n\t"
 
395
            "por        %%mm3, %%mm0    \n\t"
 
396
            MOVNTQ"     %%mm0, %0       \n\t"
 
397
            :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
 
398
        d += 4;
 
399
        s += 16;
 
400
    }
 
401
#endif
 
402
    __asm__ volatile(SFENCE:::"memory");
 
403
    __asm__ volatile(EMMS:::"memory");
 
404
#endif
 
405
    while (s < end) {
 
406
        register int rgb = *(const uint32_t*)s; s += 4;
 
407
        *d++ = ((rgb&0xFF)>>3) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>8);
 
408
    }
 
409
}
 
410
 
 
411
static inline void RENAME(rgb32tobgr16)(const uint8_t *src, uint8_t *dst, long src_size)
 
412
{
 
413
    const uint8_t *s = src;
 
414
    const uint8_t *end;
 
415
#if HAVE_MMX
 
416
    const uint8_t *mm_end;
 
417
#endif
 
418
    uint16_t *d = (uint16_t *)dst;
 
419
    end = s + src_size;
 
420
#if HAVE_MMX
 
421
    __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
 
422
    __asm__ volatile(
 
423
        "movq          %0, %%mm7    \n\t"
 
424
        "movq          %1, %%mm6    \n\t"
 
425
        ::"m"(red_16mask),"m"(green_16mask));
 
426
    mm_end = end - 15;
 
427
    while (s < mm_end) {
 
428
        __asm__ volatile(
 
429
            PREFETCH"    32%1           \n\t"
 
430
            "movd          %1, %%mm0    \n\t"
 
431
            "movd         4%1, %%mm3    \n\t"
 
432
            "punpckldq    8%1, %%mm0    \n\t"
 
433
            "punpckldq   12%1, %%mm3    \n\t"
 
434
            "movq       %%mm0, %%mm1    \n\t"
 
435
            "movq       %%mm0, %%mm2    \n\t"
 
436
            "movq       %%mm3, %%mm4    \n\t"
 
437
            "movq       %%mm3, %%mm5    \n\t"
 
438
            "psllq         $8, %%mm0    \n\t"
 
439
            "psllq         $8, %%mm3    \n\t"
 
440
            "pand       %%mm7, %%mm0    \n\t"
 
441
            "pand       %%mm7, %%mm3    \n\t"
 
442
            "psrlq         $5, %%mm1    \n\t"
 
443
            "psrlq         $5, %%mm4    \n\t"
 
444
            "pand       %%mm6, %%mm1    \n\t"
 
445
            "pand       %%mm6, %%mm4    \n\t"
 
446
            "psrlq        $19, %%mm2    \n\t"
 
447
            "psrlq        $19, %%mm5    \n\t"
 
448
            "pand          %2, %%mm2    \n\t"
 
449
            "pand          %2, %%mm5    \n\t"
 
450
            "por        %%mm1, %%mm0    \n\t"
 
451
            "por        %%mm4, %%mm3    \n\t"
 
452
            "por        %%mm2, %%mm0    \n\t"
 
453
            "por        %%mm5, %%mm3    \n\t"
 
454
            "psllq        $16, %%mm3    \n\t"
 
455
            "por        %%mm3, %%mm0    \n\t"
 
456
            MOVNTQ"     %%mm0, %0       \n\t"
 
457
            :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
 
458
        d += 4;
 
459
        s += 16;
 
460
    }
 
461
    __asm__ volatile(SFENCE:::"memory");
 
462
    __asm__ volatile(EMMS:::"memory");
 
463
#endif
 
464
    while (s < end) {
 
465
        register int rgb = *(const uint32_t*)s; s += 4;
 
466
        *d++ = ((rgb&0xF8)<<8) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>19);
 
467
    }
 
468
}
 
469
 
 
470
static inline void RENAME(rgb32to15)(const uint8_t *src, uint8_t *dst, long src_size)
 
471
{
 
472
    const uint8_t *s = src;
 
473
    const uint8_t *end;
 
474
#if HAVE_MMX
 
475
    const uint8_t *mm_end;
 
476
#endif
 
477
    uint16_t *d = (uint16_t *)dst;
 
478
    end = s + src_size;
 
479
#if HAVE_MMX
 
480
    mm_end = end - 15;
 
481
#if 1 //is faster only if multiplies are reasonably fast (FIXME figure out on which CPUs this is faster, on Athlon it is slightly faster)
 
482
    __asm__ volatile(
 
483
        "movq           %3, %%mm5   \n\t"
 
484
        "movq           %4, %%mm6   \n\t"
 
485
        "movq           %5, %%mm7   \n\t"
 
486
        "jmp            2f          \n\t"
 
487
        ASMALIGN(4)
 
488
        "1:                         \n\t"
 
489
        PREFETCH"   32(%1)          \n\t"
 
490
        "movd         (%1), %%mm0   \n\t"
 
491
        "movd        4(%1), %%mm3   \n\t"
 
492
        "punpckldq   8(%1), %%mm0   \n\t"
 
493
        "punpckldq  12(%1), %%mm3   \n\t"
 
494
        "movq        %%mm0, %%mm1   \n\t"
 
495
        "movq        %%mm3, %%mm4   \n\t"
 
496
        "pand        %%mm6, %%mm0   \n\t"
 
497
        "pand        %%mm6, %%mm3   \n\t"
 
498
        "pmaddwd     %%mm7, %%mm0   \n\t"
 
499
        "pmaddwd     %%mm7, %%mm3   \n\t"
 
500
        "pand        %%mm5, %%mm1   \n\t"
 
501
        "pand        %%mm5, %%mm4   \n\t"
 
502
        "por         %%mm1, %%mm0   \n\t"
 
503
        "por         %%mm4, %%mm3   \n\t"
 
504
        "psrld          $6, %%mm0   \n\t"
 
505
        "pslld         $10, %%mm3   \n\t"
 
506
        "por         %%mm3, %%mm0   \n\t"
 
507
        MOVNTQ"      %%mm0, (%0)    \n\t"
 
508
        "add           $16,  %1     \n\t"
 
509
        "add            $8,  %0     \n\t"
 
510
        "2:                         \n\t"
 
511
        "cmp            %2,  %1     \n\t"
 
512
        " jb            1b          \n\t"
 
513
        : "+r" (d), "+r"(s)
 
514
        : "r" (mm_end), "m" (mask3215g), "m" (mask3216br), "m" (mul3215)
 
515
    );
 
516
#else
 
517
    __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
 
518
    __asm__ volatile(
 
519
        "movq          %0, %%mm7    \n\t"
 
520
        "movq          %1, %%mm6    \n\t"
 
521
        ::"m"(red_15mask),"m"(green_15mask));
 
522
    while (s < mm_end) {
 
523
        __asm__ volatile(
 
524
            PREFETCH"    32%1           \n\t"
 
525
            "movd          %1, %%mm0    \n\t"
 
526
            "movd         4%1, %%mm3    \n\t"
 
527
            "punpckldq    8%1, %%mm0    \n\t"
 
528
            "punpckldq   12%1, %%mm3    \n\t"
 
529
            "movq       %%mm0, %%mm1    \n\t"
 
530
            "movq       %%mm0, %%mm2    \n\t"
 
531
            "movq       %%mm3, %%mm4    \n\t"
 
532
            "movq       %%mm3, %%mm5    \n\t"
 
533
            "psrlq         $3, %%mm0    \n\t"
 
534
            "psrlq         $3, %%mm3    \n\t"
 
535
            "pand          %2, %%mm0    \n\t"
 
536
            "pand          %2, %%mm3    \n\t"
 
537
            "psrlq         $6, %%mm1    \n\t"
 
538
            "psrlq         $6, %%mm4    \n\t"
 
539
            "pand       %%mm6, %%mm1    \n\t"
 
540
            "pand       %%mm6, %%mm4    \n\t"
 
541
            "psrlq         $9, %%mm2    \n\t"
 
542
            "psrlq         $9, %%mm5    \n\t"
 
543
            "pand       %%mm7, %%mm2    \n\t"
 
544
            "pand       %%mm7, %%mm5    \n\t"
 
545
            "por        %%mm1, %%mm0    \n\t"
 
546
            "por        %%mm4, %%mm3    \n\t"
 
547
            "por        %%mm2, %%mm0    \n\t"
 
548
            "por        %%mm5, %%mm3    \n\t"
 
549
            "psllq        $16, %%mm3    \n\t"
 
550
            "por        %%mm3, %%mm0    \n\t"
 
551
            MOVNTQ"     %%mm0, %0       \n\t"
 
552
            :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
 
553
        d += 4;
 
554
        s += 16;
 
555
    }
 
556
#endif
 
557
    __asm__ volatile(SFENCE:::"memory");
 
558
    __asm__ volatile(EMMS:::"memory");
 
559
#endif
 
560
    while (s < end) {
 
561
        register int rgb = *(const uint32_t*)s; s += 4;
 
562
        *d++ = ((rgb&0xFF)>>3) + ((rgb&0xF800)>>6) + ((rgb&0xF80000)>>9);
 
563
    }
 
564
}
 
565
 
 
566
static inline void RENAME(rgb32tobgr15)(const uint8_t *src, uint8_t *dst, long src_size)
 
567
{
 
568
    const uint8_t *s = src;
 
569
    const uint8_t *end;
 
570
#if HAVE_MMX
 
571
    const uint8_t *mm_end;
 
572
#endif
 
573
    uint16_t *d = (uint16_t *)dst;
 
574
    end = s + src_size;
 
575
#if HAVE_MMX
 
576
    __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
 
577
    __asm__ volatile(
 
578
        "movq          %0, %%mm7    \n\t"
 
579
        "movq          %1, %%mm6    \n\t"
 
580
        ::"m"(red_15mask),"m"(green_15mask));
 
581
    mm_end = end - 15;
 
582
    while (s < mm_end) {
 
583
        __asm__ volatile(
 
584
            PREFETCH"    32%1           \n\t"
 
585
            "movd          %1, %%mm0    \n\t"
 
586
            "movd         4%1, %%mm3    \n\t"
 
587
            "punpckldq    8%1, %%mm0    \n\t"
 
588
            "punpckldq   12%1, %%mm3    \n\t"
 
589
            "movq       %%mm0, %%mm1    \n\t"
 
590
            "movq       %%mm0, %%mm2    \n\t"
 
591
            "movq       %%mm3, %%mm4    \n\t"
 
592
            "movq       %%mm3, %%mm5    \n\t"
 
593
            "psllq         $7, %%mm0    \n\t"
 
594
            "psllq         $7, %%mm3    \n\t"
 
595
            "pand       %%mm7, %%mm0    \n\t"
 
596
            "pand       %%mm7, %%mm3    \n\t"
 
597
            "psrlq         $6, %%mm1    \n\t"
 
598
            "psrlq         $6, %%mm4    \n\t"
 
599
            "pand       %%mm6, %%mm1    \n\t"
 
600
            "pand       %%mm6, %%mm4    \n\t"
 
601
            "psrlq        $19, %%mm2    \n\t"
 
602
            "psrlq        $19, %%mm5    \n\t"
 
603
            "pand          %2, %%mm2    \n\t"
 
604
            "pand          %2, %%mm5    \n\t"
 
605
            "por        %%mm1, %%mm0    \n\t"
 
606
            "por        %%mm4, %%mm3    \n\t"
 
607
            "por        %%mm2, %%mm0    \n\t"
 
608
            "por        %%mm5, %%mm3    \n\t"
 
609
            "psllq        $16, %%mm3    \n\t"
 
610
            "por        %%mm3, %%mm0    \n\t"
 
611
            MOVNTQ"     %%mm0, %0       \n\t"
 
612
            :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
 
613
        d += 4;
 
614
        s += 16;
 
615
    }
 
616
    __asm__ volatile(SFENCE:::"memory");
 
617
    __asm__ volatile(EMMS:::"memory");
 
618
#endif
 
619
    while (s < end) {
 
620
        register int rgb = *(const uint32_t*)s; s += 4;
 
621
        *d++ = ((rgb&0xF8)<<7) + ((rgb&0xF800)>>6) + ((rgb&0xF80000)>>19);
 
622
    }
 
623
}
 
624
 
 
625
static inline void RENAME(rgb24tobgr16)(const uint8_t *src, uint8_t *dst, long src_size)
 
626
{
 
627
    const uint8_t *s = src;
 
628
    const uint8_t *end;
 
629
#if HAVE_MMX
 
630
    const uint8_t *mm_end;
 
631
#endif
 
632
    uint16_t *d = (uint16_t *)dst;
 
633
    end = s + src_size;
 
634
#if HAVE_MMX
 
635
    __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
 
636
    __asm__ volatile(
 
637
        "movq         %0, %%mm7     \n\t"
 
638
        "movq         %1, %%mm6     \n\t"
 
639
        ::"m"(red_16mask),"m"(green_16mask));
 
640
    mm_end = end - 11;
 
641
    while (s < mm_end) {
 
642
        __asm__ volatile(
 
643
            PREFETCH"    32%1           \n\t"
 
644
            "movd          %1, %%mm0    \n\t"
 
645
            "movd         3%1, %%mm3    \n\t"
 
646
            "punpckldq    6%1, %%mm0    \n\t"
 
647
            "punpckldq    9%1, %%mm3    \n\t"
 
648
            "movq       %%mm0, %%mm1    \n\t"
 
649
            "movq       %%mm0, %%mm2    \n\t"
 
650
            "movq       %%mm3, %%mm4    \n\t"
 
651
            "movq       %%mm3, %%mm5    \n\t"
 
652
            "psrlq         $3, %%mm0    \n\t"
 
653
            "psrlq         $3, %%mm3    \n\t"
 
654
            "pand          %2, %%mm0    \n\t"
 
655
            "pand          %2, %%mm3    \n\t"
 
656
            "psrlq         $5, %%mm1    \n\t"
 
657
            "psrlq         $5, %%mm4    \n\t"
 
658
            "pand       %%mm6, %%mm1    \n\t"
 
659
            "pand       %%mm6, %%mm4    \n\t"
 
660
            "psrlq         $8, %%mm2    \n\t"
 
661
            "psrlq         $8, %%mm5    \n\t"
 
662
            "pand       %%mm7, %%mm2    \n\t"
 
663
            "pand       %%mm7, %%mm5    \n\t"
 
664
            "por        %%mm1, %%mm0    \n\t"
 
665
            "por        %%mm4, %%mm3    \n\t"
 
666
            "por        %%mm2, %%mm0    \n\t"
 
667
            "por        %%mm5, %%mm3    \n\t"
 
668
            "psllq        $16, %%mm3    \n\t"
 
669
            "por        %%mm3, %%mm0    \n\t"
 
670
            MOVNTQ"     %%mm0, %0       \n\t"
 
671
            :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
 
672
        d += 4;
 
673
        s += 12;
 
674
    }
 
675
    __asm__ volatile(SFENCE:::"memory");
 
676
    __asm__ volatile(EMMS:::"memory");
 
677
#endif
 
678
    while (s < end) {
 
679
        const int b = *s++;
 
680
        const int g = *s++;
 
681
        const int r = *s++;
 
682
        *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
 
683
    }
 
684
}
 
685
 
 
686
static inline void RENAME(rgb24to16)(const uint8_t *src, uint8_t *dst, long src_size)
 
687
{
 
688
    const uint8_t *s = src;
 
689
    const uint8_t *end;
 
690
#if HAVE_MMX
 
691
    const uint8_t *mm_end;
 
692
#endif
 
693
    uint16_t *d = (uint16_t *)dst;
 
694
    end = s + src_size;
 
695
#if HAVE_MMX
 
696
    __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
 
697
    __asm__ volatile(
 
698
        "movq         %0, %%mm7     \n\t"
 
699
        "movq         %1, %%mm6     \n\t"
 
700
        ::"m"(red_16mask),"m"(green_16mask));
 
701
    mm_end = end - 15;
 
702
    while (s < mm_end) {
 
703
        __asm__ volatile(
 
704
            PREFETCH"    32%1           \n\t"
 
705
            "movd          %1, %%mm0    \n\t"
 
706
            "movd         3%1, %%mm3    \n\t"
 
707
            "punpckldq    6%1, %%mm0    \n\t"
 
708
            "punpckldq    9%1, %%mm3    \n\t"
 
709
            "movq       %%mm0, %%mm1    \n\t"
 
710
            "movq       %%mm0, %%mm2    \n\t"
 
711
            "movq       %%mm3, %%mm4    \n\t"
 
712
            "movq       %%mm3, %%mm5    \n\t"
 
713
            "psllq         $8, %%mm0    \n\t"
 
714
            "psllq         $8, %%mm3    \n\t"
 
715
            "pand       %%mm7, %%mm0    \n\t"
 
716
            "pand       %%mm7, %%mm3    \n\t"
 
717
            "psrlq         $5, %%mm1    \n\t"
 
718
            "psrlq         $5, %%mm4    \n\t"
 
719
            "pand       %%mm6, %%mm1    \n\t"
 
720
            "pand       %%mm6, %%mm4    \n\t"
 
721
            "psrlq        $19, %%mm2    \n\t"
 
722
            "psrlq        $19, %%mm5    \n\t"
 
723
            "pand          %2, %%mm2    \n\t"
 
724
            "pand          %2, %%mm5    \n\t"
 
725
            "por        %%mm1, %%mm0    \n\t"
 
726
            "por        %%mm4, %%mm3    \n\t"
 
727
            "por        %%mm2, %%mm0    \n\t"
 
728
            "por        %%mm5, %%mm3    \n\t"
 
729
            "psllq        $16, %%mm3    \n\t"
 
730
            "por        %%mm3, %%mm0    \n\t"
 
731
            MOVNTQ"     %%mm0, %0       \n\t"
 
732
            :"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");
 
733
        d += 4;
 
734
        s += 12;
 
735
    }
 
736
    __asm__ volatile(SFENCE:::"memory");
 
737
    __asm__ volatile(EMMS:::"memory");
 
738
#endif
 
739
    while (s < end) {
 
740
        const int r = *s++;
 
741
        const int g = *s++;
 
742
        const int b = *s++;
 
743
        *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
 
744
    }
 
745
}
 
746
 
 
747
static inline void RENAME(rgb24tobgr15)(const uint8_t *src, uint8_t *dst, long src_size)
 
748
{
 
749
    const uint8_t *s = src;
 
750
    const uint8_t *end;
 
751
#if HAVE_MMX
 
752
    const uint8_t *mm_end;
 
753
#endif
 
754
    uint16_t *d = (uint16_t *)dst;
 
755
    end = s + src_size;
 
756
#if HAVE_MMX
 
757
    __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
 
758
    __asm__ volatile(
 
759
        "movq          %0, %%mm7    \n\t"
 
760
        "movq          %1, %%mm6    \n\t"
 
761
        ::"m"(red_15mask),"m"(green_15mask));
 
762
    mm_end = end - 11;
 
763
    while (s < mm_end) {
 
764
        __asm__ volatile(
 
765
            PREFETCH"    32%1           \n\t"
 
766
            "movd          %1, %%mm0    \n\t"
 
767
            "movd         3%1, %%mm3    \n\t"
 
768
            "punpckldq    6%1, %%mm0    \n\t"
 
769
            "punpckldq    9%1, %%mm3    \n\t"
 
770
            "movq       %%mm0, %%mm1    \n\t"
 
771
            "movq       %%mm0, %%mm2    \n\t"
 
772
            "movq       %%mm3, %%mm4    \n\t"
 
773
            "movq       %%mm3, %%mm5    \n\t"
 
774
            "psrlq         $3, %%mm0    \n\t"
 
775
            "psrlq         $3, %%mm3    \n\t"
 
776
            "pand          %2, %%mm0    \n\t"
 
777
            "pand          %2, %%mm3    \n\t"
 
778
            "psrlq         $6, %%mm1    \n\t"
 
779
            "psrlq         $6, %%mm4    \n\t"
 
780
            "pand       %%mm6, %%mm1    \n\t"
 
781
            "pand       %%mm6, %%mm4    \n\t"
 
782
            "psrlq         $9, %%mm2    \n\t"
 
783
            "psrlq         $9, %%mm5    \n\t"
 
784
            "pand       %%mm7, %%mm2    \n\t"
 
785
            "pand       %%mm7, %%mm5    \n\t"
 
786
            "por        %%mm1, %%mm0    \n\t"
 
787
            "por        %%mm4, %%mm3    \n\t"
 
788
            "por        %%mm2, %%mm0    \n\t"
 
789
            "por        %%mm5, %%mm3    \n\t"
 
790
            "psllq        $16, %%mm3    \n\t"
 
791
            "por        %%mm3, %%mm0    \n\t"
 
792
            MOVNTQ"     %%mm0, %0       \n\t"
 
793
            :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
 
794
        d += 4;
 
795
        s += 12;
 
796
    }
 
797
    __asm__ volatile(SFENCE:::"memory");
 
798
    __asm__ volatile(EMMS:::"memory");
 
799
#endif
 
800
    while (s < end) {
 
801
        const int b = *s++;
 
802
        const int g = *s++;
 
803
        const int r = *s++;
 
804
        *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
 
805
    }
 
806
}
 
807
 
 
808
static inline void RENAME(rgb24to15)(const uint8_t *src, uint8_t *dst, long src_size)
 
809
{
 
810
    const uint8_t *s = src;
 
811
    const uint8_t *end;
 
812
#if HAVE_MMX
 
813
    const uint8_t *mm_end;
 
814
#endif
 
815
    uint16_t *d = (uint16_t *)dst;
 
816
    end = s + src_size;
 
817
#if HAVE_MMX
 
818
    __asm__ volatile(PREFETCH"    %0"::"m"(*src):"memory");
 
819
    __asm__ volatile(
 
820
        "movq         %0, %%mm7     \n\t"
 
821
        "movq         %1, %%mm6     \n\t"
 
822
        ::"m"(red_15mask),"m"(green_15mask));
 
823
    mm_end = end - 15;
 
824
    while (s < mm_end) {
 
825
        __asm__ volatile(
 
826
            PREFETCH"   32%1            \n\t"
 
827
            "movd         %1, %%mm0     \n\t"
 
828
            "movd        3%1, %%mm3     \n\t"
 
829
            "punpckldq   6%1, %%mm0     \n\t"
 
830
            "punpckldq   9%1, %%mm3     \n\t"
 
831
            "movq      %%mm0, %%mm1     \n\t"
 
832
            "movq      %%mm0, %%mm2     \n\t"
 
833
            "movq      %%mm3, %%mm4     \n\t"
 
834
            "movq      %%mm3, %%mm5     \n\t"
 
835
            "psllq        $7, %%mm0     \n\t"
 
836
            "psllq        $7, %%mm3     \n\t"
 
837
            "pand      %%mm7, %%mm0     \n\t"
 
838
            "pand      %%mm7, %%mm3     \n\t"
 
839
            "psrlq        $6, %%mm1     \n\t"
 
840
            "psrlq        $6, %%mm4     \n\t"
 
841
            "pand      %%mm6, %%mm1     \n\t"
 
842
            "pand      %%mm6, %%mm4     \n\t"
 
843
            "psrlq       $19, %%mm2     \n\t"
 
844
            "psrlq       $19, %%mm5     \n\t"
 
845
            "pand         %2, %%mm2     \n\t"
 
846
            "pand         %2, %%mm5     \n\t"
 
847
            "por       %%mm1, %%mm0     \n\t"
 
848
            "por       %%mm4, %%mm3     \n\t"
 
849
            "por       %%mm2, %%mm0     \n\t"
 
850
            "por       %%mm5, %%mm3     \n\t"
 
851
            "psllq       $16, %%mm3     \n\t"
 
852
            "por       %%mm3, %%mm0     \n\t"
 
853
            MOVNTQ"    %%mm0, %0        \n\t"
 
854
            :"=m"(*d):"m"(*s),"m"(blue_15mask):"memory");
 
855
        d += 4;
 
856
        s += 12;
 
857
    }
 
858
    __asm__ volatile(SFENCE:::"memory");
 
859
    __asm__ volatile(EMMS:::"memory");
 
860
#endif
 
861
    while (s < end) {
 
862
        const int r = *s++;
 
863
        const int g = *s++;
 
864
        const int b = *s++;
 
865
        *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
 
866
    }
 
867
}
 
868
 
 
869
/*
 
870
  I use less accurate approximation here by simply left-shifting the input
 
871
  value and filling the low order bits with zeroes. This method improves PNG
 
872
  compression but this scheme cannot reproduce white exactly, since it does
 
873
  not generate an all-ones maximum value; the net effect is to darken the
 
874
  image slightly.
 
875
 
 
876
  The better method should be "left bit replication":
 
877
 
 
878
   4 3 2 1 0
 
879
   ---------
 
880
   1 1 0 1 1
 
881
 
 
882
   7 6 5 4 3  2 1 0
 
883
   ----------------
 
884
   1 1 0 1 1  1 1 0
 
885
   |=======|  |===|
 
886
       |      leftmost bits repeated to fill open bits
 
887
       |
 
888
   original bits
 
889
*/
 
890
static inline void RENAME(rgb15tobgr24)(const uint8_t *src, uint8_t *dst, long src_size)
 
891
{
 
892
    const uint16_t *end;
 
893
#if HAVE_MMX
 
894
    const uint16_t *mm_end;
 
895
#endif
 
896
    uint8_t *d = dst;
 
897
    const uint16_t *s = (const uint16_t*)src;
 
898
    end = s + src_size/2;
 
899
#if HAVE_MMX
 
900
    __asm__ volatile(PREFETCH"    %0"::"m"(*s):"memory");
 
901
    mm_end = end - 7;
 
902
    while (s < mm_end) {
 
903
        __asm__ volatile(
 
904
            PREFETCH"    32%1           \n\t"
 
905
            "movq          %1, %%mm0    \n\t"
 
906
            "movq          %1, %%mm1    \n\t"
 
907
            "movq          %1, %%mm2    \n\t"
 
908
            "pand          %2, %%mm0    \n\t"
 
909
            "pand          %3, %%mm1    \n\t"
 
910
            "pand          %4, %%mm2    \n\t"
 
911
            "psllq         $3, %%mm0    \n\t"
 
912
            "psrlq         $2, %%mm1    \n\t"
 
913
            "psrlq         $7, %%mm2    \n\t"
 
914
            "movq       %%mm0, %%mm3    \n\t"
 
915
            "movq       %%mm1, %%mm4    \n\t"
 
916
            "movq       %%mm2, %%mm5    \n\t"
 
917
            "punpcklwd     %5, %%mm0    \n\t"
 
918
            "punpcklwd     %5, %%mm1    \n\t"
 
919
            "punpcklwd     %5, %%mm2    \n\t"
 
920
            "punpckhwd     %5, %%mm3    \n\t"
 
921
            "punpckhwd     %5, %%mm4    \n\t"
 
922
            "punpckhwd     %5, %%mm5    \n\t"
 
923
            "psllq         $8, %%mm1    \n\t"
 
924
            "psllq        $16, %%mm2    \n\t"
 
925
            "por        %%mm1, %%mm0    \n\t"
 
926
            "por        %%mm2, %%mm0    \n\t"
 
927
            "psllq         $8, %%mm4    \n\t"
 
928
            "psllq        $16, %%mm5    \n\t"
 
929
            "por        %%mm4, %%mm3    \n\t"
 
930
            "por        %%mm5, %%mm3    \n\t"
 
931
 
 
932
            "movq       %%mm0, %%mm6    \n\t"
 
933
            "movq       %%mm3, %%mm7    \n\t"
 
934
 
 
935
            "movq         8%1, %%mm0    \n\t"
 
936
            "movq         8%1, %%mm1    \n\t"
 
937
            "movq         8%1, %%mm2    \n\t"
 
938
            "pand          %2, %%mm0    \n\t"
 
939
            "pand          %3, %%mm1    \n\t"
 
940
            "pand          %4, %%mm2    \n\t"
 
941
            "psllq         $3, %%mm0    \n\t"
 
942
            "psrlq         $2, %%mm1    \n\t"
 
943
            "psrlq         $7, %%mm2    \n\t"
 
944
            "movq       %%mm0, %%mm3    \n\t"
 
945
            "movq       %%mm1, %%mm4    \n\t"
 
946
            "movq       %%mm2, %%mm5    \n\t"
 
947
            "punpcklwd     %5, %%mm0    \n\t"
 
948
            "punpcklwd     %5, %%mm1    \n\t"
 
949
            "punpcklwd     %5, %%mm2    \n\t"
 
950
            "punpckhwd     %5, %%mm3    \n\t"
 
951
            "punpckhwd     %5, %%mm4    \n\t"
 
952
            "punpckhwd     %5, %%mm5    \n\t"
 
953
            "psllq         $8, %%mm1    \n\t"
 
954
            "psllq        $16, %%mm2    \n\t"
 
955
            "por        %%mm1, %%mm0    \n\t"
 
956
            "por        %%mm2, %%mm0    \n\t"
 
957
            "psllq         $8, %%mm4    \n\t"
 
958
            "psllq        $16, %%mm5    \n\t"
 
959
            "por        %%mm4, %%mm3    \n\t"
 
960
            "por        %%mm5, %%mm3    \n\t"
 
961
 
 
962
            :"=m"(*d)
 
963
            :"m"(*s),"m"(mask15b),"m"(mask15g),"m"(mask15r), "m"(mmx_null)
 
964
            :"memory");
 
965
        /* borrowed 32 to 24 */
 
966
        __asm__ volatile(
 
967
            "movq       %%mm0, %%mm4    \n\t"
 
968
            "movq       %%mm3, %%mm5    \n\t"
 
969
            "movq       %%mm6, %%mm0    \n\t"
 
970
            "movq       %%mm7, %%mm1    \n\t"
 
971
 
 
972
            "movq       %%mm4, %%mm6    \n\t"
 
973
            "movq       %%mm5, %%mm7    \n\t"
 
974
            "movq       %%mm0, %%mm2    \n\t"
 
975
            "movq       %%mm1, %%mm3    \n\t"
 
976
 
 
977
            STORE_BGR24_MMX
 
978
 
 
979
            :"=m"(*d)
 
980
            :"m"(*s)
 
981
            :"memory");
 
982
        d += 24;
 
983
        s += 8;
 
984
    }
 
985
    __asm__ volatile(SFENCE:::"memory");
 
986
    __asm__ volatile(EMMS:::"memory");
 
987
#endif
 
988
    while (s < end) {
 
989
        register uint16_t bgr;
 
990
        bgr = *s++;
 
991
        *d++ = (bgr&0x1F)<<3;
 
992
        *d++ = (bgr&0x3E0)>>2;
 
993
        *d++ = (bgr&0x7C00)>>7;
 
994
    }
 
995
}
 
996
 
 
997
static inline void RENAME(rgb16tobgr24)(const uint8_t *src, uint8_t *dst, long src_size)
 
998
{
 
999
    const uint16_t *end;
 
1000
#if HAVE_MMX
 
1001
    const uint16_t *mm_end;
 
1002
#endif
 
1003
    uint8_t *d = (uint8_t *)dst;
 
1004
    const uint16_t *s = (const uint16_t *)src;
 
1005
    end = s + src_size/2;
 
1006
#if HAVE_MMX
 
1007
    __asm__ volatile(PREFETCH"    %0"::"m"(*s):"memory");
 
1008
    mm_end = end - 7;
 
1009
    while (s < mm_end) {
 
1010
        __asm__ volatile(
 
1011
            PREFETCH"    32%1           \n\t"
 
1012
            "movq          %1, %%mm0    \n\t"
 
1013
            "movq          %1, %%mm1    \n\t"
 
1014
            "movq          %1, %%mm2    \n\t"
 
1015
            "pand          %2, %%mm0    \n\t"
 
1016
            "pand          %3, %%mm1    \n\t"
 
1017
            "pand          %4, %%mm2    \n\t"
 
1018
            "psllq         $3, %%mm0    \n\t"
 
1019
            "psrlq         $3, %%mm1    \n\t"
 
1020
            "psrlq         $8, %%mm2    \n\t"
 
1021
            "movq       %%mm0, %%mm3    \n\t"
 
1022
            "movq       %%mm1, %%mm4    \n\t"
 
1023
            "movq       %%mm2, %%mm5    \n\t"
 
1024
            "punpcklwd     %5, %%mm0    \n\t"
 
1025
            "punpcklwd     %5, %%mm1    \n\t"
 
1026
            "punpcklwd     %5, %%mm2    \n\t"
 
1027
            "punpckhwd     %5, %%mm3    \n\t"
 
1028
            "punpckhwd     %5, %%mm4    \n\t"
 
1029
            "punpckhwd     %5, %%mm5    \n\t"
 
1030
            "psllq         $8, %%mm1    \n\t"
 
1031
            "psllq        $16, %%mm2    \n\t"
 
1032
            "por        %%mm1, %%mm0    \n\t"
 
1033
            "por        %%mm2, %%mm0    \n\t"
 
1034
            "psllq         $8, %%mm4    \n\t"
 
1035
            "psllq        $16, %%mm5    \n\t"
 
1036
            "por        %%mm4, %%mm3    \n\t"
 
1037
            "por        %%mm5, %%mm3    \n\t"
 
1038
 
 
1039
            "movq       %%mm0, %%mm6    \n\t"
 
1040
            "movq       %%mm3, %%mm7    \n\t"
 
1041
 
 
1042
            "movq         8%1, %%mm0    \n\t"
 
1043
            "movq         8%1, %%mm1    \n\t"
 
1044
            "movq         8%1, %%mm2    \n\t"
 
1045
            "pand          %2, %%mm0    \n\t"
 
1046
            "pand          %3, %%mm1    \n\t"
 
1047
            "pand          %4, %%mm2    \n\t"
 
1048
            "psllq         $3, %%mm0    \n\t"
 
1049
            "psrlq         $3, %%mm1    \n\t"
 
1050
            "psrlq         $8, %%mm2    \n\t"
 
1051
            "movq       %%mm0, %%mm3    \n\t"
 
1052
            "movq       %%mm1, %%mm4    \n\t"
 
1053
            "movq       %%mm2, %%mm5    \n\t"
 
1054
            "punpcklwd     %5, %%mm0    \n\t"
 
1055
            "punpcklwd     %5, %%mm1    \n\t"
 
1056
            "punpcklwd     %5, %%mm2    \n\t"
 
1057
            "punpckhwd     %5, %%mm3    \n\t"
 
1058
            "punpckhwd     %5, %%mm4    \n\t"
 
1059
            "punpckhwd     %5, %%mm5    \n\t"
 
1060
            "psllq         $8, %%mm1    \n\t"
 
1061
            "psllq        $16, %%mm2    \n\t"
 
1062
            "por        %%mm1, %%mm0    \n\t"
 
1063
            "por        %%mm2, %%mm0    \n\t"
 
1064
            "psllq         $8, %%mm4    \n\t"
 
1065
            "psllq        $16, %%mm5    \n\t"
 
1066
            "por        %%mm4, %%mm3    \n\t"
 
1067
            "por        %%mm5, %%mm3    \n\t"
 
1068
            :"=m"(*d)
 
1069
            :"m"(*s),"m"(mask16b),"m"(mask16g),"m"(mask16r),"m"(mmx_null)
 
1070
            :"memory");
 
1071
        /* borrowed 32 to 24 */
 
1072
        __asm__ volatile(
 
1073
            "movq       %%mm0, %%mm4    \n\t"
 
1074
            "movq       %%mm3, %%mm5    \n\t"
 
1075
            "movq       %%mm6, %%mm0    \n\t"
 
1076
            "movq       %%mm7, %%mm1    \n\t"
 
1077
 
 
1078
            "movq       %%mm4, %%mm6    \n\t"
 
1079
            "movq       %%mm5, %%mm7    \n\t"
 
1080
            "movq       %%mm0, %%mm2    \n\t"
 
1081
            "movq       %%mm1, %%mm3    \n\t"
 
1082
 
 
1083
            STORE_BGR24_MMX
 
1084
 
 
1085
            :"=m"(*d)
 
1086
            :"m"(*s)
 
1087
            :"memory");
 
1088
        d += 24;
 
1089
        s += 8;
 
1090
    }
 
1091
    __asm__ volatile(SFENCE:::"memory");
 
1092
    __asm__ volatile(EMMS:::"memory");
 
1093
#endif
 
1094
    while (s < end) {
 
1095
        register uint16_t bgr;
 
1096
        bgr = *s++;
 
1097
        *d++ = (bgr&0x1F)<<3;
 
1098
        *d++ = (bgr&0x7E0)>>3;
 
1099
        *d++ = (bgr&0xF800)>>8;
 
1100
    }
 
1101
}
 
1102
 
 
1103
/*
 
1104
 * mm0 = 00 B3 00 B2 00 B1 00 B0
 
1105
 * mm1 = 00 G3 00 G2 00 G1 00 G0
 
1106
 * mm2 = 00 R3 00 R2 00 R1 00 R0
 
1107
 * mm6 = FF FF FF FF FF FF FF FF
 
1108
 * mm7 = 00 00 00 00 00 00 00 00
 
1109
 */
 
1110
#define PACK_RGB32 \
 
1111
    "packuswb   %%mm7, %%mm0    \n\t" /* 00 00 00 00 B3 B2 B1 B0 */ \
 
1112
    "packuswb   %%mm7, %%mm1    \n\t" /* 00 00 00 00 G3 G2 G1 G0 */ \
 
1113
    "packuswb   %%mm7, %%mm2    \n\t" /* 00 00 00 00 R3 R2 R1 R0 */ \
 
1114
    "punpcklbw  %%mm1, %%mm0    \n\t" /* G3 B3 G2 B2 G1 B1 G0 B0 */ \
 
1115
    "punpcklbw  %%mm6, %%mm2    \n\t" /* FF R3 FF R2 FF R1 FF R0 */ \
 
1116
    "movq       %%mm0, %%mm3    \n\t"                               \
 
1117
    "punpcklwd  %%mm2, %%mm0    \n\t" /* FF R1 G1 B1 FF R0 G0 B0 */ \
 
1118
    "punpckhwd  %%mm2, %%mm3    \n\t" /* FF R3 G3 B3 FF R2 G2 B2 */ \
 
1119
    MOVNTQ"     %%mm0,  %0      \n\t"                               \
 
1120
    MOVNTQ"     %%mm3, 8%0      \n\t"                               \
 
1121
 
 
1122
static inline void RENAME(rgb15to32)(const uint8_t *src, uint8_t *dst, long src_size)
 
1123
{
 
1124
    const uint16_t *end;
 
1125
#if HAVE_MMX
 
1126
    const uint16_t *mm_end;
 
1127
#endif
 
1128
    uint8_t *d = dst;
 
1129
    const uint16_t *s = (const uint16_t *)src;
 
1130
    end = s + src_size/2;
 
1131
#if HAVE_MMX
 
1132
    __asm__ volatile(PREFETCH"    %0"::"m"(*s):"memory");
 
1133
    __asm__ volatile("pxor    %%mm7,%%mm7    \n\t":::"memory");
 
1134
    __asm__ volatile("pcmpeqd %%mm6,%%mm6    \n\t":::"memory");
 
1135
    mm_end = end - 3;
 
1136
    while (s < mm_end) {
 
1137
        __asm__ volatile(
 
1138
            PREFETCH"    32%1           \n\t"
 
1139
            "movq          %1, %%mm0    \n\t"
 
1140
            "movq          %1, %%mm1    \n\t"
 
1141
            "movq          %1, %%mm2    \n\t"
 
1142
            "pand          %2, %%mm0    \n\t"
 
1143
            "pand          %3, %%mm1    \n\t"
 
1144
            "pand          %4, %%mm2    \n\t"
 
1145
            "psllq         $3, %%mm0    \n\t"
 
1146
            "psrlq         $2, %%mm1    \n\t"
 
1147
            "psrlq         $7, %%mm2    \n\t"
 
1148
            PACK_RGB32
 
1149
            :"=m"(*d)
 
1150
            :"m"(*s),"m"(mask15b),"m"(mask15g),"m"(mask15r)
 
1151
            :"memory");
 
1152
        d += 16;
 
1153
        s += 4;
 
1154
    }
 
1155
    __asm__ volatile(SFENCE:::"memory");
 
1156
    __asm__ volatile(EMMS:::"memory");
 
1157
#endif
 
1158
    while (s < end) {
 
1159
        register uint16_t bgr;
 
1160
        bgr = *s++;
 
1161
#if HAVE_BIGENDIAN
 
1162
        *d++ = 255;
 
1163
        *d++ = (bgr&0x7C00)>>7;
 
1164
        *d++ = (bgr&0x3E0)>>2;
 
1165
        *d++ = (bgr&0x1F)<<3;
 
1166
#else
 
1167
        *d++ = (bgr&0x1F)<<3;
 
1168
        *d++ = (bgr&0x3E0)>>2;
 
1169
        *d++ = (bgr&0x7C00)>>7;
 
1170
        *d++ = 255;
 
1171
#endif
 
1172
    }
 
1173
}
 
1174
 
 
1175
static inline void RENAME(rgb16to32)(const uint8_t *src, uint8_t *dst, long src_size)
 
1176
{
 
1177
    const uint16_t *end;
 
1178
#if HAVE_MMX
 
1179
    const uint16_t *mm_end;
 
1180
#endif
 
1181
    uint8_t *d = dst;
 
1182
    const uint16_t *s = (const uint16_t*)src;
 
1183
    end = s + src_size/2;
 
1184
#if HAVE_MMX
 
1185
    __asm__ volatile(PREFETCH"    %0"::"m"(*s):"memory");
 
1186
    __asm__ volatile("pxor    %%mm7,%%mm7    \n\t":::"memory");
 
1187
    __asm__ volatile("pcmpeqd %%mm6,%%mm6    \n\t":::"memory");
 
1188
    mm_end = end - 3;
 
1189
    while (s < mm_end) {
 
1190
        __asm__ volatile(
 
1191
            PREFETCH"    32%1           \n\t"
 
1192
            "movq          %1, %%mm0    \n\t"
 
1193
            "movq          %1, %%mm1    \n\t"
 
1194
            "movq          %1, %%mm2    \n\t"
 
1195
            "pand          %2, %%mm0    \n\t"
 
1196
            "pand          %3, %%mm1    \n\t"
 
1197
            "pand          %4, %%mm2    \n\t"
 
1198
            "psllq         $3, %%mm0    \n\t"
 
1199
            "psrlq         $3, %%mm1    \n\t"
 
1200
            "psrlq         $8, %%mm2    \n\t"
 
1201
            PACK_RGB32
 
1202
            :"=m"(*d)
 
1203
            :"m"(*s),"m"(mask16b),"m"(mask16g),"m"(mask16r)
 
1204
            :"memory");
 
1205
        d += 16;
 
1206
        s += 4;
 
1207
    }
 
1208
    __asm__ volatile(SFENCE:::"memory");
 
1209
    __asm__ volatile(EMMS:::"memory");
 
1210
#endif
 
1211
    while (s < end) {
 
1212
        register uint16_t bgr;
 
1213
        bgr = *s++;
 
1214
#if HAVE_BIGENDIAN
 
1215
        *d++ = 255;
 
1216
        *d++ = (bgr&0xF800)>>8;
 
1217
        *d++ = (bgr&0x7E0)>>3;
 
1218
        *d++ = (bgr&0x1F)<<3;
 
1219
#else
 
1220
        *d++ = (bgr&0x1F)<<3;
 
1221
        *d++ = (bgr&0x7E0)>>3;
 
1222
        *d++ = (bgr&0xF800)>>8;
 
1223
        *d++ = 255;
 
1224
#endif
 
1225
    }
 
1226
}
 
1227
 
 
1228
static inline void RENAME(rgb32tobgr32)(const uint8_t *src, uint8_t *dst, long src_size)
 
1229
{
 
1230
    x86_reg idx = 15 - src_size;
 
1231
    const uint8_t *s = src-idx;
 
1232
    uint8_t *d = dst-idx;
 
1233
#if HAVE_MMX
 
1234
    __asm__ volatile(
 
1235
        "test          %0, %0           \n\t"
 
1236
        "jns           2f               \n\t"
 
1237
        PREFETCH"       (%1, %0)        \n\t"
 
1238
        "movq          %3, %%mm7        \n\t"
 
1239
        "pxor          %4, %%mm7        \n\t"
 
1240
        "movq       %%mm7, %%mm6        \n\t"
 
1241
        "pxor          %5, %%mm7        \n\t"
 
1242
        ASMALIGN(4)
 
1243
        "1:                             \n\t"
 
1244
        PREFETCH"     32(%1, %0)        \n\t"
 
1245
        "movq           (%1, %0), %%mm0 \n\t"
 
1246
        "movq          8(%1, %0), %%mm1 \n\t"
 
1247
# if HAVE_MMX2
 
1248
        "pshufw      $177, %%mm0, %%mm3 \n\t"
 
1249
        "pshufw      $177, %%mm1, %%mm5 \n\t"
 
1250
        "pand       %%mm7, %%mm0        \n\t"
 
1251
        "pand       %%mm6, %%mm3        \n\t"
 
1252
        "pand       %%mm7, %%mm1        \n\t"
 
1253
        "pand       %%mm6, %%mm5        \n\t"
 
1254
        "por        %%mm3, %%mm0        \n\t"
 
1255
        "por        %%mm5, %%mm1        \n\t"
 
1256
# else
 
1257
        "movq       %%mm0, %%mm2        \n\t"
 
1258
        "movq       %%mm1, %%mm4        \n\t"
 
1259
        "pand       %%mm7, %%mm0        \n\t"
 
1260
        "pand       %%mm6, %%mm2        \n\t"
 
1261
        "pand       %%mm7, %%mm1        \n\t"
 
1262
        "pand       %%mm6, %%mm4        \n\t"
 
1263
        "movq       %%mm2, %%mm3        \n\t"
 
1264
        "movq       %%mm4, %%mm5        \n\t"
 
1265
        "pslld        $16, %%mm2        \n\t"
 
1266
        "psrld        $16, %%mm3        \n\t"
 
1267
        "pslld        $16, %%mm4        \n\t"
 
1268
        "psrld        $16, %%mm5        \n\t"
 
1269
        "por        %%mm2, %%mm0        \n\t"
 
1270
        "por        %%mm4, %%mm1        \n\t"
 
1271
        "por        %%mm3, %%mm0        \n\t"
 
1272
        "por        %%mm5, %%mm1        \n\t"
 
1273
# endif
 
1274
        MOVNTQ"     %%mm0,  (%2, %0)    \n\t"
 
1275
        MOVNTQ"     %%mm1, 8(%2, %0)    \n\t"
 
1276
        "add          $16, %0           \n\t"
 
1277
        "js            1b               \n\t"
 
1278
        SFENCE"                         \n\t"
 
1279
        EMMS"                           \n\t"
 
1280
        "2:                             \n\t"
 
1281
        : "+&r"(idx)
 
1282
        : "r" (s), "r" (d), "m" (mask32b), "m" (mask32r), "m" (mmx_one)
 
1283
        : "memory");
 
1284
#endif
 
1285
    for (; idx<15; idx+=4) {
 
1286
        register int v = *(const uint32_t *)&s[idx], g = v & 0xff00ff00;
 
1287
        v &= 0xff00ff;
 
1288
        *(uint32_t *)&d[idx] = (v>>16) + g + (v<<16);
 
1289
    }
 
1290
}
 
1291
 
 
1292
static inline void RENAME(rgb24tobgr24)(const uint8_t *src, uint8_t *dst, long src_size)
 
1293
{
 
1294
    unsigned i;
 
1295
#if HAVE_MMX
 
1296
    x86_reg mmx_size= 23 - src_size;
 
1297
    __asm__ volatile (
 
1298
        "test             %%"REG_a", %%"REG_a"          \n\t"
 
1299
        "jns                     2f                     \n\t"
 
1300
        "movq     "MANGLE(mask24r)", %%mm5              \n\t"
 
1301
        "movq     "MANGLE(mask24g)", %%mm6              \n\t"
 
1302
        "movq     "MANGLE(mask24b)", %%mm7              \n\t"
 
1303
        ASMALIGN(4)
 
1304
        "1:                                             \n\t"
 
1305
        PREFETCH" 32(%1, %%"REG_a")                     \n\t"
 
1306
        "movq       (%1, %%"REG_a"), %%mm0              \n\t" // BGR BGR BG
 
1307
        "movq       (%1, %%"REG_a"), %%mm1              \n\t" // BGR BGR BG
 
1308
        "movq      2(%1, %%"REG_a"), %%mm2              \n\t" // R BGR BGR B
 
1309
        "psllq                  $16, %%mm0              \n\t" // 00 BGR BGR
 
1310
        "pand                 %%mm5, %%mm0              \n\t"
 
1311
        "pand                 %%mm6, %%mm1              \n\t"
 
1312
        "pand                 %%mm7, %%mm2              \n\t"
 
1313
        "por                  %%mm0, %%mm1              \n\t"
 
1314
        "por                  %%mm2, %%mm1              \n\t"
 
1315
        "movq      6(%1, %%"REG_a"), %%mm0              \n\t" // BGR BGR BG
 
1316
        MOVNTQ"               %%mm1,   (%2, %%"REG_a")  \n\t" // RGB RGB RG
 
1317
        "movq      8(%1, %%"REG_a"), %%mm1              \n\t" // R BGR BGR B
 
1318
        "movq     10(%1, %%"REG_a"), %%mm2              \n\t" // GR BGR BGR
 
1319
        "pand                 %%mm7, %%mm0              \n\t"
 
1320
        "pand                 %%mm5, %%mm1              \n\t"
 
1321
        "pand                 %%mm6, %%mm2              \n\t"
 
1322
        "por                  %%mm0, %%mm1              \n\t"
 
1323
        "por                  %%mm2, %%mm1              \n\t"
 
1324
        "movq     14(%1, %%"REG_a"), %%mm0              \n\t" // R BGR BGR B
 
1325
        MOVNTQ"               %%mm1,  8(%2, %%"REG_a")  \n\t" // B RGB RGB R
 
1326
        "movq     16(%1, %%"REG_a"), %%mm1              \n\t" // GR BGR BGR
 
1327
        "movq     18(%1, %%"REG_a"), %%mm2              \n\t" // BGR BGR BG
 
1328
        "pand                 %%mm6, %%mm0              \n\t"
 
1329
        "pand                 %%mm7, %%mm1              \n\t"
 
1330
        "pand                 %%mm5, %%mm2              \n\t"
 
1331
        "por                  %%mm0, %%mm1              \n\t"
 
1332
        "por                  %%mm2, %%mm1              \n\t"
 
1333
        MOVNTQ"               %%mm1, 16(%2, %%"REG_a")  \n\t"
 
1334
        "add                    $24, %%"REG_a"          \n\t"
 
1335
        " js                     1b                     \n\t"
 
1336
        "2:                                             \n\t"
 
1337
        : "+a" (mmx_size)
 
1338
        : "r" (src-mmx_size), "r"(dst-mmx_size)
 
1339
    );
 
1340
 
 
1341
    __asm__ volatile(SFENCE:::"memory");
 
1342
    __asm__ volatile(EMMS:::"memory");
 
1343
 
 
1344
    if (mmx_size==23) return; //finished, was multiple of 8
 
1345
 
 
1346
    src+= src_size;
 
1347
    dst+= src_size;
 
1348
    src_size= 23-mmx_size;
 
1349
    src-= src_size;
 
1350
    dst-= src_size;
 
1351
#endif
 
1352
    for (i=0; i<src_size; i+=3) {
 
1353
        register uint8_t x;
 
1354
        x          = src[i + 2];
 
1355
        dst[i + 1] = src[i + 1];
 
1356
        dst[i + 2] = src[i + 0];
 
1357
        dst[i + 0] = x;
 
1358
    }
 
1359
}
 
1360
 
 
1361
static inline void RENAME(yuvPlanartoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
 
1362
                                           long width, long height,
 
1363
                                           long lumStride, long chromStride, long dstStride, long vertLumPerChroma)
 
1364
{
 
1365
    long y;
 
1366
    const x86_reg chromWidth= width>>1;
 
1367
    for (y=0; y<height; y++) {
 
1368
#if HAVE_MMX
 
1369
        //FIXME handle 2 lines at once (fewer prefetches, reuse some chroma, but very likely memory-limited anyway)
 
1370
        __asm__ volatile(
 
1371
            "xor                 %%"REG_a", %%"REG_a"   \n\t"
 
1372
            ASMALIGN(4)
 
1373
            "1:                                         \n\t"
 
1374
            PREFETCH"    32(%1, %%"REG_a", 2)           \n\t"
 
1375
            PREFETCH"    32(%2, %%"REG_a")              \n\t"
 
1376
            PREFETCH"    32(%3, %%"REG_a")              \n\t"
 
1377
            "movq          (%2, %%"REG_a"), %%mm0       \n\t" // U(0)
 
1378
            "movq                    %%mm0, %%mm2       \n\t" // U(0)
 
1379
            "movq          (%3, %%"REG_a"), %%mm1       \n\t" // V(0)
 
1380
            "punpcklbw               %%mm1, %%mm0       \n\t" // UVUV UVUV(0)
 
1381
            "punpckhbw               %%mm1, %%mm2       \n\t" // UVUV UVUV(8)
 
1382
 
 
1383
            "movq        (%1, %%"REG_a",2), %%mm3       \n\t" // Y(0)
 
1384
            "movq       8(%1, %%"REG_a",2), %%mm5       \n\t" // Y(8)
 
1385
            "movq                    %%mm3, %%mm4       \n\t" // Y(0)
 
1386
            "movq                    %%mm5, %%mm6       \n\t" // Y(8)
 
1387
            "punpcklbw               %%mm0, %%mm3       \n\t" // YUYV YUYV(0)
 
1388
            "punpckhbw               %%mm0, %%mm4       \n\t" // YUYV YUYV(4)
 
1389
            "punpcklbw               %%mm2, %%mm5       \n\t" // YUYV YUYV(8)
 
1390
            "punpckhbw               %%mm2, %%mm6       \n\t" // YUYV YUYV(12)
 
1391
 
 
1392
            MOVNTQ"                  %%mm3,   (%0, %%"REG_a", 4)    \n\t"
 
1393
            MOVNTQ"                  %%mm4,  8(%0, %%"REG_a", 4)    \n\t"
 
1394
            MOVNTQ"                  %%mm5, 16(%0, %%"REG_a", 4)    \n\t"
 
1395
            MOVNTQ"                  %%mm6, 24(%0, %%"REG_a", 4)    \n\t"
 
1396
 
 
1397
            "add                        $8, %%"REG_a"   \n\t"
 
1398
            "cmp                        %4, %%"REG_a"   \n\t"
 
1399
            " jb                        1b              \n\t"
 
1400
            ::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "g" (chromWidth)
 
1401
            : "%"REG_a
 
1402
        );
 
1403
#else
 
1404
 
 
1405
#if ARCH_ALPHA && HAVE_MVI
 
1406
#define pl2yuy2(n)                  \
 
1407
    y1 = yc[n];                     \
 
1408
    y2 = yc2[n];                    \
 
1409
    u = uc[n];                      \
 
1410
    v = vc[n];                      \
 
1411
    __asm__("unpkbw %1, %0" : "=r"(y1) : "r"(y1));  \
 
1412
    __asm__("unpkbw %1, %0" : "=r"(y2) : "r"(y2));  \
 
1413
    __asm__("unpkbl %1, %0" : "=r"(u) : "r"(u));    \
 
1414
    __asm__("unpkbl %1, %0" : "=r"(v) : "r"(v));    \
 
1415
    yuv1 = (u << 8) + (v << 24);                \
 
1416
    yuv2 = yuv1 + y2;               \
 
1417
    yuv1 += y1;                     \
 
1418
    qdst[n]  = yuv1;                \
 
1419
    qdst2[n] = yuv2;
 
1420
 
 
1421
        int i;
 
1422
        uint64_t *qdst = (uint64_t *) dst;
 
1423
        uint64_t *qdst2 = (uint64_t *) (dst + dstStride);
 
1424
        const uint32_t *yc = (uint32_t *) ysrc;
 
1425
        const uint32_t *yc2 = (uint32_t *) (ysrc + lumStride);
 
1426
        const uint16_t *uc = (uint16_t*) usrc, *vc = (uint16_t*) vsrc;
 
1427
        for (i = 0; i < chromWidth; i += 8) {
 
1428
            uint64_t y1, y2, yuv1, yuv2;
 
1429
            uint64_t u, v;
 
1430
            /* Prefetch */
 
1431
            __asm__("ldq $31,64(%0)" :: "r"(yc));
 
1432
            __asm__("ldq $31,64(%0)" :: "r"(yc2));
 
1433
            __asm__("ldq $31,64(%0)" :: "r"(uc));
 
1434
            __asm__("ldq $31,64(%0)" :: "r"(vc));
 
1435
 
 
1436
            pl2yuy2(0);
 
1437
            pl2yuy2(1);
 
1438
            pl2yuy2(2);
 
1439
            pl2yuy2(3);
 
1440
 
 
1441
            yc    += 4;
 
1442
            yc2   += 4;
 
1443
            uc    += 4;
 
1444
            vc    += 4;
 
1445
            qdst  += 4;
 
1446
            qdst2 += 4;
 
1447
        }
 
1448
        y++;
 
1449
        ysrc += lumStride;
 
1450
        dst += dstStride;
 
1451
 
 
1452
#elif HAVE_FAST_64BIT
 
1453
        int i;
 
1454
        uint64_t *ldst = (uint64_t *) dst;
 
1455
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
 
1456
        for (i = 0; i < chromWidth; i += 2) {
 
1457
            uint64_t k, l;
 
1458
            k = yc[0] + (uc[0] << 8) +
 
1459
                (yc[1] << 16) + (vc[0] << 24);
 
1460
            l = yc[2] + (uc[1] << 8) +
 
1461
                (yc[3] << 16) + (vc[1] << 24);
 
1462
            *ldst++ = k + (l << 32);
 
1463
            yc += 4;
 
1464
            uc += 2;
 
1465
            vc += 2;
 
1466
        }
 
1467
 
 
1468
#else
 
1469
        int i, *idst = (int32_t *) dst;
 
1470
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
 
1471
        for (i = 0; i < chromWidth; i++) {
 
1472
#if HAVE_BIGENDIAN
 
1473
            *idst++ = (yc[0] << 24)+ (uc[0] << 16) +
 
1474
                (yc[1] << 8) + (vc[0] << 0);
 
1475
#else
 
1476
            *idst++ = yc[0] + (uc[0] << 8) +
 
1477
                (yc[1] << 16) + (vc[0] << 24);
 
1478
#endif
 
1479
            yc += 2;
 
1480
            uc++;
 
1481
            vc++;
 
1482
        }
 
1483
#endif
 
1484
#endif
 
1485
        if ((y&(vertLumPerChroma-1)) == vertLumPerChroma-1) {
 
1486
            usrc += chromStride;
 
1487
            vsrc += chromStride;
 
1488
        }
 
1489
        ysrc += lumStride;
 
1490
        dst  += dstStride;
 
1491
    }
 
1492
#if HAVE_MMX
 
1493
    __asm__(EMMS"       \n\t"
 
1494
            SFENCE"     \n\t"
 
1495
            :::"memory");
 
1496
#endif
 
1497
}
 
1498
 
 
1499
/**
 
1500
 * Height should be a multiple of 2 and width should be a multiple of 16.
 
1501
 * (If this is a problem for anyone then tell me, and I will fix it.)
 
1502
 */
 
1503
static inline void RENAME(yv12toyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
 
1504
                                      long width, long height,
 
1505
                                      long lumStride, long chromStride, long dstStride)
 
1506
{
 
1507
    //FIXME interpolate chroma
 
1508
    RENAME(yuvPlanartoyuy2)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 2);
 
1509
}
 
1510
 
 
1511
static inline void RENAME(yuvPlanartouyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
 
1512
                                           long width, long height,
 
1513
                                           long lumStride, long chromStride, long dstStride, long vertLumPerChroma)
 
1514
{
 
1515
    long y;
 
1516
    const x86_reg chromWidth= width>>1;
 
1517
    for (y=0; y<height; y++) {
 
1518
#if HAVE_MMX
 
1519
        //FIXME handle 2 lines at once (fewer prefetches, reuse some chroma, but very likely memory-limited anyway)
 
1520
        __asm__ volatile(
 
1521
            "xor                %%"REG_a", %%"REG_a"    \n\t"
 
1522
            ASMALIGN(4)
 
1523
            "1:                                         \n\t"
 
1524
            PREFETCH"   32(%1, %%"REG_a", 2)            \n\t"
 
1525
            PREFETCH"   32(%2, %%"REG_a")               \n\t"
 
1526
            PREFETCH"   32(%3, %%"REG_a")               \n\t"
 
1527
            "movq         (%2, %%"REG_a"), %%mm0        \n\t" // U(0)
 
1528
            "movq                   %%mm0, %%mm2        \n\t" // U(0)
 
1529
            "movq         (%3, %%"REG_a"), %%mm1        \n\t" // V(0)
 
1530
            "punpcklbw              %%mm1, %%mm0        \n\t" // UVUV UVUV(0)
 
1531
            "punpckhbw              %%mm1, %%mm2        \n\t" // UVUV UVUV(8)
 
1532
 
 
1533
            "movq       (%1, %%"REG_a",2), %%mm3        \n\t" // Y(0)
 
1534
            "movq      8(%1, %%"REG_a",2), %%mm5        \n\t" // Y(8)
 
1535
            "movq                   %%mm0, %%mm4        \n\t" // Y(0)
 
1536
            "movq                   %%mm2, %%mm6        \n\t" // Y(8)
 
1537
            "punpcklbw              %%mm3, %%mm0        \n\t" // YUYV YUYV(0)
 
1538
            "punpckhbw              %%mm3, %%mm4        \n\t" // YUYV YUYV(4)
 
1539
            "punpcklbw              %%mm5, %%mm2        \n\t" // YUYV YUYV(8)
 
1540
            "punpckhbw              %%mm5, %%mm6        \n\t" // YUYV YUYV(12)
 
1541
 
 
1542
            MOVNTQ"                 %%mm0,   (%0, %%"REG_a", 4)     \n\t"
 
1543
            MOVNTQ"                 %%mm4,  8(%0, %%"REG_a", 4)     \n\t"
 
1544
            MOVNTQ"                 %%mm2, 16(%0, %%"REG_a", 4)     \n\t"
 
1545
            MOVNTQ"                 %%mm6, 24(%0, %%"REG_a", 4)     \n\t"
 
1546
 
 
1547
            "add                       $8, %%"REG_a"    \n\t"
 
1548
            "cmp                       %4, %%"REG_a"    \n\t"
 
1549
            " jb                       1b               \n\t"
 
1550
            ::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "g" (chromWidth)
 
1551
            : "%"REG_a
 
1552
        );
 
1553
#else
 
1554
//FIXME adapt the Alpha ASM code from yv12->yuy2
 
1555
 
 
1556
#if HAVE_FAST_64BIT
 
1557
        int i;
 
1558
        uint64_t *ldst = (uint64_t *) dst;
 
1559
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
 
1560
        for (i = 0; i < chromWidth; i += 2) {
 
1561
            uint64_t k, l;
 
1562
            k = uc[0] + (yc[0] << 8) +
 
1563
                (vc[0] << 16) + (yc[1] << 24);
 
1564
            l = uc[1] + (yc[2] << 8) +
 
1565
                (vc[1] << 16) + (yc[3] << 24);
 
1566
            *ldst++ = k + (l << 32);
 
1567
            yc += 4;
 
1568
            uc += 2;
 
1569
            vc += 2;
 
1570
        }
 
1571
 
 
1572
#else
 
1573
        int i, *idst = (int32_t *) dst;
 
1574
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
 
1575
        for (i = 0; i < chromWidth; i++) {
 
1576
#if HAVE_BIGENDIAN
 
1577
            *idst++ = (uc[0] << 24)+ (yc[0] << 16) +
 
1578
                (vc[0] << 8) + (yc[1] << 0);
 
1579
#else
 
1580
            *idst++ = uc[0] + (yc[0] << 8) +
 
1581
               (vc[0] << 16) + (yc[1] << 24);
 
1582
#endif
 
1583
            yc += 2;
 
1584
            uc++;
 
1585
            vc++;
 
1586
        }
 
1587
#endif
 
1588
#endif
 
1589
        if ((y&(vertLumPerChroma-1)) == vertLumPerChroma-1) {
 
1590
            usrc += chromStride;
 
1591
            vsrc += chromStride;
 
1592
        }
 
1593
        ysrc += lumStride;
 
1594
        dst += dstStride;
 
1595
    }
 
1596
#if HAVE_MMX
 
1597
    __asm__(EMMS"       \n\t"
 
1598
            SFENCE"     \n\t"
 
1599
            :::"memory");
 
1600
#endif
 
1601
}
 
1602
 
 
1603
/**
 
1604
 * Height should be a multiple of 2 and width should be a multiple of 16
 
1605
 * (If this is a problem for anyone then tell me, and I will fix it.)
 
1606
 */
 
1607
static inline void RENAME(yv12touyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
 
1608
                                      long width, long height,
 
1609
                                      long lumStride, long chromStride, long dstStride)
 
1610
{
 
1611
    //FIXME interpolate chroma
 
1612
    RENAME(yuvPlanartouyvy)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 2);
 
1613
}
 
1614
 
 
1615
/**
 
1616
 * Width should be a multiple of 16.
 
1617
 */
 
1618
static inline void RENAME(yuv422ptouyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
 
1619
                                         long width, long height,
 
1620
                                         long lumStride, long chromStride, long dstStride)
 
1621
{
 
1622
    RENAME(yuvPlanartouyvy)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 1);
 
1623
}
 
1624
 
 
1625
/**
 
1626
 * Width should be a multiple of 16.
 
1627
 */
 
1628
static inline void RENAME(yuv422ptoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
 
1629
                                         long width, long height,
 
1630
                                         long lumStride, long chromStride, long dstStride)
 
1631
{
 
1632
    RENAME(yuvPlanartoyuy2)(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride, 1);
 
1633
}
 
1634
 
 
1635
/**
 
1636
 * Height should be a multiple of 2 and width should be a multiple of 16.
 
1637
 * (If this is a problem for anyone then tell me, and I will fix it.)
 
1638
 */
 
1639
static inline void RENAME(yuy2toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
 
1640
                                      long width, long height,
 
1641
                                      long lumStride, long chromStride, long srcStride)
 
1642
{
 
1643
    long y;
 
1644
    const x86_reg chromWidth= width>>1;
 
1645
    for (y=0; y<height; y+=2) {
 
1646
#if HAVE_MMX
 
1647
        __asm__ volatile(
 
1648
            "xor                 %%"REG_a", %%"REG_a"   \n\t"
 
1649
            "pcmpeqw                 %%mm7, %%mm7       \n\t"
 
1650
            "psrlw                      $8, %%mm7       \n\t" // FF,00,FF,00...
 
1651
            ASMALIGN(4)
 
1652
            "1:                \n\t"
 
1653
            PREFETCH" 64(%0, %%"REG_a", 4)              \n\t"
 
1654
            "movq       (%0, %%"REG_a", 4), %%mm0       \n\t" // YUYV YUYV(0)
 
1655
            "movq      8(%0, %%"REG_a", 4), %%mm1       \n\t" // YUYV YUYV(4)
 
1656
            "movq                    %%mm0, %%mm2       \n\t" // YUYV YUYV(0)
 
1657
            "movq                    %%mm1, %%mm3       \n\t" // YUYV YUYV(4)
 
1658
            "psrlw                      $8, %%mm0       \n\t" // U0V0 U0V0(0)
 
1659
            "psrlw                      $8, %%mm1       \n\t" // U0V0 U0V0(4)
 
1660
            "pand                    %%mm7, %%mm2       \n\t" // Y0Y0 Y0Y0(0)
 
1661
            "pand                    %%mm7, %%mm3       \n\t" // Y0Y0 Y0Y0(4)
 
1662
            "packuswb                %%mm1, %%mm0       \n\t" // UVUV UVUV(0)
 
1663
            "packuswb                %%mm3, %%mm2       \n\t" // YYYY YYYY(0)
 
1664
 
 
1665
            MOVNTQ"                  %%mm2, (%1, %%"REG_a", 2)  \n\t"
 
1666
 
 
1667
            "movq     16(%0, %%"REG_a", 4), %%mm1       \n\t" // YUYV YUYV(8)
 
1668
            "movq     24(%0, %%"REG_a", 4), %%mm2       \n\t" // YUYV YUYV(12)
 
1669
            "movq                    %%mm1, %%mm3       \n\t" // YUYV YUYV(8)
 
1670
            "movq                    %%mm2, %%mm4       \n\t" // YUYV YUYV(12)
 
1671
            "psrlw                      $8, %%mm1       \n\t" // U0V0 U0V0(8)
 
1672
            "psrlw                      $8, %%mm2       \n\t" // U0V0 U0V0(12)
 
1673
            "pand                    %%mm7, %%mm3       \n\t" // Y0Y0 Y0Y0(8)
 
1674
            "pand                    %%mm7, %%mm4       \n\t" // Y0Y0 Y0Y0(12)
 
1675
            "packuswb                %%mm2, %%mm1       \n\t" // UVUV UVUV(8)
 
1676
            "packuswb                %%mm4, %%mm3       \n\t" // YYYY YYYY(8)
 
1677
 
 
1678
            MOVNTQ"                  %%mm3, 8(%1, %%"REG_a", 2) \n\t"
 
1679
 
 
1680
            "movq                    %%mm0, %%mm2       \n\t" // UVUV UVUV(0)
 
1681
            "movq                    %%mm1, %%mm3       \n\t" // UVUV UVUV(8)
 
1682
            "psrlw                      $8, %%mm0       \n\t" // V0V0 V0V0(0)
 
1683
            "psrlw                      $8, %%mm1       \n\t" // V0V0 V0V0(8)
 
1684
            "pand                    %%mm7, %%mm2       \n\t" // U0U0 U0U0(0)
 
1685
            "pand                    %%mm7, %%mm3       \n\t" // U0U0 U0U0(8)
 
1686
            "packuswb                %%mm1, %%mm0       \n\t" // VVVV VVVV(0)
 
1687
            "packuswb                %%mm3, %%mm2       \n\t" // UUUU UUUU(0)
 
1688
 
 
1689
            MOVNTQ"                  %%mm0, (%3, %%"REG_a")     \n\t"
 
1690
            MOVNTQ"                  %%mm2, (%2, %%"REG_a")     \n\t"
 
1691
 
 
1692
            "add                        $8, %%"REG_a"   \n\t"
 
1693
            "cmp                        %4, %%"REG_a"   \n\t"
 
1694
            " jb                        1b              \n\t"
 
1695
            ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
 
1696
            : "memory", "%"REG_a
 
1697
        );
 
1698
 
 
1699
        ydst += lumStride;
 
1700
        src  += srcStride;
 
1701
 
 
1702
        __asm__ volatile(
 
1703
            "xor                 %%"REG_a", %%"REG_a"   \n\t"
 
1704
            ASMALIGN(4)
 
1705
            "1:                                         \n\t"
 
1706
            PREFETCH" 64(%0, %%"REG_a", 4)              \n\t"
 
1707
            "movq       (%0, %%"REG_a", 4), %%mm0       \n\t" // YUYV YUYV(0)
 
1708
            "movq      8(%0, %%"REG_a", 4), %%mm1       \n\t" // YUYV YUYV(4)
 
1709
            "movq     16(%0, %%"REG_a", 4), %%mm2       \n\t" // YUYV YUYV(8)
 
1710
            "movq     24(%0, %%"REG_a", 4), %%mm3       \n\t" // YUYV YUYV(12)
 
1711
            "pand                    %%mm7, %%mm0       \n\t" // Y0Y0 Y0Y0(0)
 
1712
            "pand                    %%mm7, %%mm1       \n\t" // Y0Y0 Y0Y0(4)
 
1713
            "pand                    %%mm7, %%mm2       \n\t" // Y0Y0 Y0Y0(8)
 
1714
            "pand                    %%mm7, %%mm3       \n\t" // Y0Y0 Y0Y0(12)
 
1715
            "packuswb                %%mm1, %%mm0       \n\t" // YYYY YYYY(0)
 
1716
            "packuswb                %%mm3, %%mm2       \n\t" // YYYY YYYY(8)
 
1717
 
 
1718
            MOVNTQ"                  %%mm0,  (%1, %%"REG_a", 2) \n\t"
 
1719
            MOVNTQ"                  %%mm2, 8(%1, %%"REG_a", 2) \n\t"
 
1720
 
 
1721
            "add                        $8, %%"REG_a"   \n\t"
 
1722
            "cmp                        %4, %%"REG_a"   \n\t"
 
1723
            " jb                        1b              \n\t"
 
1724
 
 
1725
            ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
 
1726
            : "memory", "%"REG_a
 
1727
        );
 
1728
#else
 
1729
        long i;
 
1730
        for (i=0; i<chromWidth; i++) {
 
1731
            ydst[2*i+0]     = src[4*i+0];
 
1732
            udst[i]     = src[4*i+1];
 
1733
            ydst[2*i+1]     = src[4*i+2];
 
1734
            vdst[i]     = src[4*i+3];
 
1735
        }
 
1736
        ydst += lumStride;
 
1737
        src  += srcStride;
 
1738
 
 
1739
        for (i=0; i<chromWidth; i++) {
 
1740
            ydst[2*i+0]     = src[4*i+0];
 
1741
            ydst[2*i+1]     = src[4*i+2];
 
1742
        }
 
1743
#endif
 
1744
        udst += chromStride;
 
1745
        vdst += chromStride;
 
1746
        ydst += lumStride;
 
1747
        src  += srcStride;
 
1748
    }
 
1749
#if HAVE_MMX
 
1750
    __asm__ volatile(EMMS"       \n\t"
 
1751
                     SFENCE"     \n\t"
 
1752
                     :::"memory");
 
1753
#endif
 
1754
}
 
1755
 
 
1756
static inline void RENAME(yvu9toyv12)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc,
 
1757
                                      uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
 
1758
                                      long width, long height, long lumStride, long chromStride)
 
1759
{
 
1760
    /* Y Plane */
 
1761
    memcpy(ydst, ysrc, width*height);
 
1762
 
 
1763
    /* XXX: implement upscaling for U,V */
 
1764
}
 
1765
 
 
1766
static inline void RENAME(planar2x)(const uint8_t *src, uint8_t *dst, long srcWidth, long srcHeight, long srcStride, long dstStride)
 
1767
{
 
1768
    long x,y;
 
1769
 
 
1770
    dst[0]= src[0];
 
1771
 
 
1772
    // first line
 
1773
    for (x=0; x<srcWidth-1; x++) {
 
1774
        dst[2*x+1]= (3*src[x] +   src[x+1])>>2;
 
1775
        dst[2*x+2]= (  src[x] + 3*src[x+1])>>2;
 
1776
    }
 
1777
    dst[2*srcWidth-1]= src[srcWidth-1];
 
1778
 
 
1779
    dst+= dstStride;
 
1780
 
 
1781
    for (y=1; y<srcHeight; y++) {
 
1782
#if HAVE_MMX2 || HAVE_AMD3DNOW
 
1783
        const x86_reg mmxSize= srcWidth&~15;
 
1784
        __asm__ volatile(
 
1785
            "mov           %4, %%"REG_a"            \n\t"
 
1786
            "1:                                     \n\t"
 
1787
            "movq         (%0, %%"REG_a"), %%mm0    \n\t"
 
1788
            "movq         (%1, %%"REG_a"), %%mm1    \n\t"
 
1789
            "movq        1(%0, %%"REG_a"), %%mm2    \n\t"
 
1790
            "movq        1(%1, %%"REG_a"), %%mm3    \n\t"
 
1791
            "movq       -1(%0, %%"REG_a"), %%mm4    \n\t"
 
1792
            "movq       -1(%1, %%"REG_a"), %%mm5    \n\t"
 
1793
            PAVGB"                  %%mm0, %%mm5    \n\t"
 
1794
            PAVGB"                  %%mm0, %%mm3    \n\t"
 
1795
            PAVGB"                  %%mm0, %%mm5    \n\t"
 
1796
            PAVGB"                  %%mm0, %%mm3    \n\t"
 
1797
            PAVGB"                  %%mm1, %%mm4    \n\t"
 
1798
            PAVGB"                  %%mm1, %%mm2    \n\t"
 
1799
            PAVGB"                  %%mm1, %%mm4    \n\t"
 
1800
            PAVGB"                  %%mm1, %%mm2    \n\t"
 
1801
            "movq                   %%mm5, %%mm7    \n\t"
 
1802
            "movq                   %%mm4, %%mm6    \n\t"
 
1803
            "punpcklbw              %%mm3, %%mm5    \n\t"
 
1804
            "punpckhbw              %%mm3, %%mm7    \n\t"
 
1805
            "punpcklbw              %%mm2, %%mm4    \n\t"
 
1806
            "punpckhbw              %%mm2, %%mm6    \n\t"
 
1807
#if 1
 
1808
            MOVNTQ"                 %%mm5,  (%2, %%"REG_a", 2)  \n\t"
 
1809
            MOVNTQ"                 %%mm7, 8(%2, %%"REG_a", 2)  \n\t"
 
1810
            MOVNTQ"                 %%mm4,  (%3, %%"REG_a", 2)  \n\t"
 
1811
            MOVNTQ"                 %%mm6, 8(%3, %%"REG_a", 2)  \n\t"
 
1812
#else
 
1813
            "movq                   %%mm5,  (%2, %%"REG_a", 2)  \n\t"
 
1814
            "movq                   %%mm7, 8(%2, %%"REG_a", 2)  \n\t"
 
1815
            "movq                   %%mm4,  (%3, %%"REG_a", 2)  \n\t"
 
1816
            "movq                   %%mm6, 8(%3, %%"REG_a", 2)  \n\t"
 
1817
#endif
 
1818
            "add                       $8, %%"REG_a"            \n\t"
 
1819
            " js                       1b                       \n\t"
 
1820
            :: "r" (src + mmxSize  ), "r" (src + srcStride + mmxSize  ),
 
1821
            "r" (dst + mmxSize*2), "r" (dst + dstStride + mmxSize*2),
 
1822
            "g" (-mmxSize)
 
1823
            : "%"REG_a
 
1824
 
 
1825
        );
 
1826
#else
 
1827
        const x86_reg mmxSize=1;
 
1828
#endif
 
1829
        dst[0        ]= (3*src[0] +   src[srcStride])>>2;
 
1830
        dst[dstStride]= (  src[0] + 3*src[srcStride])>>2;
 
1831
 
 
1832
        for (x=mmxSize-1; x<srcWidth-1; x++) {
 
1833
            dst[2*x          +1]= (3*src[x+0] +   src[x+srcStride+1])>>2;
 
1834
            dst[2*x+dstStride+2]= (  src[x+0] + 3*src[x+srcStride+1])>>2;
 
1835
            dst[2*x+dstStride+1]= (  src[x+1] + 3*src[x+srcStride  ])>>2;
 
1836
            dst[2*x          +2]= (3*src[x+1] +   src[x+srcStride  ])>>2;
 
1837
        }
 
1838
        dst[srcWidth*2 -1            ]= (3*src[srcWidth-1] +   src[srcWidth-1 + srcStride])>>2;
 
1839
        dst[srcWidth*2 -1 + dstStride]= (  src[srcWidth-1] + 3*src[srcWidth-1 + srcStride])>>2;
 
1840
 
 
1841
        dst+=dstStride*2;
 
1842
        src+=srcStride;
 
1843
    }
 
1844
 
 
1845
    // last line
 
1846
#if 1
 
1847
    dst[0]= src[0];
 
1848
 
 
1849
    for (x=0; x<srcWidth-1; x++) {
 
1850
        dst[2*x+1]= (3*src[x] +   src[x+1])>>2;
 
1851
        dst[2*x+2]= (  src[x] + 3*src[x+1])>>2;
 
1852
    }
 
1853
    dst[2*srcWidth-1]= src[srcWidth-1];
 
1854
#else
 
1855
    for (x=0; x<srcWidth; x++) {
 
1856
        dst[2*x+0]=
 
1857
        dst[2*x+1]= src[x];
 
1858
    }
 
1859
#endif
 
1860
 
 
1861
#if HAVE_MMX
 
1862
    __asm__ volatile(EMMS"       \n\t"
 
1863
                     SFENCE"     \n\t"
 
1864
                     :::"memory");
 
1865
#endif
 
1866
}
 
1867
 
 
1868
/**
 
1869
 * Height should be a multiple of 2 and width should be a multiple of 16.
 
1870
 * (If this is a problem for anyone then tell me, and I will fix it.)
 
1871
 * Chrominance data is only taken from every second line, others are ignored.
 
1872
 * FIXME: Write HQ version.
 
1873
 */
 
1874
static inline void RENAME(uyvytoyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
 
1875
                                      long width, long height,
 
1876
                                      long lumStride, long chromStride, long srcStride)
 
1877
{
 
1878
    long y;
 
1879
    const x86_reg chromWidth= width>>1;
 
1880
    for (y=0; y<height; y+=2) {
 
1881
#if HAVE_MMX
 
1882
        __asm__ volatile(
 
1883
            "xor                 %%"REG_a", %%"REG_a"   \n\t"
 
1884
            "pcmpeqw             %%mm7, %%mm7   \n\t"
 
1885
            "psrlw                  $8, %%mm7   \n\t" // FF,00,FF,00...
 
1886
            ASMALIGN(4)
 
1887
            "1:                                 \n\t"
 
1888
            PREFETCH" 64(%0, %%"REG_a", 4)          \n\t"
 
1889
            "movq       (%0, %%"REG_a", 4), %%mm0   \n\t" // UYVY UYVY(0)
 
1890
            "movq      8(%0, %%"REG_a", 4), %%mm1   \n\t" // UYVY UYVY(4)
 
1891
            "movq                %%mm0, %%mm2   \n\t" // UYVY UYVY(0)
 
1892
            "movq                %%mm1, %%mm3   \n\t" // UYVY UYVY(4)
 
1893
            "pand                %%mm7, %%mm0   \n\t" // U0V0 U0V0(0)
 
1894
            "pand                %%mm7, %%mm1   \n\t" // U0V0 U0V0(4)
 
1895
            "psrlw                  $8, %%mm2   \n\t" // Y0Y0 Y0Y0(0)
 
1896
            "psrlw                  $8, %%mm3   \n\t" // Y0Y0 Y0Y0(4)
 
1897
            "packuswb            %%mm1, %%mm0   \n\t" // UVUV UVUV(0)
 
1898
            "packuswb            %%mm3, %%mm2   \n\t" // YYYY YYYY(0)
 
1899
 
 
1900
            MOVNTQ"              %%mm2,  (%1, %%"REG_a", 2) \n\t"
 
1901
 
 
1902
            "movq     16(%0, %%"REG_a", 4), %%mm1   \n\t" // UYVY UYVY(8)
 
1903
            "movq     24(%0, %%"REG_a", 4), %%mm2   \n\t" // UYVY UYVY(12)
 
1904
            "movq                %%mm1, %%mm3   \n\t" // UYVY UYVY(8)
 
1905
            "movq                %%mm2, %%mm4   \n\t" // UYVY UYVY(12)
 
1906
            "pand                %%mm7, %%mm1   \n\t" // U0V0 U0V0(8)
 
1907
            "pand                %%mm7, %%mm2   \n\t" // U0V0 U0V0(12)
 
1908
            "psrlw                  $8, %%mm3   \n\t" // Y0Y0 Y0Y0(8)
 
1909
            "psrlw                  $8, %%mm4   \n\t" // Y0Y0 Y0Y0(12)
 
1910
            "packuswb            %%mm2, %%mm1   \n\t" // UVUV UVUV(8)
 
1911
            "packuswb            %%mm4, %%mm3   \n\t" // YYYY YYYY(8)
 
1912
 
 
1913
            MOVNTQ"              %%mm3, 8(%1, %%"REG_a", 2) \n\t"
 
1914
 
 
1915
            "movq                %%mm0, %%mm2   \n\t" // UVUV UVUV(0)
 
1916
            "movq                %%mm1, %%mm3   \n\t" // UVUV UVUV(8)
 
1917
            "psrlw                  $8, %%mm0   \n\t" // V0V0 V0V0(0)
 
1918
            "psrlw                  $8, %%mm1   \n\t" // V0V0 V0V0(8)
 
1919
            "pand                %%mm7, %%mm2   \n\t" // U0U0 U0U0(0)
 
1920
            "pand                %%mm7, %%mm3   \n\t" // U0U0 U0U0(8)
 
1921
            "packuswb            %%mm1, %%mm0   \n\t" // VVVV VVVV(0)
 
1922
            "packuswb            %%mm3, %%mm2   \n\t" // UUUU UUUU(0)
 
1923
 
 
1924
            MOVNTQ"              %%mm0, (%3, %%"REG_a") \n\t"
 
1925
            MOVNTQ"              %%mm2, (%2, %%"REG_a") \n\t"
 
1926
 
 
1927
            "add                    $8, %%"REG_a"   \n\t"
 
1928
            "cmp                    %4, %%"REG_a"   \n\t"
 
1929
            " jb                    1b          \n\t"
 
1930
            ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
 
1931
            : "memory", "%"REG_a
 
1932
        );
 
1933
 
 
1934
        ydst += lumStride;
 
1935
        src  += srcStride;
 
1936
 
 
1937
        __asm__ volatile(
 
1938
            "xor                 %%"REG_a", %%"REG_a"   \n\t"
 
1939
            ASMALIGN(4)
 
1940
            "1:                                 \n\t"
 
1941
            PREFETCH" 64(%0, %%"REG_a", 4)          \n\t"
 
1942
            "movq       (%0, %%"REG_a", 4), %%mm0   \n\t" // YUYV YUYV(0)
 
1943
            "movq      8(%0, %%"REG_a", 4), %%mm1   \n\t" // YUYV YUYV(4)
 
1944
            "movq     16(%0, %%"REG_a", 4), %%mm2   \n\t" // YUYV YUYV(8)
 
1945
            "movq     24(%0, %%"REG_a", 4), %%mm3   \n\t" // YUYV YUYV(12)
 
1946
            "psrlw                  $8, %%mm0   \n\t" // Y0Y0 Y0Y0(0)
 
1947
            "psrlw                  $8, %%mm1   \n\t" // Y0Y0 Y0Y0(4)
 
1948
            "psrlw                  $8, %%mm2   \n\t" // Y0Y0 Y0Y0(8)
 
1949
            "psrlw                  $8, %%mm3   \n\t" // Y0Y0 Y0Y0(12)
 
1950
            "packuswb            %%mm1, %%mm0   \n\t" // YYYY YYYY(0)
 
1951
            "packuswb            %%mm3, %%mm2   \n\t" // YYYY YYYY(8)
 
1952
 
 
1953
            MOVNTQ"              %%mm0,  (%1, %%"REG_a", 2) \n\t"
 
1954
            MOVNTQ"              %%mm2, 8(%1, %%"REG_a", 2) \n\t"
 
1955
 
 
1956
            "add                    $8, %%"REG_a"   \n\t"
 
1957
            "cmp                    %4, %%"REG_a"   \n\t"
 
1958
            " jb                    1b          \n\t"
 
1959
 
 
1960
            ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "g" (chromWidth)
 
1961
            : "memory", "%"REG_a
 
1962
        );
 
1963
#else
 
1964
        long i;
 
1965
        for (i=0; i<chromWidth; i++) {
 
1966
            udst[i]     = src[4*i+0];
 
1967
            ydst[2*i+0] = src[4*i+1];
 
1968
            vdst[i]     = src[4*i+2];
 
1969
            ydst[2*i+1] = src[4*i+3];
 
1970
        }
 
1971
        ydst += lumStride;
 
1972
        src  += srcStride;
 
1973
 
 
1974
        for (i=0; i<chromWidth; i++) {
 
1975
            ydst[2*i+0] = src[4*i+1];
 
1976
            ydst[2*i+1] = src[4*i+3];
 
1977
        }
 
1978
#endif
 
1979
        udst += chromStride;
 
1980
        vdst += chromStride;
 
1981
        ydst += lumStride;
 
1982
        src  += srcStride;
 
1983
    }
 
1984
#if HAVE_MMX
 
1985
    __asm__ volatile(EMMS"       \n\t"
 
1986
                     SFENCE"     \n\t"
 
1987
                     :::"memory");
 
1988
#endif
 
1989
}
 
1990
 
 
1991
/**
 
1992
 * Height should be a multiple of 2 and width should be a multiple of 2.
 
1993
 * (If this is a problem for anyone then tell me, and I will fix it.)
 
1994
 * Chrominance data is only taken from every second line,
 
1995
 * others are ignored in the C version.
 
1996
 * FIXME: Write HQ version.
 
1997
 */
 
1998
static inline void RENAME(rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
 
1999
                                       long width, long height,
 
2000
                                       long lumStride, long chromStride, long srcStride)
 
2001
{
 
2002
    long y;
 
2003
    const x86_reg chromWidth= width>>1;
 
2004
#if HAVE_MMX
 
2005
    for (y=0; y<height-2; y+=2) {
 
2006
        long i;
 
2007
        for (i=0; i<2; i++) {
 
2008
            __asm__ volatile(
 
2009
                "mov                        %2, %%"REG_a"   \n\t"
 
2010
                "movq  "MANGLE(ff_bgr2YCoeff)", %%mm6       \n\t"
 
2011
                "movq       "MANGLE(ff_w1111)", %%mm5       \n\t"
 
2012
                "pxor                    %%mm7, %%mm7       \n\t"
 
2013
                "lea (%%"REG_a", %%"REG_a", 2), %%"REG_d"   \n\t"
 
2014
                ASMALIGN(4)
 
2015
                "1:                                         \n\t"
 
2016
                PREFETCH"    64(%0, %%"REG_d")              \n\t"
 
2017
                "movd          (%0, %%"REG_d"), %%mm0       \n\t"
 
2018
                "movd         3(%0, %%"REG_d"), %%mm1       \n\t"
 
2019
                "punpcklbw               %%mm7, %%mm0       \n\t"
 
2020
                "punpcklbw               %%mm7, %%mm1       \n\t"
 
2021
                "movd         6(%0, %%"REG_d"), %%mm2       \n\t"
 
2022
                "movd         9(%0, %%"REG_d"), %%mm3       \n\t"
 
2023
                "punpcklbw               %%mm7, %%mm2       \n\t"
 
2024
                "punpcklbw               %%mm7, %%mm3       \n\t"
 
2025
                "pmaddwd                 %%mm6, %%mm0       \n\t"
 
2026
                "pmaddwd                 %%mm6, %%mm1       \n\t"
 
2027
                "pmaddwd                 %%mm6, %%mm2       \n\t"
 
2028
                "pmaddwd                 %%mm6, %%mm3       \n\t"
 
2029
#ifndef FAST_BGR2YV12
 
2030
                "psrad                      $8, %%mm0       \n\t"
 
2031
                "psrad                      $8, %%mm1       \n\t"
 
2032
                "psrad                      $8, %%mm2       \n\t"
 
2033
                "psrad                      $8, %%mm3       \n\t"
 
2034
#endif
 
2035
                "packssdw                %%mm1, %%mm0       \n\t"
 
2036
                "packssdw                %%mm3, %%mm2       \n\t"
 
2037
                "pmaddwd                 %%mm5, %%mm0       \n\t"
 
2038
                "pmaddwd                 %%mm5, %%mm2       \n\t"
 
2039
                "packssdw                %%mm2, %%mm0       \n\t"
 
2040
                "psraw                      $7, %%mm0       \n\t"
 
2041
 
 
2042
                "movd        12(%0, %%"REG_d"), %%mm4       \n\t"
 
2043
                "movd        15(%0, %%"REG_d"), %%mm1       \n\t"
 
2044
                "punpcklbw               %%mm7, %%mm4       \n\t"
 
2045
                "punpcklbw               %%mm7, %%mm1       \n\t"
 
2046
                "movd        18(%0, %%"REG_d"), %%mm2       \n\t"
 
2047
                "movd        21(%0, %%"REG_d"), %%mm3       \n\t"
 
2048
                "punpcklbw               %%mm7, %%mm2       \n\t"
 
2049
                "punpcklbw               %%mm7, %%mm3       \n\t"
 
2050
                "pmaddwd                 %%mm6, %%mm4       \n\t"
 
2051
                "pmaddwd                 %%mm6, %%mm1       \n\t"
 
2052
                "pmaddwd                 %%mm6, %%mm2       \n\t"
 
2053
                "pmaddwd                 %%mm6, %%mm3       \n\t"
 
2054
#ifndef FAST_BGR2YV12
 
2055
                "psrad                      $8, %%mm4       \n\t"
 
2056
                "psrad                      $8, %%mm1       \n\t"
 
2057
                "psrad                      $8, %%mm2       \n\t"
 
2058
                "psrad                      $8, %%mm3       \n\t"
 
2059
#endif
 
2060
                "packssdw                %%mm1, %%mm4       \n\t"
 
2061
                "packssdw                %%mm3, %%mm2       \n\t"
 
2062
                "pmaddwd                 %%mm5, %%mm4       \n\t"
 
2063
                "pmaddwd                 %%mm5, %%mm2       \n\t"
 
2064
                "add                       $24, %%"REG_d"   \n\t"
 
2065
                "packssdw                %%mm2, %%mm4       \n\t"
 
2066
                "psraw                      $7, %%mm4       \n\t"
 
2067
 
 
2068
                "packuswb                %%mm4, %%mm0       \n\t"
 
2069
                "paddusb "MANGLE(ff_bgr2YOffset)", %%mm0    \n\t"
 
2070
 
 
2071
                MOVNTQ"                  %%mm0, (%1, %%"REG_a") \n\t"
 
2072
                "add                        $8,      %%"REG_a"  \n\t"
 
2073
                " js                        1b                  \n\t"
 
2074
                : : "r" (src+width*3), "r" (ydst+width), "g" ((x86_reg)-width)
 
2075
                : "%"REG_a, "%"REG_d
 
2076
            );
 
2077
            ydst += lumStride;
 
2078
            src  += srcStride;
 
2079
        }
 
2080
        src -= srcStride*2;
 
2081
        __asm__ volatile(
 
2082
            "mov                        %4, %%"REG_a"   \n\t"
 
2083
            "movq       "MANGLE(ff_w1111)", %%mm5       \n\t"
 
2084
            "movq  "MANGLE(ff_bgr2UCoeff)", %%mm6       \n\t"
 
2085
            "pxor                    %%mm7, %%mm7       \n\t"
 
2086
            "lea (%%"REG_a", %%"REG_a", 2), %%"REG_d"   \n\t"
 
2087
            "add                 %%"REG_d", %%"REG_d"   \n\t"
 
2088
            ASMALIGN(4)
 
2089
            "1:                                         \n\t"
 
2090
            PREFETCH"    64(%0, %%"REG_d")              \n\t"
 
2091
            PREFETCH"    64(%1, %%"REG_d")              \n\t"
 
2092
#if HAVE_MMX2 || HAVE_AMD3DNOW
 
2093
            "movq          (%0, %%"REG_d"), %%mm0       \n\t"
 
2094
            "movq          (%1, %%"REG_d"), %%mm1       \n\t"
 
2095
            "movq         6(%0, %%"REG_d"), %%mm2       \n\t"
 
2096
            "movq         6(%1, %%"REG_d"), %%mm3       \n\t"
 
2097
            PAVGB"                   %%mm1, %%mm0       \n\t"
 
2098
            PAVGB"                   %%mm3, %%mm2       \n\t"
 
2099
            "movq                    %%mm0, %%mm1       \n\t"
 
2100
            "movq                    %%mm2, %%mm3       \n\t"
 
2101
            "psrlq                     $24, %%mm0       \n\t"
 
2102
            "psrlq                     $24, %%mm2       \n\t"
 
2103
            PAVGB"                   %%mm1, %%mm0       \n\t"
 
2104
            PAVGB"                   %%mm3, %%mm2       \n\t"
 
2105
            "punpcklbw               %%mm7, %%mm0       \n\t"
 
2106
            "punpcklbw               %%mm7, %%mm2       \n\t"
 
2107
#else
 
2108
            "movd          (%0, %%"REG_d"), %%mm0       \n\t"
 
2109
            "movd          (%1, %%"REG_d"), %%mm1       \n\t"
 
2110
            "movd         3(%0, %%"REG_d"), %%mm2       \n\t"
 
2111
            "movd         3(%1, %%"REG_d"), %%mm3       \n\t"
 
2112
            "punpcklbw               %%mm7, %%mm0       \n\t"
 
2113
            "punpcklbw               %%mm7, %%mm1       \n\t"
 
2114
            "punpcklbw               %%mm7, %%mm2       \n\t"
 
2115
            "punpcklbw               %%mm7, %%mm3       \n\t"
 
2116
            "paddw                   %%mm1, %%mm0       \n\t"
 
2117
            "paddw                   %%mm3, %%mm2       \n\t"
 
2118
            "paddw                   %%mm2, %%mm0       \n\t"
 
2119
            "movd         6(%0, %%"REG_d"), %%mm4       \n\t"
 
2120
            "movd         6(%1, %%"REG_d"), %%mm1       \n\t"
 
2121
            "movd         9(%0, %%"REG_d"), %%mm2       \n\t"
 
2122
            "movd         9(%1, %%"REG_d"), %%mm3       \n\t"
 
2123
            "punpcklbw               %%mm7, %%mm4       \n\t"
 
2124
            "punpcklbw               %%mm7, %%mm1       \n\t"
 
2125
            "punpcklbw               %%mm7, %%mm2       \n\t"
 
2126
            "punpcklbw               %%mm7, %%mm3       \n\t"
 
2127
            "paddw                   %%mm1, %%mm4       \n\t"
 
2128
            "paddw                   %%mm3, %%mm2       \n\t"
 
2129
            "paddw                   %%mm4, %%mm2       \n\t"
 
2130
            "psrlw                      $2, %%mm0       \n\t"
 
2131
            "psrlw                      $2, %%mm2       \n\t"
 
2132
#endif
 
2133
            "movq  "MANGLE(ff_bgr2VCoeff)", %%mm1       \n\t"
 
2134
            "movq  "MANGLE(ff_bgr2VCoeff)", %%mm3       \n\t"
 
2135
 
 
2136
            "pmaddwd                 %%mm0, %%mm1       \n\t"
 
2137
            "pmaddwd                 %%mm2, %%mm3       \n\t"
 
2138
            "pmaddwd                 %%mm6, %%mm0       \n\t"
 
2139
            "pmaddwd                 %%mm6, %%mm2       \n\t"
 
2140
#ifndef FAST_BGR2YV12
 
2141
            "psrad                      $8, %%mm0       \n\t"
 
2142
            "psrad                      $8, %%mm1       \n\t"
 
2143
            "psrad                      $8, %%mm2       \n\t"
 
2144
            "psrad                      $8, %%mm3       \n\t"
 
2145
#endif
 
2146
            "packssdw                %%mm2, %%mm0       \n\t"
 
2147
            "packssdw                %%mm3, %%mm1       \n\t"
 
2148
            "pmaddwd                 %%mm5, %%mm0       \n\t"
 
2149
            "pmaddwd                 %%mm5, %%mm1       \n\t"
 
2150
            "packssdw                %%mm1, %%mm0       \n\t" // V1 V0 U1 U0
 
2151
            "psraw                      $7, %%mm0       \n\t"
 
2152
 
 
2153
#if HAVE_MMX2 || HAVE_AMD3DNOW
 
2154
            "movq        12(%0, %%"REG_d"), %%mm4       \n\t"
 
2155
            "movq        12(%1, %%"REG_d"), %%mm1       \n\t"
 
2156
            "movq        18(%0, %%"REG_d"), %%mm2       \n\t"
 
2157
            "movq        18(%1, %%"REG_d"), %%mm3       \n\t"
 
2158
            PAVGB"                   %%mm1, %%mm4       \n\t"
 
2159
            PAVGB"                   %%mm3, %%mm2       \n\t"
 
2160
            "movq                    %%mm4, %%mm1       \n\t"
 
2161
            "movq                    %%mm2, %%mm3       \n\t"
 
2162
            "psrlq                     $24, %%mm4       \n\t"
 
2163
            "psrlq                     $24, %%mm2       \n\t"
 
2164
            PAVGB"                   %%mm1, %%mm4       \n\t"
 
2165
            PAVGB"                   %%mm3, %%mm2       \n\t"
 
2166
            "punpcklbw               %%mm7, %%mm4       \n\t"
 
2167
            "punpcklbw               %%mm7, %%mm2       \n\t"
 
2168
#else
 
2169
            "movd        12(%0, %%"REG_d"), %%mm4       \n\t"
 
2170
            "movd        12(%1, %%"REG_d"), %%mm1       \n\t"
 
2171
            "movd        15(%0, %%"REG_d"), %%mm2       \n\t"
 
2172
            "movd        15(%1, %%"REG_d"), %%mm3       \n\t"
 
2173
            "punpcklbw               %%mm7, %%mm4       \n\t"
 
2174
            "punpcklbw               %%mm7, %%mm1       \n\t"
 
2175
            "punpcklbw               %%mm7, %%mm2       \n\t"
 
2176
            "punpcklbw               %%mm7, %%mm3       \n\t"
 
2177
            "paddw                   %%mm1, %%mm4       \n\t"
 
2178
            "paddw                   %%mm3, %%mm2       \n\t"
 
2179
            "paddw                   %%mm2, %%mm4       \n\t"
 
2180
            "movd        18(%0, %%"REG_d"), %%mm5       \n\t"
 
2181
            "movd        18(%1, %%"REG_d"), %%mm1       \n\t"
 
2182
            "movd        21(%0, %%"REG_d"), %%mm2       \n\t"
 
2183
            "movd        21(%1, %%"REG_d"), %%mm3       \n\t"
 
2184
            "punpcklbw               %%mm7, %%mm5       \n\t"
 
2185
            "punpcklbw               %%mm7, %%mm1       \n\t"
 
2186
            "punpcklbw               %%mm7, %%mm2       \n\t"
 
2187
            "punpcklbw               %%mm7, %%mm3       \n\t"
 
2188
            "paddw                   %%mm1, %%mm5       \n\t"
 
2189
            "paddw                   %%mm3, %%mm2       \n\t"
 
2190
            "paddw                   %%mm5, %%mm2       \n\t"
 
2191
            "movq       "MANGLE(ff_w1111)", %%mm5       \n\t"
 
2192
            "psrlw                      $2, %%mm4       \n\t"
 
2193
            "psrlw                      $2, %%mm2       \n\t"
 
2194
#endif
 
2195
            "movq  "MANGLE(ff_bgr2VCoeff)", %%mm1       \n\t"
 
2196
            "movq  "MANGLE(ff_bgr2VCoeff)", %%mm3       \n\t"
 
2197
 
 
2198
            "pmaddwd                 %%mm4, %%mm1       \n\t"
 
2199
            "pmaddwd                 %%mm2, %%mm3       \n\t"
 
2200
            "pmaddwd                 %%mm6, %%mm4       \n\t"
 
2201
            "pmaddwd                 %%mm6, %%mm2       \n\t"
 
2202
#ifndef FAST_BGR2YV12
 
2203
            "psrad                      $8, %%mm4       \n\t"
 
2204
            "psrad                      $8, %%mm1       \n\t"
 
2205
            "psrad                      $8, %%mm2       \n\t"
 
2206
            "psrad                      $8, %%mm3       \n\t"
 
2207
#endif
 
2208
            "packssdw                %%mm2, %%mm4       \n\t"
 
2209
            "packssdw                %%mm3, %%mm1       \n\t"
 
2210
            "pmaddwd                 %%mm5, %%mm4       \n\t"
 
2211
            "pmaddwd                 %%mm5, %%mm1       \n\t"
 
2212
            "add                       $24, %%"REG_d"   \n\t"
 
2213
            "packssdw                %%mm1, %%mm4       \n\t" // V3 V2 U3 U2
 
2214
            "psraw                      $7, %%mm4       \n\t"
 
2215
 
 
2216
            "movq                    %%mm0, %%mm1           \n\t"
 
2217
            "punpckldq               %%mm4, %%mm0           \n\t"
 
2218
            "punpckhdq               %%mm4, %%mm1           \n\t"
 
2219
            "packsswb                %%mm1, %%mm0           \n\t"
 
2220
            "paddb "MANGLE(ff_bgr2UVOffset)", %%mm0         \n\t"
 
2221
            "movd                    %%mm0, (%2, %%"REG_a") \n\t"
 
2222
            "punpckhdq               %%mm0, %%mm0           \n\t"
 
2223
            "movd                    %%mm0, (%3, %%"REG_a") \n\t"
 
2224
            "add                        $4, %%"REG_a"       \n\t"
 
2225
            " js                        1b                  \n\t"
 
2226
            : : "r" (src+chromWidth*6), "r" (src+srcStride+chromWidth*6), "r" (udst+chromWidth), "r" (vdst+chromWidth), "g" (-chromWidth)
 
2227
            : "%"REG_a, "%"REG_d
 
2228
        );
 
2229
 
 
2230
        udst += chromStride;
 
2231
        vdst += chromStride;
 
2232
        src  += srcStride*2;
 
2233
    }
 
2234
 
 
2235
    __asm__ volatile(EMMS"       \n\t"
 
2236
                     SFENCE"     \n\t"
 
2237
                     :::"memory");
 
2238
#else
 
2239
    y=0;
 
2240
#endif
 
2241
    for (; y<height; y+=2) {
 
2242
        long i;
 
2243
        for (i=0; i<chromWidth; i++) {
 
2244
            unsigned int b = src[6*i+0];
 
2245
            unsigned int g = src[6*i+1];
 
2246
            unsigned int r = src[6*i+2];
 
2247
 
 
2248
            unsigned int Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
 
2249
            unsigned int V  =  ((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128;
 
2250
            unsigned int U  =  ((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128;
 
2251
 
 
2252
            udst[i]     = U;
 
2253
            vdst[i]     = V;
 
2254
            ydst[2*i]   = Y;
 
2255
 
 
2256
            b = src[6*i+3];
 
2257
            g = src[6*i+4];
 
2258
            r = src[6*i+5];
 
2259
 
 
2260
            Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
 
2261
            ydst[2*i+1]     = Y;
 
2262
        }
 
2263
        ydst += lumStride;
 
2264
        src  += srcStride;
 
2265
 
 
2266
        for (i=0; i<chromWidth; i++) {
 
2267
            unsigned int b = src[6*i+0];
 
2268
            unsigned int g = src[6*i+1];
 
2269
            unsigned int r = src[6*i+2];
 
2270
 
 
2271
            unsigned int Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
 
2272
 
 
2273
            ydst[2*i]     = Y;
 
2274
 
 
2275
            b = src[6*i+3];
 
2276
            g = src[6*i+4];
 
2277
            r = src[6*i+5];
 
2278
 
 
2279
            Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
 
2280
            ydst[2*i+1]     = Y;
 
2281
        }
 
2282
        udst += chromStride;
 
2283
        vdst += chromStride;
 
2284
        ydst += lumStride;
 
2285
        src  += srcStride;
 
2286
    }
 
2287
}
 
2288
 
 
2289
static void RENAME(interleaveBytes)(const uint8_t *src1, const uint8_t *src2, uint8_t *dest,
 
2290
                             long width, long height, long src1Stride,
 
2291
                             long src2Stride, long dstStride)
 
2292
{
 
2293
    long h;
 
2294
 
 
2295
    for (h=0; h < height; h++) {
 
2296
        long w;
 
2297
 
 
2298
#if HAVE_MMX
 
2299
#if HAVE_SSE2
 
2300
        __asm__(
 
2301
            "xor              %%"REG_a", %%"REG_a"  \n\t"
 
2302
            "1:                                     \n\t"
 
2303
            PREFETCH" 64(%1, %%"REG_a")             \n\t"
 
2304
            PREFETCH" 64(%2, %%"REG_a")             \n\t"
 
2305
            "movdqa     (%1, %%"REG_a"), %%xmm0     \n\t"
 
2306
            "movdqa     (%1, %%"REG_a"), %%xmm1     \n\t"
 
2307
            "movdqa     (%2, %%"REG_a"), %%xmm2     \n\t"
 
2308
            "punpcklbw           %%xmm2, %%xmm0     \n\t"
 
2309
            "punpckhbw           %%xmm2, %%xmm1     \n\t"
 
2310
            "movntdq             %%xmm0,   (%0, %%"REG_a", 2)   \n\t"
 
2311
            "movntdq             %%xmm1, 16(%0, %%"REG_a", 2)   \n\t"
 
2312
            "add                    $16, %%"REG_a"  \n\t"
 
2313
            "cmp                     %3, %%"REG_a"  \n\t"
 
2314
            " jb                     1b             \n\t"
 
2315
            ::"r"(dest), "r"(src1), "r"(src2), "r" ((x86_reg)width-15)
 
2316
            : "memory", "%"REG_a""
 
2317
        );
 
2318
#else
 
2319
        __asm__(
 
2320
            "xor %%"REG_a", %%"REG_a"               \n\t"
 
2321
            "1:                                     \n\t"
 
2322
            PREFETCH" 64(%1, %%"REG_a")             \n\t"
 
2323
            PREFETCH" 64(%2, %%"REG_a")             \n\t"
 
2324
            "movq       (%1, %%"REG_a"), %%mm0      \n\t"
 
2325
            "movq      8(%1, %%"REG_a"), %%mm2      \n\t"
 
2326
            "movq                 %%mm0, %%mm1      \n\t"
 
2327
            "movq                 %%mm2, %%mm3      \n\t"
 
2328
            "movq       (%2, %%"REG_a"), %%mm4      \n\t"
 
2329
            "movq      8(%2, %%"REG_a"), %%mm5      \n\t"
 
2330
            "punpcklbw            %%mm4, %%mm0      \n\t"
 
2331
            "punpckhbw            %%mm4, %%mm1      \n\t"
 
2332
            "punpcklbw            %%mm5, %%mm2      \n\t"
 
2333
            "punpckhbw            %%mm5, %%mm3      \n\t"
 
2334
            MOVNTQ"               %%mm0,   (%0, %%"REG_a", 2)   \n\t"
 
2335
            MOVNTQ"               %%mm1,  8(%0, %%"REG_a", 2)   \n\t"
 
2336
            MOVNTQ"               %%mm2, 16(%0, %%"REG_a", 2)   \n\t"
 
2337
            MOVNTQ"               %%mm3, 24(%0, %%"REG_a", 2)   \n\t"
 
2338
            "add                    $16, %%"REG_a"  \n\t"
 
2339
            "cmp                     %3, %%"REG_a"  \n\t"
 
2340
            " jb                     1b             \n\t"
 
2341
            ::"r"(dest), "r"(src1), "r"(src2), "r" ((x86_reg)width-15)
 
2342
            : "memory", "%"REG_a
 
2343
        );
 
2344
#endif
 
2345
        for (w= (width&(~15)); w < width; w++) {
 
2346
            dest[2*w+0] = src1[w];
 
2347
            dest[2*w+1] = src2[w];
 
2348
        }
 
2349
#else
 
2350
        for (w=0; w < width; w++) {
 
2351
            dest[2*w+0] = src1[w];
 
2352
            dest[2*w+1] = src2[w];
 
2353
        }
 
2354
#endif
 
2355
        dest += dstStride;
 
2356
                src1 += src1Stride;
 
2357
                src2 += src2Stride;
 
2358
    }
 
2359
#if HAVE_MMX
 
2360
    __asm__(
 
2361
            EMMS"       \n\t"
 
2362
            SFENCE"     \n\t"
 
2363
            ::: "memory"
 
2364
            );
 
2365
#endif
 
2366
}
 
2367
 
 
2368
static inline void RENAME(vu9_to_vu12)(const uint8_t *src1, const uint8_t *src2,
 
2369
                                       uint8_t *dst1, uint8_t *dst2,
 
2370
                                       long width, long height,
 
2371
                                       long srcStride1, long srcStride2,
 
2372
                                       long dstStride1, long dstStride2)
 
2373
{
 
2374
    x86_reg y;
 
2375
    long x,w,h;
 
2376
    w=width/2; h=height/2;
 
2377
#if HAVE_MMX
 
2378
    __asm__ volatile(
 
2379
        PREFETCH" %0    \n\t"
 
2380
        PREFETCH" %1    \n\t"
 
2381
        ::"m"(*(src1+srcStride1)),"m"(*(src2+srcStride2)):"memory");
 
2382
#endif
 
2383
    for (y=0;y<h;y++) {
 
2384
        const uint8_t* s1=src1+srcStride1*(y>>1);
 
2385
        uint8_t* d=dst1+dstStride1*y;
 
2386
        x=0;
 
2387
#if HAVE_MMX
 
2388
        for (;x<w-31;x+=32) {
 
2389
            __asm__ volatile(
 
2390
                PREFETCH"   32%1        \n\t"
 
2391
                "movq         %1, %%mm0 \n\t"
 
2392
                "movq        8%1, %%mm2 \n\t"
 
2393
                "movq       16%1, %%mm4 \n\t"
 
2394
                "movq       24%1, %%mm6 \n\t"
 
2395
                "movq      %%mm0, %%mm1 \n\t"
 
2396
                "movq      %%mm2, %%mm3 \n\t"
 
2397
                "movq      %%mm4, %%mm5 \n\t"
 
2398
                "movq      %%mm6, %%mm7 \n\t"
 
2399
                "punpcklbw %%mm0, %%mm0 \n\t"
 
2400
                "punpckhbw %%mm1, %%mm1 \n\t"
 
2401
                "punpcklbw %%mm2, %%mm2 \n\t"
 
2402
                "punpckhbw %%mm3, %%mm3 \n\t"
 
2403
                "punpcklbw %%mm4, %%mm4 \n\t"
 
2404
                "punpckhbw %%mm5, %%mm5 \n\t"
 
2405
                "punpcklbw %%mm6, %%mm6 \n\t"
 
2406
                "punpckhbw %%mm7, %%mm7 \n\t"
 
2407
                MOVNTQ"    %%mm0,   %0  \n\t"
 
2408
                MOVNTQ"    %%mm1,  8%0  \n\t"
 
2409
                MOVNTQ"    %%mm2, 16%0  \n\t"
 
2410
                MOVNTQ"    %%mm3, 24%0  \n\t"
 
2411
                MOVNTQ"    %%mm4, 32%0  \n\t"
 
2412
                MOVNTQ"    %%mm5, 40%0  \n\t"
 
2413
                MOVNTQ"    %%mm6, 48%0  \n\t"
 
2414
                MOVNTQ"    %%mm7, 56%0"
 
2415
                :"=m"(d[2*x])
 
2416
                :"m"(s1[x])
 
2417
                :"memory");
 
2418
        }
 
2419
#endif
 
2420
        for (;x<w;x++) d[2*x]=d[2*x+1]=s1[x];
 
2421
    }
 
2422
    for (y=0;y<h;y++) {
 
2423
        const uint8_t* s2=src2+srcStride2*(y>>1);
 
2424
        uint8_t* d=dst2+dstStride2*y;
 
2425
        x=0;
 
2426
#if HAVE_MMX
 
2427
        for (;x<w-31;x+=32) {
 
2428
            __asm__ volatile(
 
2429
                PREFETCH"   32%1        \n\t"
 
2430
                "movq         %1, %%mm0 \n\t"
 
2431
                "movq        8%1, %%mm2 \n\t"
 
2432
                "movq       16%1, %%mm4 \n\t"
 
2433
                "movq       24%1, %%mm6 \n\t"
 
2434
                "movq      %%mm0, %%mm1 \n\t"
 
2435
                "movq      %%mm2, %%mm3 \n\t"
 
2436
                "movq      %%mm4, %%mm5 \n\t"
 
2437
                "movq      %%mm6, %%mm7 \n\t"
 
2438
                "punpcklbw %%mm0, %%mm0 \n\t"
 
2439
                "punpckhbw %%mm1, %%mm1 \n\t"
 
2440
                "punpcklbw %%mm2, %%mm2 \n\t"
 
2441
                "punpckhbw %%mm3, %%mm3 \n\t"
 
2442
                "punpcklbw %%mm4, %%mm4 \n\t"
 
2443
                "punpckhbw %%mm5, %%mm5 \n\t"
 
2444
                "punpcklbw %%mm6, %%mm6 \n\t"
 
2445
                "punpckhbw %%mm7, %%mm7 \n\t"
 
2446
                MOVNTQ"    %%mm0,   %0  \n\t"
 
2447
                MOVNTQ"    %%mm1,  8%0  \n\t"
 
2448
                MOVNTQ"    %%mm2, 16%0  \n\t"
 
2449
                MOVNTQ"    %%mm3, 24%0  \n\t"
 
2450
                MOVNTQ"    %%mm4, 32%0  \n\t"
 
2451
                MOVNTQ"    %%mm5, 40%0  \n\t"
 
2452
                MOVNTQ"    %%mm6, 48%0  \n\t"
 
2453
                MOVNTQ"    %%mm7, 56%0"
 
2454
                :"=m"(d[2*x])
 
2455
                :"m"(s2[x])
 
2456
                :"memory");
 
2457
        }
 
2458
#endif
 
2459
        for (;x<w;x++) d[2*x]=d[2*x+1]=s2[x];
 
2460
    }
 
2461
#if HAVE_MMX
 
2462
    __asm__(
 
2463
            EMMS"       \n\t"
 
2464
            SFENCE"     \n\t"
 
2465
            ::: "memory"
 
2466
        );
 
2467
#endif
 
2468
}
 
2469
 
 
2470
static inline void RENAME(yvu9_to_yuy2)(const uint8_t *src1, const uint8_t *src2, const uint8_t *src3,
 
2471
                                        uint8_t *dst,
 
2472
                                        long width, long height,
 
2473
                                        long srcStride1, long srcStride2,
 
2474
                                        long srcStride3, long dstStride)
 
2475
{
 
2476
    x86_reg x;
 
2477
    long y,w,h;
 
2478
    w=width/2; h=height;
 
2479
    for (y=0;y<h;y++) {
 
2480
        const uint8_t* yp=src1+srcStride1*y;
 
2481
        const uint8_t* up=src2+srcStride2*(y>>2);
 
2482
        const uint8_t* vp=src3+srcStride3*(y>>2);
 
2483
        uint8_t* d=dst+dstStride*y;
 
2484
        x=0;
 
2485
#if HAVE_MMX
 
2486
        for (;x<w-7;x+=8) {
 
2487
            __asm__ volatile(
 
2488
                PREFETCH"   32(%1, %0)          \n\t"
 
2489
                PREFETCH"   32(%2, %0)          \n\t"
 
2490
                PREFETCH"   32(%3, %0)          \n\t"
 
2491
                "movq      (%1, %0, 4), %%mm0   \n\t" /* Y0Y1Y2Y3Y4Y5Y6Y7 */
 
2492
                "movq         (%2, %0), %%mm1   \n\t" /* U0U1U2U3U4U5U6U7 */
 
2493
                "movq         (%3, %0), %%mm2   \n\t" /* V0V1V2V3V4V5V6V7 */
 
2494
                "movq            %%mm0, %%mm3   \n\t" /* Y0Y1Y2Y3Y4Y5Y6Y7 */
 
2495
                "movq            %%mm1, %%mm4   \n\t" /* U0U1U2U3U4U5U6U7 */
 
2496
                "movq            %%mm2, %%mm5   \n\t" /* V0V1V2V3V4V5V6V7 */
 
2497
                "punpcklbw       %%mm1, %%mm1   \n\t" /* U0U0 U1U1 U2U2 U3U3 */
 
2498
                "punpcklbw       %%mm2, %%mm2   \n\t" /* V0V0 V1V1 V2V2 V3V3 */
 
2499
                "punpckhbw       %%mm4, %%mm4   \n\t" /* U4U4 U5U5 U6U6 U7U7 */
 
2500
                "punpckhbw       %%mm5, %%mm5   \n\t" /* V4V4 V5V5 V6V6 V7V7 */
 
2501
 
 
2502
                "movq            %%mm1, %%mm6   \n\t"
 
2503
                "punpcklbw       %%mm2, %%mm1   \n\t" /* U0V0 U0V0 U1V1 U1V1*/
 
2504
                "punpcklbw       %%mm1, %%mm0   \n\t" /* Y0U0 Y1V0 Y2U0 Y3V0*/
 
2505
                "punpckhbw       %%mm1, %%mm3   \n\t" /* Y4U1 Y5V1 Y6U1 Y7V1*/
 
2506
                MOVNTQ"          %%mm0,  (%4, %0, 8)    \n\t"
 
2507
                MOVNTQ"          %%mm3, 8(%4, %0, 8)    \n\t"
 
2508
 
 
2509
                "punpckhbw       %%mm2, %%mm6   \n\t" /* U2V2 U2V2 U3V3 U3V3*/
 
2510
                "movq     8(%1, %0, 4), %%mm0   \n\t"
 
2511
                "movq            %%mm0, %%mm3   \n\t"
 
2512
                "punpcklbw       %%mm6, %%mm0   \n\t" /* Y U2 Y V2 Y U2 Y V2*/
 
2513
                "punpckhbw       %%mm6, %%mm3   \n\t" /* Y U3 Y V3 Y U3 Y V3*/
 
2514
                MOVNTQ"          %%mm0, 16(%4, %0, 8)   \n\t"
 
2515
                MOVNTQ"          %%mm3, 24(%4, %0, 8)   \n\t"
 
2516
 
 
2517
                "movq            %%mm4, %%mm6   \n\t"
 
2518
                "movq    16(%1, %0, 4), %%mm0   \n\t"
 
2519
                "movq            %%mm0, %%mm3   \n\t"
 
2520
                "punpcklbw       %%mm5, %%mm4   \n\t"
 
2521
                "punpcklbw       %%mm4, %%mm0   \n\t" /* Y U4 Y V4 Y U4 Y V4*/
 
2522
                "punpckhbw       %%mm4, %%mm3   \n\t" /* Y U5 Y V5 Y U5 Y V5*/
 
2523
                MOVNTQ"          %%mm0, 32(%4, %0, 8)   \n\t"
 
2524
                MOVNTQ"          %%mm3, 40(%4, %0, 8)   \n\t"
 
2525
 
 
2526
                "punpckhbw       %%mm5, %%mm6   \n\t"
 
2527
                "movq    24(%1, %0, 4), %%mm0   \n\t"
 
2528
                "movq            %%mm0, %%mm3   \n\t"
 
2529
                "punpcklbw       %%mm6, %%mm0   \n\t" /* Y U6 Y V6 Y U6 Y V6*/
 
2530
                "punpckhbw       %%mm6, %%mm3   \n\t" /* Y U7 Y V7 Y U7 Y V7*/
 
2531
                MOVNTQ"          %%mm0, 48(%4, %0, 8)   \n\t"
 
2532
                MOVNTQ"          %%mm3, 56(%4, %0, 8)   \n\t"
 
2533
 
 
2534
                : "+r" (x)
 
2535
                : "r"(yp), "r" (up), "r"(vp), "r"(d)
 
2536
                :"memory");
 
2537
        }
 
2538
#endif
 
2539
        for (; x<w; x++) {
 
2540
            const long x2 = x<<2;
 
2541
            d[8*x+0] = yp[x2];
 
2542
            d[8*x+1] = up[x];
 
2543
            d[8*x+2] = yp[x2+1];
 
2544
            d[8*x+3] = vp[x];
 
2545
            d[8*x+4] = yp[x2+2];
 
2546
            d[8*x+5] = up[x];
 
2547
            d[8*x+6] = yp[x2+3];
 
2548
            d[8*x+7] = vp[x];
 
2549
        }
 
2550
    }
 
2551
#if HAVE_MMX
 
2552
    __asm__(
 
2553
            EMMS"       \n\t"
 
2554
            SFENCE"     \n\t"
 
2555
            ::: "memory"
 
2556
        );
 
2557
#endif
 
2558
}
 
2559
 
 
2560
static void RENAME(extract_even)(const uint8_t *src, uint8_t *dst, x86_reg count)
 
2561
{
 
2562
    dst +=   count;
 
2563
    src += 2*count;
 
2564
    count= - count;
 
2565
 
 
2566
#if HAVE_MMX
 
2567
    if(count <= -16) {
 
2568
        count += 15;
 
2569
        __asm__ volatile(
 
2570
            "pcmpeqw       %%mm7, %%mm7        \n\t"
 
2571
            "psrlw            $8, %%mm7        \n\t"
 
2572
            "1:                                \n\t"
 
2573
            "movq -30(%1, %0, 2), %%mm0        \n\t"
 
2574
            "movq -22(%1, %0, 2), %%mm1        \n\t"
 
2575
            "movq -14(%1, %0, 2), %%mm2        \n\t"
 
2576
            "movq  -6(%1, %0, 2), %%mm3        \n\t"
 
2577
            "pand          %%mm7, %%mm0        \n\t"
 
2578
            "pand          %%mm7, %%mm1        \n\t"
 
2579
            "pand          %%mm7, %%mm2        \n\t"
 
2580
            "pand          %%mm7, %%mm3        \n\t"
 
2581
            "packuswb      %%mm1, %%mm0        \n\t"
 
2582
            "packuswb      %%mm3, %%mm2        \n\t"
 
2583
            MOVNTQ"        %%mm0,-15(%2, %0)   \n\t"
 
2584
            MOVNTQ"        %%mm2,- 7(%2, %0)   \n\t"
 
2585
            "add             $16, %0           \n\t"
 
2586
            " js 1b                            \n\t"
 
2587
            : "+r"(count)
 
2588
            : "r"(src), "r"(dst)
 
2589
        );
 
2590
        count -= 15;
 
2591
    }
 
2592
#endif
 
2593
    while(count<0) {
 
2594
        dst[count]= src[2*count];
 
2595
        count++;
 
2596
    }
 
2597
}
 
2598
 
 
2599
static void RENAME(extract_even2)(const uint8_t *src, uint8_t *dst0, uint8_t *dst1, x86_reg count)
 
2600
{
 
2601
    dst0+=   count;
 
2602
    dst1+=   count;
 
2603
    src += 4*count;
 
2604
    count= - count;
 
2605
#if HAVE_MMX
 
2606
    if(count <= -8) {
 
2607
        count += 7;
 
2608
        __asm__ volatile(
 
2609
            "pcmpeqw       %%mm7, %%mm7        \n\t"
 
2610
            "psrlw            $8, %%mm7        \n\t"
 
2611
            "1:                                \n\t"
 
2612
            "movq -28(%1, %0, 4), %%mm0        \n\t"
 
2613
            "movq -20(%1, %0, 4), %%mm1        \n\t"
 
2614
            "movq -12(%1, %0, 4), %%mm2        \n\t"
 
2615
            "movq  -4(%1, %0, 4), %%mm3        \n\t"
 
2616
            "pand          %%mm7, %%mm0        \n\t"
 
2617
            "pand          %%mm7, %%mm1        \n\t"
 
2618
            "pand          %%mm7, %%mm2        \n\t"
 
2619
            "pand          %%mm7, %%mm3        \n\t"
 
2620
            "packuswb      %%mm1, %%mm0        \n\t"
 
2621
            "packuswb      %%mm3, %%mm2        \n\t"
 
2622
            "movq          %%mm0, %%mm1        \n\t"
 
2623
            "movq          %%mm2, %%mm3        \n\t"
 
2624
            "psrlw            $8, %%mm0        \n\t"
 
2625
            "psrlw            $8, %%mm2        \n\t"
 
2626
            "pand          %%mm7, %%mm1        \n\t"
 
2627
            "pand          %%mm7, %%mm3        \n\t"
 
2628
            "packuswb      %%mm2, %%mm0        \n\t"
 
2629
            "packuswb      %%mm3, %%mm1        \n\t"
 
2630
            MOVNTQ"        %%mm0,- 7(%3, %0)   \n\t"
 
2631
            MOVNTQ"        %%mm1,- 7(%2, %0)   \n\t"
 
2632
            "add              $8, %0           \n\t"
 
2633
            " js 1b                            \n\t"
 
2634
            : "+r"(count)
 
2635
            : "r"(src), "r"(dst0), "r"(dst1)
 
2636
        );
 
2637
        count -= 7;
 
2638
    }
 
2639
#endif
 
2640
    while(count<0) {
 
2641
        dst0[count]= src[4*count+0];
 
2642
        dst1[count]= src[4*count+2];
 
2643
        count++;
 
2644
    }
 
2645
}
 
2646
 
 
2647
static void RENAME(extract_even2avg)(const uint8_t *src0, const uint8_t *src1, uint8_t *dst0, uint8_t *dst1, x86_reg count)
 
2648
{
 
2649
    dst0 +=   count;
 
2650
    dst1 +=   count;
 
2651
    src0 += 4*count;
 
2652
    src1 += 4*count;
 
2653
    count= - count;
 
2654
#ifdef PAVGB
 
2655
    if(count <= -8) {
 
2656
        count += 7;
 
2657
        __asm__ volatile(
 
2658
            "pcmpeqw        %%mm7, %%mm7        \n\t"
 
2659
            "psrlw             $8, %%mm7        \n\t"
 
2660
            "1:                                \n\t"
 
2661
            "movq  -28(%1, %0, 4), %%mm0        \n\t"
 
2662
            "movq  -20(%1, %0, 4), %%mm1        \n\t"
 
2663
            "movq  -12(%1, %0, 4), %%mm2        \n\t"
 
2664
            "movq   -4(%1, %0, 4), %%mm3        \n\t"
 
2665
            PAVGB" -28(%2, %0, 4), %%mm0        \n\t"
 
2666
            PAVGB" -20(%2, %0, 4), %%mm1        \n\t"
 
2667
            PAVGB" -12(%2, %0, 4), %%mm2        \n\t"
 
2668
            PAVGB" - 4(%2, %0, 4), %%mm3        \n\t"
 
2669
            "pand           %%mm7, %%mm0        \n\t"
 
2670
            "pand           %%mm7, %%mm1        \n\t"
 
2671
            "pand           %%mm7, %%mm2        \n\t"
 
2672
            "pand           %%mm7, %%mm3        \n\t"
 
2673
            "packuswb       %%mm1, %%mm0        \n\t"
 
2674
            "packuswb       %%mm3, %%mm2        \n\t"
 
2675
            "movq           %%mm0, %%mm1        \n\t"
 
2676
            "movq           %%mm2, %%mm3        \n\t"
 
2677
            "psrlw             $8, %%mm0        \n\t"
 
2678
            "psrlw             $8, %%mm2        \n\t"
 
2679
            "pand           %%mm7, %%mm1        \n\t"
 
2680
            "pand           %%mm7, %%mm3        \n\t"
 
2681
            "packuswb       %%mm2, %%mm0        \n\t"
 
2682
            "packuswb       %%mm3, %%mm1        \n\t"
 
2683
            MOVNTQ"         %%mm0,- 7(%4, %0)   \n\t"
 
2684
            MOVNTQ"         %%mm1,- 7(%3, %0)   \n\t"
 
2685
            "add               $8, %0           \n\t"
 
2686
            " js 1b                            \n\t"
 
2687
            : "+r"(count)
 
2688
            : "r"(src0), "r"(src1), "r"(dst0), "r"(dst1)
 
2689
        );
 
2690
        count -= 7;
 
2691
    }
 
2692
#endif
 
2693
    while(count<0) {
 
2694
        dst0[count]= (src0[4*count+0]+src1[4*count+0])>>1;
 
2695
        dst1[count]= (src0[4*count+2]+src1[4*count+2])>>1;
 
2696
        count++;
 
2697
    }
 
2698
}
 
2699
 
 
2700
static void RENAME(extract_odd2)(const uint8_t *src, uint8_t *dst0, uint8_t *dst1, x86_reg count)
 
2701
{
 
2702
    dst0+=   count;
 
2703
    dst1+=   count;
 
2704
    src += 4*count;
 
2705
    count= - count;
 
2706
#if HAVE_MMX
 
2707
    if(count <= -8) {
 
2708
        count += 7;
 
2709
        __asm__ volatile(
 
2710
            "pcmpeqw       %%mm7, %%mm7        \n\t"
 
2711
            "psrlw            $8, %%mm7        \n\t"
 
2712
            "1:                                \n\t"
 
2713
            "movq -28(%1, %0, 4), %%mm0        \n\t"
 
2714
            "movq -20(%1, %0, 4), %%mm1        \n\t"
 
2715
            "movq -12(%1, %0, 4), %%mm2        \n\t"
 
2716
            "movq  -4(%1, %0, 4), %%mm3        \n\t"
 
2717
            "psrlw            $8, %%mm0        \n\t"
 
2718
            "psrlw            $8, %%mm1        \n\t"
 
2719
            "psrlw            $8, %%mm2        \n\t"
 
2720
            "psrlw            $8, %%mm3        \n\t"
 
2721
            "packuswb      %%mm1, %%mm0        \n\t"
 
2722
            "packuswb      %%mm3, %%mm2        \n\t"
 
2723
            "movq          %%mm0, %%mm1        \n\t"
 
2724
            "movq          %%mm2, %%mm3        \n\t"
 
2725
            "psrlw            $8, %%mm0        \n\t"
 
2726
            "psrlw            $8, %%mm2        \n\t"
 
2727
            "pand          %%mm7, %%mm1        \n\t"
 
2728
            "pand          %%mm7, %%mm3        \n\t"
 
2729
            "packuswb      %%mm2, %%mm0        \n\t"
 
2730
            "packuswb      %%mm3, %%mm1        \n\t"
 
2731
            MOVNTQ"        %%mm0,- 7(%3, %0)   \n\t"
 
2732
            MOVNTQ"        %%mm1,- 7(%2, %0)   \n\t"
 
2733
            "add              $8, %0           \n\t"
 
2734
            " js 1b                            \n\t"
 
2735
            : "+r"(count)
 
2736
            : "r"(src), "r"(dst0), "r"(dst1)
 
2737
        );
 
2738
        count -= 7;
 
2739
    }
 
2740
#endif
 
2741
    src++;
 
2742
    while(count<0) {
 
2743
        dst0[count]= src[4*count+0];
 
2744
        dst1[count]= src[4*count+2];
 
2745
        count++;
 
2746
    }
 
2747
}
 
2748
 
 
2749
static void RENAME(extract_odd2avg)(const uint8_t *src0, const uint8_t *src1, uint8_t *dst0, uint8_t *dst1, x86_reg count)
 
2750
{
 
2751
    dst0 +=   count;
 
2752
    dst1 +=   count;
 
2753
    src0 += 4*count;
 
2754
    src1 += 4*count;
 
2755
    count= - count;
 
2756
#ifdef PAVGB
 
2757
    if(count <= -8) {
 
2758
        count += 7;
 
2759
        __asm__ volatile(
 
2760
            "pcmpeqw        %%mm7, %%mm7        \n\t"
 
2761
            "psrlw             $8, %%mm7        \n\t"
 
2762
            "1:                                \n\t"
 
2763
            "movq  -28(%1, %0, 4), %%mm0        \n\t"
 
2764
            "movq  -20(%1, %0, 4), %%mm1        \n\t"
 
2765
            "movq  -12(%1, %0, 4), %%mm2        \n\t"
 
2766
            "movq   -4(%1, %0, 4), %%mm3        \n\t"
 
2767
            PAVGB" -28(%2, %0, 4), %%mm0        \n\t"
 
2768
            PAVGB" -20(%2, %0, 4), %%mm1        \n\t"
 
2769
            PAVGB" -12(%2, %0, 4), %%mm2        \n\t"
 
2770
            PAVGB" - 4(%2, %0, 4), %%mm3        \n\t"
 
2771
            "psrlw             $8, %%mm0        \n\t"
 
2772
            "psrlw             $8, %%mm1        \n\t"
 
2773
            "psrlw             $8, %%mm2        \n\t"
 
2774
            "psrlw             $8, %%mm3        \n\t"
 
2775
            "packuswb       %%mm1, %%mm0        \n\t"
 
2776
            "packuswb       %%mm3, %%mm2        \n\t"
 
2777
            "movq           %%mm0, %%mm1        \n\t"
 
2778
            "movq           %%mm2, %%mm3        \n\t"
 
2779
            "psrlw             $8, %%mm0        \n\t"
 
2780
            "psrlw             $8, %%mm2        \n\t"
 
2781
            "pand           %%mm7, %%mm1        \n\t"
 
2782
            "pand           %%mm7, %%mm3        \n\t"
 
2783
            "packuswb       %%mm2, %%mm0        \n\t"
 
2784
            "packuswb       %%mm3, %%mm1        \n\t"
 
2785
            MOVNTQ"         %%mm0,- 7(%4, %0)   \n\t"
 
2786
            MOVNTQ"         %%mm1,- 7(%3, %0)   \n\t"
 
2787
            "add               $8, %0           \n\t"
 
2788
            " js 1b                            \n\t"
 
2789
            : "+r"(count)
 
2790
            : "r"(src0), "r"(src1), "r"(dst0), "r"(dst1)
 
2791
        );
 
2792
        count -= 7;
 
2793
    }
 
2794
#endif
 
2795
    src0++;
 
2796
    src1++;
 
2797
    while(count<0) {
 
2798
        dst0[count]= (src0[4*count+0]+src1[4*count+0])>>1;
 
2799
        dst1[count]= (src0[4*count+2]+src1[4*count+2])>>1;
 
2800
        count++;
 
2801
    }
 
2802
}
 
2803
 
 
2804
static void RENAME(yuyvtoyuv420)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, const uint8_t *src,
 
2805
                                      long width, long height,
 
2806
                                      long lumStride, long chromStride, long srcStride)
 
2807
{
 
2808
    long y;
 
2809
    const long chromWidth= -((-width)>>1);
 
2810
 
 
2811
    for (y=0; y<height; y++) {
 
2812
        RENAME(extract_even)(src, ydst, width);
 
2813
        if(y&1) {
 
2814
            RENAME(extract_odd2avg)(src-srcStride, src, udst, vdst, chromWidth);
 
2815
            udst+= chromStride;
 
2816
            vdst+= chromStride;
 
2817
        }
 
2818
 
 
2819
        src += srcStride;
 
2820
        ydst+= lumStride;
 
2821
    }
 
2822
#if HAVE_MMX
 
2823
    __asm__(
 
2824
            EMMS"       \n\t"
 
2825
            SFENCE"     \n\t"
 
2826
            ::: "memory"
 
2827
        );
 
2828
#endif
 
2829
}
 
2830
 
 
2831
static void RENAME(yuyvtoyuv422)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, const uint8_t *src,
 
2832
                                      long width, long height,
 
2833
                                      long lumStride, long chromStride, long srcStride)
 
2834
{
 
2835
    long y;
 
2836
    const long chromWidth= -((-width)>>1);
 
2837
 
 
2838
    for (y=0; y<height; y++) {
 
2839
        RENAME(extract_even)(src, ydst, width);
 
2840
        RENAME(extract_odd2)(src, udst, vdst, chromWidth);
 
2841
 
 
2842
        src += srcStride;
 
2843
        ydst+= lumStride;
 
2844
        udst+= chromStride;
 
2845
        vdst+= chromStride;
 
2846
    }
 
2847
#if HAVE_MMX
 
2848
    __asm__(
 
2849
            EMMS"       \n\t"
 
2850
            SFENCE"     \n\t"
 
2851
            ::: "memory"
 
2852
        );
 
2853
#endif
 
2854
}
 
2855
 
 
2856
static void RENAME(uyvytoyuv420)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, const uint8_t *src,
 
2857
                                      long width, long height,
 
2858
                                      long lumStride, long chromStride, long srcStride)
 
2859
{
 
2860
    long y;
 
2861
    const long chromWidth= -((-width)>>1);
 
2862
 
 
2863
    for (y=0; y<height; y++) {
 
2864
        RENAME(extract_even)(src+1, ydst, width);
 
2865
        if(y&1) {
 
2866
            RENAME(extract_even2avg)(src-srcStride, src, udst, vdst, chromWidth);
 
2867
            udst+= chromStride;
 
2868
            vdst+= chromStride;
 
2869
        }
 
2870
 
 
2871
        src += srcStride;
 
2872
        ydst+= lumStride;
 
2873
    }
 
2874
#if HAVE_MMX
 
2875
    __asm__(
 
2876
            EMMS"       \n\t"
 
2877
            SFENCE"     \n\t"
 
2878
            ::: "memory"
 
2879
        );
 
2880
#endif
 
2881
}
 
2882
 
 
2883
static void RENAME(uyvytoyuv422)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, const uint8_t *src,
 
2884
                                      long width, long height,
 
2885
                                      long lumStride, long chromStride, long srcStride)
 
2886
{
 
2887
    long y;
 
2888
    const long chromWidth= -((-width)>>1);
 
2889
 
 
2890
    for (y=0; y<height; y++) {
 
2891
        RENAME(extract_even)(src+1, ydst, width);
 
2892
        RENAME(extract_even2)(src, udst, vdst, chromWidth);
 
2893
 
 
2894
        src += srcStride;
 
2895
        ydst+= lumStride;
 
2896
        udst+= chromStride;
 
2897
        vdst+= chromStride;
 
2898
    }
 
2899
#if HAVE_MMX
 
2900
    __asm__(
 
2901
            EMMS"       \n\t"
 
2902
            SFENCE"     \n\t"
 
2903
            ::: "memory"
 
2904
        );
 
2905
#endif
 
2906
}
 
2907
 
 
2908
static inline void RENAME(rgb2rgb_init)(void)
 
2909
{
 
2910
    rgb15to16       = RENAME(rgb15to16);
 
2911
    rgb15tobgr24    = RENAME(rgb15tobgr24);
 
2912
    rgb15to32       = RENAME(rgb15to32);
 
2913
    rgb16tobgr24    = RENAME(rgb16tobgr24);
 
2914
    rgb16to32       = RENAME(rgb16to32);
 
2915
    rgb16to15       = RENAME(rgb16to15);
 
2916
    rgb24tobgr16    = RENAME(rgb24tobgr16);
 
2917
    rgb24tobgr15    = RENAME(rgb24tobgr15);
 
2918
    rgb24tobgr32    = RENAME(rgb24tobgr32);
 
2919
    rgb32to16       = RENAME(rgb32to16);
 
2920
    rgb32to15       = RENAME(rgb32to15);
 
2921
    rgb32tobgr24    = RENAME(rgb32tobgr24);
 
2922
    rgb24to15       = RENAME(rgb24to15);
 
2923
    rgb24to16       = RENAME(rgb24to16);
 
2924
    rgb24tobgr24    = RENAME(rgb24tobgr24);
 
2925
    rgb32tobgr32    = RENAME(rgb32tobgr32);
 
2926
    rgb32tobgr16    = RENAME(rgb32tobgr16);
 
2927
    rgb32tobgr15    = RENAME(rgb32tobgr15);
 
2928
    yv12toyuy2      = RENAME(yv12toyuy2);
 
2929
    yv12touyvy      = RENAME(yv12touyvy);
 
2930
    yuv422ptoyuy2   = RENAME(yuv422ptoyuy2);
 
2931
    yuv422ptouyvy   = RENAME(yuv422ptouyvy);
 
2932
    yuy2toyv12      = RENAME(yuy2toyv12);
 
2933
//    yvu9toyv12      = RENAME(yvu9toyv12);
 
2934
    planar2x        = RENAME(planar2x);
 
2935
    rgb24toyv12     = RENAME(rgb24toyv12);
 
2936
    interleaveBytes = RENAME(interleaveBytes);
 
2937
    vu9_to_vu12     = RENAME(vu9_to_vu12);
 
2938
    yvu9_to_yuy2    = RENAME(yvu9_to_yuy2);
 
2939
 
 
2940
    uyvytoyuv420    = RENAME(uyvytoyuv420);
 
2941
    uyvytoyuv422    = RENAME(uyvytoyuv422);
 
2942
    yuyvtoyuv420    = RENAME(yuyvtoyuv420);
 
2943
    yuyvtoyuv422    = RENAME(yuyvtoyuv422);
 
2944
}