Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gsroprun.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Runs of RasterOps */
18
#include "std.h"
19
#include "stdpre.h"
20
#include "gsropt.h"
21
#include "gp.h"
22
#include "gxcindex.h"
23
24
/* Enable the following define to use 'template'd code (code formed by
25
 * repeated #inclusion of a header file to generate differen versions).
26
 * This code should be faster as it uses native ints where possible.
27
 * Eventually this should be the only type of code left in here and we can
28
 * remove this define. */
29
#define USE_TEMPLATES
30
31
/* Enable the following define to disable all rops (at least, all the ones
32
 * done using the rop run mechanism. For debugging only. */
33
#undef DISABLE_ROPS
34
35
/* A hack. Define this, and we will update the rop usage within a file. */
36
#undef RECORD_ROP_USAGE
37
38
/* Values used for defines used when including 'template' headers. */
39
#define MAYBE 0
40
#define YES   1
41
42
#ifdef RECORD_ROP_USAGE
43
#define MAX (1024<<7)
44
static int usage[MAX*3];
45
46
static int inited = 0;
47
48
static void write_usage(void)
49
{
50
    int i;
51
    for (i = 0; i < MAX; i++)
52
        if (usage[3*i] != 0) {
53
            int depth = ((i>>4)&3)<<3;
54
            if (depth == 0) depth = 1;
55
            if (i & (1<<6))
56
               (fprintf)(stderr, "ROP: rop=%x ", i>>7);
57
            else
58
               (fprintf)(stderr, "ROP: rop=ANY ");
59
           (fprintf)(stderr, "depth=%d flags=%d gets=%d inits=%d pixels=%d\n",
60
                     depth, i&15, usage[3*i], usage[3*i+1], usage[3*i+2]);
61
        }
62
#ifdef RECORD_BINARY
63
    {
64
    FILE *out = fopen("ropusage2.tmp", "wb");
65
    if (!out)
66
        return;
67
    fwrite(usage, sizeof(int), (1024<<7), out);
68
    fclose(out);
69
    }
70
#endif
71
}
72
73
static void record(int rop)
74
{
75
    if (inited == 0) {
76
#ifdef RECORD_BINARY
77
        FILE *in = fopen("ropusage2.tmp", "r");
78
        if (!in)
79
            memset(usage, 0, MAX*sizeof(int));
80
        else {
81
            fread(usage, sizeof(int), MAX, in);
82
            fclose(in);
83
        }
84
#endif
85
        memset(usage, 0, MAX*3*sizeof(int));
86
        atexit(write_usage);
87
        inited = 1;
88
    }
89
90
    usage[3*rop]++;
91
}
92
#endif
93
94
#define get24(ptr)\
95
  (((rop_operand)(ptr)[0] << 16) | ((rop_operand)(ptr)[1] << 8) | (ptr)[2])
96
#define put24(ptr, pixel)\
97
  (ptr)[0] = (byte)((pixel) >> 16),\
98
  (ptr)[1] = (byte)((uint)(pixel) >> 8),\
99
  (ptr)[2] = (byte)(pixel)
