~ubuntu-branches/ubuntu/lucid/fceux/lucid

« back to all changes in this revision

Viewing changes to fceu/src/drivers/common/scale2x.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fabrice Coutadeur
  • Date: 2009-12-14 08:05:17 UTC
  • Revision ID: james.westby@ubuntu.com-20091214080517-abi5tj8avthfan7c
Tags: upstream-2.1.2+repack
ImportĀ upstreamĀ versionĀ 2.1.2+repack

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of the Scale2x project.
 
3
 *
 
4
 * Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
 */
 
20
 
 
21
/*
 
22
 * This file contains a C and MMX implementation of the Scale2x effect.
 
23
 *
 
24
 * You can find an high level description of the effect at :
 
25
 *
 
26
 * http://scale2x.sourceforge.net/
 
27
 *
 
28
 * Alternatively at the previous license terms, you are allowed to use this
 
29
 * code in your program with these conditions:
 
30
 * - the program is not used in commercial activities.
 
31
 * - the whole source code of the program is released with the binary.
 
32
 * - derivative works of the program are allowed.
 
33
 */
 
34
 
 
35
#include "../../types.h" //mbg merge 7/17/06 added to get rid of __restrict__ in msvc
 
36
#include "scale2x.h"
 
37
 
 
38
#include <assert.h>
 
39
 
 
40
/***************************************************************************/
 
41
/* Scale2x C implementation */
 
42
 
 
43
static inline void scale2x_8_def_single(scale2x_uint8* __restrict__ dst, const scale2x_uint8* __restrict__ src0, const scale2x_uint8* __restrict__ src1, const scale2x_uint8* __restrict__ src2, unsigned count)
 
44
{
 
45
        assert(count >= 2);
 
46
 
 
47
        /* first pixel */
 
48
        dst[0] = src1[0];
 
49
        if (src1[1] == src0[0] && src2[0] != src0[0])
 
50
                dst[1] = src0[0];
 
51
        else
 
52
                dst[1] = src1[0];
 
53
        ++src0;
 
54
        ++src1;
 
55
        ++src2;
 
56
        dst += 2;
 
57
 
 
58
        /* central pixels */
 
59
        count -= 2;
 
60
        while (count) {
 
61
                if (src0[0] != src2[0] && src1[-1] != src1[1]) {
 
62
                        dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
 
63
                        dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
 
64
                } else {
 
65
                        dst[0] = src1[0];
 
66
                        dst[1] = src1[0];
 
67
                }
 
68
 
 
69
                ++src0;
 
70
                ++src1;
 
71
                ++src2;
 
72
                dst += 2;
 
73
                --count;
 
74
        }
 
75
 
 
76
        /* last pixel */
 
77
        if (src1[-1] == src0[0] && src2[0] != src0[0])
 
78
                dst[0] = src0[0];
 
79
        else
 
80
                dst[0] = src1[0];
 
81
        dst[1] = src1[0];
 
82
}
 
83
 
 
84
static inline void scale2x_16_def_single(scale2x_uint16* __restrict__ dst, const scale2x_uint16* __restrict__ src0, const scale2x_uint16* __restrict__ src1, const scale2x_uint16* __restrict__ src2, unsigned count)
 
85
{
 
86
        assert(count >= 2);
 
87
 
 
88
        /* first pixel */
 
89
        dst[0] = src1[0];
 
90
        if (src1[1] == src0[0] && src2[0] != src0[0])
 
91
                dst[1] = src0[0];
 
92
        else
 
93
                dst[1] = src1[0];
 
94
        ++src0;
 
95
        ++src1;
 
96
        ++src2;
 
97
        dst += 2;
 
98
 
 
99
        /* central pixels */
 
100
        count -= 2;
 
101
        while (count) {
 
102
                if (src0[0] != src2[0] && src1[-1] != src1[1]) {
 
103
                        dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
 
104
                        dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
 
105
                } else {
 
106
                        dst[0] = src1[0];
 
107
                        dst[1] = src1[0];
 
108
                }
 
109
 
 
110
                ++src0;
 
111
                ++src1;
 
112
                ++src2;
 
113
                dst += 2;
 
114
                --count;
 
115
        }
 
116
 
 
117
        /* last pixel */
 
118
        if (src1[-1] == src0[0] && src2[0] != src0[0])
 
119
                dst[0] = src0[0];
 
120
        else
 
121
                dst[0] = src1[0];
 
122
        dst[1] = src1[0];
 
123
}
 
124
 
 
125
static inline void scale2x_32_def_single(scale2x_uint32* __restrict__ dst, const scale2x_uint32* __restrict__ src0, const scale2x_uint32* __restrict__ src1, const scale2x_uint32* __restrict__ src2, unsigned count)
 
126
{
 
127
        assert(count >= 2);
 
128
 
 
129
        /* first pixel */
 
130
        dst[0] = src1[0];
 
131
        if (src1[1] == src0[0] && src2[0] != src0[0])
 
132
                dst[1] = src0[0];
 
133
        else
 
134
                dst[1] = src1[0];
 
135
        ++src0;
 
136
        ++src1;
 
137
        ++src2;
 
138
        dst += 2;
 
139
 
 
140
        /* central pixels */
 
141
        count -= 2;
 
142
        while (count) {
 
143
                if (src0[0] != src2[0] && src1[-1] != src1[1]) {
 
144
                        dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
 
145
                        dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
 
146
                } else {
 
147
                        dst[0] = src1[0];
 
148
                        dst[1] = src1[0];
 
149
                }
 
150
 
 
151
                ++src0;
 
152
                ++src1;
 
153
                ++src2;
 
154
                dst += 2;
 
155
                --count;
 
156
        }
 
157
 
 
158
        /* last pixel */
 
159
        if (src1[-1] == src0[0] && src2[0] != src0[0])
 
160
                dst[0] = src0[0];
 
161
        else
 
162
                dst[0] = src1[0];
 
163
        dst[1] = src1[0];
 
164
}
 
