1 /* Copyright (C) 2001-2019 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.,  1305 Grant Avenue - Suite 200, Novato,
13    CA 94945, U.S.A., +1(415)492-9861, 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 
write_usage(void)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 
record(int rop)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 #define SPECIFIC_CODE(O,D,S,T) do { O = ~D; } while (0)
107 #define MM_SETUP() __m128i mm_constant_ones = _mm_cmpeq_epi32(mm_constant_ones, mm_constant_ones);
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
invert_rop_run1(rop_run_op * op,byte * d,int len)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 #define SPECIFIC_CODE(O,D,S,T) do { O = ~D; } while (0)
156 #define MM_SETUP() __m128i mm_constant_ones = _mm_cmpeq_epi32(mm_constant_ones, mm_constant_ones);
157 #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
invert_rop_run8(rop_run_op * op,byte * d,int len)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 #define SPECIFIC_CODE(O,D,S,T) do { O = ~S; } while (0)
179 #define T_CONST
180 #include "gsroprun1.h"
181 #else
notS_rop_run1_const_s(rop_run_op * op,byte * d,int len)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 #define SPECIFIC_CODE(O,D,S,T) do { O = D|S; } while (0)
255 #define T_CONST
256 #include "gsroprun1.h"
257 #else
dors_rop_run1_const_t(rop_run_op * op,byte * d,int len)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 #define SPECIFIC_CODE(O,D,S,T) do { O = D^S; } while (0)
335 #define T_CONST
336 #include "gsroprun1.h"
337 #else
xor_rop_run1_const_t(rop_run_op * op,byte * d,int len)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 #define SPECIFIC_CODE(O,D,S,T) do { O = D^S; } while (0)
413 #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
xor_rop_run8_const_st(rop_run_op * op,byte * d,int len)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 #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
xor_rop_run24_const_st(rop_run_op * op,byte * d,int len)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 */
nop_rop_const_st(rop_run_op * op,byte * d,int len)456 static void nop_rop_const_st(rop_run_op *op, byte *d, int len)
457 {
458 }
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 #define SPECIFIC_CODE(O,D,S,T) do { O = S; } while (0)
465 #define T_CONST
466 #include "gsroprun1.h"
467 #else
sets_rop_run1(rop_run_op * op,byte * d,int len)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 #define SPECIFIC_CODE(O,D,S,T) do { O = S; } while (0)
540 #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
sets_rop_run8(rop_run_op * op,byte * d,int len)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 #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
copys_rop_run24(rop_run_op * op,byte * d,int len)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
generic_rop_run1(rop_run_op * op,byte * d,int len)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
generic_rop_run8(rop_run_op * op,byte * d,int len)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
generic_rop_run8_1bit(rop_run_op * op,byte * d,int len)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
generic_rop_run24(rop_run_op * op,byte * d,int len)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
generic_rop_run24_1bit(rop_run_op * op,byte * d,int len)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
generic_rop_run1_const_t(rop_run_op * op,byte * d,int len)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
generic_rop_run8_const_t(rop_run_op * op,byte * d,int len)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
generic_rop_run8_1bit_const_t(rop_run_op * op,byte * d,int len)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
generic_rop_run24_const_t(rop_run_op * op,byte * d,int len)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
generic_rop_run24_1bit_const_t(rop_run_op * op,byte * d,int len)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
generic_rop_run1_const_st(rop_run_op * op,byte * d,int len)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
generic_rop_run8_const_st(rop_run_op * op,byte * d,int len)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
generic_rop_run24_const_st(rop_run_op * op,byte * d,int len)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
record_run(rop_run_op * op,byte * d,int len)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 
rop_run_swapped(rop_run_op * op,byte * d,int len)1156 static void rop_run_swapped(rop_run_op *op, byte *d, int len)
1157 {
1158     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     local.run     = op->runswap;
1166     local.s       = op->t;
1167     local.t       = op->s;
1168     local.scolors = op->tcolors;
1169     local.tcolors = op->scolors;
1170     local.rop     = op->rop;
1171     local.depth   = op->depth;
1172     local.flags   = op->flags;
1173     local.dpos    = op->dpos;
1174     local.release = op->release;
1175     local.opaque  = op->opaque;
1176     local.mul     = op->mul;
1177 
1178     op->runswap(&local, d, len);
1179 }
1180 
rop_get_run_op(rop_run_op * op,int lop,int depth,int flags)1181 int rop_get_run_op(rop_run_op *op, int lop, int depth, int flags)
1182 {
1183     int key;
1184     int swap = 0;
1185 
1186 #ifdef DISABLE_ROPS
1187     lop = 0xAA;
1188 #endif
1189 
1190     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     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     if (!rop3_uses_S(lop)) {
1204         flags |= rop_s_constant;
1205         flags &= ~rop_s_1bit;
1206     }
1207     if (!rop3_uses_T(lop)) {
1208         flags |= rop_t_constant;
1209         flags &= ~rop_t_1bit;
1210     }
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     switch (flags)
1218     {
1219     case rop_s_constant:              /* Map 'S constant,T bitmap' -> 'S bitmap,T constant' */
1220     case rop_s_constant | rop_t_1bit: /* Map 'S constant,T 1-bitmap' -> 'S 1-bitmap,T constant' */
1221     case rop_t_1bit:                  /* Map 'S bitmap,T 1-bitmap' -> 'S 1-bitmap,T bitmap' */
1222         swap = 1;
1223         break;
1224     case rop_s_constant | rop_t_constant: /* Map 'S unused, T used' -> 'S used, T unused' */
1225         swap = ((rop_usage_table[lop & 0xff] & (rop_usage_S | rop_usage_T)) == rop_usage_T);
1226         break;
1227     }
1228     if (swap) {
1229         flags = ((flags & rop_t_constant ? rop_s_constant : 0) |
1230                  (flags & rop_s_constant ? rop_t_constant : 0) |
1231                  (flags & rop_t_1bit     ? rop_s_1bit     : 0) |
1232                  (flags & rop_s_1bit     ? rop_t_1bit     : 0));
1233         lop = lop_swap_S_T(lop);
1234     }
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     op->mul = 1;
1242     if (depth == 24) {
1243         switch (flags & (rop_s_constant | rop_s_1bit))
1244         {
1245         case 0: /* s is a bitmap. No good. */
1246         case rop_s_1bit: /* s is 1 bit data. No good. */
1247             goto no_fold_24_to_8;
1248         case rop_s_constant: /* constant or unused */
1249         {
1250             rop_operand s = swap ? op->t.c : op->s.c;
1251             if ((rop_usage_table[lop & 0xff] & rop_usage_S) &&
1252                 ((s & 0xff) != ((s>>8) & 0xff) ||
1253                  (s & 0xff) != ((s>>16) & 0xff)))
1254                 /* USED, and a colour that doesn't work out the same in 8bits */
1255                 goto no_fold_24_to_8;
1256             break;
1257         }
1258         }
1259         switch (flags & (rop_t_constant | rop_t_1bit))
1260         {
1261         case 0: /* t is a bitmap. No good. */
1262         case rop_t_1bit: /* t is 1 bit data. No good. */
1263             goto no_fold_24_to_8;
1264         case rop_t_constant: /* constant or unused */
1265         {
1266             rop_operand t = swap ? op->s.c : op->t.c;
1267             if ((rop_usage_table[lop & 0xff] & rop_usage_T) &&
1268                 ((t & 0xff) != ((t>>8) & 0xff) ||
1269                  (t & 0xff) != ((t>>16) & 0xff)))
1270                 /* USED, and a colour that doesn't work out the same in 8bits */
1271                 goto no_fold_24_to_8;
1272             break;
1273         }
1274         }
1275         /* We can safely fold down from 24 to 8 */
1276         op->mul = 3;
1277         depth = 8;
1278     no_fold_24_to_8:{}
1279     }
1280 
1281     op->flags   = (flags & (rop_s_constant | rop_t_constant | rop_s_1bit | rop_t_1bit));
1282     op->depth   = (byte)depth;
1283     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     if (op->flags == (rop_s_constant | rop_t_constant) &&
1289         rop_usage_table[lop & 0xff] == rop_usage_ST) {
1290         switch (lop & (rop3_D>>rop3_D_shift)) /* Ignore the D bits */
1291         {
1292         /* Skip 0000 as doesn't use S or T */
1293         case ((0<<6) | (0<<4) | (0<<2) | 1):
1294             op->s.c = ~(op->s.c | op->t.c);
1295             break;
1296         case ((0<<6) | (0<<4) | (1<<2) | 0):
1297             op->s.c = op->s.c & ~op->t.c;
1298             break;
1299         /* Skip 0011 as doesn't use S */
1300         case ((0<<6) | (1<<4) | (0<<2) | 0):
1301             op->s.c = ~op->s.c & op->t.c;
1302             break;
1303         /* Skip 0101 as doesn't use T */
1304         case ((0<<6) | (1<<4) | (1<<2) | 0):
1305             op->s.c = op->s.c ^ op->t.c;
1306             break;
1307         case ((0<<6) | (1<<4) | (1<<2) | 1):
1308             op->s.c = ~(op->s.c & op->t.c);
1309             break;
1310         case ((1<<6) | (0<<4) | (0<<2) | 0):
1311             op->s.c = op->s.c & op->t.c;
1312             break;
1313         case ((1<<6) | (0<<4) | (0<<2) | 1):
1314             op->s.c = ~(op->s.c ^ op->t.c);
1315             break;
1316         /* Skip 1010 as doesn't use T */
1317         case ((1<<6) | (0<<4) | (1<<2) | 1):
1318             op->s.c = op->s.c | ~op->t.c;
1319             break;
1320         /* Skip 1100 as doesn't use S */
1321         case ((1<<6) | (1<<4) | (0<<2) | 1):
1322             op->s.c = ~op->s.c | op->t.c;
1323             break;
1324         case ((1<<6) | (1<<4) | (1<<2) | 0):
1325             op->s.c = op->s.c | op->t.c;
1326             break;
1327         /* Skip 1111 as doesn't use S or T */
1328         default:
1329             /* Never happens */
1330             break;
1331         }
1332         lop = (lop & ~0xff) | rop3_S;
1333     }
1334     op->rop     = lop & 0xFF;
1335 
1336 #define ROP_SPECIFIC_KEY(lop, depth, flags) (((lop)<<7)+(1<<6)+((depth>>3)<<4)+(flags))
1337 #define KEY_IS_ROP_SPECIFIC(key)            (key & (1<<6))
1338 #define STRIP_ROP_SPECIFICITY(key)          (key &= ((1<<6)-1))
1339 #define KEY(depth, flags)                   (((depth>>3)<<4)+(flags))
1340 
1341     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 retry:
1347     switch (key)
1348     {
1349     /* First, the rop specific ones */
1350     /* 0x33 = ~S */
1351     case ROP_SPECIFIC_KEY(0x33, 1, rop_t_constant):
1352         op->run     = notS_rop_run1_const_t;
1353         break;
1354     /* 0x55 = Invert */
1355     case ROP_SPECIFIC_KEY(0x55, 1, rop_s_constant | rop_t_constant):
1356         op->run     = invert_rop_run1;
1357         op->s.b.pos = 0;
1358         op->t.b.pos = 0;
1359         op->dpos    = 0;
1360         break;
1361     case ROP_SPECIFIC_KEY(0x55, 8, rop_s_constant | rop_t_constant): /* S & T UNUSED */
1362         op->run     = invert_rop_run8;
1363         break;
1364     /* 0x66 = D xor S */
1365     case ROP_SPECIFIC_KEY(0x66, 1, rop_t_constant):
1366         op->run     = xor_rop_run1_const_t;
1367         break;
1368     case ROP_SPECIFIC_KEY(0x66, 8, rop_s_constant | rop_t_constant): /* T_UNUSED */
1369         op->run     = xor_rop_run8_const_st;
1370         break;
1371     case ROP_SPECIFIC_KEY(0x66, 24, rop_s_constant | rop_t_constant): /* T_UNUSED */
1372         op->run     = xor_rop_run24_const_st;
1373         break;
1374     case ROP_SPECIFIC_KEY(0xAA, 1, rop_s_constant | rop_t_constant): /* S & T UNUSED */
1375     case ROP_SPECIFIC_KEY(0xAA, 8, rop_s_constant | rop_t_constant): /* S & T UNUSED */
1376     case ROP_SPECIFIC_KEY(0xAA, 24, rop_s_constant | rop_t_constant):/* S & T UNUSED */
1377         op->run     = nop_rop_const_st;
1378         return 0;
1379     /* 0xCC = S */
1380     case ROP_SPECIFIC_KEY(0xCC, 1, rop_t_constant): /* T_UNUSED */
1381         op->run     = sets_rop_run1;
1382         break;
1383     case ROP_SPECIFIC_KEY(0xCC, 8, rop_s_constant | rop_t_constant): /* T_UNUSED */
1384         op->run     = sets_rop_run8;
1385         break;
1386     case ROP_SPECIFIC_KEY(0xCC, 24, rop_s_constant | rop_t_constant): /* T_UNUSED */
1387         op->run     = sets_rop_run24;
1388         break;
1389     /* 0xEE = D or S */
1390     case ROP_SPECIFIC_KEY(0xEE, 1, rop_t_constant):
1391         op->run     = dors_rop_run1_const_t;
1392         break;
1393     /* Then the generic ones */
1394     case KEY(1, 0):
1395         op->run     = generic_rop_run1;
1396         op->s.b.pos = 0;
1397         op->t.b.pos = 0;
1398         op->dpos    = 0;
1399         break;
1400     case KEY(8, 0):
1401         op->run = generic_rop_run8;
1402         break;
1403     case KEY(8, rop_s_1bit):
1404     case KEY(8, rop_s_1bit | rop_t_1bit ):
1405         op->run = generic_rop_run8_1bit;
1406         break;
1407     case KEY(24, 0):
1408         op->run   = generic_rop_run24;
1409         break;
1410     case KEY(24, rop_s_1bit):
1411     case KEY(24, rop_s_1bit | rop_t_1bit ):
1412         op->run = generic_rop_run24_1bit;
1413         break;
1414     case KEY(1, rop_t_constant):
1415         op->run   = generic_rop_run1_const_t;
1416         op->s.b.pos = 0;
1417         op->t.b.pos = 0;
1418         op->dpos    = 0;
1419         break;
1420     case KEY(8, rop_t_constant):
1421         op->run   = generic_rop_run8_const_t;
1422         break;
1423     case KEY(8, rop_s_1bit | rop_t_constant):
1424         op->run = generic_rop_run8_1bit_const_t;
1425         break;
1426     case KEY(24, rop_t_constant):
1427         op->run   = generic_rop_run24_const_t;
1428         break;
1429     case KEY(24, rop_s_1bit | rop_t_constant):
1430         op->run = generic_rop_run24_1bit_const_t;
1431         break;
1432     case KEY(1, rop_s_constant | rop_t_constant):
1433         op->run   = generic_rop_run1_const_st;
1434         op->s.b.pos = 0;
1435         op->t.b.pos = 0;
1436         op->dpos    = 0;
1437         break;
1438     case KEY(8, rop_s_constant | rop_t_constant):
1439         op->run   = generic_rop_run8_const_st;
1440         break;
1441     case KEY(24, rop_s_constant | rop_t_constant):
1442         op->run   = generic_rop_run24_const_st;
1443         break;
1444     default:
1445         /* If we failed to find a specific one for this rop value, try again
1446          * for a generic one. */
1447         if (KEY_IS_ROP_SPECIFIC(key))
1448         {
1449             STRIP_ROP_SPECIFICITY(key);
1450             goto retry;
1451         }
1452         eprintf1("This should never happen! key=%x\n", key);
1453         break;
1454     }
1455 
1456     if (swap)
1457     {
1458         op->runswap = op->run;
1459         op->run = rop_run_swapped;
1460     }
1461 #ifdef RECORD_ROP_USAGE
1462     else
1463     {
1464         op->runswap = op->run;
1465         op->run = record_run;
1466     }
1467 #endif
1468     return 1;
1469 }
1470 
1471 void (rop_set_s_constant)(rop_run_op *op, int s)
1472 {
1473     rop_set_s_constant(op, s);
1474 }
1475 
1476 void (rop_set_s_bitmap)(rop_run_op *op, const byte *s)
1477 {
1478     rop_set_s_bitmap(op, s);
1479 }
1480 
1481 void (rop_set_s_bitmap_subbyte)(rop_run_op *op, const byte *s, int pos)
1482 {
1483     rop_set_s_bitmap_subbyte(op, s, pos);
1484 }
1485 
1486 void (rop_set_s_colors)(rop_run_op *op, const byte *scolors)
1487 {
1488     rop_set_s_colors(op, scolors);
1489 }
1490 
1491 void (rop_set_t_constant)(rop_run_op *op, int t)
1492 {
1493     rop_set_t_constant(op, t);
1494 }
1495 
1496 void (rop_set_t_bitmap)(rop_run_op *op, const byte *t)
1497 {
1498     rop_set_t_bitmap(op, t);
1499 }
1500 
1501 void (rop_set_t_bitmap_subbyte)(rop_run_op *op, const byte *t, int pos)
1502 {
1503     rop_set_t_bitmap_subbyte(op, t, pos);
1504 }
1505 
1506 void (rop_set_t_colors)(rop_run_op *op, const byte *tcolors)
1507 {
1508     rop_set_t_colors(op, tcolors);
1509 }
1510 
1511 void (rop_run)(rop_run_op *op, byte *d, int len)
1512 {
1513     rop_run(op, d, len);
1514 }
1515 
1516 void (rop_run_subbyte)(rop_run_op *op, byte *d, int start, int len)
1517 {
1518     rop_run_subbyte(op, d, start, len);
1519 }
1520 
1521 void (rop_release_run_op)(rop_run_op *op)
1522 {
1523     rop_release_run_op(op);
1524 }
1525