2 * GDI bit-blit operations
4 * Copyright 1993, 1994, 2011 Alexandre Julliard
5 * Copyright 2006 Damjan Jovanovic
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(bitblt
);
40 #define DST 0 /* Destination drawable */
41 #define SRC 1 /* Source drawable */
42 #define TMP 2 /* Temporary drawable */
43 #define PAT 3 /* Pattern (brush) in destination DC */
45 #define OP(src,dst,rop) (OP_ARGS(src,dst) << 4 | (rop))
46 #define OP_ARGS(src,dst) (((src) << 2) | (dst))
48 #define OP_SRC(opcode) ((opcode) >> 6)
49 #define OP_DST(opcode) (((opcode) >> 4) & 3)
50 #define OP_SRCDST(opcode) ((opcode) >> 4)
51 #define OP_ROP(opcode) ((opcode) & 0x0f)
53 #define MAX_OP_LEN 6 /* Longest opcode + 1 for the terminating 0 */
55 static const unsigned char BITBLT_Opcodes
[256][MAX_OP_LEN
] =
57 { OP(PAT
,DST
,GXclear
) }, /* 0x00 0 */
58 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXnor
) }, /* 0x01 ~(D|(P|S)) */
59 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXand
) }, /* 0x02 D&~(P|S) */
60 { OP(PAT
,SRC
,GXnor
) }, /* 0x03 ~(P|S) */
61 { OP(PAT
,DST
,GXnor
), OP(SRC
,DST
,GXand
) }, /* 0x04 S&~(D|P) */
62 { OP(PAT
,DST
,GXnor
) }, /* 0x05 ~(D|P) */
63 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXnor
), }, /* 0x06 ~(P|~(D^S)) */
64 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXnor
) }, /* 0x07 ~(P|(D&S)) */
65 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXand
) },/* 0x08 S&D&~P */
66 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXnor
) }, /* 0x09 ~(P|(D^S)) */
67 { OP(PAT
,DST
,GXandInverted
) }, /* 0x0a D&~P */
68 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXnor
) }, /* 0x0b ~(P|(S&~D)) */
69 { OP(PAT
,SRC
,GXandInverted
) }, /* 0x0c S&~P */
70 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXnor
) },/* 0x0d ~(P|(D&~S)) */
71 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXnor
) }, /* 0x0e ~(P|~(D|S)) */
72 { OP(PAT
,DST
,GXcopyInverted
) }, /* 0x0f ~P */
73 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXand
) }, /* 0x10 P&~(S|D) */
74 { OP(SRC
,DST
,GXnor
) }, /* 0x11 ~(D|S) */
75 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXnor
) }, /* 0x12 ~(S|~(D^P)) */
76 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXnor
) }, /* 0x13 ~(S|(D&P)) */
77 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXnor
) }, /* 0x14 ~(D|~(P^S)) */
78 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXnor
) }, /* 0x15 ~(D|(P&S)) */
79 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnand
),
80 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
),
81 OP(PAT
,DST
,GXxor
) }, /* 0x16 P^S^(D&~(P&S) */
82 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
83 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
84 OP(TMP
,DST
,GXequiv
) }, /* 0x17 ~S^((S^P)&(S^D))*/
85 { OP(PAT
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
86 OP(SRC
,DST
,GXand
) }, /* 0x18 (S^P)&(D^P) */
87 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnand
),
88 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x19 ~S^(D&~(P&S)) */
89 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
),
90 OP(PAT
,DST
,GXxor
) }, /* 0x1a P^(D|(S&P)) */
91 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
92 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x1b ~S^(D&(P^S)) */
93 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
),
94 OP(PAT
,DST
,GXxor
) }, /* 0x1c P^(S|(D&P)) */
95 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
96 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x1d ~D^(S&(D^P)) */
97 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
) }, /* 0x1e P^(D|S) */
98 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXnand
) }, /* 0x1f ~(P&(D|S)) */
99 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXand
) }, /* 0x20 D&(P&~S) */
100 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXnor
) }, /* 0x21 ~(S|(D^P)) */
101 { OP(SRC
,DST
,GXandInverted
) }, /* 0x22 ~S&D */
102 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXnor
) }, /* 0x23 ~(S|(P&~D)) */
103 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
104 OP(SRC
,DST
,GXand
) }, /* 0x24 (S^P)&(S^D) */
105 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXand
),
106 OP(PAT
,DST
,GXequiv
) }, /* 0x25 ~P^(D&~(S&P)) */
107 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
108 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x26 S^(D|(S&P)) */
109 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXequiv
),
110 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x27 S^(D|~(P^S)) */
111 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
) }, /* 0x28 D&(P^S) */
112 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
113 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
),
114 OP(PAT
,DST
,GXequiv
) }, /* 0x29 ~P^S^(D|(P&S)) */
115 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXand
) }, /* 0x2a D&~(P&S) */
116 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
117 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
118 OP(TMP
,DST
,GXequiv
) }, /* 0x2b ~S^((P^S)&(P^D))*/
119 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
),
120 OP(SRC
,DST
,GXxor
) }, /* 0x2c S^(P&(S|D)) */
121 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXxor
) }, /* 0x2d P^(S|~D) */
122 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
),
123 OP(PAT
,DST
,GXxor
) }, /* 0x2e P^(S|(D^P)) */
124 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXnand
) }, /* 0x2f ~(P&(S|~D)) */
125 { OP(PAT
,SRC
,GXandReverse
) }, /* 0x30 P&~S */
126 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXnor
) },/* 0x31 ~(S|(D&~P)) */
127 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXor
),
128 OP(SRC
,DST
,GXxor
) }, /* 0x32 S^(D|P|S) */
129 { OP(SRC
,DST
,GXcopyInverted
) }, /* 0x33 ~S */
130 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
),
131 OP(SRC
,DST
,GXxor
) }, /* 0x34 S^(P|(D&S)) */
132 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXor
),
133 OP(SRC
,DST
,GXxor
) }, /* 0x35 S^(P|~(D^S)) */
134 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x36 S^(D|P) */
135 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXnand
) }, /* 0x37 ~(S&(D|P)) */
136 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
),
137 OP(PAT
,DST
,GXxor
) }, /* 0x38 P^(S&(D|P)) */
138 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x39 S^(P|~D) */
139 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
),
140 OP(SRC
,DST
,GXxor
) }, /* 0x3a S^(P|(D^S)) */
141 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXnand
) }, /* 0x3b ~(S&(P|~D)) */
142 { OP(PAT
,SRC
,GXxor
) }, /* 0x3c P^S */
143 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
),
144 OP(SRC
,DST
,GXxor
) }, /* 0x3d S^(P|~(D|S)) */
145 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
),
146 OP(SRC
,DST
,GXxor
) }, /* 0x3e S^(P|(D&~S)) */
147 { OP(PAT
,SRC
,GXnand
) }, /* 0x3f ~(P&S) */
148 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXand
) }, /* 0x40 P&S&~D */
149 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXnor
) }, /* 0x41 ~(D|(P^S)) */
150 { OP(DST
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
151 OP(SRC
,DST
,GXand
) }, /* 0x42 (S^D)&(P^D) */
152 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
),
153 OP(SRC
,DST
,GXequiv
) }, /* 0x43 ~S^(P&~(D&S)) */
154 { OP(SRC
,DST
,GXandReverse
) }, /* 0x44 S&~D */
155 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXnor
) }, /* 0x45 ~(D|(P&~S)) */
156 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
157 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x46 D^(S|(P&D)) */
158 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
159 OP(PAT
,DST
,GXequiv
) }, /* 0x47 ~P^(S&(D^P)) */
160 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
) }, /* 0x48 S&(P^D) */
161 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
162 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
),
163 OP(PAT
,DST
,GXequiv
) }, /* 0x49 ~P^D^(S|(P&D)) */
164 { OP(DST
,SRC
,GXor
), OP(PAT
,SRC
,GXand
),
165 OP(SRC
,DST
,GXxor
) }, /* 0x4a D^(P&(S|D)) */
166 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXxor
) }, /* 0x4b P^(D|~S) */
167 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXand
) }, /* 0x4c S&~(D&P) */
168 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
169 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
170 OP(TMP
,DST
,GXequiv
) }, /* 0x4d ~S^((S^P)|(S^D))*/
171 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
172 OP(PAT
,DST
,GXxor
) }, /* 0x4e P^(D|(S^P)) */
173 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXnand
) },/* 0x4f ~(P&(D|~S)) */
174 { OP(PAT
,DST
,GXandReverse
) }, /* 0x50 P&~D */
175 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXnor
) },/* 0x51 ~(D|(S&~P)) */
176 { OP(DST
,SRC
,GXand
), OP(PAT
,SRC
,GXor
),
177 OP(SRC
,DST
,GXxor
) }, /* 0x52 D^(P|(S&D)) */
178 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
),
179 OP(SRC
,DST
,GXequiv
) }, /* 0x53 ~S^(P&(D^S)) */
180 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXnor
) }, /* 0x54 ~(D|~(P|S)) */
181 { OP(PAT
,DST
,GXinvert
) }, /* 0x55 ~D */
182 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x56 D^(P|S) */
183 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXnand
) }, /* 0x57 ~(D&(P|S)) */
184 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
),
185 OP(PAT
,DST
,GXxor
) }, /* 0x58 P^(D&(P|S)) */
186 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x59 D^(P|~S) */
187 { OP(PAT
,DST
,GXxor
) }, /* 0x5a D^P */
188 { OP(DST
,SRC
,GXnor
), OP(PAT
,SRC
,GXor
),
189 OP(SRC
,DST
,GXxor
) }, /* 0x5b D^(P|~(S|D)) */
190 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXor
),
191 OP(SRC
,DST
,GXxor
) }, /* 0x5c D^(P|(S^D)) */
192 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXnand
) }, /* 0x5d ~(D&(P|~S)) */
193 { OP(DST
,SRC
,GXandInverted
), OP(PAT
,SRC
,GXor
),
194 OP(SRC
,DST
,GXxor
) }, /* 0x5e D^(P|(S&~D)) */
195 { OP(PAT
,DST
,GXnand
) }, /* 0x5f ~(D&P) */
196 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
) }, /* 0x60 P&(D^S) */
197 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXand
),
198 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
199 OP(TMP
,DST
,GXequiv
) }, /* 0x61 ~D^S^(P|(D&S)) */
200 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
201 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x62 D^(S&(P|D)) */
202 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXxor
) }, /* 0x63 S^(D|~P) */
203 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
204 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x64 S^(D&(P|S)) */
205 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXxor
) }, /* 0x65 D^(S|~P) */
206 { OP(SRC
,DST
,GXxor
) }, /* 0x66 S^D */
207 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
208 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x67 S^(D|~(S|P) */
209 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXnor
),
210 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
211 OP(TMP
,DST
,GXequiv
) }, /* 0x68 ~D^S^(P|~(D|S))*/
212 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXequiv
) }, /* 0x69 ~P^(D^S) */
213 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXxor
) }, /* 0x6a D^(P&S) */
214 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
215 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
),
216 OP(PAT
,DST
,GXequiv
) }, /* 0x6b ~P^S^(D&(P|S)) */
217 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
) }, /* 0x6c S^(D&P) */
218 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
219 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
),
220 OP(PAT
,DST
,GXequiv
) }, /* 0x6d ~P^D^(S&(P|D)) */
221 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXorReverse
),
222 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x6e S^(D&(P|~S)) */
223 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXnand
) }, /* 0x6f ~(P&~(S^D)) */
224 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
) }, /* 0x70 P&~(D&S) */
225 { OP(SRC
,TMP
,GXcopy
), OP(DST
,SRC
,GXxor
),
226 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
227 OP(TMP
,DST
,GXequiv
) }, /* 0x71 ~S^((S^D)&(P^D))*/
228 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
229 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x72 S^(D|(P^S)) */
230 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXnand
) },/* 0x73 ~(S&(D|~P)) */
231 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
232 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x74 D^(S|(P^D)) */
233 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXnand
) },/* 0x75 ~(D&(S|~P)) */
234 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXandReverse
),
235 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x76 S^(D|(P&~S)) */
236 { OP(SRC
,DST
,GXnand
) }, /* 0x77 ~(S&D) */
237 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
) }, /* 0x78 P^(D&S) */
238 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXor
),
239 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
240 OP(TMP
,DST
,GXequiv
) }, /* 0x79 ~D^S^(P&(D|S)) */
241 { OP(DST
,SRC
,GXorInverted
), OP(PAT
,SRC
,GXand
),
242 OP(SRC
,DST
,GXxor
) }, /* 0x7a D^(P&(S|~D)) */
243 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXnand
) }, /* 0x7b ~(S&~(D^P)) */
244 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
),
245 OP(SRC
,DST
,GXxor
) }, /* 0x7c S^(P&(D|~S)) */
246 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXnand
) }, /* 0x7d ~(D&~(P^S)) */
247 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
248 OP(SRC
,DST
,GXor
) }, /* 0x7e (S^P)|(S^D) */
249 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXnand
) }, /* 0x7f ~(D&P&S) */
250 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXand
) }, /* 0x80 D&P&S */
251 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
252 OP(SRC
,DST
,GXnor
) }, /* 0x81 ~((S^P)|(S^D)) */
253 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXand
) }, /* 0x82 D&~(P^S) */
254 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
),
255 OP(SRC
,DST
,GXequiv
) }, /* 0x83 ~S^(P&(D|~S)) */
256 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXand
) }, /* 0x84 S&~(D^P) */
257 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXand
),
258 OP(PAT
,DST
,GXequiv
) }, /* 0x85 ~P^(D&(S|~P)) */
259 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXor
),
260 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
261 OP(TMP
,DST
,GXxor
) }, /* 0x86 D^S^(P&(D|S)) */
262 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXequiv
) }, /* 0x87 ~P^(D&S) */
263 { OP(SRC
,DST
,GXand
) }, /* 0x88 S&D */
264 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXandReverse
),
265 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x89 ~S^(D|(P&~S)) */
266 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXand
) }, /* 0x8a D&(S|~P) */
267 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
268 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x8b ~D^(S|(P^D)) */
269 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXand
) }, /* 0x8c S&(D|~P) */
270 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
271 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x8d ~S^(D|(P^S)) */
272 { OP(SRC
,TMP
,GXcopy
), OP(DST
,SRC
,GXxor
),
273 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
274 OP(TMP
,DST
,GXxor
) }, /* 0x8e S^((S^D)&(P^D))*/
275 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXnand
) }, /* 0x8f ~(P&~(D&S)) */
276 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXand
) }, /* 0x90 P&~(D^S) */
277 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXorReverse
),
278 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x91 ~S^(D&(P|~S)) */
279 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
280 OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
),
281 OP(TMP
,DST
,GXxor
) }, /* 0x92 D^P^(S&(D|P)) */
282 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x93 ~S^(P&D) */
283 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
284 OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
),
285 OP(TMP
,DST
,GXxor
) }, /* 0x94 S^P^(D&(P|S)) */
286 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x95 ~D^(P&S) */
287 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXxor
) }, /* 0x96 D^P^S */
288 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
289 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
290 OP(TMP
,DST
,GXxor
) }, /* 0x97 S^P^(D|~(P|S)) */
291 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
292 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x98 ~S^(D|~(P|S)) */
293 { OP(SRC
,DST
,GXequiv
) }, /* 0x99 ~S^D */
294 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x9a D^(P&~S) */
295 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
296 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x9b ~S^(D&(P|S)) */
297 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x9c S^(P&~D) */
298 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
299 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x9d ~D^(S&(P|D)) */
300 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXand
),
301 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
302 OP(TMP
,DST
,GXxor
) }, /* 0x9e D^S^(P|(D&S)) */
303 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXnand
) }, /* 0x9f ~(P&(D^S)) */
304 { OP(PAT
,DST
,GXand
) }, /* 0xa0 D&P */
305 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXor
),
306 OP(PAT
,DST
,GXequiv
) }, /* 0xa1 ~P^(D|(S&~P)) */
307 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXand
) }, /* 0xa2 D&(P|~S) */
308 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXor
),
309 OP(SRC
,DST
,GXequiv
) }, /* 0xa3 ~D^(P|(S^D)) */
310 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXor
),
311 OP(PAT
,DST
,GXequiv
) }, /* 0xa4 ~P^(D|~(S|P)) */
312 { OP(PAT
,DST
,GXequiv
) }, /* 0xa5 ~P^D */
313 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXxor
) },/* 0xa6 D^(S&~P) */
314 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
),
315 OP(PAT
,DST
,GXequiv
) }, /* 0xa7 ~P^(D&(S|P)) */
316 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
) }, /* 0xa8 D&(P|S) */
317 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXequiv
) }, /* 0xa9 ~D^(P|S) */
318 { OP(PAT
,DST
,GXnoop
) }, /* 0xaa D */
319 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXor
) }, /* 0xab D|~(P|S) */
320 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
),
321 OP(SRC
,DST
,GXxor
) }, /* 0xac S^(P&(D^S)) */
322 { OP(DST
,SRC
,GXand
), OP(PAT
,SRC
,GXor
),
323 OP(SRC
,DST
,GXequiv
) }, /* 0xad ~D^(P|(S&D)) */
324 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXor
) }, /* 0xae D|(S&~P) */
325 { OP(PAT
,DST
,GXorInverted
) }, /* 0xaf D|~P */
326 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
) }, /* 0xb0 P&(D|~S) */
327 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
328 OP(PAT
,DST
,GXequiv
) }, /* 0xb1 ~P^(D|(S^P)) */
329 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
330 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
331 OP(TMP
,DST
,GXxor
) }, /* 0xb2 S^((S^P)|(S^D))*/
332 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXnand
) }, /* 0xb3 ~(S&~(D&P)) */
333 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXxor
) }, /* 0xb4 P^(S&~D) */
334 { OP(DST
,SRC
,GXor
), OP(PAT
,SRC
,GXand
),
335 OP(SRC
,DST
,GXequiv
) }, /* 0xb5 ~D^(P&(S|D)) */
336 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
337 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
338 OP(TMP
,DST
,GXxor
) }, /* 0xb6 D^P^(S|(D&P)) */
339 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXnand
) }, /* 0xb7 ~(S&(D^P)) */
340 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
341 OP(PAT
,DST
,GXxor
) }, /* 0xb8 P^(S&(D^P)) */
342 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
343 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0xb9 ~D^(S|(P&D)) */
344 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXor
) }, /* 0xba D|(P&~S) */
345 { OP(SRC
,DST
,GXorInverted
) }, /* 0xbb ~S|D */
346 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
),
347 OP(SRC
,DST
,GXxor
) }, /* 0xbc S^(P&~(D&S)) */
348 { OP(DST
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
349 OP(SRC
,DST
,GXnand
) }, /* 0xbd ~((S^D)&(P^D)) */
350 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
) }, /* 0xbe D|(P^S) */
351 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXor
) }, /* 0xbf D|~(P&S) */
352 { OP(PAT
,SRC
,GXand
) }, /* 0xc0 P&S */
353 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
),
354 OP(SRC
,DST
,GXequiv
) }, /* 0xc1 ~S^(P|(D&~S)) */
355 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
),
356 OP(SRC
,DST
,GXequiv
) }, /* 0xc2 ~S^(P|~(D|S)) */
357 { OP(PAT
,SRC
,GXequiv
) }, /* 0xc3 ~P^S */
358 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXand
) }, /* 0xc4 S&(P|~D) */
359 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
),
360 OP(SRC
,DST
,GXequiv
) }, /* 0xc5 ~S^(P|(D^S)) */
361 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXxor
) },/* 0xc6 S^(D&~P) */
362 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
),
363 OP(PAT
,DST
,GXequiv
) }, /* 0xc7 ~P^(S&(D|P)) */
364 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
) }, /* 0xc8 S&(D|P) */
365 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXequiv
) }, /* 0xc9 ~S^(P|D) */
366 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXand
),
367 OP(SRC
,DST
,GXxor
) }, /* 0xca D^(P&(S^D)) */
368 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
),
369 OP(SRC
,DST
,GXequiv
) }, /* 0xcb ~S^(P|(D&S)) */
370 { OP(SRC
,DST
,GXcopy
) }, /* 0xcc S */
371 { OP(PAT
,DST
,GXnor
), OP(SRC
,DST
,GXor
) }, /* 0xcd S|~(D|P) */
372 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXor
) }, /* 0xce S|(D&~P) */
373 { OP(PAT
,SRC
,GXorInverted
) }, /* 0xcf S|~P */
374 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXand
) }, /* 0xd0 P&(S|~D) */
375 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
),
376 OP(PAT
,DST
,GXequiv
) }, /* 0xd1 ~P^(S|(D^P)) */
377 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXxor
) },/* 0xd2 P^(D&~S) */
378 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
),
379 OP(SRC
,DST
,GXequiv
) }, /* 0xd3 ~S^(P&(D|S)) */
380 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
381 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
382 OP(TMP
,DST
,GXxor
) }, /* 0xd4 S^((S^P)&(D^P))*/
383 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXnand
) }, /* 0xd5 ~(D&~(P&S)) */
384 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
385 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
386 OP(TMP
,DST
,GXxor
) }, /* 0xd6 S^P^(D|(P&S)) */
387 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXnand
) }, /* 0xd7 ~(D&(P^S)) */
388 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
389 OP(PAT
,DST
,GXxor
) }, /* 0xd8 P^(D&(S^P)) */
390 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
391 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0xd9 ~S^(D|(P&S)) */
392 { OP(DST
,SRC
,GXnand
), OP(PAT
,SRC
,GXand
),
393 OP(SRC
,DST
,GXxor
) }, /* 0xda D^(P&~(S&D)) */
394 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
395 OP(SRC
,DST
,GXnand
) }, /* 0xdb ~((S^P)&(S^D)) */
396 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXor
) }, /* 0xdc S|(P&~D) */
397 { OP(SRC
,DST
,GXorReverse
) }, /* 0xdd S|~D */
398 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
) }, /* 0xde S|(D^P) */
399 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXor
) }, /* 0xdf S|~(D&P) */
400 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
) }, /* 0xe0 P&(D|S) */
401 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXequiv
) }, /* 0xe1 ~P^(D|S) */
402 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
403 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe2 D^(S&(P^D)) */
404 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
),
405 OP(PAT
,DST
,GXequiv
) }, /* 0xe3 ~P^(S|(D&P)) */
406 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
407 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe4 S^(D&(P^S)) */
408 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
),
409 OP(PAT
,DST
,GXequiv
) }, /* 0xe5 ~P^(D|(S&P)) */
410 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnand
),
411 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe6 S^(D&~(P&S)) */
412 { OP(PAT
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
413 OP(SRC
,DST
,GXnand
) }, /* 0xe7 ~((S^P)&(D^P)) */
414 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
415 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
416 OP(TMP
,DST
,GXxor
) }, /* 0xe8 S^((S^P)&(S^D))*/
417 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXnand
),
418 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
419 OP(TMP
,DST
,GXequiv
) }, /* 0xe9 ~D^S^(P&~(S&D))*/
420 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
) }, /* 0xea D|(P&S) */
421 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXor
) }, /* 0xeb D|~(P^S) */
422 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
) }, /* 0xec S|(D&P) */
423 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXor
) }, /* 0xed S|~(D^P) */
424 { OP(SRC
,DST
,GXor
) }, /* 0xee S|D */
425 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXor
) }, /* 0xef S|D|~P */
426 { OP(PAT
,DST
,GXcopy
) }, /* 0xf0 P */
427 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
) }, /* 0xf1 P|~(D|S) */
428 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
) }, /* 0xf2 P|(D&~S) */
429 { OP(PAT
,SRC
,GXorReverse
) }, /* 0xf3 P|~S */
430 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXor
) }, /* 0xf4 P|(S&~D) */
431 { OP(PAT
,DST
,GXorReverse
) }, /* 0xf5 P|~D */
432 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
) }, /* 0xf6 P|(D^S) */
433 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXor
) }, /* 0xf7 P|~(S&D) */
434 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
) }, /* 0xf8 P|(D&S) */
435 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXor
) }, /* 0xf9 P|~(D^S) */
436 { OP(PAT
,DST
,GXor
) }, /* 0xfa D|P */
437 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXor
) }, /* 0xfb D|P|~S */
438 { OP(PAT
,SRC
,GXor
) }, /* 0xfc P|S */
439 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXor
) }, /* 0xfd P|S|~D */
440 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXor
) }, /* 0xfe P|D|S */
441 { OP(PAT
,DST
,GXset
) } /* 0xff 1 */
444 static const unsigned char bit_swap
[256] =
446 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
447 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
448 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
449 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
450 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
451 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
452 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
453 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
454 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
455 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
456 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
457 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
458 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
459 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
460 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
461 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
462 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
463 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
464 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
465 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
466 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
467 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
468 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
469 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
470 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
471 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
472 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
473 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
474 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
475 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
476 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
477 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
480 #ifdef WORDS_BIGENDIAN
481 static const unsigned int zeropad_masks
[32] =
483 0xffffffff, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
484 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
485 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
486 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe
489 static const unsigned int zeropad_masks
[32] =
491 0xffffffff, 0x00000080, 0x000000c0, 0x000000e0, 0x000000f0, 0x000000f8, 0x000000fc, 0x000000fe,
492 0x000000ff, 0x000080ff, 0x0000c0ff, 0x0000e0ff, 0x0000f0ff, 0x0000f8ff, 0x0000fcff, 0x0000feff,
493 0x0000ffff, 0x0080ffff, 0x00c0ffff, 0x00e0ffff, 0x00f0ffff, 0x00f8ffff, 0x00fcffff, 0x00feffff,
494 0x00ffffff, 0x80ffffff, 0xc0ffffff, 0xe0ffffff, 0xf0ffffff, 0xf8ffffff, 0xfcffffff, 0xfeffffff
498 #ifdef BITBLT_TEST /* Opcodes test */
500 static int do_bitop( int s
, int d
, int rop
)
505 case GXclear
: res
= 0; break;
506 case GXand
: res
= s
& d
; break;
507 case GXandReverse
: res
= s
& ~d
; break;
508 case GXcopy
: res
= s
; break;
509 case GXandInverted
: res
= ~s
& d
; break;
510 case GXnoop
: res
= d
; break;
511 case GXxor
: res
= s
^ d
; break;
512 case GXor
: res
= s
| d
; break;
513 case GXnor
: res
= ~(s
| d
); break;
514 case GXequiv
: res
= ~s
^ d
; break;
515 case GXinvert
: res
= ~d
; break;
516 case GXorReverse
: res
= s
| ~d
; break;
517 case GXcopyInverted
: res
= ~s
; break;
518 case GXorInverted
: res
= ~s
| d
; break;
519 case GXnand
: res
= ~(s
& d
); break;
520 case GXset
: res
= 1; break;
527 int rop
, i
, res
, src
, dst
, pat
, tmp
, dstUsed
;
528 const unsigned char *opcode
;
530 for (rop
= 0; rop
< 256; rop
++)
533 for (i
= 0; i
< 8; i
++)
538 for (opcode
= BITBLT_Opcodes
[rop
]; *opcode
; opcode
++)
542 case OP_ARGS(DST
,TMP
):
543 tmp
= do_bitop( dst
, tmp
, *opcode
& 0xf );
545 case OP_ARGS(DST
,SRC
):
546 src
= do_bitop( dst
, src
, *opcode
& 0xf );
548 case OP_ARGS(SRC
,TMP
):
549 tmp
= do_bitop( src
, tmp
, *opcode
& 0xf );
551 case OP_ARGS(SRC
,DST
):
552 dst
= do_bitop( src
, dst
, *opcode
& 0xf );
555 case OP_ARGS(PAT
,DST
):
556 dst
= do_bitop( pat
, dst
, *opcode
& 0xf );
559 case OP_ARGS(PAT
,SRC
):
560 src
= do_bitop( pat
, src
, *opcode
& 0xf );
562 case OP_ARGS(TMP
,DST
):
563 dst
= do_bitop( tmp
, dst
, *opcode
& 0xf );
566 case OP_ARGS(TMP
,SRC
):
567 src
= do_bitop( tmp
, src
, *opcode
& 0xf );
570 printf( "Invalid opcode %x\n", *opcode
);
573 if (!dstUsed
) dst
= src
;
574 if (dst
) res
|= 1 << i
;
576 if (res
!= rop
) printf( "%02x: ERROR, res=%02x\n", rop
, res
);
582 #endif /* BITBLT_TEST */
585 /***********************************************************************
588 * Retrieve an area from the source DC, mapping all the
589 * pixels to Windows colors.
591 static int BITBLT_GetSrcArea( X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
592 Pixmap pixmap
, GC gc
, RECT
*visRectSrc
)
597 INT width
= visRectSrc
->right
- visRectSrc
->left
;
598 INT height
= visRectSrc
->bottom
- visRectSrc
->top
;
599 BOOL memdc
= (GetObjectType(physDevSrc
->dev
.hdc
) == OBJ_MEMDC
);
601 if (physDevSrc
->depth
== 1)
603 /* MSDN says if StretchBlt must convert a bitmap from monochrome
604 to color or vice versa, the foreground and background color of
605 the device context are used. In fact, it also applies to the
606 case when it is converted from mono to mono. */
608 if (X11DRV_PALETTE_XPixelToPalette
&& physDevDst
->depth
!= 1)
610 XSetBackground( gdi_display
, gc
, X11DRV_PALETTE_XPixelToPalette
[physDevDst
->textPixel
] );
611 XSetForeground( gdi_display
, gc
, X11DRV_PALETTE_XPixelToPalette
[physDevDst
->backgroundPixel
]);
615 XSetBackground( gdi_display
, gc
, physDevDst
->textPixel
);
616 XSetForeground( gdi_display
, gc
, physDevDst
->backgroundPixel
);
618 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
619 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
620 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
621 width
, height
, 0, 0, 1 );
625 else /* color -> color */
628 if (!X11DRV_PALETTE_XPixelToPalette
)
630 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
631 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
632 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
633 width
, height
, 0, 0);
639 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
640 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
641 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
642 width
, height
, AllPlanes
, ZPixmap
);
645 /* Make sure we don't get a BadMatch error */
646 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
647 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
648 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
649 width
, height
, 0, 0);
651 imageSrc
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
652 AllPlanes
, ZPixmap
);
654 for (y
= 0; y
< height
; y
++)
655 for (x
= 0; x
< width
; x
++)
656 XPutPixel(imageSrc
, x
, y
,
657 X11DRV_PALETTE_XPixelToPalette
[XGetPixel(imageSrc
, x
, y
)]);
658 XPutImage( gdi_display
, pixmap
, gc
, imageSrc
,
659 0, 0, 0, 0, width
, height
);
660 XDestroyImage( imageSrc
);
668 /***********************************************************************
671 * Retrieve an area from the destination DC, mapping all the
672 * pixels to Windows colors.
674 static int BITBLT_GetDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, GC gc
, const RECT
*visRectDst
)
677 INT width
= visRectDst
->right
- visRectDst
->left
;
678 INT height
= visRectDst
->bottom
- visRectDst
->top
;
679 BOOL memdc
= (GetObjectType( physDev
->dev
.hdc
) == OBJ_MEMDC
);
683 if (!X11DRV_PALETTE_XPixelToPalette
|| (physDev
->depth
== 1) ||
684 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
686 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
687 physDev
->dc_rect
.left
+ visRectDst
->left
, physDev
->dc_rect
.top
+ visRectDst
->top
,
688 width
, height
, 0, 0 );
697 image
= XGetImage( gdi_display
, physDev
->drawable
,
698 physDev
->dc_rect
.left
+ visRectDst
->left
,
699 physDev
->dc_rect
.top
+ visRectDst
->top
,
700 width
, height
, AllPlanes
, ZPixmap
);
703 /* Make sure we don't get a BadMatch error */
704 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
705 physDev
->dc_rect
.left
+ visRectDst
->left
,
706 physDev
->dc_rect
.top
+ visRectDst
->top
,
707 width
, height
, 0, 0);
709 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
710 AllPlanes
, ZPixmap
);
714 for (y
= 0; y
< height
; y
++)
715 for (x
= 0; x
< width
; x
++)
716 XPutPixel( image
, x
, y
,
717 X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, x
, y
)]);
718 XPutImage( gdi_display
, pixmap
, gc
, image
, 0, 0, 0, 0, width
, height
);
719 XDestroyImage( image
);
728 /***********************************************************************
731 * Put an area back into the destination DC, mapping the pixel
732 * colors to X pixels.
734 static int BITBLT_PutDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, const RECT
*visRectDst
)
737 INT width
= visRectDst
->right
- visRectDst
->left
;
738 INT height
= visRectDst
->bottom
- visRectDst
->top
;
740 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
742 if (!X11DRV_PALETTE_PaletteToXPixel
|| (physDev
->depth
== 1) ||
743 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
745 XCopyArea( gdi_display
, pixmap
, physDev
->drawable
, physDev
->gc
, 0, 0, width
, height
,
746 physDev
->dc_rect
.left
+ visRectDst
->left
,
747 physDev
->dc_rect
.top
+ visRectDst
->top
);
753 XImage
*image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
754 AllPlanes
, ZPixmap
);
755 for (y
= 0; y
< height
; y
++)
756 for (x
= 0; x
< width
; x
++)
758 XPutPixel( image
, x
, y
,
759 X11DRV_PALETTE_PaletteToXPixel
[XGetPixel( image
, x
, y
)]);
761 XPutImage( gdi_display
, physDev
->drawable
, physDev
->gc
, image
, 0, 0,
762 physDev
->dc_rect
.left
+ visRectDst
->left
,
763 physDev
->dc_rect
.top
+ visRectDst
->top
, width
, height
);
764 XDestroyImage( image
);
769 static BOOL
same_format(X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
)
771 if (physDevSrc
->depth
!= physDevDst
->depth
) return FALSE
;
772 if (!physDevSrc
->color_shifts
&& !physDevDst
->color_shifts
) return TRUE
;
773 if (physDevSrc
->color_shifts
&& physDevDst
->color_shifts
)
774 return !memcmp(physDevSrc
->color_shifts
, physDevDst
->color_shifts
, sizeof(ColorShifts
));
778 void execute_rop( X11DRV_PDEVICE
*physdev
, Pixmap src_pixmap
, GC gc
, const RECT
*visrect
, DWORD rop
)
781 Pixmap result
= src_pixmap
;
783 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
784 BOOL use_pat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
785 BOOL use_dst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
786 int width
= visrect
->right
- visrect
->left
;
787 int height
= visrect
->bottom
- visrect
->top
;
789 pixmaps
[SRC
] = src_pixmap
;
792 pixmaps
[DST
] = XCreatePixmap( gdi_display
, root_window
, width
, height
, physdev
->depth
);
795 if (use_dst
) BITBLT_GetDstArea( physdev
, pixmaps
[DST
], gc
, visrect
);
796 null_brush
= use_pat
&& !X11DRV_SetupGCForPatBlt( physdev
, gc
, TRUE
);
799 for ( ; *opcode
; opcode
++)
801 if (OP_DST(*opcode
) == DST
) result
= pixmaps
[DST
];
802 XSetFunction( gdi_display
, gc
, OP_ROP(*opcode
) );
803 switch(OP_SRCDST(*opcode
))
805 case OP_ARGS(DST
,TMP
):
806 case OP_ARGS(SRC
,TMP
):
808 pixmaps
[TMP
] = XCreatePixmap( gdi_display
, root_window
, width
, height
, physdev
->depth
);
810 case OP_ARGS(DST
,SRC
):
811 case OP_ARGS(SRC
,DST
):
812 case OP_ARGS(TMP
,SRC
):
813 case OP_ARGS(TMP
,DST
):
814 XCopyArea( gdi_display
, pixmaps
[OP_SRC(*opcode
)], pixmaps
[OP_DST(*opcode
)], gc
,
815 0, 0, width
, height
, 0, 0 );
817 case OP_ARGS(PAT
,DST
):
818 case OP_ARGS(PAT
,SRC
):
820 XFillRectangle( gdi_display
, pixmaps
[OP_DST(*opcode
)], gc
, 0, 0, width
, height
);
824 XSetFunction( gdi_display
, physdev
->gc
, GXcopy
);
825 physdev
->exposures
+= BITBLT_PutDstArea( physdev
, result
, visrect
);
826 XFreePixmap( gdi_display
, pixmaps
[DST
] );
827 if (pixmaps
[TMP
]) XFreePixmap( gdi_display
, pixmaps
[TMP
] );
831 /***********************************************************************
834 BOOL
X11DRV_PatBlt( PHYSDEV dev
, struct bitblt_coords
*dst
, DWORD rop
)
836 X11DRV_PDEVICE
*physDev
= get_x11drv_dev( dev
);
837 BOOL usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
838 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
840 if (usePat
&& !X11DRV_SetupGCForBrush( physDev
)) return TRUE
;
842 X11DRV_LockDIBSection( physDev
, DIB_Status_GdiMod
);
845 XSetFunction( gdi_display
, physDev
->gc
, OP_ROP(*opcode
) );
847 switch(rop
) /* a few special cases */
849 case BLACKNESS
: /* 0x00 */
850 case WHITENESS
: /* 0xff */
851 if ((physDev
->depth
!= 1) && X11DRV_PALETTE_PaletteToXPixel
)
853 XSetFunction( gdi_display
, physDev
->gc
, GXcopy
);
854 if (rop
== BLACKNESS
)
855 XSetForeground( gdi_display
, physDev
->gc
, X11DRV_PALETTE_PaletteToXPixel
[0] );
857 XSetForeground( gdi_display
, physDev
->gc
,
858 WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ));
859 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
862 case DSTINVERT
: /* 0x55 */
863 if (!(X11DRV_PALETTE_PaletteFlags
& (X11DRV_PALETTE_PRIVATE
| X11DRV_PALETTE_VIRTUAL
)))
865 /* Xor is much better when we do not have full colormap. */
866 /* Using white^black ensures that we invert at least black */
868 unsigned long xor_pix
= (WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ) ^
869 BlackPixel( gdi_display
, DefaultScreen(gdi_display
) ));
870 XSetFunction( gdi_display
, physDev
->gc
, GXxor
);
871 XSetForeground( gdi_display
, physDev
->gc
, xor_pix
);
872 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
876 XFillRectangle( gdi_display
, physDev
->drawable
, physDev
->gc
,
877 physDev
->dc_rect
.left
+ dst
->visrect
.left
,
878 physDev
->dc_rect
.top
+ dst
->visrect
.top
,
879 dst
->visrect
.right
- dst
->visrect
.left
,
880 dst
->visrect
.bottom
- dst
->visrect
.top
);
883 X11DRV_UnlockDIBSection( physDev
, TRUE
);
888 /***********************************************************************
891 BOOL
X11DRV_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
892 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
894 X11DRV_PDEVICE
*physDevDst
= get_x11drv_dev( dst_dev
);
895 X11DRV_PDEVICE
*physDevSrc
= get_x11drv_dev( src_dev
);
901 if (src_dev
->funcs
!= dst_dev
->funcs
||
902 src
->width
!= dst
->width
|| src
->height
!= dst
->height
|| /* no stretching with core X11 */
903 (physDevDst
->depth
== 1 && physDevSrc
->depth
!= 1)) /* color -> mono done by hand */
905 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pStretchBlt
);
906 return dst_dev
->funcs
->pStretchBlt( dst_dev
, dst
, src_dev
, src
, rop
);
909 width
= dst
->visrect
.right
- dst
->visrect
.left
;
910 height
= dst
->visrect
.bottom
- dst
->visrect
.top
;
912 X11DRV_LockDIBSection( physDevDst
, DIB_Status_GdiMod
);
913 if (physDevDst
!= physDevSrc
) X11DRV_LockDIBSection( physDevSrc
, DIB_Status_GdiMod
);
915 opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
917 /* a few optimizations for single-op ROPs */
918 if (!opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
))
920 if (same_format(physDevSrc
, physDevDst
))
923 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
924 XCopyArea( gdi_display
, physDevSrc
->drawable
,
925 physDevDst
->drawable
, physDevDst
->gc
,
926 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
927 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
929 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
930 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
);
931 physDevDst
->exposures
++;
935 if (physDevSrc
->depth
== 1)
938 XSetBackground( gdi_display
, physDevDst
->gc
, physDevDst
->textPixel
);
939 XSetForeground( gdi_display
, physDevDst
->gc
, physDevDst
->backgroundPixel
);
940 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
941 XCopyPlane( gdi_display
, physDevSrc
->drawable
,
942 physDevDst
->drawable
, physDevDst
->gc
,
943 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
944 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
946 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
947 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
, 1 );
948 physDevDst
->exposures
++;
955 tmpGC
= XCreateGC( gdi_display
, physDevDst
->drawable
, 0, NULL
);
956 XSetSubwindowMode( gdi_display
, tmpGC
, IncludeInferiors
);
957 XSetGraphicsExposures( gdi_display
, tmpGC
, False
);
958 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, physDevDst
->depth
);
961 BITBLT_GetSrcArea( physDevSrc
, physDevDst
, src_pixmap
, tmpGC
, &src
->visrect
);
962 execute_rop( physDevDst
, src_pixmap
, tmpGC
, &dst
->visrect
, rop
);
965 XFreePixmap( gdi_display
, src_pixmap
);
966 XFreeGC( gdi_display
, tmpGC
);
970 if (physDevDst
!= physDevSrc
) X11DRV_UnlockDIBSection( physDevSrc
, FALSE
);
971 X11DRV_UnlockDIBSection( physDevDst
, TRUE
);
976 static void free_heap_bits( struct gdi_image_bits
*bits
)
978 HeapFree( GetProcessHeap(), 0, bits
->ptr
);
981 static void free_ximage_bits( struct gdi_image_bits
*bits
)
988 /* store the palette or color mask data in the bitmap info structure */
989 static void set_color_info( PHYSDEV dev
, const ColorShifts
*color_shifts
, BITMAPINFO
*info
)
991 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
993 info
->bmiHeader
.biCompression
= BI_RGB
;
994 info
->bmiHeader
.biClrUsed
= 0;
996 switch (info
->bmiHeader
.biBitCount
)
1001 RGBQUAD
*rgb
= (RGBQUAD
*)colors
;
1002 PALETTEENTRY palette
[256];
1005 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1006 count
= X11DRV_GetSystemPaletteEntries( dev
, 0, info
->bmiHeader
.biClrUsed
, palette
);
1007 for (i
= 0; i
< count
; i
++)
1009 rgb
[i
].rgbRed
= palette
[i
].peRed
;
1010 rgb
[i
].rgbGreen
= palette
[i
].peGreen
;
1011 rgb
[i
].rgbBlue
= palette
[i
].peBlue
;
1012 rgb
[i
].rgbReserved
= 0;
1014 memset( &rgb
[count
], 0, (info
->bmiHeader
.biClrUsed
- count
) * sizeof(*rgb
) );
1018 colors
[0] = color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
;
1019 colors
[1] = color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
;
1020 colors
[2] = color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
;
1021 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1024 colors
[0] = color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
;
1025 colors
[1] = color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
;
1026 colors
[2] = color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
;
1027 if (colors
[0] != 0xff0000 || colors
[1] != 0x00ff00 || colors
[2] != 0x0000ff)
1028 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1033 /* check if the specified color info is suitable for PutImage */
1034 static BOOL
matching_color_info( PHYSDEV dev
, const ColorShifts
*color_shifts
, const BITMAPINFO
*info
)
1036 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1038 switch (info
->bmiHeader
.biBitCount
)
1041 if (info
->bmiHeader
.biCompression
!= BI_RGB
) return FALSE
;
1042 return !info
->bmiHeader
.biClrUsed
; /* color map not allowed */
1046 RGBQUAD
*rgb
= (RGBQUAD
*)colors
;
1047 PALETTEENTRY palette
[256];
1050 if (info
->bmiHeader
.biCompression
!= BI_RGB
) return FALSE
;
1051 count
= X11DRV_GetSystemPaletteEntries( dev
, 0, 1 << info
->bmiHeader
.biBitCount
, palette
);
1052 if (count
!= info
->bmiHeader
.biClrUsed
) return FALSE
;
1053 for (i
= 0; i
< count
; i
++)
1055 if (rgb
[i
].rgbRed
!= palette
[i
].peRed
||
1056 rgb
[i
].rgbGreen
!= palette
[i
].peGreen
||
1057 rgb
[i
].rgbBlue
!= palette
[i
].peBlue
) return FALSE
;
1062 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1063 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== colors
[0] &&
1064 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== colors
[1] &&
1065 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== colors
[2]);
1066 if (info
->bmiHeader
.biCompression
== BI_RGB
)
1067 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== 0x7c00 &&
1068 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== 0x03e0 &&
1069 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== 0x001f);
1072 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1073 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== colors
[0] &&
1074 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== colors
[1] &&
1075 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== colors
[2]);
1078 if (info
->bmiHeader
.biCompression
== BI_RGB
)
1079 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== 0xff0000 &&
1080 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== 0x00ff00 &&
1081 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== 0x0000ff);
1087 static inline BOOL
is_r8g8b8( int depth
, const ColorShifts
*color_shifts
)
1089 return depth
== 24 && color_shifts
->logicalBlue
.shift
== 0 && color_shifts
->logicalRed
.shift
== 16;
1092 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1093 DWORD
copy_image_bits( BITMAPINFO
*info
, BOOL is_r8g8b8
, XImage
*image
,
1094 const struct gdi_image_bits
*src_bits
, struct gdi_image_bits
*dst_bits
,
1095 struct bitblt_coords
*coords
, const int *mapping
, unsigned int zeropad_mask
)
1097 #ifdef WORDS_BIGENDIAN
1098 static const int client_byte_order
= MSBFirst
;
1100 static const int client_byte_order
= LSBFirst
;
1103 int x
, y
, height
= coords
->visrect
.bottom
- coords
->visrect
.top
;
1104 int width_bytes
= image
->bytes_per_line
;
1106 unsigned char *src
, *dst
;
1108 switch (info
->bmiHeader
.biBitCount
)
1111 need_byteswap
= (image
->bitmap_bit_order
!= MSBFirst
);
1114 need_byteswap
= (image
->byte_order
!= MSBFirst
);
1118 need_byteswap
= (image
->byte_order
!= client_byte_order
);
1121 need_byteswap
= (image
->byte_order
== MSBFirst
) ^ !is_r8g8b8
;
1124 need_byteswap
= FALSE
;
1128 src
= src_bits
->ptr
;
1129 if (info
->bmiHeader
.biHeight
> 0)
1130 src
+= (info
->bmiHeader
.biHeight
- coords
->visrect
.bottom
) * width_bytes
;
1132 src
+= coords
->visrect
.top
* width_bytes
;
1134 if ((need_byteswap
&& !src_bits
->is_copy
) || /* need to swap bytes */
1135 (zeropad_mask
!= ~0u && !src_bits
->is_copy
) || /* need to clear padding bytes */
1136 (mapping
&& !src_bits
->is_copy
) || /* need to remap pixels */
1137 (width_bytes
& 3) || /* need to fixup line alignment */
1138 (info
->bmiHeader
.biHeight
> 0)) /* need to flip vertically */
1140 width_bytes
= (width_bytes
+ 3) & ~3;
1141 info
->bmiHeader
.biSizeImage
= height
* width_bytes
;
1142 if (!(dst_bits
->ptr
= HeapAlloc( GetProcessHeap(), 0, info
->bmiHeader
.biSizeImage
)))
1143 return ERROR_OUTOFMEMORY
;
1144 dst_bits
->is_copy
= TRUE
;
1145 dst_bits
->free
= free_heap_bits
;
1149 /* swap bits in place */
1150 dst_bits
->ptr
= src
;
1151 dst_bits
->is_copy
= src_bits
->is_copy
;
1152 dst_bits
->free
= NULL
;
1153 if (!need_byteswap
&& zeropad_mask
== ~0u && !mapping
) return ERROR_SUCCESS
; /* nothing to do */
1156 dst
= dst_bits
->ptr
;
1157 padding_pos
= width_bytes
/sizeof(unsigned int) - 1;
1159 if (info
->bmiHeader
.biHeight
> 0)
1161 dst
+= (height
- 1) * width_bytes
;
1162 width_bytes
= -width_bytes
;
1165 if (need_byteswap
|| mapping
)
1167 switch (info
->bmiHeader
.biBitCount
)
1170 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1172 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1173 dst
[x
] = bit_swap
[src
[x
]];
1174 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1178 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1181 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1182 dst
[x
] = (mapping
[src
[x
] & 0x0f] << 4) | mapping
[src
[x
] >> 4];
1184 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1185 dst
[x
] = (src
[x
] << 4) | (src
[x
] >> 4);
1186 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1190 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1192 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1193 dst
[x
] = mapping
[src
[x
]];
1194 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1198 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1200 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1201 ((USHORT
*)dst
)[x
] = RtlUshortByteSwap( ((const USHORT
*)src
)[x
] );
1202 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1206 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1208 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1210 unsigned char tmp
= src
[3 * x
];
1211 dst
[3 * x
] = src
[3 * x
+ 2];
1212 dst
[3 * x
+ 1] = src
[3 * x
+ 1];
1213 dst
[3 * x
+ 2] = tmp
;
1215 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1219 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1220 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1221 ((ULONG
*)dst
)[x
] = RtlUlongByteSwap( ((const ULONG
*)src
)[x
] );
1225 else if (src
!= dst
)
1227 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1229 memcpy( dst
, src
, image
->bytes_per_line
);
1230 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1233 else /* only need to clear the padding */
1235 for (y
= 0; y
< height
; y
++, dst
+= width_bytes
)
1236 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1238 return ERROR_SUCCESS
;
1241 /***********************************************************************
1244 DWORD
X11DRV_PutImage( PHYSDEV dev
, HBITMAP hbitmap
, HRGN clip
, BITMAPINFO
*info
,
1245 const struct gdi_image_bits
*bits
, struct bitblt_coords
*src
,
1246 struct bitblt_coords
*dst
, DWORD rop
)
1248 X11DRV_PDEVICE
*physdev
;
1249 X_PHYSBITMAP
*bitmap
;
1253 struct gdi_image_bits dst_bits
;
1254 const XPixmapFormatValues
*format
;
1255 const ColorShifts
*color_shifts
;
1256 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1257 const int *mapping
= NULL
;
1261 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
1263 depth
= bitmap
->depth
;
1264 color_shifts
= &bitmap
->color_shifts
;
1268 physdev
= get_x11drv_dev( dev
);
1270 depth
= physdev
->depth
;
1271 color_shifts
= physdev
->color_shifts
;
1273 format
= pixmap_formats
[depth
];
1275 if (info
->bmiHeader
.biPlanes
!= 1) goto update_format
;
1276 if (info
->bmiHeader
.biBitCount
!= format
->bits_per_pixel
) goto update_format
;
1277 /* FIXME: could try to handle 1-bpp using XCopyPlane */
1278 if (!matching_color_info( dev
, color_shifts
, info
)) goto update_format
;
1279 if (!bits
) return ERROR_SUCCESS
; /* just querying the format */
1280 if ((src
->width
!= dst
->width
) || (src
->height
!= dst
->height
)) return ERROR_TRANSFORM_NOT_SUPPORTED
;
1283 image
= XCreateImage( gdi_display
, visual
, depth
, ZPixmap
, 0, NULL
,
1284 info
->bmiHeader
.biWidth
, src
->visrect
.bottom
- src
->visrect
.top
, 32, 0 );
1285 wine_tsx11_unlock();
1286 if (!image
) return ERROR_OUTOFMEMORY
;
1288 if (image
->bits_per_pixel
== 4 || image
->bits_per_pixel
== 8)
1290 if (bitmap
|| (!opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
)))
1291 mapping
= X11DRV_PALETTE_PaletteToXPixel
;
1294 ret
= copy_image_bits( info
, is_r8g8b8(depth
,color_shifts
), image
, bits
, &dst_bits
, src
, mapping
, ~0u );
1298 int width
= dst
->visrect
.right
- dst
->visrect
.left
;
1299 int height
= dst
->visrect
.bottom
- dst
->visrect
.top
;
1301 image
->data
= dst_bits
.ptr
;
1302 /* hack: make sure the bits are readable if we are reading from a DIB section */
1303 /* to be removed once we get rid of DIB access protections */
1304 if (!dst_bits
.is_copy
) IsBadReadPtr( dst_bits
.ptr
, height
* image
->bytes_per_line
);
1308 RGNDATA
*clip_data
= NULL
;
1311 if (clip
) clip_data
= X11DRV_GetRegionData( clip
, 0 );
1312 X11DRV_DIB_Lock( bitmap
, DIB_Status_GdiMod
);
1315 gc
= XCreateGC( gdi_display
, bitmap
->pixmap
, 0, NULL
);
1316 XSetGraphicsExposures( gdi_display
, gc
, False
);
1317 if (clip_data
) XSetClipRectangles( gdi_display
, gc
, 0, 0, (XRectangle
*)clip_data
->Buffer
,
1318 clip_data
->rdh
.nCount
, YXBanded
);
1319 XPutImage( gdi_display
, bitmap
->pixmap
, gc
, image
, src
->visrect
.left
, 0,
1320 dst
->visrect
.left
, dst
->visrect
.top
, width
, height
);
1321 XFreeGC( gdi_display
, gc
);
1322 wine_tsx11_unlock();
1324 X11DRV_DIB_Unlock( bitmap
, TRUE
);
1325 HeapFree( GetProcessHeap(), 0, clip_data
);
1329 RGNDATA
*saved_region
= NULL
;
1331 if (clip
) saved_region
= add_extra_clipping_region( physdev
, clip
);
1332 X11DRV_LockDIBSection( physdev
, DIB_Status_GdiMod
);
1334 /* optimization for single-op ROPs */
1335 if (!opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
))
1338 XSetFunction( gdi_display
, physdev
->gc
, OP_ROP(*opcode
) );
1339 XPutImage( gdi_display
, physdev
->drawable
, physdev
->gc
, image
, src
->visrect
.left
, 0,
1340 physdev
->dc_rect
.left
+ dst
->visrect
.left
,
1341 physdev
->dc_rect
.top
+ dst
->visrect
.top
, width
, height
);
1342 wine_tsx11_unlock();
1350 gc
= XCreateGC( gdi_display
, physdev
->drawable
, 0, NULL
);
1351 XSetSubwindowMode( gdi_display
, gc
, IncludeInferiors
);
1352 XSetGraphicsExposures( gdi_display
, gc
, False
);
1353 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, depth
);
1354 XPutImage( gdi_display
, src_pixmap
, gc
, image
, src
->visrect
.left
, 0, 0, 0, width
, height
);
1355 wine_tsx11_unlock();
1357 execute_rop( physdev
, src_pixmap
, gc
, &dst
->visrect
, rop
);
1360 XFreePixmap( gdi_display
, src_pixmap
);
1361 XFreeGC( gdi_display
, gc
);
1362 wine_tsx11_unlock();
1365 X11DRV_UnlockDIBSection( physdev
, !ret
);
1366 restore_clipping_region( physdev
, saved_region
);
1372 XDestroyImage( image
);
1373 wine_tsx11_unlock();
1374 if (dst_bits
.free
) dst_bits
.free( &dst_bits
);
1378 info
->bmiHeader
.biPlanes
= 1;
1379 info
->bmiHeader
.biBitCount
= format
->bits_per_pixel
;
1380 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
1381 set_color_info( dev
, color_shifts
, info
);
1382 return ERROR_BAD_FORMAT
;
1385 /***********************************************************************
1388 DWORD
X11DRV_GetImage( PHYSDEV dev
, HBITMAP hbitmap
, BITMAPINFO
*info
,
1389 struct gdi_image_bits
*bits
, struct bitblt_coords
*src
)
1391 X11DRV_PDEVICE
*physdev
;
1392 X_PHYSBITMAP
*bitmap
;
1393 DWORD ret
= ERROR_SUCCESS
;
1395 UINT align
, x
, y
, width
, height
;
1397 struct gdi_image_bits src_bits
;
1398 const XPixmapFormatValues
*format
;
1399 const ColorShifts
*color_shifts
;
1400 const int *mapping
= NULL
;
1404 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
1406 depth
= bitmap
->depth
;
1407 color_shifts
= &bitmap
->color_shifts
;
1411 physdev
= get_x11drv_dev( dev
);
1413 depth
= physdev
->depth
;
1414 color_shifts
= physdev
->color_shifts
;
1416 format
= pixmap_formats
[depth
];
1418 /* align start and width to 32-bit boundary */
1419 switch (format
->bits_per_pixel
)
1421 case 1: align
= 32; break;
1422 case 4: align
= 8; mapping
= X11DRV_PALETTE_XPixelToPalette
; break;
1423 case 8: align
= 4; mapping
= X11DRV_PALETTE_XPixelToPalette
; break;
1424 case 16: align
= 2; break;
1425 case 24: align
= 4; break;
1426 case 32: align
= 1; break;
1428 FIXME( "depth %u bpp %u not supported yet\n", depth
, format
->bits_per_pixel
);
1429 return ERROR_BAD_FORMAT
;
1432 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1433 info
->bmiHeader
.biPlanes
= 1;
1434 info
->bmiHeader
.biBitCount
= format
->bits_per_pixel
;
1435 info
->bmiHeader
.biXPelsPerMeter
= 0;
1436 info
->bmiHeader
.biYPelsPerMeter
= 0;
1437 info
->bmiHeader
.biClrImportant
= 0;
1438 set_color_info( dev
, color_shifts
, info
);
1440 if (!bits
) return ERROR_SUCCESS
; /* just querying the color information */
1442 x
= src
->visrect
.left
& ~(align
- 1);
1443 y
= src
->visrect
.top
;
1444 width
= src
->visrect
.right
- x
;
1445 height
= src
->visrect
.bottom
- src
->visrect
.top
;
1446 if (format
->scanline_pad
!= 32) width
= (width
+ (align
- 1)) & ~(align
- 1);
1447 /* make the source rectangle relative to the returned bits */
1450 OffsetRect( &src
->visrect
, -x
, -y
);
1455 GetObjectW( hbitmap
, sizeof(bm
), &bm
);
1456 width
= min( width
, bm
.bmWidth
- x
);
1457 height
= min( height
, bm
.bmHeight
- y
);
1458 X11DRV_DIB_Lock( bitmap
, DIB_Status_GdiMod
);
1460 image
= XGetImage( gdi_display
, bitmap
->pixmap
, x
, y
, width
, height
, AllPlanes
, ZPixmap
);
1461 wine_tsx11_unlock();
1462 X11DRV_DIB_Unlock( bitmap
, TRUE
);
1464 else if (GetObjectType( dev
->hdc
) == OBJ_MEMDC
)
1466 X11DRV_LockDIBSection( physdev
, DIB_Status_GdiMod
);
1467 width
= min( width
, physdev
->dc_rect
.right
- physdev
->dc_rect
.left
- x
);
1468 height
= min( height
, physdev
->dc_rect
.bottom
- physdev
->dc_rect
.top
- y
);
1470 image
= XGetImage( gdi_display
, physdev
->drawable
,
1471 physdev
->dc_rect
.left
+ x
, physdev
->dc_rect
.top
+ y
,
1472 width
, height
, AllPlanes
, ZPixmap
);
1473 wine_tsx11_unlock();
1474 X11DRV_UnlockDIBSection( physdev
, FALSE
);
1481 /* use a temporary pixmap to avoid BadMatch errors */
1482 pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, depth
);
1483 XCopyArea( gdi_display
, physdev
->drawable
, pixmap
, get_bitmap_gc(depth
),
1484 physdev
->dc_rect
.left
+ x
, physdev
->dc_rect
.top
+ y
, width
, height
, 0, 0 );
1485 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
, AllPlanes
, ZPixmap
);
1486 XFreePixmap( gdi_display
, pixmap
);
1487 wine_tsx11_unlock();
1489 if (!image
) return ERROR_OUTOFMEMORY
;
1491 info
->bmiHeader
.biWidth
= width
;
1492 info
->bmiHeader
.biHeight
= -height
;
1493 info
->bmiHeader
.biSizeImage
= height
* image
->bytes_per_line
;
1495 src_bits
.ptr
= image
->data
;
1496 src_bits
.is_copy
= TRUE
;
1497 ret
= copy_image_bits( info
, is_r8g8b8(depth
,color_shifts
), image
, &src_bits
, bits
, src
, mapping
,
1498 zeropad_masks
[(width
* image
->bits_per_pixel
) & 31] );
1500 if (!ret
&& bits
->ptr
== image
->data
)
1502 bits
->free
= free_ximage_bits
;
1506 XDestroyImage( image
);
1507 wine_tsx11_unlock();