165
 
 
166
/**
 
167
 * Scale by a factor of 2 a row of pixels of 8 bits.
 
168
 * The function is implemented in C.
 
169
 * The pixels over the left and right borders are assumed of the same color of
 
170
 * the pixels on the border.
 
171
 * \param src0 Pointer at the first pixel of the previous row.
 
172
 * \param src1 Pointer at the first pixel of the current row.
 
173
 * \param src2 Pointer at the first pixel of the next row.
 
174
 * \param count Length in pixels of the src0, src1 and src2 rows.
 
175
 * It must be at least 2.
 
176
 * \param dst0 First destination row, double length in pixels.
 
177
 * \param dst1 Second destination row, double length in pixels.
 
178
 */
 
179
void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)
 
180
{
 
181
        assert(count >= 2);
 
182
 
 
183
        scale2x_8_def_single(dst0, src0, src1, src2, count);
 
184
        scale2x_8_def_single(dst1, src2, src1, src0, count);
 
185
}
 
186
 
 
187
/**
 
188
 * Scale by a factor of 2 a row of pixels of 16 bits.
 
189
 * This function operates like scale2x_8_def() but for 16 bits pixels.
 
190
 * \param src0 Pointer at the first pixel of the previous row.
 
191
 * \param src1 Pointer at the first pixel of the current row.
 
192
 * \param src2 Pointer at the first pixel of the next row.
 
193
 * \param count Length in pixels of the src0, src1 and src2 rows.
 
194
 * It must be at least 2.
 
195
 * \param dst0 First destination row, double length in pixels.
 
196
 * \param dst1 Second destination row, double length in pixels.
 
197
 */
 
198
void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)
 
199
{
 
200
        assert(count >= 2);
 
201
 
 
202
        scale2x_16_def_single(dst0, src0, src1, src2, count);
 
203
        scale2x_16_def_single(dst1, src2, src1, src0, count);
 
204
}
 
205
 
 
206
/**
 
207
 * Scale by a factor of 2 a row of pixels of 32 bits.
 
208
 * This function operates like scale2x_8_def() but for 32 bits pixels.
 
209
 * \param src0 Pointer at the first pixel of the previous row.
 
210
 * \param src1 Pointer at the first pixel of the current row.
 
211
 * \param src2 Pointer at the first pixel of the next row.
 
212
 * \param count Length in pixels of the src0, src1 and src2 rows.
 
213
 * It must be at least 2.
 
214
 * \param dst0 First destination row, double length in pixels.
 
215
 * \param dst1 Second destination row, double length in pixels.
 
216
 */
 
217
void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)
 
218
{
 
219
        assert(count >= 2);
 
220
 
 
221
        scale2x_32_def_single(dst0, src0, src1, src2, count);
 
222
        scale2x_32_def_single(dst1, src2, src1, src0, count);
 
223
}
 
224
 
 
225
/***************************************************************************/
 
226
/* Scale2x MMX implementation */
 
227
 
 
228
#if defined(__GNUC__) && defined(__i386__)
 
229
 
 
230
/*
 
231
 * Apply the Scale2x effect at a single row.
 
232
 * This function must be called only by the other scale2x functions.
 
233
 *
 
234
 * Considering the pixel map :
 
235
 *
 
236
 *      ABC (src0)
 
237
 *      DEF (src1)
 
238
 *      GHI (src2)
 
239
 *
 
240
 * this functions compute 2 new pixels in substitution of the source pixel E
 
241
 * like this map :
 
242
 *
 
243
 *      ab (dst)
 
244
 *
 
245
 * with these variables :
 
246
 *
 
247
 *      &current -> E
 
248
 *      &current_left -> D
 
249
 *      &current_right -> F
 
250
 *      &current_upper -> B
 
251
 *      &current_lower -> H
 
252
 *
 
253
 *      %0 -> current_upper
 
254
 *      %1 -> current
 
255
 *      %2 -> current_lower
 
256
 *      %3 -> dst
 
257
 *      %4 -> counter
 
258
 *
 
259
 *      %mm0 -> *current_left
 
260
 *      %mm1 -> *current_next
 
261
 *      %mm2 -> tmp0
 
262
 *      %mm3 -> tmp1
 
263
 *      %mm4 -> tmp2
 
264
 *      %mm5 -> tmp3
 
265
 *      %mm6 -> *current_upper
 
266
 *      %mm7 -> *current
 
267
 */
 
268
static inline void scale2x_8_mmx_single(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)
 
