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 /* return a mask for meaningful bits when doing an XGetPixel on an image */
586 static unsigned long image_pixel_mask( X11DRV_PDEVICE
*physDev
)
589 ColorShifts
*shifts
= physDev
->color_shifts
;
591 if (!shifts
) shifts
= &X11DRV_PALETTE_default_shifts
;
592 ret
= (shifts
->physicalRed
.max
<< shifts
->physicalRed
.shift
) |
593 (shifts
->physicalGreen
.max
<< shifts
->physicalGreen
.shift
) |
594 (shifts
->physicalBlue
.max
<< shifts
->physicalBlue
.shift
);
595 if (!ret
) ret
= (1 << physDev
->depth
) - 1;
600 /***********************************************************************
603 * Retrieve an area from the source DC, mapping all the
604 * pixels to Windows colors.
606 static int BITBLT_GetSrcArea( X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
607 Pixmap pixmap
, GC gc
, RECT
*visRectSrc
)
609 XImage
*imageSrc
, *imageDst
;
612 INT width
= visRectSrc
->right
- visRectSrc
->left
;
613 INT height
= visRectSrc
->bottom
- visRectSrc
->top
;
614 BOOL memdc
= (GetObjectType(physDevSrc
->dev
.hdc
) == OBJ_MEMDC
);
616 if (physDevSrc
->depth
== physDevDst
->depth
)
619 if (!X11DRV_PALETTE_XPixelToPalette
||
620 (physDevDst
->depth
== 1)) /* monochrome -> monochrome */
622 if (physDevDst
->depth
== 1)
624 /* MSDN says if StretchBlt must convert a bitmap from monochrome
625 to color or vice versa, the foreground and background color of
626 the device context are used. In fact, it also applies to the
627 case when it is converted from mono to mono. */
628 XSetBackground( gdi_display
, gc
, physDevDst
->textPixel
);
629 XSetForeground( gdi_display
, gc
, physDevDst
->backgroundPixel
);
630 XCopyPlane( 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, 1);
636 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
637 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
638 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
639 width
, height
, 0, 0);
642 else /* color -> color */
645 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
646 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
647 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
648 width
, height
, AllPlanes
, ZPixmap
);
651 /* Make sure we don't get a BadMatch error */
652 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
653 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
654 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
655 width
, height
, 0, 0);
657 imageSrc
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
658 AllPlanes
, ZPixmap
);
660 for (y
= 0; y
< height
; y
++)
661 for (x
= 0; x
< width
; x
++)
662 XPutPixel(imageSrc
, x
, y
,
663 X11DRV_PALETTE_XPixelToPalette
[XGetPixel(imageSrc
, x
, y
)]);
664 XPutImage( gdi_display
, pixmap
, gc
, imageSrc
,
665 0, 0, 0, 0, width
, height
);
666 XDestroyImage( imageSrc
);
672 if (physDevSrc
->depth
== 1) /* monochrome -> color */
675 if (X11DRV_PALETTE_XPixelToPalette
)
677 XSetBackground( gdi_display
, gc
, X11DRV_PALETTE_XPixelToPalette
[physDevDst
->textPixel
] );
678 XSetForeground( gdi_display
, gc
, X11DRV_PALETTE_XPixelToPalette
[physDevDst
->backgroundPixel
]);
682 XSetBackground( gdi_display
, gc
, physDevDst
->textPixel
);
683 XSetForeground( gdi_display
, gc
, physDevDst
->backgroundPixel
);
685 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
686 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
687 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
688 width
, height
, 0, 0, 1 );
692 else /* color -> monochrome */
694 unsigned long pixel_mask
;
696 /* FIXME: avoid BadMatch error */
697 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
698 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
699 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
700 width
, height
, AllPlanes
, ZPixmap
);
706 imageDst
= X11DRV_DIB_CreateXImage( width
, height
, physDevDst
->depth
);
709 XDestroyImage(imageSrc
);
713 pixel_mask
= image_pixel_mask( physDevSrc
);
714 for (y
= 0; y
< height
; y
++)
715 for (x
= 0; x
< width
; x
++)
716 XPutPixel(imageDst
, x
, y
,
717 !((XGetPixel(imageSrc
,x
,y
) ^ physDevSrc
->backgroundPixel
) & pixel_mask
));
718 XPutImage( gdi_display
, pixmap
, gc
, imageDst
,
719 0, 0, 0, 0, width
, height
);
720 XDestroyImage( imageSrc
);
721 X11DRV_DIB_DestroyXImage( imageDst
);
729 /***********************************************************************
732 * Retrieve an area from the destination DC, mapping all the
733 * pixels to Windows colors.
735 static int BITBLT_GetDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, GC gc
, const RECT
*visRectDst
)
738 INT width
= visRectDst
->right
- visRectDst
->left
;
739 INT height
= visRectDst
->bottom
- visRectDst
->top
;
740 BOOL memdc
= (GetObjectType( physDev
->dev
.hdc
) == OBJ_MEMDC
);
744 if (!X11DRV_PALETTE_XPixelToPalette
|| (physDev
->depth
== 1) ||
745 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
747 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
748 physDev
->dc_rect
.left
+ visRectDst
->left
, physDev
->dc_rect
.top
+ visRectDst
->top
,
749 width
, height
, 0, 0 );
758 image
= XGetImage( gdi_display
, physDev
->drawable
,
759 physDev
->dc_rect
.left
+ visRectDst
->left
,
760 physDev
->dc_rect
.top
+ visRectDst
->top
,
761 width
, height
, AllPlanes
, ZPixmap
);
764 /* Make sure we don't get a BadMatch error */
765 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
766 physDev
->dc_rect
.left
+ visRectDst
->left
,
767 physDev
->dc_rect
.top
+ visRectDst
->top
,
768 width
, height
, 0, 0);
770 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
771 AllPlanes
, ZPixmap
);
775 for (y
= 0; y
< height
; y
++)
776 for (x
= 0; x
< width
; x
++)
777 XPutPixel( image
, x
, y
,
778 X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, x
, y
)]);
779 XPutImage( gdi_display
, pixmap
, gc
, image
, 0, 0, 0, 0, width
, height
);
780 XDestroyImage( image
);
789 /***********************************************************************
792 * Put an area back into the destination DC, mapping the pixel
793 * colors to X pixels.
795 static int BITBLT_PutDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, const RECT
*visRectDst
)
798 INT width
= visRectDst
->right
- visRectDst
->left
;
799 INT height
= visRectDst
->bottom
- visRectDst
->top
;
801 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
803 if (!X11DRV_PALETTE_PaletteToXPixel
|| (physDev
->depth
== 1) ||
804 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
806 XCopyArea( gdi_display
, pixmap
, physDev
->drawable
, physDev
->gc
, 0, 0, width
, height
,
807 physDev
->dc_rect
.left
+ visRectDst
->left
,
808 physDev
->dc_rect
.top
+ visRectDst
->top
);
814 XImage
*image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
815 AllPlanes
, ZPixmap
);
816 for (y
= 0; y
< height
; y
++)
817 for (x
= 0; x
< width
; x
++)
819 XPutPixel( image
, x
, y
,
820 X11DRV_PALETTE_PaletteToXPixel
[XGetPixel( image
, x
, y
)]);
822 XPutImage( gdi_display
, physDev
->drawable
, physDev
->gc
, image
, 0, 0,
823 physDev
->dc_rect
.left
+ visRectDst
->left
,
824 physDev
->dc_rect
.top
+ visRectDst
->top
, width
, height
);
825 XDestroyImage( image
);
830 static BOOL
same_format(X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
)
832 if (physDevSrc
->depth
!= physDevDst
->depth
) return FALSE
;
833 if (!physDevSrc
->color_shifts
&& !physDevDst
->color_shifts
) return TRUE
;
834 if (physDevSrc
->color_shifts
&& physDevDst
->color_shifts
)
835 return !memcmp(physDevSrc
->color_shifts
, physDevDst
->color_shifts
, sizeof(ColorShifts
));
839 void execute_rop( X11DRV_PDEVICE
*physdev
, Pixmap src_pixmap
, GC gc
, const RECT
*visrect
, DWORD rop
)
842 Pixmap result
= src_pixmap
;
844 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
845 BOOL use_pat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
846 BOOL use_dst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
847 int width
= visrect
->right
- visrect
->left
;
848 int height
= visrect
->bottom
- visrect
->top
;
850 pixmaps
[SRC
] = src_pixmap
;
853 pixmaps
[DST
] = XCreatePixmap( gdi_display
, root_window
, width
, height
, physdev
->depth
);
856 if (use_dst
) BITBLT_GetDstArea( physdev
, pixmaps
[DST
], gc
, visrect
);
857 null_brush
= use_pat
&& !X11DRV_SetupGCForPatBlt( physdev
, gc
, TRUE
);
860 for ( ; *opcode
; opcode
++)
862 if (OP_DST(*opcode
) == DST
) result
= pixmaps
[DST
];
863 XSetFunction( gdi_display
, gc
, OP_ROP(*opcode
) );
864 switch(OP_SRCDST(*opcode
))
866 case OP_ARGS(DST
,TMP
):
867 case OP_ARGS(SRC
,TMP
):
869 pixmaps
[TMP
] = XCreatePixmap( gdi_display
, root_window
, width
, height
, physdev
->depth
);
871 case OP_ARGS(DST
,SRC
):
872 case OP_ARGS(SRC
,DST
):
873 case OP_ARGS(TMP
,SRC
):
874 case OP_ARGS(TMP
,DST
):
875 XCopyArea( gdi_display
, pixmaps
[OP_SRC(*opcode
)], pixmaps
[OP_DST(*opcode
)], gc
,
876 0, 0, width
, height
, 0, 0 );
878 case OP_ARGS(PAT
,DST
):
879 case OP_ARGS(PAT
,SRC
):
881 XFillRectangle( gdi_display
, pixmaps
[OP_DST(*opcode
)], gc
, 0, 0, width
, height
);
885 XSetFunction( gdi_display
, physdev
->gc
, GXcopy
);
886 physdev
->exposures
+= BITBLT_PutDstArea( physdev
, result
, visrect
);
887 XFreePixmap( gdi_display
, pixmaps
[DST
] );
888 if (pixmaps
[TMP
]) XFreePixmap( gdi_display
, pixmaps
[TMP
] );
892 /***********************************************************************
895 BOOL
X11DRV_PatBlt( PHYSDEV dev
, struct bitblt_coords
*dst
, DWORD rop
)
897 X11DRV_PDEVICE
*physDev
= get_x11drv_dev( dev
);
898 BOOL usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
899 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
901 if (usePat
&& !X11DRV_SetupGCForBrush( physDev
)) return TRUE
;
903 X11DRV_LockDIBSection( physDev
, DIB_Status_GdiMod
);
906 XSetFunction( gdi_display
, physDev
->gc
, OP_ROP(*opcode
) );
908 switch(rop
) /* a few special cases */
910 case BLACKNESS
: /* 0x00 */
911 case WHITENESS
: /* 0xff */
912 if ((physDev
->depth
!= 1) && X11DRV_PALETTE_PaletteToXPixel
)
914 XSetFunction( gdi_display
, physDev
->gc
, GXcopy
);
915 if (rop
== BLACKNESS
)
916 XSetForeground( gdi_display
, physDev
->gc
, X11DRV_PALETTE_PaletteToXPixel
[0] );
918 XSetForeground( gdi_display
, physDev
->gc
,
919 WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ));
920 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
923 case DSTINVERT
: /* 0x55 */
924 if (!(X11DRV_PALETTE_PaletteFlags
& (X11DRV_PALETTE_PRIVATE
| X11DRV_PALETTE_VIRTUAL
)))
926 /* Xor is much better when we do not have full colormap. */
927 /* Using white^black ensures that we invert at least black */
929 unsigned long xor_pix
= (WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ) ^
930 BlackPixel( gdi_display
, DefaultScreen(gdi_display
) ));
931 XSetFunction( gdi_display
, physDev
->gc
, GXxor
);
932 XSetForeground( gdi_display
, physDev
->gc
, xor_pix
);
933 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
937 XFillRectangle( gdi_display
, physDev
->drawable
, physDev
->gc
,
938 physDev
->dc_rect
.left
+ dst
->visrect
.left
,
939 physDev
->dc_rect
.top
+ dst
->visrect
.top
,
940 dst
->visrect
.right
- dst
->visrect
.left
,
941 dst
->visrect
.bottom
- dst
->visrect
.top
);
944 X11DRV_UnlockDIBSection( physDev
, TRUE
);
949 /***********************************************************************
952 BOOL
X11DRV_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
953 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
955 X11DRV_PDEVICE
*physDevDst
= get_x11drv_dev( dst_dev
);
956 X11DRV_PDEVICE
*physDevSrc
= get_x11drv_dev( src_dev
);
962 if (src_dev
->funcs
!= dst_dev
->funcs
||
963 src
->width
!= dst
->width
|| src
->height
!= dst
->height
) /* no stretching with core X11 */
965 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pStretchBlt
);
966 return dst_dev
->funcs
->pStretchBlt( dst_dev
, dst
, src_dev
, src
, rop
);
969 width
= dst
->visrect
.right
- dst
->visrect
.left
;
970 height
= dst
->visrect
.bottom
- dst
->visrect
.top
;
972 X11DRV_LockDIBSection( physDevDst
, DIB_Status_GdiMod
);
973 if (physDevDst
!= physDevSrc
) X11DRV_LockDIBSection( physDevSrc
, DIB_Status_GdiMod
);
975 opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
977 /* a few optimizations for single-op ROPs */
978 if (!opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
))
980 if (same_format(physDevSrc
, physDevDst
))
983 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
984 XCopyArea( gdi_display
, physDevSrc
->drawable
,
985 physDevDst
->drawable
, physDevDst
->gc
,
986 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
987 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
989 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
990 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
);
991 physDevDst
->exposures
++;
995 if (physDevSrc
->depth
== 1)
998 XSetBackground( gdi_display
, physDevDst
->gc
, physDevDst
->textPixel
);
999 XSetForeground( gdi_display
, physDevDst
->gc
, physDevDst
->backgroundPixel
);
1000 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
1001 XCopyPlane( gdi_display
, physDevSrc
->drawable
,
1002 physDevDst
->drawable
, physDevDst
->gc
,
1003 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
1004 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
1006 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
1007 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
, 1 );
1008 physDevDst
->exposures
++;
1009 wine_tsx11_unlock();
1015 tmpGC
= XCreateGC( gdi_display
, physDevDst
->drawable
, 0, NULL
);
1016 XSetSubwindowMode( gdi_display
, tmpGC
, IncludeInferiors
);
1017 XSetGraphicsExposures( gdi_display
, tmpGC
, False
);
1018 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, physDevDst
->depth
);
1019 wine_tsx11_unlock();
1021 BITBLT_GetSrcArea( physDevSrc
, physDevDst
, src_pixmap
, tmpGC
, &src
->visrect
);
1022 execute_rop( physDevDst
, src_pixmap
, tmpGC
, &dst
->visrect
, rop
);
1025 XFreePixmap( gdi_display
, src_pixmap
);
1026 XFreeGC( gdi_display
, tmpGC
);
1027 wine_tsx11_unlock();
1030 if (physDevDst
!= physDevSrc
) X11DRV_UnlockDIBSection( physDevSrc
, FALSE
);
1031 X11DRV_UnlockDIBSection( physDevDst
, TRUE
);
1036 static void free_heap_bits( struct gdi_image_bits
*bits
)
1038 HeapFree( GetProcessHeap(), 0, bits
->ptr
);
1041 static void free_ximage_bits( struct gdi_image_bits
*bits
)
1045 wine_tsx11_unlock();
1048 /* store the palette or color mask data in the bitmap info structure */
1049 static void set_color_info( PHYSDEV dev
, const ColorShifts
*color_shifts
, BITMAPINFO
*info
)
1051 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1053 info
->bmiHeader
.biCompression
= BI_RGB
;
1054 info
->bmiHeader
.biClrUsed
= 0;
1056 switch (info
->bmiHeader
.biBitCount
)
1061 RGBQUAD
*rgb
= (RGBQUAD
*)colors
;
1062 PALETTEENTRY palette
[256];
1065 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1066 count
= X11DRV_GetSystemPaletteEntries( dev
, 0, info
->bmiHeader
.biClrUsed
, palette
);
1067 for (i
= 0; i
< count
; i
++)
1069 rgb
[i
].rgbRed
= palette
[i
].peRed
;
1070 rgb
[i
].rgbGreen
= palette
[i
].peGreen
;
1071 rgb
[i
].rgbBlue
= palette
[i
].peBlue
;
1072 rgb
[i
].rgbReserved
= 0;
1074 memset( &rgb
[count
], 0, (info
->bmiHeader
.biClrUsed
- count
) * sizeof(*rgb
) );
1078 colors
[0] = color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
;
1079 colors
[1] = color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
;
1080 colors
[2] = color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
;
1081 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1084 colors
[0] = color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
;
1085 colors
[1] = color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
;
1086 colors
[2] = color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
;
1087 if (colors
[0] != 0xff0000 || colors
[1] != 0x00ff00 || colors
[2] != 0x0000ff)
1088 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1093 /* check if the specified color info is suitable for PutImage */
1094 static BOOL
matching_color_info( PHYSDEV dev
, const ColorShifts
*color_shifts
, const BITMAPINFO
*info
)
1096 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1098 switch (info
->bmiHeader
.biBitCount
)
1101 if (info
->bmiHeader
.biCompression
!= BI_RGB
) return FALSE
;
1102 return !info
->bmiHeader
.biClrUsed
; /* color map not allowed */
1106 RGBQUAD
*rgb
= (RGBQUAD
*)colors
;
1107 PALETTEENTRY palette
[256];
1110 if (info
->bmiHeader
.biCompression
!= BI_RGB
) return FALSE
;
1111 count
= X11DRV_GetSystemPaletteEntries( dev
, 0, 1 << info
->bmiHeader
.biBitCount
, palette
);
1112 if (count
!= info
->bmiHeader
.biClrUsed
) return FALSE
;
1113 for (i
= 0; i
< count
; i
++)
1115 if (rgb
[i
].rgbRed
!= palette
[i
].peRed
||
1116 rgb
[i
].rgbGreen
!= palette
[i
].peGreen
||
1117 rgb
[i
].rgbBlue
!= palette
[i
].peBlue
) return FALSE
;
1122 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1123 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== colors
[0] &&
1124 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== colors
[1] &&
1125 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== colors
[2]);
1126 if (info
->bmiHeader
.biCompression
== BI_RGB
)
1127 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== 0x7c00 &&
1128 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== 0x03e0 &&
1129 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== 0x001f);
1132 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1133 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== colors
[0] &&
1134 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== colors
[1] &&
1135 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== colors
[2]);
1138 if (info
->bmiHeader
.biCompression
== BI_RGB
)
1139 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== 0xff0000 &&
1140 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== 0x00ff00 &&
1141 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== 0x0000ff);
1147 static inline BOOL
is_r8g8b8( int depth
, const ColorShifts
*color_shifts
)
1149 return depth
== 24 && color_shifts
->logicalBlue
.shift
== 0 && color_shifts
->logicalRed
.shift
== 16;
1152 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1153 DWORD
copy_image_bits( BITMAPINFO
*info
, BOOL is_r8g8b8
, XImage
*image
,
1154 const struct gdi_image_bits
*src_bits
, struct gdi_image_bits
*dst_bits
,
1155 struct bitblt_coords
*coords
, const int *mapping
, unsigned int zeropad_mask
)
1157 #ifdef WORDS_BIGENDIAN
1158 static const int client_byte_order
= MSBFirst
;
1160 static const int client_byte_order
= LSBFirst
;
1163 int x
, y
, height
= coords
->visrect
.bottom
- coords
->visrect
.top
;
1164 int width_bytes
= image
->bytes_per_line
;
1166 unsigned char *src
, *dst
;
1168 switch (info
->bmiHeader
.biBitCount
)
1171 need_byteswap
= (image
->bitmap_bit_order
!= MSBFirst
);
1174 need_byteswap
= (image
->byte_order
!= MSBFirst
);
1178 need_byteswap
= (image
->byte_order
!= client_byte_order
);
1181 need_byteswap
= (image
->byte_order
== MSBFirst
) ^ !is_r8g8b8
;
1184 need_byteswap
= FALSE
;
1188 src
= src_bits
->ptr
;
1189 if (info
->bmiHeader
.biHeight
> 0)
1190 src
+= (info
->bmiHeader
.biHeight
- coords
->visrect
.bottom
) * width_bytes
;
1192 src
+= coords
->visrect
.top
* width_bytes
;
1194 if ((need_byteswap
&& !src_bits
->is_copy
) || /* need to swap bytes */
1195 (zeropad_mask
!= ~0u && !src_bits
->is_copy
) || /* need to clear padding bytes */
1196 (mapping
&& !src_bits
->is_copy
) || /* need to remap pixels */
1197 (width_bytes
& 3) || /* need to fixup line alignment */
1198 (info
->bmiHeader
.biHeight
> 0)) /* need to flip vertically */
1200 width_bytes
= (width_bytes
+ 3) & ~3;
1201 info
->bmiHeader
.biSizeImage
= height
* width_bytes
;
1202 if (!(dst_bits
->ptr
= HeapAlloc( GetProcessHeap(), 0, info
->bmiHeader
.biSizeImage
)))
1203 return ERROR_OUTOFMEMORY
;
1204 dst_bits
->is_copy
= TRUE
;
1205 dst_bits
->free
= free_heap_bits
;
1209 /* swap bits in place */
1210 dst_bits
->ptr
= src
;
1211 dst_bits
->is_copy
= src_bits
->is_copy
;
1212 dst_bits
->free
= NULL
;
1213 if (!need_byteswap
&& zeropad_mask
== ~0u && !mapping
) return ERROR_SUCCESS
; /* nothing to do */
1216 dst
= dst_bits
->ptr
;
1217 padding_pos
= width_bytes
/sizeof(unsigned int) - 1;
1219 if (info
->bmiHeader
.biHeight
> 0)
1221 dst
+= (height
- 1) * width_bytes
;
1222 width_bytes
= -width_bytes
;
1225 if (need_byteswap
|| mapping
)
1227 switch (info
->bmiHeader
.biBitCount
)
1230 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1232 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1233 dst
[x
] = bit_swap
[src
[x
]];
1234 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1238 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1241 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1242 dst
[x
] = (mapping
[src
[x
] & 0x0f] << 4) | mapping
[src
[x
] >> 4];
1244 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1245 dst
[x
] = (src
[x
] << 4) | (src
[x
] >> 4);
1246 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1250 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1252 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1253 dst
[x
] = mapping
[src
[x
]];
1254 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1258 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1260 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1261 ((USHORT
*)dst
)[x
] = RtlUshortByteSwap( ((const USHORT
*)src
)[x
] );
1262 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1266 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1268 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1270 unsigned char tmp
= src
[3 * x
];
1271 dst
[3 * x
] = src
[3 * x
+ 2];
1272 dst
[3 * x
+ 1] = src
[3 * x
+ 1];
1273 dst
[3 * x
+ 2] = tmp
;
1275 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1279 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1280 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1281 ((ULONG
*)dst
)[x
] = RtlUlongByteSwap( ((const ULONG
*)src
)[x
] );
1285 else if (src
!= dst
)
1287 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1289 memcpy( dst
, src
, image
->bytes_per_line
);
1290 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1293 else /* only need to clear the padding */
1295 for (y
= 0; y
< height
; y
++, dst
+= width_bytes
)
1296 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1298 return ERROR_SUCCESS
;
1301 /***********************************************************************
1304 DWORD
X11DRV_PutImage( PHYSDEV dev
, HBITMAP hbitmap
, HRGN clip
, BITMAPINFO
*info
,
1305 const struct gdi_image_bits
*bits
, struct bitblt_coords
*src
,
1306 struct bitblt_coords
*dst
, DWORD rop
)
1308 X11DRV_PDEVICE
*physdev
;
1309 X_PHYSBITMAP
*bitmap
;
1313 struct gdi_image_bits dst_bits
;
1314 const XPixmapFormatValues
*format
;
1315 const ColorShifts
*color_shifts
;
1316 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1317 const int *mapping
= NULL
;
1321 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
1323 depth
= bitmap
->depth
;
1324 color_shifts
= &bitmap
->color_shifts
;
1328 physdev
= get_x11drv_dev( dev
);
1330 depth
= physdev
->depth
;
1331 color_shifts
= physdev
->color_shifts
;
1333 format
= pixmap_formats
[depth
];
1335 if (info
->bmiHeader
.biPlanes
!= 1) goto update_format
;
1336 if (info
->bmiHeader
.biBitCount
!= format
->bits_per_pixel
) goto update_format
;
1337 /* FIXME: could try to handle 1-bpp using XCopyPlane */
1338 if (!matching_color_info( dev
, color_shifts
, info
)) goto update_format
;
1339 if (!bits
) return ERROR_SUCCESS
; /* just querying the format */
1340 if ((src
->width
!= dst
->width
) || (src
->height
!= dst
->height
)) return ERROR_TRANSFORM_NOT_SUPPORTED
;
1343 image
= XCreateImage( gdi_display
, visual
, depth
, ZPixmap
, 0, NULL
,
1344 info
->bmiHeader
.biWidth
, src
->visrect
.bottom
- src
->visrect
.top
, 32, 0 );
1345 wine_tsx11_unlock();
1346 if (!image
) return ERROR_OUTOFMEMORY
;
1348 if (image
->bits_per_pixel
== 4 || image
->bits_per_pixel
== 8)
1350 if (bitmap
|| (!opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
)))
1351 mapping
= X11DRV_PALETTE_PaletteToXPixel
;
1354 ret
= copy_image_bits( info
, is_r8g8b8(depth
,color_shifts
), image
, bits
, &dst_bits
, src
, mapping
, ~0u );
1358 int width
= dst
->visrect
.right
- dst
->visrect
.left
;
1359 int height
= dst
->visrect
.bottom
- dst
->visrect
.top
;
1361 image
->data
= dst_bits
.ptr
;
1362 /* hack: make sure the bits are readable if we are reading from a DIB section */
1363 /* to be removed once we get rid of DIB access protections */
1364 if (!dst_bits
.is_copy
) IsBadReadPtr( dst_bits
.ptr
, height
* image
->bytes_per_line
);
1368 RGNDATA
*clip_data
= NULL
;
1371 if (clip
) clip_data
= X11DRV_GetRegionData( clip
, 0 );
1372 X11DRV_DIB_Lock( bitmap
, DIB_Status_GdiMod
);
1375 gc
= XCreateGC( gdi_display
, bitmap
->pixmap
, 0, NULL
);
1376 XSetGraphicsExposures( gdi_display
, gc
, False
);
1377 if (clip_data
) XSetClipRectangles( gdi_display
, gc
, 0, 0, (XRectangle
*)clip_data
->Buffer
,
1378 clip_data
->rdh
.nCount
, YXBanded
);
1379 XPutImage( gdi_display
, bitmap
->pixmap
, gc
, image
, src
->visrect
.left
, 0,
1380 dst
->visrect
.left
, dst
->visrect
.top
, width
, height
);
1381 XFreeGC( gdi_display
, gc
);
1382 wine_tsx11_unlock();
1384 X11DRV_DIB_Unlock( bitmap
, TRUE
);
1385 HeapFree( GetProcessHeap(), 0, clip_data
);
1389 RGNDATA
*saved_region
= NULL
;
1391 if (clip
) saved_region
= add_extra_clipping_region( physdev
, clip
);
1392 X11DRV_LockDIBSection( physdev
, DIB_Status_GdiMod
);
1394 /* optimization for single-op ROPs */
1395 if (!opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
))
1398 XSetFunction( gdi_display
, physdev
->gc
, OP_ROP(*opcode
) );
1399 XPutImage( gdi_display
, physdev
->drawable
, physdev
->gc
, image
, src
->visrect
.left
, 0,
1400 physdev
->dc_rect
.left
+ dst
->visrect
.left
,
1401 physdev
->dc_rect
.top
+ dst
->visrect
.top
, width
, height
);
1402 wine_tsx11_unlock();
1410 gc
= XCreateGC( gdi_display
, physdev
->drawable
, 0, NULL
);
1411 XSetSubwindowMode( gdi_display
, gc
, IncludeInferiors
);
1412 XSetGraphicsExposures( gdi_display
, gc
, False
);
1413 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, depth
);
1414 XPutImage( gdi_display
, src_pixmap
, gc
, image
, src
->visrect
.left
, 0, 0, 0, width
, height
);
1415 wine_tsx11_unlock();
1417 execute_rop( physdev
, src_pixmap
, gc
, &dst
->visrect
, rop
);
1420 XFreePixmap( gdi_display
, src_pixmap
);
1421 XFreeGC( gdi_display
, gc
);
1422 wine_tsx11_unlock();
1425 X11DRV_UnlockDIBSection( physdev
, !ret
);
1426 restore_clipping_region( physdev
, saved_region
);
1432 XDestroyImage( image
);
1433 wine_tsx11_unlock();
1434 if (dst_bits
.free
) dst_bits
.free( &dst_bits
);
1438 info
->bmiHeader
.biPlanes
= 1;
1439 info
->bmiHeader
.biBitCount
= format
->bits_per_pixel
;
1440 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
1441 set_color_info( dev
, color_shifts
, info
);
1442 return ERROR_BAD_FORMAT
;
1445 /***********************************************************************
1448 DWORD
X11DRV_GetImage( PHYSDEV dev
, HBITMAP hbitmap
, BITMAPINFO
*info
,
1449 struct gdi_image_bits
*bits
, struct bitblt_coords
*src
)
1451 X11DRV_PDEVICE
*physdev
;
1452 X_PHYSBITMAP
*bitmap
;
1453 DWORD ret
= ERROR_SUCCESS
;
1455 UINT align
, x
, y
, width
, height
;
1457 struct gdi_image_bits src_bits
;
1458 const XPixmapFormatValues
*format
;
1459 const ColorShifts
*color_shifts
;
1460 const int *mapping
= NULL
;
1464 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
1466 depth
= bitmap
->depth
;
1467 color_shifts
= &bitmap
->color_shifts
;
1471 physdev
= get_x11drv_dev( dev
);
1473 depth
= physdev
->depth
;
1474 color_shifts
= physdev
->color_shifts
;
1476 format
= pixmap_formats
[depth
];
1478 /* align start and width to 32-bit boundary */
1479 switch (format
->bits_per_pixel
)
1481 case 1: align
= 32; break;
1482 case 4: align
= 8; mapping
= X11DRV_PALETTE_XPixelToPalette
; break;
1483 case 8: align
= 4; mapping
= X11DRV_PALETTE_XPixelToPalette
; break;
1484 case 16: align
= 2; break;
1485 case 24: align
= 4; break;
1486 case 32: align
= 1; break;
1488 FIXME( "depth %u bpp %u not supported yet\n", depth
, format
->bits_per_pixel
);
1489 return ERROR_BAD_FORMAT
;
1492 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1493 info
->bmiHeader
.biPlanes
= 1;
1494 info
->bmiHeader
.biBitCount
= format
->bits_per_pixel
;
1495 info
->bmiHeader
.biXPelsPerMeter
= 0;
1496 info
->bmiHeader
.biYPelsPerMeter
= 0;
1497 info
->bmiHeader
.biClrImportant
= 0;
1498 set_color_info( dev
, color_shifts
, info
);
1500 if (!bits
) return ERROR_SUCCESS
; /* just querying the color information */
1502 x
= src
->visrect
.left
& ~(align
- 1);
1503 y
= src
->visrect
.top
;
1504 width
= src
->visrect
.right
- x
;
1505 height
= src
->visrect
.bottom
- src
->visrect
.top
;
1506 if (format
->scanline_pad
!= 32) width
= (width
+ (align
- 1)) & ~(align
- 1);
1507 /* make the source rectangle relative to the returned bits */
1510 OffsetRect( &src
->visrect
, -x
, -y
);
1515 GetObjectW( hbitmap
, sizeof(bm
), &bm
);
1516 width
= min( width
, bm
.bmWidth
- x
);
1517 height
= min( height
, bm
.bmHeight
- y
);
1518 X11DRV_DIB_Lock( bitmap
, DIB_Status_GdiMod
);
1520 image
= XGetImage( gdi_display
, bitmap
->pixmap
, x
, y
, width
, height
, AllPlanes
, ZPixmap
);
1521 wine_tsx11_unlock();
1522 X11DRV_DIB_Unlock( bitmap
, TRUE
);
1524 else if (GetObjectType( dev
->hdc
) == OBJ_MEMDC
)
1526 X11DRV_LockDIBSection( physdev
, DIB_Status_GdiMod
);
1527 width
= min( width
, physdev
->dc_rect
.right
- physdev
->dc_rect
.left
- x
);
1528 height
= min( height
, physdev
->dc_rect
.bottom
- physdev
->dc_rect
.top
- y
);
1530 image
= XGetImage( gdi_display
, physdev
->drawable
,
1531 physdev
->dc_rect
.left
+ x
, physdev
->dc_rect
.top
+ y
,
1532 width
, height
, AllPlanes
, ZPixmap
);
1533 wine_tsx11_unlock();
1534 X11DRV_UnlockDIBSection( physdev
, FALSE
);
1541 /* use a temporary pixmap to avoid BadMatch errors */
1542 pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, depth
);
1543 XCopyArea( gdi_display
, physdev
->drawable
, pixmap
, get_bitmap_gc(depth
),
1544 physdev
->dc_rect
.left
+ x
, physdev
->dc_rect
.top
+ y
, width
, height
, 0, 0 );
1545 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
, AllPlanes
, ZPixmap
);
1546 XFreePixmap( gdi_display
, pixmap
);
1547 wine_tsx11_unlock();
1549 if (!image
) return ERROR_OUTOFMEMORY
;
1551 info
->bmiHeader
.biWidth
= width
;
1552 info
->bmiHeader
.biHeight
= -height
;
1553 info
->bmiHeader
.biSizeImage
= height
* image
->bytes_per_line
;
1555 src_bits
.ptr
= image
->data
;
1556 src_bits
.is_copy
= TRUE
;
1557 ret
= copy_image_bits( info
, is_r8g8b8(depth
,color_shifts
), image
, &src_bits
, bits
, src
, mapping
,
1558 zeropad_masks
[(width
* image
->bits_per_pixel
) & 31] );
1560 if (!ret
&& bits
->ptr
== image
->data
)
1562 bits
->free
= free_ximage_bits
;
1566 XDestroyImage( image
);
1567 wine_tsx11_unlock();