2 * Copyright © 2016 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
17 #include "ao_draw_int.h"
23 uint32_t ca1, cx1, ca2, cx2;
26 const struct ao_merge_rop ao_merge_rop[16] = {
27 {O, O, O, O}, /* clear 0x0 0 */
28 {I, O, O, O}, /* and 0x1 src AND dst */
29 {I, O, I, O}, /* andReverse 0x2 src AND NOT dst */
30 {O, O, I, O}, /* copy 0x3 src */
31 {I, I, O, O}, /* andInverted 0x4 NOT src AND dst */
32 {O, I, O, O}, /* noop 0x5 dst */
33 {O, I, I, O}, /* xor 0x6 src XOR dst */
34 {I, I, I, O}, /* or 0x7 src OR dst */
35 {I, I, I, I}, /* nor 0x8 NOT src AND NOT dst */
36 {O, I, I, I}, /* equiv 0x9 NOT src XOR dst */
37 {O, I, O, I}, /* invert 0xa NOT dst */
38 {I, I, O, I}, /* orReverse 0xb src OR NOT dst */
39 {O, O, I, I}, /* copyInverted 0xc NOT src */
40 {I, O, I, I}, /* orInverted 0xd NOT src OR dst */
41 {I, O, O, I}, /* nand 0xe NOT src OR NOT dst */
42 {O, O, O, I}, /* set 0xf 1 */
45 #define ao_do_merge_rop(src, dst) \
46 (((dst) & (((src) & _ca1) ^ _cx1)) ^ (((src) & _ca2) ^ _cx2))
48 #define ao_do_dst_invarient_merge_rop(src) (((src) & _ca2) ^ _cx2)
50 #define ao_do_mask_merge_rop(src, dst, mask) \
51 (((dst) & ((((src) & _ca1) ^ _cx1) | ~(mask))) ^ ((((src) & _ca2) ^ _cx2) & (mask)))
53 #define ao_dst_invarient_merge_rop() (_ca1 == 0 && _cx1 == 0)
56 ao_blt(uint32_t *src_line,
69 uint32_t _ca1, _cx1, _ca2, _cx2;
70 uint8_t dst_invarient;
71 uint32_t startmask, endmask;
74 int16_t left_shift, right_shift;
76 _ca1 = ao_merge_rop[rop].ca1;
77 _cx1 = ao_merge_rop[rop].cx1;
78 _ca2 = ao_merge_rop[rop].ca2;
79 _cx2 = ao_merge_rop[rop].cx2;
80 dst_invarient = ao_dst_invarient_merge_rop();
83 src_line += (height - 1) * src_stride;
84 dst_line += (height - 1) * dst_stride;
85 src_stride = -src_stride;
86 dst_stride = -dst_stride;
89 ao_mask_bits(dst_x, width, startmask, nmiddle, endmask);
91 src_line += ((src_x + width - 1) >> AO_SHIFT) + 1;
92 dst_line += ((dst_x + width - 1) >> AO_SHIFT) + 1;
93 src_x = (src_x + width - 1) & AO_MASK;
94 dst_x = (dst_x + width - 1) & AO_MASK;
96 src_line += src_x >> AO_SHIFT;
97 dst_line += dst_x >> AO_SHIFT;
101 if (src_x == dst_x) {
104 src_line += src_stride;
106 dst_line += dst_stride;
111 *dst = ao_do_mask_merge_rop(bits, *dst, endmask);
116 *--dst = ao_do_dst_invarient_merge_rop(*--src);
122 *dst = ao_do_merge_rop(bits, *dst);
128 *dst = ao_do_mask_merge_rop(bits, *dst, startmask);
134 *dst = ao_do_mask_merge_rop(bits, *dst, startmask);
140 *dst++ = ao_do_dst_invarient_merge_rop(*src++);
145 *dst = ao_do_merge_rop(bits, *dst);
151 *dst = ao_do_mask_merge_rop(bits, *dst, endmask);
157 left_shift = src_x - dst_x;
158 right_shift = AO_UNIT - left_shift;
160 right_shift = dst_x - src_x;
161 left_shift = AO_UNIT - right_shift;
165 src_line += src_stride;
167 dst_line += dst_stride;
174 bits = ao_right(bits1, right_shift);
175 if (ao_right(endmask, left_shift)) {
177 bits |= ao_left(bits1, left_shift);
180 *dst = ao_do_mask_merge_rop(bits, *dst, endmask);
185 bits = ao_right(bits1, right_shift);
187 bits |= ao_left(bits1, left_shift);
189 *dst = ao_do_dst_invarient_merge_rop(bits);
193 bits = ao_right(bits1, right_shift);
195 bits |= ao_left(bits1, left_shift);
197 *dst = ao_do_merge_rop(bits, *dst);
201 bits = ao_right(bits1, right_shift);
202 if (ao_right(startmask, left_shift)) {
204 bits |= ao_left(bits1, left_shift);
207 *dst = ao_do_mask_merge_rop(bits, *dst, startmask);
214 bits = ao_left(bits1, left_shift);
215 if (ao_left(startmask, right_shift)) {
217 bits |= ao_right(bits1, right_shift);
219 *dst = ao_do_mask_merge_rop(bits, *dst, startmask);
225 bits = ao_left(bits1, left_shift);
227 bits |= ao_right(bits1, right_shift);
228 *dst = ao_do_dst_invarient_merge_rop(bits);
234 bits = ao_left(bits1, left_shift);
236 bits |= ao_right(bits1, right_shift);
237 *dst = ao_do_merge_rop(bits, *dst);
242 bits = ao_left(bits1, left_shift);
243 if (ao_left(endmask, right_shift)) {
245 bits |= ao_right(bits1, right_shift);
247 *dst = ao_do_mask_merge_rop(bits, *dst, endmask);
255 ao_solid(uint32_t and,
263 uint32_t startmask, endmask;
267 dst += dst_x >> AO_SHIFT;
270 ao_mask_bits(dst_x, width, startmask, nmiddle, endmask);
275 dst_stride -= nmiddle;
278 *dst = ao_do_mask_rrop(*dst, and, xor, startmask);
287 *dst = ao_do_rrop(*dst, and, xor);
291 *dst = ao_do_mask_rrop(*dst, and, xor, endmask);