269
{
 
270
        assert(count >= 16);
 
271
        assert(count % 8 == 0);
 
272
 
 
273
        /* always do the first and last run */
 
274
        count -= 2*8;
 
275
 
 
276
        __asm__ __volatile__(
 
277
/* first run */
 
278
                /* set the current, current_pre, current_next registers */
 
279
                "movq 0(%1), %%mm0\n"
 
280
                "movq 0(%1), %%mm7\n"
 
281
                "movq 8(%1), %%mm1\n"
 
282
                "psllq $56, %%mm0\n"
 
283
                "psllq $56, %%mm1\n"
 
284
                "psrlq $56, %%mm0\n"
 
285
                "movq %%mm7, %%mm2\n"
 
286
                "movq %%mm7, %%mm3\n"
 
287
                "psllq $8, %%mm2\n"
 
288
                "psrlq $8, %%mm3\n"
 
289
                "por %%mm2, %%mm0\n"
 
290
                "por %%mm3, %%mm1\n"
 
291
 
 
292
                /* current_upper */
 
293
                "movq (%0), %%mm6\n"
 
294
 
 
295
                /* compute the upper-left pixel for dst on %%mm2 */
 
296
                /* compute the upper-right pixel for dst on %%mm4 */
 
297
                "movq %%mm0, %%mm2\n"
 
298
                "movq %%mm1, %%mm4\n"
 
299
                "movq %%mm0, %%mm3\n"
 
300
                "movq %%mm1, %%mm5\n"
 
301
                "pcmpeqb %%mm6, %%mm2\n"
 
302
                "pcmpeqb %%mm6, %%mm4\n"
 
303
                "pcmpeqb (%2), %%mm3\n"
 
304
                "pcmpeqb (%2), %%mm5\n"
 
305
                "pandn %%mm2, %%mm3\n"
 
306
                "pandn %%mm4, %%mm5\n"
 
307
                "movq %%mm0, %%mm2\n"
 
308
                "movq %%mm1, %%mm4\n"
 
309
                "pcmpeqb %%mm1, %%mm2\n"
 
310
                "pcmpeqb %%mm0, %%mm4\n"
 
311
                "pandn %%mm3, %%mm2\n"
 
312
                "pandn %%mm5, %%mm4\n"
 
313
                "movq %%mm2, %%mm3\n"
 
314
                "movq %%mm4, %%mm5\n"
 
315
                "pand %%mm6, %%mm2\n"
 
316
                "pand %%mm6, %%mm4\n"
 
317
                "pandn %%mm7, %%mm3\n"
 
318
                "pandn %%mm7, %%mm5\n"
 
319
                "por %%mm3, %%mm2\n"
 
320
                "por %%mm5, %%mm4\n"
 
321
 
 
322
                /* set *dst */
 
323
                "movq %%mm2, %%mm3\n"
 
324
                "punpcklbw %%mm4, %%mm2\n"
 
325
                "punpckhbw %%mm4, %%mm3\n"
 
326
                "movq %%mm2, (%3)\n"
 
327
                "movq %%mm3, 8(%3)\n"
 
328
 
 
329
                /* next */
 
330
                "addl $8, %0\n"
 
331
                "addl $8, %1\n"
 
332
                "addl $8, %2\n"
 
333
                "addl $16, %3\n"
 
334
 
 
335
/* central runs */
 
336
                "shrl $3, %4\n"
 
337
                "jz 1f\n"
 
338
 
 
339
                "0:\n"
 
340
 
 
341
                /* set the current, current_pre, current_next registers */
 
342
                "movq -8(%1), %%mm0\n"
 
343
                "movq (%1), %%mm7\n"
 
344
                "movq 8(%1), %%mm1\n"
 
345
                "psrlq $56, %%mm0\n"
 
346
                "psllq $56, %%mm1\n"
 
347
                "movq %%mm7, %%mm2\n"
 
348
                "movq %%mm7, %%mm3\n"
 
349
                "psllq $8, %%mm2\n"
 
350
                "psrlq $8, %%mm3\n"
 
351
                "por %%mm2, %%mm0\n"
 
352
                "por %%mm3, %%mm1\n"
 
353
 
 
354
                /* current_upper */
 
355
                "movq (%0), %%mm6\n"
 
356
 
 
357
                /* compute the upper-left pixel for dst on %%mm2 */
 
358
                /* compute the upper-right pixel for dst on %%mm4 */
 
359
                "movq %%mm0, %%mm2\n"
 
360
                "movq %%mm1, %%mm4\n"
 
361
                "movq %%mm0, %%mm3\n"
 
362
                "movq %%mm1, %%mm5\n"
 
363
                "pcmpeqb %%mm6, %%mm2\n"
 
364
                "pcmpeqb %%mm6, %%mm4\n"
 
365
                "pcmpeqb (%2), %%mm3\n"
 
366
                "pcmpeqb (%2), %%mm5\n"
 
367
                "pandn %%mm2, %%mm3\n"
 
368
                "pandn %%mm4, %%mm5\n"
 
369
                "movq %%mm0, %%mm2\n"
 
370
                "movq %%mm1, %%mm4\n"
 
371
                "pcmpeqb %%mm1, %%mm2\n"
 
372
                "pcmpeqb %%mm0, %%mm4\n"
 
373
                "pandn %%mm3, %%mm2\n"
 
374
                "pandn %%mm5, %%mm4\n"
 
375
                "movq %%mm2, %%mm3\n"
 
376
                "movq %%mm4, %%mm5\n"
 
377
                "pand %%mm6, %%mm2\n"
 
378
                "pand %%mm6, %%mm4\n"
 
379
                "pandn %%mm7, %%mm3\n"
 
380
                "pandn %%mm7, %%mm5\n"
 
381
                "por %%mm3, %%mm2\n"
 
382
                "por %%mm5, %%mm4\n"
 
383
 
 
384
                /* set *dst */
 
385
                "movq %%mm2, %%mm3\n"
 
386
                "punpcklbw %%mm4, %%mm2\n"
 
387
                "punpckhbw %%mm4, %%mm3\n"
 
388
                "movq %%mm2, (%3)\n"
 
389
                "movq %%mm3, 8(%3)\n"
 
390
 
 
391
                /* next */
 
392
                "addl $8, %0\n"
 
393
                "addl $8, %1\n"
 
394
                "addl $8, %2\n"
 
395
                "addl $16, %3\n"
 
396
 
 
397
                "decl %4\n"
 
398
                "jnz 0b\n"
 
399
                "1:\n"
 
400
 
 
401
/* final run */
 
402
                /* set the current, current_pre, current_next registers */
 
403
                "movq (%1), %%mm1\n"
 
404
                "movq (%1), %%mm7\n"
 
405
                "movq -8(%1), %%mm0\n"
 
406
                "psrlq $56, %%mm1\n"
 
407
                "psrlq $56, %%mm0\n"
 
408
                "psllq $56, %%mm1\n"
 
409
                "movq %%mm7, %%mm2\n"
 
410
                "movq %%mm7, %%mm3\n"
 
411
                "psllq $8, %%mm2\n"
 
412
                "psrlq $8, %%mm3\n"
 
413
                "por %%mm2, %%mm0\n"
 
414
                "por %%mm3, %%mm1\n"
 
415
 
 
416
                /* current_upper */
 
417
                "movq (%0), %%mm6\n"
 
418
 
 
419
                /* compute the upper-left pixel for dst on %%mm2 */
 
420
                /* compute the upper-right pixel for dst on %%mm4 */
 
421
                "movq %%mm0, %%mm2\n"
 
422
                "movq %%mm1, %%mm4\n"
 
423
                "movq %%mm0, %%mm3\n"
 
424
                "movq %%mm1, %%mm5\n"
 
425
                "pcmpeqb %%mm6, %%mm2\n"
 
426
                "pcmpeqb %%mm6, %%mm4\n"
 
427
                "pcmpeqb (%2), %%mm3\n"
 
428
                "pcmpeqb (%2), %%mm5\n"
 
429
                "pandn %%mm2, %%mm3\n"
 
430
                "pandn %%mm4, %%mm5\n"
 
431
                "movq %%mm0, %%mm2\n"
 
432
                "movq %%mm1, %%mm4\n"
 
433
                "pcmpeqb %%mm1, %%mm2\n"
 
434
                "pcmpeqb %%mm0, %%mm4\n"
 
435
                "pandn %%mm3, %%mm2\n"
 
436
                "pandn %%mm5, %%mm4\n"
 
437
                "movq %%mm2, %%mm3\n"
 
438
                "movq %%mm4, %%mm5\n"
 
439
                "pand %%mm6, %%mm2\n"
 
440
                "pand %%mm6, %%mm4\n"
 
441
                "pandn %%mm7, %%mm3\n"
 
442
                "pandn %%mm7, %%mm5\n"
 
443
                "por %%mm3, %%mm2\n"
 
444
                "por %%mm5, %%mm4\n"
 
445
 
 
446
                /* set *dst */
 
447
                "movq %%mm2, %%mm3\n"
 
448
                "punpcklbw %%mm4, %%mm2\n"
 
449
                "punpckhbw %%mm4, %%mm3\n"
 
450
                "movq %%mm2, (%3)\n"
 
451
                "movq %%mm3, 8(%3)\n"
 
452
 
 
453
                : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
 
454
                :
 
455
                : "cc"
 
456
        );
 
457
}
 
