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