100
101
/* Rop specific code */
102
/* Rop 0x55 = Invert   dep=1  (all cases) */
103
#ifdef USE_TEMPLATES
104
#define TEMPLATE_NAME          invert_rop_run1
105
#define SPECIFIC_ROP           0x55
106
0
#define SPECIFIC_CODE(O,D,S,T) do { O = ~D; } while (0)
107
#define MM_SETUP() static __m128i mm_constant_zeros; __m128i mm_constant_ones = _mm_cmpeq_epi32(mm_constant_zeros, mm_constant_zeros);
108
#define MM_SPECIFIC_CODE(O,D,S,T) do { _mm_storeu_si128(O,_mm_xor_si128(_mm_loadu_si128(D),mm_constant_ones)); } while (0 == 1)
109
#define S_CONST
110
#define T_CONST
111
#include "gsroprun1.h"
112
#else
113
static void invert_rop_run1(rop_run_op *op, byte *d, int len)
114
{
115
    byte lmask, rmask;
116
117
    len    = len * op->depth + op->dpos;
118
    /* lmask = the set of bits to alter in the output bitmap on the left
119
     * hand edge of the run. rmask = the set of bits NOT to alter in the
120
     * output bitmap on the right hand edge of the run. */
121
    lmask  = 255>>(7 & op->dpos);
122
    rmask  = 255>>(7 & len);
123
124
    len -= 8;
125
    if (len < 0) {
126
        /* Short case - starts and ends in the same byte */
127
        lmask &= ~rmask; /* Combined mask = bits to alter */
128
        *d = (*d & ~lmask) | ((~*d) & lmask);
129
        return;
130
    }
131
    if (lmask != 0xFF) {
132
        *d = (*d & ~lmask) | ((~*d) & lmask);
133
        d++;
134
        len -= 8;
135
    }
136
    if (len >= 0) {
137
        /* Simple middle case (complete destination bytes). */
138
        do {
139
            *d = ~*d;
140
            d++;
141
            len -= 8;
142
        } while (len >= 0);
143
    }
144
    if (rmask != 0xFF) {
145
        /* Unaligned right hand case */
146
        *d = ((~*d) & ~rmask) | (*d & rmask);
147
    }
148
}
149
#endif
150
151
/* Rop 0x55 = Invert   dep=8  (all cases) */
152
#ifdef USE_TEMPLATES
153
#define TEMPLATE_NAME          invert_rop_run8
154
#define SPECIFIC_ROP           0x55
155
0
#define SPECIFIC_CODE(O,D,S,T) do { O = ~D; } while (0)
156
0
#define MM_SETUP() static __m128i mm_constant_zeros; __m128i mm_constant_ones = _mm_cmpeq_epi32(mm_constant_zeros, mm_constant_zeros);
157
0
#define MM_SPECIFIC_CODE(O,D,S,T) do { _mm_storeu_si128(O,_mm_xor_si128(_mm_loadu_si128(D),mm_constant_ones)); } while (0 == 1)
158
#define S_CONST
159
#define T_CONST
160
#include "gsroprun8.h"
161
#else
162
static void invert_rop_run8(rop_run_op *op, byte *d, int len)
163
{
164
    do {
165
        *d = ~*d;
166
        d++;
167
    }
168
    while (--len);
169
}
170
#endif
171
172
/* Rop 0x33 = ~s */
173
174
/* 0x33 = ~s  dep=1 t_constant */
175
#ifdef USE_TEMPLATES
176
#define TEMPLATE_NAME          notS_rop_run1_const_t
177
#define SPECIFIC_ROP           0x33
178
4.13M
#define SPECIFIC_CODE(O,D,S,T) do { O = ~S; } while (0)
179
#define T_CONST
180
#include "gsroprun1.h"
181
#else
182
static void notS_rop_run1_const_s(rop_run_op *op, byte *d, int len)
183
{
184
    byte        lmask, rmask;
185
    const byte *s = op->s.b.ptr;
186
    byte        S;
187
    int         s_skew;
188
189
    len    = len * op->depth + op->dpos;
190
    /* lmask = the set of bits to alter in the output bitmap on the left
191
     * hand edge of the run. rmask = the set of bits NOT to alter in the
192
     * output bitmap on the right hand edge of the run. */
193
    lmask  = 255>>(7 & op->dpos);
194
    rmask  = 255>>(7 & len);
195
196
    /* Note #1: This mirrors what the original code did, but I think it has
197
     * the risk of moving s and t back beyond officially allocated space. We
198
     * may be saved by the fact that all blocks have a word or two in front
199
     * of them due to the allocator. If we ever get valgrind properly marking
200
     * allocated blocks as readable etc, then this may throw some spurious
201
     * errors. RJW. */
202
    s_skew = op->t.b.pos - op->dpos;
203
    if (s_skew < 0) {
204
        s_skew += 8;
205
        s--;
206
    }
207
208
    len -= 8;
209
    if (len < 0) {
210
        /* Short case - starts and ends in the same byte */
211
        lmask &= ~rmask; /* Combined mask = bits to alter */
212
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
213
        *d = (*d & ~lmask) | (~S & lmask);
214
        return;
215
    }
216
    if (lmask != 0xFF) {
217
        /* Unaligned left hand case */
218
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
219
        s++;
220
        *d = (*d & ~lmask) | (~S & lmask);
221
        d++;
222
        len -= 8;
223
    }
224
    if (len >= 0) {
225
        /* Simple middle case (complete destination bytes). */
226
        if (s_skew == 0) {
227
            do {
228
                *d++ = ~*s++;
229
                len -= 8;
230
            } while (len >= 0);
231
        } else {
232
            do {
233
                S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
234
                s++;
235
                *d++ = ~S;
236
                len -= 8;
237
            } while (len >= 0);
238
        }
239
    }
240
    if (rmask != 0xFF) {
241
        /* Unaligned right hand case */
242
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
243
        *d = (~S & ~rmask) | (*d & rmask);
244
    }
245
}
246
#endif
247
248
/* Rop 0xEE = d|s */
249
250
/* 0xEE = d|s  dep=1 t_constant */
251
#ifdef USE_TEMPLATES
252
#define TEMPLATE_NAME          dors_rop_run1_const_t
253
#define SPECIFIC_ROP           0xEE
254
12.8M
#define SPECIFIC_CODE(O,D,S,T) do { O = D|S; } while (0)
255
#define T_CONST
256
#include "gsroprun1.h"
257
#else
258
static void dors_rop_run1_const_t(rop_run_op *op, byte *d, int len)
259
{
260
    byte        lmask, rmask;
261
    const byte *s = op->s.b.ptr;
262
    byte        S, D;
263
    int         s_skew;
264
265
    len    = len * op->depth + op->dpos;
266
    /* lmask = the set of bits to alter in the output bitmap on the left
267
     * hand edge of the run. rmask = the set of bits NOT to alter in the
268
     * output bitmap on the right hand edge of the run. */
269
    lmask  = 255>>(7 & op->dpos);
270
    rmask  = 255>>(7 & len);
271
272
    /* Note #1: This mirrors what the original code did, but I think it has
273
     * the risk of moving s and t back beyond officially allocated space. We
274
     * may be saved by the fact that all blocks have a word or two in front
275
     * of them due to the allocator. If we ever get valgrind properly marking
276
     * allocated blocks as readable etc, then this may throw some spurious
277
     * errors. RJW. */
278
    s_skew = op->s.b.pos - op->dpos;
279
    if (s_skew < 0) {
280
        s_skew += 8;
281
        s--;
282
    }
283
284
    len -= 8;
285
    if (len < 0) {
286
        /* Short case - starts and ends in the same byte */
287
        lmask &= ~rmask; /* Combined mask = bits to alter */
288
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
289
        D = *d | S;
290
        *d = (*d & ~lmask) | (D & lmask);
291
        return;
292
    }
293
    if (lmask != 0xFF) {
294
        /* Unaligned left hand case */
295
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
296
        s++;
297
        D = *d | S;
298
        *d = (*d & ~lmask) | (D & lmask);
299
        d++;
300
        len -= 8;
301
    }
302
    if (len >= 0) {
303
        /* Simple middle case (complete destination bytes). */
304
        if (s_skew == 0) {
305
            do {
306
                *d++ |= *s++;
307
                len -= 8;
308
            } while (len >= 0);
309
        } else {
310
            do {
311
                S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
312
                s++;
313
                *d |= S;
314
                d++;
315
                len -= 8;
316
            } while (len >= 0);
317
        }
318
    }
319
    if (rmask != 0xFF) {
320
        /* Unaligned right hand case */
321
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
322
        D = *d | S;
323
        *d = (D & ~rmask) | (*d & rmask);
324
    }
325
}
326
#endif
327
328
/* Rop 0x66 = d^s (and 0x5A = d^t) */
329
330
/* 0x66 = d^s  dep=1 t_constant */
331
#ifdef USE_TEMPLATES
332
#define TEMPLATE_NAME          xor_rop_run1_const_t
333
#define SPECIFIC_ROP           0x66
334
0
#define SPECIFIC_CODE(O,D,S,T) do { O = D^S; } while (0)
335
#define T_CONST
336
#include "gsroprun1.h"
337
#else
338
static void xor_rop_run1_const_t(rop_run_op *op, byte *d, int len)
339
{
340
    byte        lmask, rmask;
341
    const byte *s = op->s.b.ptr;
342
    byte        S, D;
343
    int         s_skew;
344
345
    len    = len * op->depth + op->dpos;
346
    /* lmask = the set of bits to alter in the output bitmap on the left
347
     * hand edge of the run. rmask = the set of bits NOT to alter in the
348
     * output bitmap on the right hand edge of the run. */
349
    lmask  = 255>>(7 & op->dpos);
350
    rmask  = 255>>(7 & len);
351
352
    /* Note #1: This mirrors what the original code did, but I think it has
353
     * the risk of moving s and t back beyond officially allocated space. We
354
     * may be saved by the fact that all blocks have a word or two in front
355
     * of them due to the allocator. If we ever get valgrind properly marking
356
     * allocated blocks as readable etc, then this may throw some spurious
357
     * errors. RJW. */
358
    s_skew = op->s.b.pos - op->dpos;
359
    if (s_skew < 0) {
360
        s_skew += 8;
361
        s--;
362
    }
363
364
    len -= 8;
365
    if (len < 0) {
366
        /* Short case - starts and ends in the same byte */
367
        lmask &= ~rmask; /* Combined mask = bits to alter */
368
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
369
        D = *d ^ S;
370
        *d = (*d & ~lmask) | (D & lmask);
371
        return;
372
    }
373
    if (lmask != 0xFF) {
374
        /* Unaligned left hand case */
375
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
376
        s++;
377
        D = *d ^ S;
378
        *d = (*d & ~lmask) | (D & lmask);
379
        d++;
380
        len -= 8;
381
    }
382
    if (len >= 0) {
383
        /* Simple middle case (complete destination bytes). */
384
        if (s_skew == 0) {
385
            do {
386
                *d++ ^= *s++;
387
                len -= 8;
388
            } while (len >= 0);
389
        } else {
390
            do {
391
                S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
392
                s++;
393
                *d = *d ^ S;
394
                d++;
395
                len -= 8;
396
            } while (len >= 0);
397
        }
398
    }
399
    if (rmask != 0xFF) {
400
        /* Unaligned right hand case */
401
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
402
        D = *d ^ S;
403
        *d = (D & ~rmask) | (*d & rmask);
404
    }
405
}
406
#endif
407
408
/* rop = 0x66 = d^s  dep=8  s_constant t_constant */
409
#ifdef USE_TEMPLATES
410
#define TEMPLATE_NAME          xor_rop_run8_const_st
411
#define SPECIFIC_ROP           0x66
412
0
#define SPECIFIC_CODE(O,D,S,T) do { O = D^S; } while (0)
413
0
#define MM_SPECIFIC_CODE(O,D,S,T) do { _mm_storeu_si128(O,_mm_xor_si128(_mm_loadu_si128(D),S)); } while (0 == 1)
414
#define S_CONST
415
#define T_CONST
416
#include "gsroprun8.h"
417
#else
418
static void xor_rop_run8_const_st(rop_run_op *op, byte *d, int len)
419
{
420
    const byte S = op->s.c;
421
    if (S == 0)
422
        return;
423
    do {
424
        *d ^= S;
425
        d++;
426
    }
427
    while (--len);
428
}
429
#endif
430
431
/* rop = 0x66 = d^s  dep=24  s_constant t_constant */
432
#ifdef USE_TEMPLATES
433
#define TEMPLATE_NAME          xor_rop_run24_const_st
434
#define SPECIFIC_ROP           0x66
435
0
#define SPECIFIC_CODE(O,D,S,T) do { O = D^S; } while (0)
436
#define S_CONST
437
#define T_CONST
438
#include "gsroprun24.h"
439
#else
440
static void xor_rop_run24_const_st(rop_run_op *op, byte *d, int len)
441
{
442
    rop_operand S = op->s.c;
443
    if (S == 0)
444
        return;
445
    do
446
    {
447
        rop_operand D = get24(d) ^ S;
448
        put24(d, D);
449
        d += 3;
450
    }
451
    while (--len);
452
}
453
#endif
454
455
/* rop = 0xAA = d  dep=?  s_constant t_constant */
456
static void nop_rop_const_st(rop_run_op *op, byte *d, int len)
457
0
{
458
0
}
459
460
/* rop = 0xCC = s dep=1 t_constant */
461
#ifdef USE_TEMPLATES
462
#define TEMPLATE_NAME          sets_rop_run1
463
#define SPECIFIC_ROP           0xCC
464
1.11G
#define SPECIFIC_CODE(O,D,S,T) do { O = S; } while (0)
465
#define T_CONST
466
#include "gsroprun1.h"
467
#else
468
static void sets_rop_run1(rop_run_op *op, byte *d, int len)
469
{
470
    rop_proc    proc = rop_proc_table[op->rop];
471
    byte        lmask, rmask;
472
    byte        S, D;
473
    const byte *s = op->s.b.ptr;
474
    int         s_skew;
475
476
    len    = len*op->depth + op->dpos;
477
    /* lmask = the set of bits to alter in the output bitmap on the left
478
     * hand edge of the run. rmask = the set of bits NOT to alter in the
479
     * output bitmap on the right hand edge of the run. */
480
    lmask  = 255>>(7 & op->dpos);
481
    rmask  = 255>>(7 & len);
482
483
    /* See note #1 above. RJW. */
484
    s_skew = op->s.b.pos - op->dpos;
485
    if (s_skew < 0) {
486
        s_skew += 8;
487
        s--;
488
    }
489
490
    len -= 8;
491
    if (len < 0) {
492
        /* Short case - starts and ends in the same byte */
493
        lmask &= ~rmask; /* Combined mask = bits to alter */
494
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
495
        D = proc(*d, S, 0);
496
        *d = (*d & ~lmask) | (D & lmask);
497
        return;
498
    }
499
    if (lmask != 0xFF) {
500
        /* Unaligned left hand case */
501
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
502
        s++;
503
        D = proc(*d, S, 0);
504
        *d = (*d & ~lmask) | (D & lmask);
505
        d++;
506
        len -= 8;
507
    }
508
    if (len >= 0) {
509
        /* Simple middle case (complete destination bytes). */
510
        if (s_skew == 0) {
511
            do {
512
                *d = proc(*d, *s++, 0);
513
                d++;
514
                len -= 8;
515
            } while (len >= 0);
516
        } else {
517
            do {
518
                S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
519
                s++;
520
                *d = proc(*d, S, 0);
521
                d++;
522
                len -= 8;
523
            } while (len >= 0);
524
        }
525
    }
526
    if (rmask != 0xFF) {
527
        /* Unaligned right hand case */
528
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
529
        D = proc(*d, S, 0);
530
        *d = (D & ~rmask) | (*d & rmask);
531
    }
532
}
533
#endif
534
535
/* rop = 0xCC = s dep=8 s_constant | t_constant */
536
#ifdef USE_TEMPLATES
537
#define TEMPLATE_NAME          sets_rop_run8
538
#define SPECIFIC_ROP           0xCC
539
0
#define SPECIFIC_CODE(O,D,S,T) do { O = S; } while (0)
540
0
#define MM_SPECIFIC_CODE(O,D,S,T) do { _mm_storeu_si128(O,S); } while (0 == 1)
541
#define S_CONST
542
#define T_CONST
543
#include "gsroprun8.h"
544
#else
545
static void sets_rop_run8(rop_run_op *op, byte *d, int len)
546
{
547
    const byte S = op->s.c;
548
    do {
549
        *d++ = S;
550
    }
551
    while (--len);
552
}
553
#endif
554
555
/* rop = 0xCC = s dep=24 s_constant | t_constant */
556
#ifdef USE_TEMPLATES
557
#define TEMPLATE_NAME          sets_rop_run24
558
#define SPECIFIC_ROP           0xCC
559
0
#define SPECIFIC_CODE(O,D,S,T) do { O = S; } while (0)
560
#define S_CONST
561
#define T_CONST
562
#include "gsroprun24.h"
563
#else
564
static void copys_rop_run24(rop_run_op *op, byte *d, int len)
565
{
566
    rop_operand S = op->s.c;
567
    {
568
        put24(d, S);
569
        d += 3;
570
    }
571
    while (--len);
572
}
573
#endif
574
575
/* Generic ROP run code */
576
#ifdef USE_TEMPLATES
577
#define TEMPLATE_NAME          generic_rop_run1
578
#include "gsroprun1.h"
579
#else
580
static void generic_rop_run1(rop_run_op *op, byte *d, int len)
581
{
582
    rop_proc    proc = rop_proc_table[op->rop];
583
    byte        lmask, rmask;
584
    const byte *s = op->s.b.ptr;
585
    const byte *t = op->t.b.ptr;
586
    byte        S, T, D;
587
    int         s_skew, t_skew;
588
589
    len    = len * op->depth + op->dpos;
590
    /* lmask = the set of bits to alter in the output bitmap on the left
591
     * hand edge of the run. rmask = the set of bits NOT to alter in the
592
     * output bitmap on the right hand edge of the run. */
593
    lmask  = 255>>(7 & op->dpos);
594
    rmask  = 255>>(7 & len);
595
596
    /* Note #1: This mirrors what the original code did, but I think it has
597
     * the risk of moving s and t back beyond officially allocated space. We
598
     * may be saved by the fact that all blocks have a word or two in front
599
     * of them due to the allocator. If we ever get valgrind properly marking
600
     * allocated blocks as readable etc, then this may throw some spurious
601
     * errors. RJW. */
602
    s_skew = op->s.b.pos - op->dpos;
603
    if (s_skew < 0) {
604
        s_skew += 8;
605
        s--;
606
    }
607
    t_skew = op->t.b.pos - op->dpos;
608
    if (t_skew < 0) {
609
        t_skew += 8;
610
        t--;
611
    }
612
613
    len -= 8;
614
    if (len < 0) {
615
        /* Short case - starts and ends in the same byte */
616
        lmask &= ~rmask; /* Combined mask = bits to alter */
617
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
618
        T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
619
        D = proc(*d, S, T);
620
        *d = (*d & ~lmask) | (D & lmask);
621
        return;
622
    }
623
    if (lmask != 0xFF) {
624
        /* Unaligned left hand case */
625
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
626
        s++;
627
        T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
628
        t++;
629
        D = proc(*d, S, T);
630
        *d = (*d & ~lmask) | (D & lmask);
631
        d++;
632
        len -= 8;
633
    }
634
    if (len >= 0) {
635
        /* Simple middle case (complete destination bytes). */
636
        if (s_skew == 0) {
637
            if (t_skew == 0) {
638
                do {
639
                    *d = proc(*d, *s++, *t++);
640
                    d++;
641
                    len -= 8;
642
                } while (len >= 0);
643
            } else {
644
                do {
645
                    T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
646
                    t++;
647
                    *d = proc(*d, *s++, T);
648
                    d++;
649
                    len -= 8;
650
                } while (len >= 0);
651
            }
652
        } else {
653
            if (t_skew == 0) {
654
                do {
655
                    S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
656
                    s++;
657
                    *d = proc(*d, S, *t++);
658
                    d++;
659
                    len -= 8;
660
                } while (len >= 0);
661
            } else {
662
                do {
663
                    S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
664
                    s++;
665
                    T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
666
                    t++;
667
                    *d = proc(*d, S, T);
668
                    d++;
669
                    len -= 8;
670
                } while (len >= 0);
671
            }
672
        }
673
    }
674
    if (rmask != 0xFF) {
675
        /* Unaligned right hand case */
676
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
677
        T = (t[0]<<t_skew) | (t[1]>>(8-t_skew));
678
        D = proc(*d, S, T);
679
        *d = (D & ~rmask) | (*d & rmask);
680
    }
681
}
682
#endif
683
684
#ifdef USE_TEMPLATES
685
#define TEMPLATE_NAME          generic_rop_run8
686
#include "gsroprun8.h"
687
#else
688
static void generic_rop_run8(rop_run_op *op, byte *d, int len)
689
{
690
    rop_proc    proc = rop_proc_table[op->rop];
691
    const byte *s = op->s.b.ptr;
692
    const byte *t = op->t.b.ptr;
693
    do {
694
        *d = proc(*d, *s++, *t++);
695
        d++;
696
    }
697
    while (--len);
698
}
699
#endif
700
701
#ifdef USE_TEMPLATES
702
#define TEMPLATE_NAME          generic_rop_run8_1bit
703
#define S_TRANS MAYBE
704
#define T_TRANS MAYBE
705
#define S_1BIT  MAYBE
706
#define T_1BIT  MAYBE
707
#include "gsroprun8.h"
708
#else
709
static void generic_rop_run8_1bit(rop_run_op *op, byte *d, int len)
710
{
711
    rop_proc     proc = rop_proc_table[lop_rop(op->rop)];
712
    const byte  *s = op->s.b.ptr;
713
    const byte  *t = op->t.b.ptr;
714
    int          sroll, troll;
715
    const gx_color_index *scolors = op->scolors;
716
    const gx_color_index *tcolors = op->tcolors;
717
    if (op->flags & rop_s_1bit) {
718
        s = op->s.b.ptr + (op->s.b.pos>>3);
719
        sroll = 8-(op->s.b.pos & 7);
720
    } else
721
        sroll = 0;
722
    if (op->flags & rop_t_1bit) {
723
        t = op->t.b.ptr + (op->t.b.pos>>3);
724
        troll = 8-(op->t.b.pos & 7);
725
    } else
726
        troll = 0;
727
    do {
728
        rop_operand S, T;
729
        if (sroll == 0)
730
            S = *s++;
731
        else {
732
            --sroll;
733
            S = scolors[(*s >> sroll) & 1];
734
            if (sroll == 0) {
735
                sroll = 8;
736
                s++;
737
            }
738
        }
739
        if (troll == 0)
740
            T = *t++;
741
        else {
742
            --troll;
743
            T = tcolors[(*t >> troll) & 1];
744
            if (troll == 0) {
745
                troll = 8;
746
                t++;
747
            }
748
        }
749
        *d = proc(*d, S, T);
750
        d++;
751
    }
752
    while (--len);
753
}
754
#endif
755
756
#ifdef USE_TEMPLATES
757
#define TEMPLATE_NAME          generic_rop_run24
758
#include "gsroprun24.h"
759
#else
760
static void generic_rop_run24(rop_run_op *op, byte *d, int len)
761
{
762
    rop_proc    proc = rop_proc_table[op->rop];
763
    const byte *s = op->s.b.ptr;
764
    const byte *t = op->t.b.ptr;
765
    do
766
    {
767
        rop_operand D = proc(get24(d), get24(s), get24(t));
768
        put24(d, D);
769
        s += 3;
770
        t += 3;
771
        d += 3;
772
    }
773
    while (--len);
774
}
775
#endif
776
777
#ifdef USE_TEMPLATES
778
#define TEMPLATE_NAME          generic_rop_run24_1bit
779
#define S_TRANS MAYBE
780
#define T_TRANS MAYBE
781
#define S_1BIT MAYBE
782
#define T_1BIT MAYBE
783
#include "gsroprun24.h"
784
#else
785
static void generic_rop_run24_1bit(rop_run_op *op, byte *d, int len)
786
{
787
    rop_proc     proc = rop_proc_table[lop_rop(op->rop)];
788
    const byte  *s = op->s.b.ptr;
789
    const byte  *t = op->t.b.ptr;
790
    int          sroll, troll;
791
    const gx_color_index *scolors = op->scolors;
792
    const gx_color_index *tcolors = op->tcolors;
793
    if (op->flags & rop_s_1bit) {
794
        s = op->s.b.ptr + (op->s.b.pos>>3);
795
        sroll = 8-(op->s.b.pos & 7);
796
    } else
797
        sroll = 0;
798
    if (op->flags & rop_t_1bit) {
799
        t = op->t.b.ptr + (op->t.b.pos>>3);
800
        troll = 8-(op->t.b.pos & 7);
801
    } else
802
        troll = 0;
803
    do {
804
        rop_operand S, T;
805
        if (sroll == 0) {
806
            S = get24(s);
807
            s += 3;
808
        } else {
809
            --sroll;
810
            S = scolors[(*s >> sroll) & 1];
811
            if (sroll == 0) {
812
                sroll = 8;
813
                s++;
814
            }
815
        }
816
        if (troll == 0) {
817
            T = get24(t);
818
            t += 3;
819
        } else {
820
            --troll;
821
            T = tcolors[(*t >> troll) & 1];
822
            if (troll == 0) {
823
                troll = 8;
824
                t++;
825
            }
826
        }
827
        {
828
            rop_operand D = proc(get24(d), S, T);
829
            put24(d, D);
830
        }
831
        d += 3;
832
    }
833
    while (--len);
834
}
835
#endif
836
837
#ifdef USE_TEMPLATES
838
#define TEMPLATE_NAME          generic_rop_run1_const_t
839
#define T_CONST
840
#include "gsroprun1.h"
841
#else
842
static void generic_rop_run1_const_t(rop_run_op *op, byte *d, int len)
843
{
844
    rop_proc    proc = rop_proc_table[op->rop];
845
    byte        lmask, rmask;
846
    byte        T = (byte)op->t.c;
847
    byte        S, D;
848
    const byte *s = op->s.b.ptr;
849
    int         s_skew;
850
851
    /* T should be supplied as 'depth' bits. Duplicate that up to be byte
852
     * size (if it's supplied byte sized, that's fine too). */
853
    if (op->depth & 1)
854
        T |= T<<1;
855
    if (op->depth & 3)
856
        T |= T<<2;
857
    if (op->depth & 7)
858
        T |= T<<4;
859
860
    len    = len*op->depth + op->dpos;
861
    /* lmask = the set of bits to alter in the output bitmap on the left
862
     * hand edge of the run. rmask = the set of bits NOT to alter in the
863
     * output bitmap on the right hand edge of the run. */
864
    lmask  = 255>>(7 & op->dpos);
865
    rmask  = 255>>(7 & len);
866
867
    /* See note #1 above. RJW. */
868
    s_skew = op->s.b.pos - op->dpos;
869
    if (s_skew < 0) {
870
        s_skew += 8;
871
        s--;
872
    }
873
874
    len -= 8;
875
    if (len < 0) {
876
        /* Short case - starts and ends in the same byte */
877
        lmask &= ~rmask; /* Combined mask = bits to alter */
878
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
879
        D = proc(*d, S, T);
880
        *d = (*d & ~lmask) | (D & lmask);
881
        return;
882
    }
883
    if (lmask != 0xFF) {
884
        /* Unaligned left hand case */
885
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
886
        s++;
887
        D = proc(*d, S, T);
888
        *d = (*d & ~lmask) | (D & lmask);
889
        d++;
890
        len -= 8;
891
    }
892
    if (len >= 0) {
893
        /* Simple middle case (complete destination bytes). */
894
        if (s_skew == 0) {
895
            do {
896
                *d = proc(*d, *s++, T);
897
                d++;
898
                len -= 8;
899
            } while (len >= 0);
900
        } else {
901
            do {
902
                S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
903
                s++;
904
                *d = proc(*d, S, T);
905
                d++;
906
                len -= 8;
907
            } while (len >= 0);
908
        }
909
    }
910
    if (rmask != 0xFF) {
911
        /* Unaligned right hand case */
912
        S = (s[0]<<s_skew) | (s[1]>>(8-s_skew));
913
        D = proc(*d, S, T);
914
        *d = (D & ~rmask) | (*d & rmask);
915
    }
916
}
917
#endif
918
919
#ifdef USE_TEMPLATES
920
#define TEMPLATE_NAME          generic_rop_run8_const_t
921
#define T_CONST
922
#include "gsroprun8.h"
923
#else
924
static void generic_rop_run8_const_t(rop_run_op *op, byte *d, int len)
925
{
926
    rop_proc    proc = rop_proc_table[op->rop];
927
    const byte *s = op->s.b.ptr;
928
    byte        t = op->t.c;
929
    do
930
    {
931
        *d = proc(*d, s, *t++);
932
        d++;
933
    }
934
    while (--len);
935
}
936
#endif
937
938
#ifdef USE_TEMPLATES
939
#define TEMPLATE_NAME          generic_rop_run8_1bit_const_t
940
#define S_TRANS MAYBE
941
#define S_1BIT YES
942
#define T_CONST
943
#include "gsroprun8.h"
944
#else
945
static void generic_rop_run8_1bit_const_t(rop_run_op *op, byte *d, int len)
946
{
947
    rop_proc     proc = rop_proc_table[lop_rop(op->rop)];
948
    byte         T = op->t.c;
949
    const byte  *s = op->s.b.ptr;
950
    int          sroll;
951
    const byte  *scolors = op->scolors;
952
    s = op->s.b.ptr + (op->s.b.pos>>3);
953
    sroll = 8-(op->s.b.pos & 7);
954
    do {
955
        rop_operand S;
956
        --sroll;
957
        S = scolors[(*s >> sroll) & 1];
958
        if (sroll == 0) {
959
            sroll = 8;
960
            s++;
961
        }
962
        *d++ = proc(*d, S, T);
963
    }
964
    while (--len);
965
}
966
#endif
967
968
#ifdef USE_TEMPLATES
969
#define TEMPLATE_NAME          generic_rop_run24_const_t
970
#define T_CONST
971
#include "gsroprun24.h"
972
#else
973
static void generic_rop_run24_const_t(rop_run_op *op, byte *d, int len)
974
{
975
    rop_proc     proc = rop_proc_table[op->rop];
976
    const byte  *s = op->s.b.ptr;
977
    rop_operand  T = op->t.c;
978
    do
979
    {
980
        rop_operand D = proc(get24(d), get24(s), T);
981
        put24(d, D);
982
        s += 3;
983
        d += 3;
984
    }
985
    while (--len);
986
}
987
#endif
988
989
#ifdef USE_TEMPLATES
990
#define TEMPLATE_NAME          generic_rop_run24_1bit_const_t
991
#define S_1BIT YES
992
#define S_TRANS MAYBE
993
#define T_CONST
994
#define T_TRANS MAYBE
995
#include "gsroprun24.h"
996
#else
997
static void generic_rop_run24_1bit_const_t(rop_run_op *op, byte *d, int len)
998
{
999
    rop_proc     proc = rop_proc_table[lop_rop(op->rop)];
1000
    rop_operand  T = op->t.c;
1001
    const byte  *s = op->s.b.ptr;
1002
    int          sroll;
1003
    const byte  *scolors = op->scolors;
1004
    rop_operand  sc[2];
1005
    s = op->s.b.ptr + (op->s.b.pos>>3);
1006
    sroll = 8-(op->s.b.pos & 7);
1007
    sc[0] = ((const gx_color_index *)op->scolors)[0];
1008
    sc[1] = ((const gx_color_index *)op->scolors)[3];
1009
    do {
1010
        rop_operand S, D;
1011
        --sroll;
1012
        S = sc[(*s >> sroll) & 1];
1013
        if (sroll == 0) {
1014
            sroll = 8;
1015
            s++;
1016
        }
1017
        D = proc(get24(d), S, T);
1018
        put24(d, D);
1019
        d += 3;
1020
    }
1021
    while (--len);
1022
}
1023
#endif
1024
1025
#ifdef USE_TEMPLATES
1026
#define TEMPLATE_NAME          generic_rop_run1_const_st
1027
#define T_CONST
1028
#define S_CONST
1029
#include "gsroprun1.h"
1030
#else
1031
static void generic_rop_run1_const_st(rop_run_op *op, byte *d, int len)
1032
{
1033
    rop_proc proc = rop_proc_table[op->rop];
1034
    byte     lmask, rmask;
1035
    byte     S = (byte)op->s.c;
1036
    byte     T = (byte)op->t.c;
1037
    byte     D;
1038
1039
    /* S and T should be supplied as 'depth' bits. Duplicate them up to be
1040
     * byte size (if they are supplied byte sized, that's fine too). */
1041
    if (op->depth & 1) {
1042
        S |= S<<1;
1043
        T |= T<<1;
1044
    }
1045
    if (op->depth & 3) {
1046
        S |= S<<2;
1047
        T |= T<<2;
1048
    }
1049
    if (op->depth & 7) {
1050
        S |= S<<4;
1051
        T |= T<<4;
1052
    }
1053
1054
    len    = len*op->depth + op->dpos;
1055
    /* lmask = the set of bits to alter in the output bitmap on the left
1056
     * hand edge of the run. rmask = the set of bits NOT to alter in the
1057
     * output bitmap on the right hand edge of the run. */
1058
    lmask  = 255>>(7 & op->dpos);
1059
    rmask  = 255>>(7 & len);
1060
1061
    len -= 8;
1062
    if (len < 0) {
1063
        /* Short case - starts and ends in the same byte */
1064
        lmask &= ~rmask; /* Combined mask = bits to alter */
1065
        D = proc(*d, S, T);
1066
        *d = (*d & ~lmask) | (D & lmask);
1067
        return;
1068
    }
1069
    if (lmask != 0xFF) {
1070
        /* Unaligned left hand case */
1071
        D = proc(*d, S, T);
1072
        *d = (*d & ~lmask) | (D & lmask);
1073
        d++;
1074
        len -= 8;
1075
    }
1076
    while (len >= 0) {
1077
        /* Simple middle case (complete destination bytes). */
1078
        *d = proc(*d, S, T);
1079
        d++;
1080
        len -= 8;
1081
    }
1082
    if (rmask != 0xFF) {
1083
        /* Unaligned right hand case */
1084
        D = proc(*d, S, T);
1085
        *d = (D & ~rmask) | (*d & rmask);
1086
    }
1087
}
1088
#endif
1089
1090
#ifdef USE_TEMPLATES
1091
#define TEMPLATE_NAME          generic_rop_run8_const_st
1092
#define S_CONST
1093
#define T_CONST
1094
#include "gsroprun8.h"
1095
#else
1096
static void generic_rop_run8_const_st(rop_run_op *op, byte *d, int len)
1097
{
1098
    rop_proc proc = rop_proc_table[op->rop];
1099
    byte     s = op->s.c;
1100
    byte     t = op->t.c;
1101
    do
1102
    {
1103
        *d = proc(*d, s, t);
1104
        d++;
1105
    }
1106
    while (--len);
1107
}
1108
#endif
1109
1110
#ifdef USE_TEMPLATES
1111
#define TEMPLATE_NAME          generic_rop_run24_const_st
1112
#define S_CONST
1113
#define T_CONST
1114
#include "gsroprun24.h"
1115
#else
1116
static void generic_rop_run24_const_st(rop_run_op *op, byte *d, int len)
1117
{
1118
    rop_proc    proc = rop_proc_table[op->rop];
1119
    rop_operand s    = op->s.c;
1120
    rop_operand t    = op->t.c;
1121
    do
1122
    {
1123
        rop_operand D = proc(get24(d), s, t);
1124
        put24(d, D);
1125
        d += 3;
1126
    }
1127
    while (--len);
1128
}
1129
#endif
1130
1131
#ifdef RECORD_ROP_USAGE
1132
static void record_run(rop_run_op *op, byte *d, int len)
1133
{
1134
    rop_run_op local;
1135
1136
    usage[(int)op->opaque*3 + 1]++;
1137
    usage[(int)op->opaque*3 + 2] += len;
1138
1139
    local.run     = op->runswap;
1140
    local.s       = op->s;
1141
    local.t       = op->t;
1142
    local.scolors = op->scolors;
1143
    local.tcolors = op->tcolors;
1144
    local.rop     = op->rop;
1145
    local.depth   = op->depth;
1146
    local.flags   = op->flags;
1147
    local.dpos    = op->dpos;
1148
    local.release = op->release;
1149
    local.opaque  = op->opaque;
1150
    local.mul     = op->mul;
1151
1152
    op->runswap(&local, d, len);
1153
}
1154
#endif
1155
1156
static void rop_run_swapped(rop_run_op *op, byte *d, int len)
1157
0
{
1158
0
    rop_run_op local;
1159
1160
#ifdef RECORD_ROP_USAGE
1161
    usage[(int)op->opaque*3 + 1]++;
1162
    usage[(int)op->opaque*3 + 2] += len;
1163
#endif
1164
1165
0
    local.run     = op->runswap;
1166
0
    local.s       = op->t;
1167
0
    local.t       = op->s;
1168
0
    local.scolors = op->tcolors;
1169
0
    local.tcolors = op->scolors;
1170
0
    local.rop     = op->rop;
1171
0
    local.depth   = op->depth;
1172
0
    local.flags   = op->flags;
1173
0
    local.dpos    = op->dpos;
1174
0
    local.release = op->release;
1175
0
    local.opaque  = op->opaque;
1176
0
    local.mul     = op->mul;
1177
1178
0
    op->runswap(&local, d, len);
1179
0
}
1180
1181
int rop_get_run_op(rop_run_op *op, int lop, int depth, int flags)
1182
32.8M
{
1183
32.8M
    int key;
1184
32.8M
    int swap = 0;
1185
1186
#ifdef DISABLE_ROPS
1187
    lop = 0xAA;
1188
#endif
1189
1190
32.8M
    lop = lop_sanitize(lop);
1191
1192
    /* This is a simple initialisation to quiet a Coverity warning. It complains that
1193
     * the 'if (swap)' at the end of the function uses 'run' uninitialised. While its
1194
     * true that some ROPs do not instantly set the run member, they go through code
1195
     * which, I believe, swaps the lop source and texture, then executes the switch
1196
     * statement once more and the second execution sets run. So in summary I don't
1197
     * think this is a real problem, and this fixes the Coverity warning.
1198
     */
1199
32.8M
    op->run = 0;
1200
1201
    /* If the lop ignores either S or T, then we might as well set them to
1202
     * be constants; will save us slaving through memory. */
1203
32.8M
    if (!rop3_uses_S(lop)) {
1204
0
        flags |= rop_s_constant;
1205
0
        flags &= ~rop_s_1bit;
1206
0
    }
1207
32.8M
    if (!rop3_uses_T(lop)) {
1208
32.8M
        flags |= rop_t_constant;
1209
32.8M
        flags &= ~rop_t_1bit;
1210
32.8M
    }
1211
1212
    /* Cut down the number of cases. */
1213
    /* S or T can either be constant, bitmaps, or '1-bitmaps'
1214
     * (arrays of single bits to choose between 2 preset colors).
1215
     * If S or T is unused, then it will appear as constant.
1216
     */
1217
32.8M
    switch (flags)
1218
32.8M
    {
1219
0
    case rop_s_constant:              /* Map 'S constant,T bitmap' -> 'S bitmap,T constant' */
1220
0
    case rop_s_constant | rop_t_1bit: /* Map 'S constant,T 1-bitmap' -> 'S 1-bitmap,T constant' */
1221
0
    case rop_t_1bit:                  /* Map 'S bitmap,T 1-bitmap' -> 'S 1-bitmap,T bitmap' */
1222
0
        swap = 1;
1223
0
        break;
1224
0
    case rop_s_constant | rop_t_constant: /* Map 'S unused, T used' -> 'S used, T unused' */
1225
0
        swap = ((rop_usage_table[lop & 0xff] & (rop_usage_S | rop_usage_T)) == rop_usage_T);
1226
0
        break;
1227
32.8M
    }
1228
32.8M
    if (swap) {
1229
0
        flags = ((flags & rop_t_constant ? rop_s_constant : 0) |
1230
0
                 (flags & rop_s_constant ? rop_t_constant : 0) |
1231
0
                 (flags & rop_t_1bit     ? rop_s_1bit     : 0) |
1232
0
                 (flags & rop_s_1bit     ? rop_t_1bit     : 0));
1233
0
        lop = lop_swap_S_T(lop);
1234
0
    }
1235
    /* At this point, we know that in the ordering:
1236
     *   'unused' < 'constant' < 'bitmap' < '1-bitmap',
1237
     * that S >= T.
1238
     */
1239
1240
    /* Can we fold down from 24bit to 8bit? */
1241
32.8M
    op->mul = 1;
1242
32.8M
    if (depth == 24) {
1243
0
        switch (flags & (rop_s_constant | rop_s_1bit))
1244
0
        {
1245
0
        case 0: /* s is a bitmap. No good. */
1246
0
        case rop_s_1bit: /* s is 1 bit data. No good. */
1247
0
            goto no_fold_24_to_8;
1248
0
        case rop_s_constant: /* constant or unused */
1249
0
        {
1250
0
            rop_operand s = swap ? op->t.c : op->s.c;
1251
0
            if ((rop_usage_table[lop & 0xff] & rop_usage_S) &&
1252
0
                ((s & 0xff) != ((s>>8) & 0xff) ||
1253
0
                 (s & 0xff) != ((s>>16) & 0xff)))
1254
                /* USED, and a colour that doesn't work out the same in 8bits */
1255
0
                goto no_fold_24_to_8;
1256
0
            break;
1257
0
        }
1258
0
        }
1259
0
        switch (flags & (rop_t_constant | rop_t_1bit))
1260
0
        {
1261
0
        case 0: /* t is a bitmap. No good. */
1262
0
        case rop_t_1bit: /* t is 1 bit data. No good. */
1263
0
            goto no_fold_24_to_8;
1264
0
        case rop_t_constant: /* constant or unused */
1265
0
        {
1266
0
            rop_operand t = swap ? op->s.c : op->t.c;
1267
0
            if ((rop_usage_table[lop & 0xff] & rop_usage_T) &&
1268
0
                ((t & 0xff) != ((t>>8) & 0xff) ||
1269
0
                 (t & 0xff) != ((t>>16) & 0xff)))
1270
                /* USED, and a colour that doesn't work out the same in 8bits */
1271
0
                goto no_fold_24_to_8;
1272
0
            break;
1273
0
        }
1274
0
        }
1275
        /* We can safely fold down from 24 to 8 */
1276
0
        op->mul = 3;
1277
0
        depth = 8;
1278
0
    no_fold_24_to_8:{}
1279
0
    }
1280
1281
32.8M
    op->flags   = (flags & (rop_s_constant | rop_t_constant | rop_s_1bit | rop_t_1bit));
1282
32.8M
    op->depth   = (byte)depth;
1283
32.8M
    op->release = NULL;
1284
1285
    /* If S and T are constant, and the lop uses both of them, we can combine them.
1286
     * Currently this only works for cases where D is unused.
1287
     */
1288
32.8M
    if (op->flags == (rop_s_constant | rop_t_constant) &&
1289
32.8M
        rop_usage_table[lop & 0xff] == rop_usage_ST) {
1290
0
        switch (lop & (rop3_D>>rop3_D_shift)) /* Ignore the D bits */
1291
0
        {
1292
        /* Skip 0000 as doesn't use S or T */
1293
0
        case ((0<<6) | (0<<4) | (0<<2) | 1):
1294
0
            op->s.c = ~(op->s.c | op->t.c);
1295
0
            break;
1296
0
        case ((0<<6) | (0<<4) | (1<<2) | 0):
1297
0
            op->s.c = op->s.c & ~op->t.c;
1298
0
            break;
1299
        /* Skip 0011 as doesn't use S */
1300
0
        case ((0<<6) | (1<<4) | (0<<2) | 0):
1301
0
            op->s.c = ~op->s.c & op->t.c;
1302
0
            break;
1303
        /* Skip 0101 as doesn't use T */
1304
0
        case ((0<<6) | (1<<4) | (1<<2) | 0):
1305
0
            op->s.c = op->s.c ^ op->t.c;
1306
0
            break;
1307
0
        case ((0<<6) | (1<<4) | (1<<2) | 1):
1308
0
            op->s.c = ~(op->s.c & op->t.c);
1309
0
            break;
1310
0
        case ((1<<6) | (0<<4) | (0<<2) | 0):
1311
0
            op->s.c = op->s.c & op->t.c;
1312
0
            break;
1313
0
        case ((1<<6) | (0<<4) | (0<<2) | 1):
1314
0
            op->s.c = ~(op->s.c ^ op->t.c);
1315
0
            break;
1316
        /* Skip 1010 as doesn't use T */
1317
0
        case ((1<<6) | (0<<4) | (1<<2) | 1):
1318
0
            op->s.c = op->s.c | ~op->t.c;
1319
0
            break;
1320
        /* Skip 1100 as doesn't use S */
1321
0
        case ((1<<6) | (1<<4) | (0<<2) | 1):
1322
0
            op->s.c = ~op->s.c | op->t.c;
1323
0
            break;
1324
0
        case ((1<<6) | (1<<4) | (1<<2) | 0):
1325
0
            op->s.c = op->s.c | op->t.c;
1326
0
            break;
1327
        /* Skip 1111 as doesn't use S or T */
1328
0
        default:
1329
            /* Never happens */
1330
0
            break;
1331
0
        }
1332
0
        lop = (lop & ~0xff) | rop3_S;
1333
0
    }
1334
32.8M
    op->rop     = lop & 0xFF;
1335
1336
65.4M
#define ROP_SPECIFIC_KEY(lop, depth, flags) (((lop)<<7)+(1<<6)+((depth>>3)<<4)+(flags))
1337
32.8M
#define KEY_IS_ROP_SPECIFIC(key)            (key & (1<<6))
1338
32.8M
#define STRIP_ROP_SPECIFICITY(key)          (key &= ((1<<6)-1))
1339
32.8M
#define KEY(depth, flags)                   (((depth>>3)<<4)+(flags))
1340
1341
32.8M
    key = ROP_SPECIFIC_KEY(lop, depth, flags);
1342
#ifdef RECORD_ROP_USAGE
1343
    op->opaque = (void*)(key & (MAX-1));
1344
    record((int)op->opaque);
1345
#endif
1346
33.1M
retry:
1347
33.1M
    switch (key)
1348
33.1M
    {
1349
    /* First, the rop specific ones */
1350
    /* 0x33 = ~S */
1351
94.0k
    case ROP_SPECIFIC_KEY(0x33, 1, rop_t_constant):
1352
94.0k
        op->run     = notS_rop_run1_const_t;
1353
94.0k
        break;
1354
    /* 0x55 = Invert */
1355
0
    case ROP_SPECIFIC_KEY(0x55, 1, rop_s_constant | rop_t_constant):
1356
0
        op->run     = invert_rop_run1;
1357
0
        op->s.b.pos = 0;
1358
0
        op->t.b.pos = 0;
1359
0
        op->dpos    = 0;
1360
0
        break;
1361
0
    case ROP_SPECIFIC_KEY(0x55, 8, rop_s_constant | rop_t_constant): /* S & T UNUSED */
1362
0
        op->run     = invert_rop_run8;
1363
0
        break;
1364
    /* 0x66 = D xor S */
1365
0
    case ROP_SPECIFIC_KEY(0x66, 1, rop_t_constant):
1366
0
        op->run     = xor_rop_run1_const_t;
1367
0
        break;
1368
0
    case ROP_SPECIFIC_KEY(0x66, 8, rop_s_constant | rop_t_constant): /* T_UNUSED */
1369
0
        op->run     = xor_rop_run8_const_st;
1370
0
        break;
1371
0
    case ROP_SPECIFIC_KEY(0x66, 24, rop_s_constant | rop_t_constant): /* T_UNUSED */
1372
0
        op->run     = xor_rop_run24_const_st;
1373
0
        break;
1374
0
    case ROP_SPECIFIC_KEY(0xAA, 1, rop_s_constant | rop_t_constant): /* S & T UNUSED */
1375
0
    case ROP_SPECIFIC_KEY(0xAA, 8, rop_s_constant | rop_t_constant): /* S & T UNUSED */
1376
0
    case ROP_SPECIFIC_KEY(0xAA, 24, rop_s_constant | rop_t_constant):/* S & T UNUSED */
1377
0
        op->run     = nop_rop_const_st;
1378
0
        return 0;
1379
    /* 0xCC = S */
1380
32.3M
    case ROP_SPECIFIC_KEY(0xCC, 1, rop_t_constant): /* T_UNUSED */
1381
32.3M
        op->run     = sets_rop_run1;
1382
32.3M
        break;
1383
0
    case ROP_SPECIFIC_KEY(0xCC, 8, rop_s_constant | rop_t_constant): /* T_UNUSED */
1384
0
        op->run     = sets_rop_run8;
1385
0
        break;
1386
0
    case ROP_SPECIFIC_KEY(0xCC, 24, rop_s_constant | rop_t_constant): /* T_UNUSED */
1387
0
        op->run     = sets_rop_run24;
1388
0
        break;
1389
    /* 0xEE = D or S */
1390
120k
    case ROP_SPECIFIC_KEY(0xEE, 1, rop_t_constant):
1391
120k
        op->run     = dors_rop_run1_const_t;
1392
120k
        break;
1393
    /* Then the generic ones */
1394
0
    case KEY(1, 0):
1395
0
        op->run     = generic_rop_run1;
1396
0
        op->s.b.pos = 0;
1397
0
        op->t.b.pos = 0;
1398
0
        op->dpos    = 0;
1399
0
        break;
1400
0
    case KEY(8, 0):
1401
0
        op->run = generic_rop_run8;
1402
0
        break;
1403
0
    case KEY(8, rop_s_1bit):
1404
0
    case KEY(8, rop_s_1bit | rop_t_1bit ):
1405
0
        op->run = generic_rop_run8_1bit;
1406
0
        break;
1407
0
    case KEY(24, 0):
1408
0
        op->run   = generic_rop_run24;
1409
0
        break;
1410
0
    case KEY(24, rop_s_1bit):
1411
0
    case KEY(24, rop_s_1bit | rop_t_1bit ):
1412
0
        op->run = generic_rop_run24_1bit;
1413
0
        break;
1414
265k
    case KEY(1, rop_t_constant):
1415
265k
        op->run   = generic_rop_run1_const_t;
1416
265k
        op->s.b.pos = 0;
1417
265k
        op->t.b.pos = 0;
1418
265k
        op->dpos    = 0;
1419
265k
        break;
1420
0
    case KEY(8, rop_t_constant):
1421
0
        op->run   = generic_rop_run8_const_t;
1422
0
        break;
1423
0
    case KEY(8, rop_s_1bit | rop_t_constant):
1424
0
        op->run = generic_rop_run8_1bit_const_t;
1425
0
        break;
1426
0
    case KEY(24, rop_t_constant):
1427
0
        op->run   = generic_rop_run24_const_t;
1428
0
        break;
1429
0
    case KEY(24, rop_s_1bit | rop_t_constant):
1430
0
        op->run = generic_rop_run24_1bit_const_t;
1431
0
        break;
1432
0
    case KEY(1, rop_s_constant | rop_t_constant):
1433
0
        op->run   = generic_rop_run1_const_st;
1434
0
        op->s.b.pos = 0;
1435
0
        op->t.b.pos = 0;
1436
0
        op->dpos    = 0;
1437
0
        break;
1438
0
    case KEY(8, rop_s_constant | rop_t_constant):
1439
0
        op->run   = generic_rop_run8_const_st;
1440
0
        break;
1441
0
    case KEY(24, rop_s_constant | rop_t_constant):
1442
0
        op->run   = generic_rop_run24_const_st;
1443
0
        break;
1444
265k
    default:
1445
        /* If we failed to find a specific one for this rop value, try again
1446
         * for a generic one. */
1447
265k
        if (KEY_IS_ROP_SPECIFIC(key))
1448
265k
        {
1449
265k
            STRIP_ROP_SPECIFICITY(key);
1450
265k
            goto retry;
1451
265k
        }
1452
0
        eprintf1("This should never happen! key=%x\n", key);
1453
0
        break;
1454
33.1M
    }
1455
1456
32.8M
    if (swap)
1457
0
    {
1458
0
        op->runswap = op->run;
1459
0
        op->run = rop_run_swapped;
1460
0
    }
1461
#ifdef RECORD_ROP_USAGE
1462
    else
1463
    {
1464
        op->runswap = op->run;
1465
        op->run = record_run;
1466
    }
1467
#endif
1468
32.8M
    return 1;
1469
33.1M
}
1470
1471
void (rop_set_s_constant)(rop_run_op *op, int s)
1472
0
{
1473
0
    rop_set_s_constant(op, s);
1474
0
}
1475
1476
void (rop_set_s_bitmap)(rop_run_op *op, const byte *s)
1477
0
{
1478
0
    rop_set_s_bitmap(op, s);
1479
0
}
1480
1481
void (rop_set_s_bitmap_subbyte)(rop_run_op *op, const byte *s, int pos)
1482
0
{
1483
0
    rop_set_s_bitmap_subbyte(op, s, pos);
1484
0
}
1485
1486
void (rop_set_s_colors)(rop_run_op *op, const byte *scolors)
1487
0
{
1488
0
    rop_set_s_colors(op, scolors);
1489
0
}
1490
1491
void (rop_set_t_constant)(rop_run_op *op, int t)
1492
0
{
1493
0
    rop_set_t_constant(op, t);
1494
0
}
1495
1496
void (rop_set_t_bitmap)(rop_run_op *op, const byte *t)
1497
0
{
1498
0
    rop_set_t_bitmap(op, t);
1499
0
}
1500
1501
void (rop_set_t_bitmap_subbyte)(rop_run_op *op, const byte *t, int pos)
1502
0
{
1503
0
    rop_set_t_bitmap_subbyte(op, t, pos);
1504
0
}
1505
1506
void (rop_set_t_colors)(rop_run_op *op, const byte *tcolors)
1507
0
{
1508
0
    rop_set_t_colors(op, tcolors);
1509
0
}
1510
1511
void (rop_run)(rop_run_op *op, byte *d, int len)
1512
0
{
1513
0
    rop_run(op, d, len);
1514
0
}
1515
1516
void (rop_run_subbyte)(rop_run_op *op, byte *d, int start, int len)
1517
0
{
1518
0
    rop_run_subbyte(op, d, start, len);
1519
0
}
1520
1521
void (rop_release_run_op)(rop_run_op *op)
1522
0
{
1523
0
    rop_release_run_op(op);
1524
0
}