458
 
 
459
static inline void scale2x_16_mmx_single(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)
 
460
{
 
461
        assert(count >= 8);
 
462
        assert(count % 4 == 0);
 
463
 
 
464
        /* always do the first and last run */
 
465
        count -= 2*4;
 
466
 
 
467
        __asm__ __volatile__(
 
468
/* first run */
 
469
                /* set the current, current_pre, current_next registers */
 
470
                "movq 0(%1), %%mm0\n"
 
471
                "movq 0(%1), %%mm7\n"
 
472
                "movq 8(%1), %%mm1\n"
 
473
                "psllq $48, %%mm0\n"
 
474
                "psllq $48, %%mm1\n"
 
475
                "psrlq $48, %%mm0\n"
 
476
                "movq %%mm7, %%mm2\n"
 
477
                "movq %%mm7, %%mm3\n"
 
478
                "psllq $16, %%mm2\n"
 
479
                "psrlq $16, %%mm3\n"
 
480
                "por %%mm2, %%mm0\n"
 
481
                "por %%mm3, %%mm1\n"
 
482
 
 
483
                /* current_upper */
 
484
                "movq (%0), %%mm6\n"
 
485
 
 
486
                /* compute the upper-left pixel for dst on %%mm2 */
 
487
                /* compute the upper-right pixel for dst on %%mm4 */
 
488
                "movq %%mm0, %%mm2\n"
 
489
                "movq %%mm1, %%mm4\n"
 
490
                "movq %%mm0, %%mm3\n"
 
491
                "movq %%mm1, %%mm5\n"
 
492
                "pcmpeqw %%mm6, %%mm2\n"
 
493
                "pcmpeqw %%mm6, %%mm4\n"
 
494
                "pcmpeqw (%2), %%mm3\n"
 
495
                "pcmpeqw (%2), %%mm5\n"
 
496
                "pandn %%mm2, %%mm3\n"
 
497
                "pandn %%mm4, %%mm5\n"
 
498
                "movq %%mm0, %%mm2\n"
 
499
                "movq %%mm1, %%mm4\n"
 
500
                "pcmpeqw %%mm1, %%mm2\n"
 
501
                "pcmpeqw %%mm0, %%mm4\n"
 
502
                "pandn %%mm3, %%mm2\n"
 
503
                "pandn %%mm5, %%mm4\n"
 
504
                "movq %%mm2, %%mm3\n"
 
505
                "movq %%mm4, %%mm5\n"
 
506
                "pand %%mm6, %%mm2\n"
 
507
                "pand %%mm6, %%mm4\n"
 
508
                "pandn %%mm7, %%mm3\n"
 
509
                "pandn %%mm7, %%mm5\n"
 
510
                "por %%mm3, %%mm2\n"
 
511
                "por %%mm5, %%mm4\n"
 
512
 
 
513
                /* set *dst */
 
514
                "movq %%mm2, %%mm3\n"
 
515
                "punpcklwd %%mm4, %%mm2\n"
 
516
                "punpckhwd %%mm4, %%mm3\n"
 
517
                "movq %%mm2, (%3)\n"
 
518
                "movq %%mm3, 8(%3)\n"
 
519
 
 
520
                /* next */
 
521
                "addl $8, %0\n"
 
522
                "addl $8, %1\n"
 
523
                "addl $8, %2\n"
 
524
                "addl $16, %3\n"
 
525
 
 
526
/* central runs */
 
527
                "shrl $2, %4\n"
 
528
                "jz 1f\n"
 
529
 
 
530
                "0:\n"
 
531
 
 
532
                /* set the current, current_pre, current_next registers */
 
533
                "movq -8(%1), %%mm0\n"
 
534
                "movq (%1), %%mm7\n"
 
535
                "movq 8(%1), %%mm1\n"
 
536
                "psrlq $48, %%mm0\n"
 
537
                "psllq $48, %%mm1\n"
 
538
                "movq %%mm7, %%mm2\n"
 
539
                "movq %%mm7, %%mm3\n"
 
540
                "psllq $16, %%mm2\n"
 
541
                "psrlq $16, %%mm3\n"
 
542
                "por %%mm2, %%mm0\n"
 
543
                "por %%mm3, %%mm1\n"
 
544
 
 
545
                /* current_upper */
 
546
                "movq (%0), %%mm6\n"
 
547
 
 
548
                /* compute the upper-left pixel for dst on %%mm2 */
 
549
                /* compute the upper-right pixel for dst on %%mm4 */
 
550
                "movq %%mm0, %%mm2\n"
 
551
                "movq %%mm1, %%mm4\n"
 
552
                "movq %%mm0, %%mm3\n"
 
553
                "movq %%mm1, %%mm5\n"
 
554
                "pcmpeqw %%mm6, %%mm2\n"
 
555
                "pcmpeqw %%mm6, %%mm4\n"
 
556
                "pcmpeqw (%2), %%mm3\n"
 
557
                "pcmpeqw (%2), %%mm5\n"
 
558
                "pandn %%mm2, %%mm3\n"
 
559
                "pandn %%mm4, %%mm5\n"
 
560
                "movq %%mm0, %%mm2\n"
 
561
                "movq %%mm1, %%mm4\n"
 
562
                "pcmpeqw %%mm1, %%mm2\n"
 
563
                "pcmpeqw %%mm0, %%mm4\n"
 
564
                "pandn %%mm3, %%mm2\n"
 
565
                "pandn %%mm5, %%mm4\n"
 
566
                "movq %%mm2, %%mm3\n"
 
567
                "movq %%mm4, %%mm5\n"
 
568
                "pand %%mm6, %%mm2\n"
 
569
                "pand %%mm6, %%mm4\n"
 
570
                "pandn %%mm7, %%mm3\n"
 
571
                "pandn %%mm7, %%mm5\n"
 
572
                "por %%mm3, %%mm2\n"
 
573
                "por %%mm5, %%mm4\n"
 
574
 
 
575
                /* set *dst */
 
576
                "movq %%mm2, %%mm3\n"
 
577
                "punpcklwd %%mm4, %%mm2\n"
 
578
                "punpckhwd %%mm4, %%mm3\n"
 
579
                "movq %%mm2, (%3)\n"
 
580
                "movq %%mm3, 8(%3)\n"
 
581
 
 
582
                /* next */
 
583
                "addl $8, %0\n"
 
584
                "addl $8, %1\n"
 
585
                "addl $8, %2\n"
 
586
                "addl $16, %3\n"
 
587
 
 
588
                "decl %4\n"
 
589
                "jnz 0b\n"
 
590
                "1:\n"
 
591
 
 
592
/* final run */
 
593
                /* set the current, current_pre, current_next registers */
 
594
                "movq (%1), %%mm1\n"
 
595
                "movq (%1), %%mm7\n"
 
596
                "movq -8(%1), %%mm0\n"
 
597
                "psrlq $48, %%mm1\n"
 
598
                "psrlq $48, %%mm0\n"
 
599
                "psllq $48, %%mm1\n"
 
600
                "movq %%mm7, %%mm2\n"
 
601
                "movq %%mm7, %%mm3\n"
 
602
                "psllq $16, %%mm2\n"
 
603
                "psrlq $16, %%mm3\n"
 
604
                "por %%mm2, %%mm0\n"
 
605
                "por %%mm3, %%mm1\n"
 
606
 
 
607
                /* current_upper */
 
608
                "movq (%0), %%mm6\n"
 
609
 
 
610
                /* compute the upper-left pixel for dst on %%mm2 */
 
611
                /* compute the upper-right pixel for dst on %%mm4 */
 
612
                "movq %%mm0, %%mm2\n"
 
613
                "movq %%mm1, %%mm4\n"
 
614
                "movq %%mm0, %%mm3\n"
 
615
                "movq %%mm1, %%mm5\n"
 
616
                "pcmpeqw %%mm6, %%mm2\n"
 
617
                "pcmpeqw %%mm6, %%mm4\n"
 
618
                "pcmpeqw (%2), %%mm3\n"
 
619
                "pcmpeqw (%2), %%mm5\n"
 
620
                "pandn %%mm2, %%mm3\n"
 
621
                "pandn %%mm4, %%mm5\n"
 
622
                "movq %%mm0, %%mm2\n"
 
623
                "movq %%mm1, %%mm4\n"
 
624
                "pcmpeqw %%mm1, %%mm2\n"
 
625
                "pcmpeqw %%mm0, %%mm4\n"
 
626
                "pandn %%mm3, %%mm2\n"
 
627
                "pandn %%mm5, %%mm4\n"
 
628
                "movq %%mm2, %%mm3\n"
 
629
                "movq %%mm4, %%mm5\n"
 
630
                "pand %%mm6, %%mm2\n"
 
631
                "pand %%mm6, %%mm4\n"
 
632
                "pandn %%mm7, %%mm3\n"
 
633
                "pandn %%mm7, %%mm5\n"
 
634
                "por %%mm3, %%mm2\n"
 
635
                "por %%mm5, %%mm4\n"
 
636
 
 
637
                /* set *dst */
 
638
                "movq %%mm2, %%mm3\n"
 
639
                "punpcklwd %%mm4, %%mm2\n"
 
640
                "punpckhwd %%mm4, %%mm3\n"
 
641
                "movq %%mm2, (%3)\n"
 
642
                "movq %%mm3, 8(%3)\n"
 
643
 
 
644
                : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
 
645
                :
 
646
                : "cc"
 
647
        );
 
648
}
 
