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