649
 
 
650
static inline void scale2x_32_mmx_single(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)
 
651
{
 
652
        assert(count >= 4);
 
653
        assert(count % 2 == 0);
 
654
 
 
655
        /* always do the first and last run */
 
656
        count -= 2*2;
 
657
 
 
658
        __asm__ __volatile__(
 
659
/* first run */
 
660
                /* set the current, current_pre, current_next registers */
 
661
                "movq 0(%1), %%mm0\n"
 
662
                "movq 0(%1), %%mm7\n"
 
663
                "movq 8(%1), %%mm1\n"
 
664
                "psllq $32, %%mm0\n"
 
665
                "psllq $32, %%mm1\n"
 
666
                "psrlq $32, %%mm0\n"
 
667
                "movq %%mm7, %%mm2\n"
 
668
                "movq %%mm7, %%mm3\n"
 
669
                "psllq $32, %%mm2\n"
 
670
                "psrlq $32, %%mm3\n"
 
671
                "por %%mm2, %%mm0\n"
 
672
                "por %%mm3, %%mm1\n"
 
673
 
 
674
                /* current_upper */
 
675
                "movq (%0), %%mm6\n"
 
676
 
 
677
                /* compute the upper-left pixel for dst on %%mm2 */
 
678
                /* compute the upper-right pixel for dst on %%mm4 */
 
679
                "movq %%mm0, %%mm2\n"
 
680
                "movq %%mm1, %%mm4\n"
 
681
                "movq %%mm0, %%mm3\n"
 
682
                "movq %%mm1, %%mm5\n"
 
683
                "pcmpeqd %%mm6, %%mm2\n"
 
684
                "pcmpeqd %%mm6, %%mm4\n"
 
685
                "pcmpeqd (%2), %%mm3\n"
 
686
                "pcmpeqd (%2), %%mm5\n"
 
687
                "pandn %%mm2, %%mm3\n"
 
688
                "pandn %%mm4, %%mm5\n"
 
689
                "movq %%mm0, %%mm2\n"
 
690
                "movq %%mm1, %%mm4\n"
 
691
                "pcmpeqd %%mm1, %%mm2\n"
 
692
                "pcmpeqd %%mm0, %%mm4\n"
 
693
                "pandn %%mm3, %%mm2\n"
 
694
                "pandn %%mm5, %%mm4\n"
 
695
                "movq %%mm2, %%mm3\n"
 
696
                "movq %%mm4, %%mm5\n"
 
697
                "pand %%mm6, %%mm2\n"
 
698
                "pand %%mm6, %%mm4\n"
 
699
                "pandn %%mm7, %%mm3\n"
 
700
                "pandn %%mm7, %%mm5\n"
 
701
                "por %%mm3, %%mm2\n"
 
702
                "por %%mm5, %%mm4\n"
 
703
 
 
704
                /* set *dst */
 
705
                "movq %%mm2, %%mm3\n"
 
706
                "punpckldq %%mm4, %%mm2\n"
 
707
                "punpckhdq %%mm4, %%mm3\n"
 
708
                "movq %%mm2, (%3)\n"
 
709
                "movq %%mm3, 8(%3)\n"
 
710
 
 
711
                /* next */
 
712
                "addl $8, %0\n"
 
713
                "addl $8, %1\n"
 
714
                "addl $8, %2\n"
 
715
                "addl $16, %3\n"
 
716
 
 
717
/* central runs */
 
718
                "shrl $1, %4\n"
 
719
                "jz 1f\n"
 
720
 
 
721
                "0:\n"
 
722
 
 
723
                /* set the current, current_pre, current_next registers */
 
724
                "movq -8(%1), %%mm0\n"
 
725
                "movq (%1), %%mm7\n"
 
726
                "movq 8(%1), %%mm1\n"
 
727
                "psrlq $32, %%mm0\n"
 
728
                "psllq $32, %%mm1\n"
 
729
                "movq %%mm7, %%mm2\n"
 
730
                "movq %%mm7, %%mm3\n"
 
731
                "psllq $32, %%mm2\n"
 
732
                "psrlq $32, %%mm3\n"
 
733
                "por %%mm2, %%mm0\n"
 
734
                "por %%mm3, %%mm1\n"
 
735
 
 
736
                /* current_upper */
 
737
                "movq (%0), %%mm6\n"
 
738
 
 
739
                /* compute the upper-left pixel for dst on %%mm2 */
 
740
                /* compute the upper-right pixel for dst on %%mm4 */
 
741
                "movq %%mm0, %%mm2\n"
 
742
                "movq %%mm1, %%mm4\n"
 
743
                "movq %%mm0, %%mm3\n"
 
744
                "movq %%mm1, %%mm5\n"
 
745
                "pcmpeqd %%mm6, %%mm2\n"
 
746
                "pcmpeqd %%mm6, %%mm4\n"
 
747
                "pcmpeqd (%2), %%mm3\n"
 
748
                "pcmpeqd (%2), %%mm5\n"
 
749
                "pandn %%mm2, %%mm3\n"
 
750
                "pandn %%mm4, %%mm5\n"
 
751
                "movq %%mm0, %%mm2\n"
 
752
                "movq %%mm1, %%mm4\n"
 
753
                "pcmpeqd %%mm1, %%mm2\n"
 
754
                "pcmpeqd %%mm0, %%mm4\n"
 
755
                "pandn %%mm3, %%mm2\n"
 
756
                "pandn %%mm5, %%mm4\n"
 
757
                "movq %%mm2, %%mm3\n"
 
758
                "movq %%mm4, %%mm5\n"
 
759
                "pand %%mm6, %%mm2\n"
 
760
                "pand %%mm6, %%mm4\n"
 
761
                "pandn %%mm7, %%mm3\n"
 
762
                "pandn %%mm7, %%mm5\n"
 
763
                "por %%mm3, %%mm2\n"
 
764
                "por %%mm5, %%mm4\n"
 
765
 
 
766
                /* set *dst */
 
767
                "movq %%mm2, %%mm3\n"
 
768
                "punpckldq %%mm4, %%mm2\n"
 
769
                "punpckhdq %%mm4, %%mm3\n"
 
770
                "movq %%mm2, (%3)\n"
 
771
                "movq %%mm3, 8(%3)\n"
 
772
 
 
773
                /* next */
 
774
                "addl $8, %0\n"
 
775
                "addl $8, %1\n"
 
776
                "addl $8, %2\n"
 
777
                "addl $16, %3\n"
 
778
 
 
779
                "decl %4\n"
 
780
                "jnz 0b\n"
 
781
                "1:\n"
 
782
 
 
783
/* final run */
 
784
                /* set the current, current_pre, current_next registers */
 
785
                "movq (%1), %%mm1\n"
 
786
                "movq (%1), %%mm7\n"
 
787
                "movq -8(%1), %%mm0\n"
 
788
                "psrlq $32, %%mm1\n"
 
789
                "psrlq $32, %%mm0\n"
 
790
                "psllq $32, %%mm1\n"
 
791
                "movq %%mm7, %%mm2\n"
 
792
                "movq %%mm7, %%mm3\n"
 
793
                "psllq $32, %%mm2\n"
 
794
                "psrlq $32, %%mm3\n"
 
795
                "por %%mm2, %%mm0\n"
 
796
                "por %%mm3, %%mm1\n"
 
797
 
 
798
                /* current_upper */
 
799
                "movq (%0), %%mm6\n"
 
800
 
 
801
                /* compute the upper-left pixel for dst on %%mm2 */
 
802
                /* compute the upper-right pixel for dst on %%mm4 */
 
803
                "movq %%mm0, %%mm2\n"
 
804
                "movq %%mm1, %%mm4\n"
 
805
                "movq %%mm0, %%mm3\n"
 
806
                "movq %%mm1, %%mm5\n"
 
807
                "pcmpeqd %%mm6, %%mm2\n"
 
808
                "pcmpeqd %%mm6, %%mm4\n"
 
809
                "pcmpeqd (%2), %%mm3\n"
 
810
                "pcmpeqd (%2), %%mm5\n"
 
811
                "pandn %%mm2, %%mm3\n"
 
812
                "pandn %%mm4, %%mm5\n"
 
813
                "movq %%mm0, %%mm2\n"
 
814
                "movq %%mm1, %%mm4\n"
 
815
                "pcmpeqd %%mm1, %%mm2\n"
 
816
                "pcmpeqd %%mm0, %%mm4\n"
 
817
                "pandn %%mm3, %%mm2\n"
 
818
                "pandn %%mm5, %%mm4\n"
 
819
                "movq %%mm2, %%mm3\n"
 
820
                "movq %%mm4, %%mm5\n"
 
821
                "pand %%mm6, %%mm2\n"
 
822
                "pand %%mm6, %%mm4\n"
 
823
                "pandn %%mm7, %%mm3\n"
 
824
                "pandn %%mm7, %%mm5\n"
 
825
                "por %%mm3, %%mm2\n"
 
826
                "por %%mm5, %%mm4\n"
 
827
 
 
828
                /* set *dst */
 
829
                "movq %%mm2, %%mm3\n"
 
830
                "punpckldq %%mm4, %%mm2\n"
 
831
                "punpckhdq %%mm4, %%mm3\n"
 
832
                "movq %%mm2, (%3)\n"
 
833
                "movq %%mm3, 8(%3)\n"
 
834
 
 
835
                : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
 
836
                :
 
837
                : "cc"
 
838
        );
 
839
}
 
840
 
 
841
/**
 
842
 * Scale by a factor of 2 a row of pixels of 8 bits.
 
843
 * This is a very fast MMX implementation.
 
844
 * The implementation uses a combination of cmp/and/not operations to
 
845
 * completly remove the need of conditional jumps. This trick give the
 
846
 * major speed improvement.
 
847
 * Also, using the 8 bytes MMX registers more than one pixel are computed
 
848
 * at the same time.
 
849
 * Before calling this function you must ensure that the currenct CPU supports
 
850
 * the MMX instruction set. After calling it you must be sure to call the EMMS
 
851
 * instruction before any floating-point operation.
 
852
 * The pixels over the left and right borders are assumed of the same color of
 
853
 * the pixels on the border.
 
854
 * \param src0 Pointer at the first pixel of the previous row.
 
855
 * \param src1 Pointer at the first pixel of the current row.
 
856
 * \param src2 Pointer at the first pixel of the next row.
 
857
 * \param count Length in pixels of the src0, src1 and src2 rows. It must
 
858
 * be at least 16 and a multiple of 8.
 
859
 * \param dst0 First destination row, double length in pixels.
 
860
 * \param dst1 Second destination row, double length in pixels.
 
861
 */
 
862
void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)
 
863
{
 
864
        if (count % 8 != 0 || count < 16) {
 
865
                scale2x_8_def(dst0, dst1, src0, src1, src2, count);
 
866
        } else {
 
867
                assert(count >= 16);
 
868
                assert(count % 8 == 0);
 
869
 
 
870
                scale2x_8_mmx_single(dst0, src0, src1, src2, count);
 
871
                scale2x_8_mmx_single(dst1, src2, src1, src0, count);
 
872
        }
 
873
}
 
874
 
 
875
/**
 
876
 * Scale by a factor of 2 a row of pixels of 16 bits.
 
877
 * This function operates like scale2x_8_mmx() but for 16 bits pixels.
 
878
 * \param src0 Pointer at the first pixel of the previous row.
 
879
 * \param src1 Pointer at the first pixel of the current row.
 
880
 * \param src2 Pointer at the first pixel of the next row.
 
881
 * \param count Length in pixels of the src0, src1 and src2 rows. It must
 
882
 * be at least 8 and a multiple of 4.
 
883
 * \param dst0 First destination row, double length in pixels.
 
884
 * \param dst1 Second destination row, double length in pixels.
 
885
 */
 
886
void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)
 
887
{
 
888
        if (count % 4 != 0 || count < 8) {
 
889
                scale2x_16_def(dst0, dst1, src0, src1, src2, count);
 
890
        } else {
 
891
                assert(count >= 8);
 
892
                assert(count % 4 == 0);
 
893
 
 
894
                scale2x_16_mmx_single(dst0, src0, src1, src2, count);
 
895
                scale2x_16_mmx_single(dst1, src2, src1, src0, count);
 
896
        }
 
897
}
 
898
 
 
899
/**
 
900
 * Scale by a factor of 2 a row of pixels of 32 bits.
 
901
 * This function operates like scale2x_8_mmx() but for 32 bits pixels.
 
902
 * \param src0 Pointer at the first pixel of the previous row.
 
903
 * \param src1 Pointer at the first pixel of the current row.
 
904
 * \param src2 Pointer at the first pixel of the next row.
 
905
 * \param count Length in pixels of the src0, src1 and src2 rows. It must
 
906
 * be at least 4 and a multiple of 2.
 
907
 * \param dst0 First destination row, double length in pixels.
 
908
 * \param dst1 Second destination row, double length in pixels.
 
909
 */
 
910
void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)
 
911
{
 
912
        if (count % 2 != 0 || count < 4) {
 
913
                scale2x_32_def(dst0, dst1, src0, src1, src2, count);
 
914
        } else {
 
915
                assert(count >= 4);
 
916
                assert(count % 2 == 0);
 
917
 
 
918
                scale2x_32_mmx_single(dst0, src0, src1, src2, count);
 
919
                scale2x_32_mmx_single(dst1, src2, src1, src0, count);
 
920
        }
 
921
}
 
922
 
 
923
#endif
 
924