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 #define SWAP_INT32(i1,i2) \
56 do { INT __t = *(i1); *(i1) = *(i2); *(i2) = __t; } while(0)
58 static const unsigned char BITBLT_Opcodes
[256][MAX_OP_LEN
] =
60 { OP(PAT
,DST
,GXclear
) }, /* 0x00 0 */
61 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXnor
) }, /* 0x01 ~(D|(P|S)) */
62 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXand
) }, /* 0x02 D&~(P|S) */
63 { OP(PAT
,SRC
,GXnor
) }, /* 0x03 ~(P|S) */
64 { OP(PAT
,DST
,GXnor
), OP(SRC
,DST
,GXand
) }, /* 0x04 S&~(D|P) */
65 { OP(PAT
,DST
,GXnor
) }, /* 0x05 ~(D|P) */
66 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXnor
), }, /* 0x06 ~(P|~(D^S)) */
67 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXnor
) }, /* 0x07 ~(P|(D&S)) */
68 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXand
) },/* 0x08 S&D&~P */
69 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXnor
) }, /* 0x09 ~(P|(D^S)) */
70 { OP(PAT
,DST
,GXandInverted
) }, /* 0x0a D&~P */
71 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXnor
) }, /* 0x0b ~(P|(S&~D)) */
72 { OP(PAT
,SRC
,GXandInverted
) }, /* 0x0c S&~P */
73 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXnor
) },/* 0x0d ~(P|(D&~S)) */
74 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXnor
) }, /* 0x0e ~(P|~(D|S)) */
75 { OP(PAT
,DST
,GXcopyInverted
) }, /* 0x0f ~P */
76 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXand
) }, /* 0x10 P&~(S|D) */
77 { OP(SRC
,DST
,GXnor
) }, /* 0x11 ~(D|S) */
78 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXnor
) }, /* 0x12 ~(S|~(D^P)) */
79 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXnor
) }, /* 0x13 ~(S|(D&P)) */
80 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXnor
) }, /* 0x14 ~(D|~(P^S)) */
81 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXnor
) }, /* 0x15 ~(D|(P&S)) */
82 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnand
),
83 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
),
84 OP(PAT
,DST
,GXxor
) }, /* 0x16 P^S^(D&~(P&S) */
85 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
86 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
87 OP(TMP
,DST
,GXequiv
) }, /* 0x17 ~S^((S^P)&(S^D))*/
88 { OP(PAT
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
89 OP(SRC
,DST
,GXand
) }, /* 0x18 (S^P)&(D^P) */
90 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnand
),
91 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x19 ~S^(D&~(P&S)) */
92 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
),
93 OP(PAT
,DST
,GXxor
) }, /* 0x1a P^(D|(S&P)) */
94 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
95 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x1b ~S^(D&(P^S)) */
96 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
),
97 OP(PAT
,DST
,GXxor
) }, /* 0x1c P^(S|(D&P)) */
98 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
99 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x1d ~D^(S&(D^P)) */
100 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
) }, /* 0x1e P^(D|S) */
101 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXnand
) }, /* 0x1f ~(P&(D|S)) */
102 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXand
) }, /* 0x20 D&(P&~S) */
103 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXnor
) }, /* 0x21 ~(S|(D^P)) */
104 { OP(SRC
,DST
,GXandInverted
) }, /* 0x22 ~S&D */
105 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXnor
) }, /* 0x23 ~(S|(P&~D)) */
106 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
107 OP(SRC
,DST
,GXand
) }, /* 0x24 (S^P)&(S^D) */
108 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXand
),
109 OP(PAT
,DST
,GXequiv
) }, /* 0x25 ~P^(D&~(S&P)) */
110 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
111 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x26 S^(D|(S&P)) */
112 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXequiv
),
113 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x27 S^(D|~(P^S)) */
114 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
) }, /* 0x28 D&(P^S) */
115 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
116 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
),
117 OP(PAT
,DST
,GXequiv
) }, /* 0x29 ~P^S^(D|(P&S)) */
118 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXand
) }, /* 0x2a D&~(P&S) */
119 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
120 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
121 OP(TMP
,DST
,GXequiv
) }, /* 0x2b ~S^((P^S)&(P^D))*/
122 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
),
123 OP(SRC
,DST
,GXxor
) }, /* 0x2c S^(P&(S|D)) */
124 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXxor
) }, /* 0x2d P^(S|~D) */
125 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
),
126 OP(PAT
,DST
,GXxor
) }, /* 0x2e P^(S|(D^P)) */
127 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXnand
) }, /* 0x2f ~(P&(S|~D)) */
128 { OP(PAT
,SRC
,GXandReverse
) }, /* 0x30 P&~S */
129 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXnor
) },/* 0x31 ~(S|(D&~P)) */
130 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXor
),
131 OP(SRC
,DST
,GXxor
) }, /* 0x32 S^(D|P|S) */
132 { OP(SRC
,DST
,GXcopyInverted
) }, /* 0x33 ~S */
133 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
),
134 OP(SRC
,DST
,GXxor
) }, /* 0x34 S^(P|(D&S)) */
135 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXor
),
136 OP(SRC
,DST
,GXxor
) }, /* 0x35 S^(P|~(D^S)) */
137 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x36 S^(D|P) */
138 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXnand
) }, /* 0x37 ~(S&(D|P)) */
139 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
),
140 OP(PAT
,DST
,GXxor
) }, /* 0x38 P^(S&(D|P)) */
141 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x39 S^(P|~D) */
142 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
),
143 OP(SRC
,DST
,GXxor
) }, /* 0x3a S^(P|(D^S)) */
144 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXnand
) }, /* 0x3b ~(S&(P|~D)) */
145 { OP(PAT
,SRC
,GXxor
) }, /* 0x3c P^S */
146 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
),
147 OP(SRC
,DST
,GXxor
) }, /* 0x3d S^(P|~(D|S)) */
148 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
),
149 OP(SRC
,DST
,GXxor
) }, /* 0x3e S^(P|(D&~S)) */
150 { OP(PAT
,SRC
,GXnand
) }, /* 0x3f ~(P&S) */
151 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXand
) }, /* 0x40 P&S&~D */
152 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXnor
) }, /* 0x41 ~(D|(P^S)) */
153 { OP(DST
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
154 OP(SRC
,DST
,GXand
) }, /* 0x42 (S^D)&(P^D) */
155 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
),
156 OP(SRC
,DST
,GXequiv
) }, /* 0x43 ~S^(P&~(D&S)) */
157 { OP(SRC
,DST
,GXandReverse
) }, /* 0x44 S&~D */
158 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXnor
) }, /* 0x45 ~(D|(P&~S)) */
159 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
160 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x46 D^(S|(P&D)) */
161 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
162 OP(PAT
,DST
,GXequiv
) }, /* 0x47 ~P^(S&(D^P)) */
163 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
) }, /* 0x48 S&(P^D) */
164 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
165 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
),
166 OP(PAT
,DST
,GXequiv
) }, /* 0x49 ~P^D^(S|(P&D)) */
167 { OP(DST
,SRC
,GXor
), OP(PAT
,SRC
,GXand
),
168 OP(SRC
,DST
,GXxor
) }, /* 0x4a D^(P&(S|D)) */
169 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXxor
) }, /* 0x4b P^(D|~S) */
170 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXand
) }, /* 0x4c S&~(D&P) */
171 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
172 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
173 OP(TMP
,DST
,GXequiv
) }, /* 0x4d ~S^((S^P)|(S^D))*/
174 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
175 OP(PAT
,DST
,GXxor
) }, /* 0x4e P^(D|(S^P)) */
176 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXnand
) },/* 0x4f ~(P&(D|~S)) */
177 { OP(PAT
,DST
,GXandReverse
) }, /* 0x50 P&~D */
178 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXnor
) },/* 0x51 ~(D|(S&~P)) */
179 { OP(DST
,SRC
,GXand
), OP(PAT
,SRC
,GXor
),
180 OP(SRC
,DST
,GXxor
) }, /* 0x52 D^(P|(S&D)) */
181 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
),
182 OP(SRC
,DST
,GXequiv
) }, /* 0x53 ~S^(P&(D^S)) */
183 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXnor
) }, /* 0x54 ~(D|~(P|S)) */
184 { OP(PAT
,DST
,GXinvert
) }, /* 0x55 ~D */
185 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x56 D^(P|S) */
186 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXnand
) }, /* 0x57 ~(D&(P|S)) */
187 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
),
188 OP(PAT
,DST
,GXxor
) }, /* 0x58 P^(D&(P|S)) */
189 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x59 D^(P|~S) */
190 { OP(PAT
,DST
,GXxor
) }, /* 0x5a D^P */
191 { OP(DST
,SRC
,GXnor
), OP(PAT
,SRC
,GXor
),
192 OP(SRC
,DST
,GXxor
) }, /* 0x5b D^(P|~(S|D)) */
193 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXor
),
194 OP(SRC
,DST
,GXxor
) }, /* 0x5c D^(P|(S^D)) */
195 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXnand
) }, /* 0x5d ~(D&(P|~S)) */
196 { OP(DST
,SRC
,GXandInverted
), OP(PAT
,SRC
,GXor
),
197 OP(SRC
,DST
,GXxor
) }, /* 0x5e D^(P|(S&~D)) */
198 { OP(PAT
,DST
,GXnand
) }, /* 0x5f ~(D&P) */
199 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
) }, /* 0x60 P&(D^S) */
200 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXand
),
201 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
202 OP(TMP
,DST
,GXequiv
) }, /* 0x61 ~D^S^(P|(D&S)) */
203 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
204 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x62 D^(S&(P|D)) */
205 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXxor
) }, /* 0x63 S^(D|~P) */
206 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
207 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x64 S^(D&(P|S)) */
208 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXxor
) }, /* 0x65 D^(S|~P) */
209 { OP(SRC
,DST
,GXxor
) }, /* 0x66 S^D */
210 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
211 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x67 S^(D|~(S|P) */
212 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXnor
),
213 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
214 OP(TMP
,DST
,GXequiv
) }, /* 0x68 ~D^S^(P|~(D|S))*/
215 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXequiv
) }, /* 0x69 ~P^(D^S) */
216 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXxor
) }, /* 0x6a D^(P&S) */
217 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
218 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
),
219 OP(PAT
,DST
,GXequiv
) }, /* 0x6b ~P^S^(D&(P|S)) */
220 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
) }, /* 0x6c S^(D&P) */
221 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
222 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
),
223 OP(PAT
,DST
,GXequiv
) }, /* 0x6d ~P^D^(S&(P|D)) */
224 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXorReverse
),
225 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x6e S^(D&(P|~S)) */
226 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXnand
) }, /* 0x6f ~(P&~(S^D)) */
227 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
) }, /* 0x70 P&~(D&S) */
228 { OP(SRC
,TMP
,GXcopy
), OP(DST
,SRC
,GXxor
),
229 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
230 OP(TMP
,DST
,GXequiv
) }, /* 0x71 ~S^((S^D)&(P^D))*/
231 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
232 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x72 S^(D|(P^S)) */
233 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXnand
) },/* 0x73 ~(S&(D|~P)) */
234 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
235 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x74 D^(S|(P^D)) */
236 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXnand
) },/* 0x75 ~(D&(S|~P)) */
237 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXandReverse
),
238 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x76 S^(D|(P&~S)) */
239 { OP(SRC
,DST
,GXnand
) }, /* 0x77 ~(S&D) */
240 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
) }, /* 0x78 P^(D&S) */
241 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXor
),
242 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
243 OP(TMP
,DST
,GXequiv
) }, /* 0x79 ~D^S^(P&(D|S)) */
244 { OP(DST
,SRC
,GXorInverted
), OP(PAT
,SRC
,GXand
),
245 OP(SRC
,DST
,GXxor
) }, /* 0x7a D^(P&(S|~D)) */
246 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXnand
) }, /* 0x7b ~(S&~(D^P)) */
247 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
),
248 OP(SRC
,DST
,GXxor
) }, /* 0x7c S^(P&(D|~S)) */
249 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXnand
) }, /* 0x7d ~(D&~(P^S)) */
250 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
251 OP(SRC
,DST
,GXor
) }, /* 0x7e (S^P)|(S^D) */
252 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXnand
) }, /* 0x7f ~(D&P&S) */
253 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXand
) }, /* 0x80 D&P&S */
254 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
255 OP(SRC
,DST
,GXnor
) }, /* 0x81 ~((S^P)|(S^D)) */
256 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXand
) }, /* 0x82 D&~(P^S) */
257 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
),
258 OP(SRC
,DST
,GXequiv
) }, /* 0x83 ~S^(P&(D|~S)) */
259 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXand
) }, /* 0x84 S&~(D^P) */
260 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXand
),
261 OP(PAT
,DST
,GXequiv
) }, /* 0x85 ~P^(D&(S|~P)) */
262 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXor
),
263 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
264 OP(TMP
,DST
,GXxor
) }, /* 0x86 D^S^(P&(D|S)) */
265 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXequiv
) }, /* 0x87 ~P^(D&S) */
266 { OP(SRC
,DST
,GXand
) }, /* 0x88 S&D */
267 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXandReverse
),
268 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x89 ~S^(D|(P&~S)) */
269 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXand
) }, /* 0x8a D&(S|~P) */
270 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
271 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x8b ~D^(S|(P^D)) */
272 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXand
) }, /* 0x8c S&(D|~P) */
273 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
274 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x8d ~S^(D|(P^S)) */
275 { OP(SRC
,TMP
,GXcopy
), OP(DST
,SRC
,GXxor
),
276 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
277 OP(TMP
,DST
,GXxor
) }, /* 0x8e S^((S^D)&(P^D))*/
278 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXnand
) }, /* 0x8f ~(P&~(D&S)) */
279 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXand
) }, /* 0x90 P&~(D^S) */
280 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXorReverse
),
281 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x91 ~S^(D&(P|~S)) */
282 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
283 OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
),
284 OP(TMP
,DST
,GXxor
) }, /* 0x92 D^P^(S&(D|P)) */
285 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x93 ~S^(P&D) */
286 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
287 OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
),
288 OP(TMP
,DST
,GXxor
) }, /* 0x94 S^P^(D&(P|S)) */
289 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x95 ~D^(P&S) */
290 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXxor
) }, /* 0x96 D^P^S */
291 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
292 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
293 OP(TMP
,DST
,GXxor
) }, /* 0x97 S^P^(D|~(P|S)) */
294 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
295 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x98 ~S^(D|~(P|S)) */
296 { OP(SRC
,DST
,GXequiv
) }, /* 0x99 ~S^D */
297 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x9a D^(P&~S) */
298 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
299 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x9b ~S^(D&(P|S)) */
300 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x9c S^(P&~D) */
301 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
302 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x9d ~D^(S&(P|D)) */
303 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXand
),
304 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
305 OP(TMP
,DST
,GXxor
) }, /* 0x9e D^S^(P|(D&S)) */
306 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXnand
) }, /* 0x9f ~(P&(D^S)) */
307 { OP(PAT
,DST
,GXand
) }, /* 0xa0 D&P */
308 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXor
),
309 OP(PAT
,DST
,GXequiv
) }, /* 0xa1 ~P^(D|(S&~P)) */
310 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXand
) }, /* 0xa2 D&(P|~S) */
311 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXor
),
312 OP(SRC
,DST
,GXequiv
) }, /* 0xa3 ~D^(P|(S^D)) */
313 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXor
),
314 OP(PAT
,DST
,GXequiv
) }, /* 0xa4 ~P^(D|~(S|P)) */
315 { OP(PAT
,DST
,GXequiv
) }, /* 0xa5 ~P^D */
316 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXxor
) },/* 0xa6 D^(S&~P) */
317 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
),
318 OP(PAT
,DST
,GXequiv
) }, /* 0xa7 ~P^(D&(S|P)) */
319 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
) }, /* 0xa8 D&(P|S) */
320 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXequiv
) }, /* 0xa9 ~D^(P|S) */
321 { OP(PAT
,DST
,GXnoop
) }, /* 0xaa D */
322 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXor
) }, /* 0xab D|~(P|S) */
323 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
),
324 OP(SRC
,DST
,GXxor
) }, /* 0xac S^(P&(D^S)) */
325 { OP(DST
,SRC
,GXand
), OP(PAT
,SRC
,GXor
),
326 OP(SRC
,DST
,GXequiv
) }, /* 0xad ~D^(P|(S&D)) */
327 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXor
) }, /* 0xae D|(S&~P) */
328 { OP(PAT
,DST
,GXorInverted
) }, /* 0xaf D|~P */
329 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
) }, /* 0xb0 P&(D|~S) */
330 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
331 OP(PAT
,DST
,GXequiv
) }, /* 0xb1 ~P^(D|(S^P)) */
332 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
333 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
334 OP(TMP
,DST
,GXxor
) }, /* 0xb2 S^((S^P)|(S^D))*/
335 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXnand
) }, /* 0xb3 ~(S&~(D&P)) */
336 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXxor
) }, /* 0xb4 P^(S&~D) */
337 { OP(DST
,SRC
,GXor
), OP(PAT
,SRC
,GXand
),
338 OP(SRC
,DST
,GXequiv
) }, /* 0xb5 ~D^(P&(S|D)) */
339 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
340 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
341 OP(TMP
,DST
,GXxor
) }, /* 0xb6 D^P^(S|(D&P)) */
342 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXnand
) }, /* 0xb7 ~(S&(D^P)) */
343 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
344 OP(PAT
,DST
,GXxor
) }, /* 0xb8 P^(S&(D^P)) */
345 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
346 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0xb9 ~D^(S|(P&D)) */
347 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXor
) }, /* 0xba D|(P&~S) */
348 { OP(SRC
,DST
,GXorInverted
) }, /* 0xbb ~S|D */
349 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
),
350 OP(SRC
,DST
,GXxor
) }, /* 0xbc S^(P&~(D&S)) */
351 { OP(DST
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
352 OP(SRC
,DST
,GXnand
) }, /* 0xbd ~((S^D)&(P^D)) */
353 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
) }, /* 0xbe D|(P^S) */
354 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXor
) }, /* 0xbf D|~(P&S) */
355 { OP(PAT
,SRC
,GXand
) }, /* 0xc0 P&S */
356 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
),
357 OP(SRC
,DST
,GXequiv
) }, /* 0xc1 ~S^(P|(D&~S)) */
358 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
),
359 OP(SRC
,DST
,GXequiv
) }, /* 0xc2 ~S^(P|~(D|S)) */
360 { OP(PAT
,SRC
,GXequiv
) }, /* 0xc3 ~P^S */
361 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXand
) }, /* 0xc4 S&(P|~D) */
362 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
),
363 OP(SRC
,DST
,GXequiv
) }, /* 0xc5 ~S^(P|(D^S)) */
364 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXxor
) },/* 0xc6 S^(D&~P) */
365 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
),
366 OP(PAT
,DST
,GXequiv
) }, /* 0xc7 ~P^(S&(D|P)) */
367 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
) }, /* 0xc8 S&(D|P) */
368 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXequiv
) }, /* 0xc9 ~S^(P|D) */
369 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXand
),
370 OP(SRC
,DST
,GXxor
) }, /* 0xca D^(P&(S^D)) */
371 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
),
372 OP(SRC
,DST
,GXequiv
) }, /* 0xcb ~S^(P|(D&S)) */
373 { OP(SRC
,DST
,GXcopy
) }, /* 0xcc S */
374 { OP(PAT
,DST
,GXnor
), OP(SRC
,DST
,GXor
) }, /* 0xcd S|~(D|P) */
375 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXor
) }, /* 0xce S|(D&~P) */
376 { OP(PAT
,SRC
,GXorInverted
) }, /* 0xcf S|~P */
377 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXand
) }, /* 0xd0 P&(S|~D) */
378 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
),
379 OP(PAT
,DST
,GXequiv
) }, /* 0xd1 ~P^(S|(D^P)) */
380 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXxor
) },/* 0xd2 P^(D&~S) */
381 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
),
382 OP(SRC
,DST
,GXequiv
) }, /* 0xd3 ~S^(P&(D|S)) */
383 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
384 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
385 OP(TMP
,DST
,GXxor
) }, /* 0xd4 S^((S^P)&(D^P))*/
386 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXnand
) }, /* 0xd5 ~(D&~(P&S)) */
387 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
388 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
389 OP(TMP
,DST
,GXxor
) }, /* 0xd6 S^P^(D|(P&S)) */
390 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXnand
) }, /* 0xd7 ~(D&(P^S)) */
391 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
392 OP(PAT
,DST
,GXxor
) }, /* 0xd8 P^(D&(S^P)) */
393 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
394 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0xd9 ~S^(D|(P&S)) */
395 { OP(DST
,SRC
,GXnand
), OP(PAT
,SRC
,GXand
),
396 OP(SRC
,DST
,GXxor
) }, /* 0xda D^(P&~(S&D)) */
397 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
398 OP(SRC
,DST
,GXnand
) }, /* 0xdb ~((S^P)&(S^D)) */
399 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXor
) }, /* 0xdc S|(P&~D) */
400 { OP(SRC
,DST
,GXorReverse
) }, /* 0xdd S|~D */
401 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
) }, /* 0xde S|(D^P) */
402 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXor
) }, /* 0xdf S|~(D&P) */
403 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
) }, /* 0xe0 P&(D|S) */
404 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXequiv
) }, /* 0xe1 ~P^(D|S) */
405 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
406 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe2 D^(S&(P^D)) */
407 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
),
408 OP(PAT
,DST
,GXequiv
) }, /* 0xe3 ~P^(S|(D&P)) */
409 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
410 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe4 S^(D&(P^S)) */
411 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
),
412 OP(PAT
,DST
,GXequiv
) }, /* 0xe5 ~P^(D|(S&P)) */
413 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnand
),
414 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe6 S^(D&~(P&S)) */
415 { OP(PAT
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
416 OP(SRC
,DST
,GXnand
) }, /* 0xe7 ~((S^P)&(D^P)) */
417 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
418 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
419 OP(TMP
,DST
,GXxor
) }, /* 0xe8 S^((S^P)&(S^D))*/
420 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXnand
),
421 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
422 OP(TMP
,DST
,GXequiv
) }, /* 0xe9 ~D^S^(P&~(S&D))*/
423 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
) }, /* 0xea D|(P&S) */
424 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXor
) }, /* 0xeb D|~(P^S) */
425 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
) }, /* 0xec S|(D&P) */
426 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXor
) }, /* 0xed S|~(D^P) */
427 { OP(SRC
,DST
,GXor
) }, /* 0xee S|D */
428 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXor
) }, /* 0xef S|D|~P */
429 { OP(PAT
,DST
,GXcopy
) }, /* 0xf0 P */
430 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
) }, /* 0xf1 P|~(D|S) */
431 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
) }, /* 0xf2 P|(D&~S) */
432 { OP(PAT
,SRC
,GXorReverse
) }, /* 0xf3 P|~S */
433 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXor
) }, /* 0xf4 P|(S&~D) */
434 { OP(PAT
,DST
,GXorReverse
) }, /* 0xf5 P|~D */
435 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
) }, /* 0xf6 P|(D^S) */
436 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXor
) }, /* 0xf7 P|~(S&D) */
437 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
) }, /* 0xf8 P|(D&S) */
438 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXor
) }, /* 0xf9 P|~(D^S) */
439 { OP(PAT
,DST
,GXor
) }, /* 0xfa D|P */
440 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXor
) }, /* 0xfb D|P|~S */
441 { OP(PAT
,SRC
,GXor
) }, /* 0xfc P|S */
442 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXor
) }, /* 0xfd P|S|~D */
443 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXor
) }, /* 0xfe P|D|S */
444 { OP(PAT
,DST
,GXset
) } /* 0xff 1 */
447 static const unsigned char bit_swap
[256] =
449 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
450 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
451 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
452 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
453 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
454 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
455 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
456 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
457 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
458 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
459 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
460 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
461 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
462 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
463 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
464 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
465 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
466 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
467 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
468 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
469 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
470 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
471 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
472 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
473 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
474 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
475 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
476 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
477 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
478 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
479 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
480 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
483 #ifdef WORDS_BIGENDIAN
484 static const unsigned int zeropad_masks
[32] =
486 0xffffffff, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
487 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
488 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
489 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe
492 static const unsigned int zeropad_masks
[32] =
494 0xffffffff, 0x00000080, 0x000000c0, 0x000000e0, 0x000000f0, 0x000000f8, 0x000000fc, 0x000000fe,
495 0x000000ff, 0x000080ff, 0x0000c0ff, 0x0000e0ff, 0x0000f0ff, 0x0000f8ff, 0x0000fcff, 0x0000feff,
496 0x0000ffff, 0x0080ffff, 0x00c0ffff, 0x00e0ffff, 0x00f0ffff, 0x00f8ffff, 0x00fcffff, 0x00feffff,
497 0x00ffffff, 0x80ffffff, 0xc0ffffff, 0xe0ffffff, 0xf0ffffff, 0xf8ffffff, 0xfcffffff, 0xfeffffff
501 #ifdef BITBLT_TEST /* Opcodes test */
503 static int do_bitop( int s
, int d
, int rop
)
508 case GXclear
: res
= 0; break;
509 case GXand
: res
= s
& d
; break;
510 case GXandReverse
: res
= s
& ~d
; break;
511 case GXcopy
: res
= s
; break;
512 case GXandInverted
: res
= ~s
& d
; break;
513 case GXnoop
: res
= d
; break;
514 case GXxor
: res
= s
^ d
; break;
515 case GXor
: res
= s
| d
; break;
516 case GXnor
: res
= ~(s
| d
); break;
517 case GXequiv
: res
= ~s
^ d
; break;
518 case GXinvert
: res
= ~d
; break;
519 case GXorReverse
: res
= s
| ~d
; break;
520 case GXcopyInverted
: res
= ~s
; break;
521 case GXorInverted
: res
= ~s
| d
; break;
522 case GXnand
: res
= ~(s
& d
); break;
523 case GXset
: res
= 1; break;
530 int rop
, i
, res
, src
, dst
, pat
, tmp
, dstUsed
;
531 const unsigned char *opcode
;
533 for (rop
= 0; rop
< 256; rop
++)
536 for (i
= 0; i
< 8; i
++)
541 for (opcode
= BITBLT_Opcodes
[rop
]; *opcode
; opcode
++)
545 case OP_ARGS(DST
,TMP
):
546 tmp
= do_bitop( dst
, tmp
, *opcode
& 0xf );
548 case OP_ARGS(DST
,SRC
):
549 src
= do_bitop( dst
, src
, *opcode
& 0xf );
551 case OP_ARGS(SRC
,TMP
):
552 tmp
= do_bitop( src
, tmp
, *opcode
& 0xf );
554 case OP_ARGS(SRC
,DST
):
555 dst
= do_bitop( src
, dst
, *opcode
& 0xf );
558 case OP_ARGS(PAT
,DST
):
559 dst
= do_bitop( pat
, dst
, *opcode
& 0xf );
562 case OP_ARGS(PAT
,SRC
):
563 src
= do_bitop( pat
, src
, *opcode
& 0xf );
565 case OP_ARGS(TMP
,DST
):
566 dst
= do_bitop( tmp
, dst
, *opcode
& 0xf );
569 case OP_ARGS(TMP
,SRC
):
570 src
= do_bitop( tmp
, src
, *opcode
& 0xf );
573 printf( "Invalid opcode %x\n", *opcode
);
576 if (!dstUsed
) dst
= src
;
577 if (dst
) res
|= 1 << i
;
579 if (res
!= rop
) printf( "%02x: ERROR, res=%02x\n", rop
, res
);
585 #endif /* BITBLT_TEST */
588 static void get_colors(X11DRV_PDEVICE
*physDevDst
, X11DRV_PDEVICE
*physDevSrc
,
593 *fg
= physDevDst
->textPixel
;
594 *bg
= physDevDst
->backgroundPixel
;
595 if(physDevSrc
->depth
== 1) {
596 if(GetDIBColorTable(physDevSrc
->dev
.hdc
, 0, 2, rgb
) == 2) {
598 logcolor
= RGB(rgb
[0].rgbRed
, rgb
[0].rgbGreen
, rgb
[0].rgbBlue
);
599 *fg
= X11DRV_PALETTE_ToPhysical( physDevDst
, logcolor
);
600 logcolor
= RGB(rgb
[1].rgbRed
, rgb
[1].rgbGreen
,rgb
[1].rgbBlue
);
601 *bg
= X11DRV_PALETTE_ToPhysical( physDevDst
, logcolor
);
606 /* return a mask for meaningful bits when doing an XGetPixel on an image */
607 static unsigned long image_pixel_mask( X11DRV_PDEVICE
*physDev
)
610 ColorShifts
*shifts
= physDev
->color_shifts
;
612 if (!shifts
) shifts
= &X11DRV_PALETTE_default_shifts
;
613 ret
= (shifts
->physicalRed
.max
<< shifts
->physicalRed
.shift
) |
614 (shifts
->physicalGreen
.max
<< shifts
->physicalGreen
.shift
) |
615 (shifts
->physicalBlue
.max
<< shifts
->physicalBlue
.shift
);
616 if (!ret
) ret
= (1 << physDev
->depth
) - 1;
621 /***********************************************************************
624 * Stretch a row of pixels. Helper function for BITBLT_StretchImage.
626 static void BITBLT_StretchRow( int *rowSrc
, int *rowDst
,
627 INT startDst
, INT widthDst
,
628 INT xinc
, INT xoff
, WORD mode
)
630 register INT xsrc
= xinc
* startDst
+ xoff
;
634 case STRETCH_ANDSCANS
:
635 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
636 *rowDst
++ &= rowSrc
[xsrc
>> 16];
638 case STRETCH_ORSCANS
:
639 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
640 *rowDst
++ |= rowSrc
[xsrc
>> 16];
642 case STRETCH_DELETESCANS
:
643 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
644 *rowDst
++ = rowSrc
[xsrc
>> 16];
650 /***********************************************************************
653 * Shrink a row of pixels. Helper function for BITBLT_StretchImage.
655 static void BITBLT_ShrinkRow( int *rowSrc
, int *rowDst
,
656 INT startSrc
, INT widthSrc
,
657 INT xinc
, INT xoff
, WORD mode
)
659 register INT xdst
= xinc
* startSrc
+ xoff
;
663 case STRETCH_ORSCANS
:
664 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
665 rowDst
[xdst
>> 16] |= *rowSrc
++;
667 case STRETCH_ANDSCANS
:
668 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
669 rowDst
[xdst
>> 16] &= *rowSrc
++;
671 case STRETCH_DELETESCANS
:
672 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
673 rowDst
[xdst
>> 16] = *rowSrc
++;
679 /***********************************************************************
682 * Retrieve a row from an image. Helper function for BITBLT_StretchImage.
684 static void BITBLT_GetRow( XImage
*image
, int *pdata
, INT row
,
685 INT start
, INT width
, INT depthDst
,
686 int fg
, int bg
, unsigned long pixel_mask
, BOOL swap
)
690 assert( (row
>= 0) && (row
< image
->height
) );
691 assert( (start
>= 0) && (width
<= image
->width
) );
693 pdata
+= swap
? start
+width
-1 : start
;
694 if (image
->depth
== depthDst
) /* color -> color */
696 if (X11DRV_PALETTE_XPixelToPalette
&& (depthDst
!= 1))
697 if (swap
) for (i
= 0; i
< width
; i
++)
698 *pdata
-- = X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, i
, row
)];
699 else for (i
= 0; i
< width
; i
++)
700 *pdata
++ = X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, i
, row
)];
702 if (swap
) for (i
= 0; i
< width
; i
++)
703 *pdata
-- = XGetPixel( image
, i
, row
);
704 else for (i
= 0; i
< width
; i
++)
705 *pdata
++ = XGetPixel( image
, i
, row
);
709 if (image
->depth
== 1) /* monochrome -> color */
711 if (X11DRV_PALETTE_XPixelToPalette
)
713 fg
= X11DRV_PALETTE_XPixelToPalette
[fg
];
714 bg
= X11DRV_PALETTE_XPixelToPalette
[bg
];
716 if (swap
) for (i
= 0; i
< width
; i
++)
717 *pdata
-- = XGetPixel( image
, i
, row
) ? bg
: fg
;
718 else for (i
= 0; i
< width
; i
++)
719 *pdata
++ = XGetPixel( image
, i
, row
) ? bg
: fg
;
721 else /* color -> monochrome */
723 if (swap
) for (i
= 0; i
< width
; i
++)
724 *pdata
-- = ((XGetPixel( image
, i
, row
) & pixel_mask
) == bg
) ? 1 : 0;
725 else for (i
= 0; i
< width
; i
++)
726 *pdata
++ = ((XGetPixel( image
, i
, row
) & pixel_mask
) == bg
) ? 1 : 0;
732 /***********************************************************************
733 * BITBLT_StretchImage
735 * Stretch an X image.
736 * FIXME: does not work for full 32-bit coordinates.
738 static void BITBLT_StretchImage( XImage
*srcImage
, XImage
*dstImage
,
739 INT widthSrc
, INT heightSrc
,
740 INT widthDst
, INT heightDst
,
741 RECT
*visRectSrc
, RECT
*visRectDst
,
742 int foreground
, int background
,
743 unsigned long pixel_mask
, WORD mode
)
745 int *rowSrc
, *rowDst
, *pixel
;
747 INT xinc
, xoff
, yinc
, ysrc
, ydst
;
749 BOOL hstretch
, vstretch
, hswap
, vswap
;
751 hswap
= widthSrc
* widthDst
< 0;
752 vswap
= heightSrc
* heightDst
< 0;
753 widthSrc
= abs(widthSrc
);
754 heightSrc
= abs(heightSrc
);
755 widthDst
= abs(widthDst
);
756 heightDst
= abs(heightDst
);
758 if (!(rowSrc
= HeapAlloc( GetProcessHeap(), 0,
759 (widthSrc
+widthDst
)*sizeof(int) ))) return;
760 rowDst
= rowSrc
+ widthSrc
;
762 /* When stretching, all modes are the same, and DELETESCANS is faster */
763 if ((widthSrc
< widthDst
) && (heightSrc
< heightDst
))
764 mode
= STRETCH_DELETESCANS
;
766 if (mode
== STRETCH_HALFTONE
) /* FIXME */
767 mode
= STRETCH_DELETESCANS
;
769 if (mode
!= STRETCH_DELETESCANS
)
770 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
771 widthDst
*sizeof(int) );
773 hstretch
= (widthSrc
< widthDst
);
774 vstretch
= (heightSrc
< heightDst
);
778 xinc
= (widthSrc
<< 16) / widthDst
;
779 xoff
= ((widthSrc
<< 16) - (xinc
* widthDst
)) / 2;
783 xinc
= ((int)widthDst
<< 16) / widthSrc
;
784 xoff
= ((widthDst
<< 16) - (xinc
* widthSrc
)) / 2;
790 yinc
= (heightSrc
<< 16) / heightDst
;
791 ydst
= visRectDst
->top
;
794 ysrc
= yinc
* (heightDst
- ydst
- 1);
800 for ( ; (ydst
< visRectDst
->bottom
); ysrc
+= yinc
, ydst
++)
802 if (((ysrc
>> 16) < visRectSrc
->top
) ||
803 ((ysrc
>> 16) >= visRectSrc
->bottom
)) continue;
805 /* Retrieve a source row */
806 BITBLT_GetRow( srcImage
, rowSrc
, (ysrc
>> 16) - visRectSrc
->top
,
807 visRectSrc
->left
, visRectSrc
->right
- visRectSrc
->left
,
808 dstImage
->depth
, foreground
, background
, pixel_mask
, hswap
);
810 /* Stretch or shrink it */
812 BITBLT_StretchRow( rowSrc
, rowDst
, visRectDst
->left
,
813 visRectDst
->right
- visRectDst
->left
,
815 else BITBLT_ShrinkRow( rowSrc
, rowDst
, visRectSrc
->left
,
816 visRectSrc
->right
- visRectSrc
->left
,
819 /* Store the destination row */
820 pixel
= rowDst
+ visRectDst
->right
- 1;
821 y
= ydst
- visRectDst
->top
;
822 for (x
= visRectDst
->right
-visRectDst
->left
-1; x
>= 0; x
--)
823 XPutPixel( dstImage
, x
, y
, *pixel
-- );
824 if (mode
!= STRETCH_DELETESCANS
)
825 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
826 widthDst
*sizeof(int) );
828 /* Make copies of the destination row */
830 pdata
= dstImage
->data
+ dstImage
->bytes_per_line
* y
;
831 while (((ysrc
+ yinc
) >> 16 == ysrc
>> 16) &&
832 (ydst
< visRectDst
->bottom
-1))
834 memcpy( pdata
+ dstImage
->bytes_per_line
, pdata
,
835 dstImage
->bytes_per_line
);
836 pdata
+= dstImage
->bytes_per_line
;
844 yinc
= (heightDst
<< 16) / heightSrc
;
845 ysrc
= visRectSrc
->top
;
846 ydst
= ((heightDst
<< 16) - (yinc
* heightSrc
)) / 2;
849 ydst
+= yinc
* (heightSrc
- ysrc
- 1);
855 for( ; (ysrc
< visRectSrc
->bottom
); ydst
+= yinc
, ysrc
++)
857 if (((ydst
>> 16) < visRectDst
->top
) ||
858 ((ydst
>> 16) >= visRectDst
->bottom
)) continue;
860 /* Retrieve a source row */
861 BITBLT_GetRow( srcImage
, rowSrc
, ysrc
- visRectSrc
->top
,
862 visRectSrc
->left
, visRectSrc
->right
- visRectSrc
->left
,
863 dstImage
->depth
, foreground
, background
, pixel_mask
, hswap
);
865 /* Stretch or shrink it */
867 BITBLT_StretchRow( rowSrc
, rowDst
, visRectDst
->left
,
868 visRectDst
->right
- visRectDst
->left
,
870 else BITBLT_ShrinkRow( rowSrc
, rowDst
, visRectSrc
->left
,
871 visRectSrc
->right
- visRectSrc
->left
,
874 /* Merge several source rows into the destination */
875 if (mode
== STRETCH_DELETESCANS
)
877 /* Simply skip the overlapping rows */
878 while (((ydst
+ yinc
) >> 16 == ydst
>> 16) &&
879 (ysrc
< visRectSrc
->bottom
-1))
885 else if (((ydst
+ yinc
) >> 16 == ydst
>> 16) &&
886 (ysrc
< visRectSrc
->bottom
-1))
887 continue; /* Restart loop for next overlapping row */
889 /* Store the destination row */
890 pixel
= rowDst
+ visRectDst
->right
- 1;
891 y
= (ydst
>> 16) - visRectDst
->top
;
892 for (x
= visRectDst
->right
-visRectDst
->left
-1; x
>= 0; x
--)
893 XPutPixel( dstImage
, x
, y
, *pixel
-- );
894 if (mode
!= STRETCH_DELETESCANS
)
895 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
896 widthDst
*sizeof(int) );
900 HeapFree( GetProcessHeap(), 0, rowSrc
);
904 /***********************************************************************
905 * BITBLT_GetSrcAreaStretch
907 * Retrieve an area from the source DC, stretching and mapping all the
908 * pixels to Windows colors.
910 static int BITBLT_GetSrcAreaStretch( X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
911 Pixmap pixmap
, GC gc
,
912 const struct bitblt_coords
*src
, const struct bitblt_coords
*dst
)
914 XImage
*imageSrc
, *imageDst
;
915 RECT rectSrc
= src
->visrect
;
916 RECT rectDst
= dst
->visrect
;
919 rectSrc
.left
-= src
->x
;
920 rectSrc
.right
-= src
->x
;
921 rectSrc
.top
-= src
->y
;
922 rectSrc
.bottom
-= src
->y
;
923 rectDst
.left
-= dst
->x
;
924 rectDst
.right
-= dst
->x
;
925 rectDst
.top
-= dst
->y
;
926 rectDst
.bottom
-= dst
->y
;
929 rectSrc
.left
-= src
->width
;
930 rectSrc
.right
-= src
->width
;
934 rectDst
.left
-= dst
->width
;
935 rectDst
.right
-= dst
->width
;
939 rectSrc
.top
-= src
->height
;
940 rectSrc
.bottom
-= src
->height
;
944 rectDst
.top
-= dst
->height
;
945 rectDst
.bottom
-= dst
->height
;
948 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
950 /* FIXME: avoid BadMatch errors */
951 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
952 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
953 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
954 src
->visrect
.right
- src
->visrect
.left
,
955 src
->visrect
.bottom
- src
->visrect
.top
,
956 AllPlanes
, ZPixmap
);
959 imageDst
= X11DRV_DIB_CreateXImage( rectDst
.right
- rectDst
.left
,
960 rectDst
.bottom
- rectDst
.top
, physDevDst
->depth
);
961 BITBLT_StretchImage( imageSrc
, imageDst
, src
->width
, src
->height
,
962 dst
->width
, dst
->height
, &rectSrc
, &rectDst
,
963 fg
, physDevDst
->depth
!= 1 ? bg
: physDevSrc
->backgroundPixel
,
964 image_pixel_mask( physDevSrc
), GetStretchBltMode(physDevDst
->dev
.hdc
) );
966 XPutImage( gdi_display
, pixmap
, gc
, imageDst
, 0, 0, 0, 0,
967 rectDst
.right
- rectDst
.left
, rectDst
.bottom
- rectDst
.top
);
968 XDestroyImage( imageSrc
);
969 X11DRV_DIB_DestroyXImage( imageDst
);
971 return 0; /* no exposure events generated */
975 /***********************************************************************
978 * Retrieve an area from the source DC, mapping all the
979 * pixels to Windows colors.
981 static int BITBLT_GetSrcArea( X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
982 Pixmap pixmap
, GC gc
, RECT
*visRectSrc
)
984 XImage
*imageSrc
, *imageDst
;
987 INT width
= visRectSrc
->right
- visRectSrc
->left
;
988 INT height
= visRectSrc
->bottom
- visRectSrc
->top
;
990 BOOL memdc
= (GetObjectType(physDevSrc
->dev
.hdc
) == OBJ_MEMDC
);
992 if (physDevSrc
->depth
== physDevDst
->depth
)
995 if (!X11DRV_PALETTE_XPixelToPalette
||
996 (physDevDst
->depth
== 1)) /* monochrome -> monochrome */
998 if (physDevDst
->depth
== 1)
1000 /* MSDN says if StretchBlt must convert a bitmap from monochrome
1001 to color or vice versa, the foreground and background color of
1002 the device context are used. In fact, it also applies to the
1003 case when it is converted from mono to mono. */
1004 XSetBackground( gdi_display
, gc
, physDevDst
->textPixel
);
1005 XSetForeground( gdi_display
, gc
, physDevDst
->backgroundPixel
);
1006 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
1007 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1008 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1009 width
, height
, 0, 0, 1);
1012 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
1013 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1014 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1015 width
, height
, 0, 0);
1018 else /* color -> color */
1021 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
1022 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1023 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1024 width
, height
, AllPlanes
, ZPixmap
);
1027 /* Make sure we don't get a BadMatch error */
1028 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
1029 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1030 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1031 width
, height
, 0, 0);
1033 imageSrc
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1034 AllPlanes
, ZPixmap
);
1036 for (y
= 0; y
< height
; y
++)
1037 for (x
= 0; x
< width
; x
++)
1038 XPutPixel(imageSrc
, x
, y
,
1039 X11DRV_PALETTE_XPixelToPalette
[XGetPixel(imageSrc
, x
, y
)]);
1040 XPutImage( gdi_display
, pixmap
, gc
, imageSrc
,
1041 0, 0, 0, 0, width
, height
);
1042 XDestroyImage( imageSrc
);
1044 wine_tsx11_unlock();
1048 if (physDevSrc
->depth
== 1) /* monochrome -> color */
1050 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
1053 if (X11DRV_PALETTE_XPixelToPalette
)
1055 XSetBackground( gdi_display
, gc
,
1056 X11DRV_PALETTE_XPixelToPalette
[fg
] );
1057 XSetForeground( gdi_display
, gc
,
1058 X11DRV_PALETTE_XPixelToPalette
[bg
]);
1062 XSetBackground( gdi_display
, gc
, fg
);
1063 XSetForeground( gdi_display
, gc
, bg
);
1065 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
1066 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1067 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1068 width
, height
, 0, 0, 1 );
1070 wine_tsx11_unlock();
1072 else /* color -> monochrome */
1074 unsigned long pixel_mask
;
1076 /* FIXME: avoid BadMatch error */
1077 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
1078 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1079 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1080 width
, height
, AllPlanes
, ZPixmap
);
1083 wine_tsx11_unlock();
1086 imageDst
= X11DRV_DIB_CreateXImage( width
, height
, physDevDst
->depth
);
1089 XDestroyImage(imageSrc
);
1090 wine_tsx11_unlock();
1093 pixel_mask
= image_pixel_mask( physDevSrc
);
1094 for (y
= 0; y
< height
; y
++)
1095 for (x
= 0; x
< width
; x
++)
1096 XPutPixel(imageDst
, x
, y
,
1097 !((XGetPixel(imageSrc
,x
,y
) ^ physDevSrc
->backgroundPixel
) & pixel_mask
));
1098 XPutImage( gdi_display
, pixmap
, gc
, imageDst
,
1099 0, 0, 0, 0, width
, height
);
1100 XDestroyImage( imageSrc
);
1101 X11DRV_DIB_DestroyXImage( imageDst
);
1102 wine_tsx11_unlock();
1109 /***********************************************************************
1112 * Retrieve an area from the destination DC, mapping all the
1113 * pixels to Windows colors.
1115 static int BITBLT_GetDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, GC gc
, const RECT
*visRectDst
)
1118 INT width
= visRectDst
->right
- visRectDst
->left
;
1119 INT height
= visRectDst
->bottom
- visRectDst
->top
;
1120 BOOL memdc
= (GetObjectType( physDev
->dev
.hdc
) == OBJ_MEMDC
);
1124 if (!X11DRV_PALETTE_XPixelToPalette
|| (physDev
->depth
== 1) ||
1125 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
1127 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
1128 physDev
->dc_rect
.left
+ visRectDst
->left
, physDev
->dc_rect
.top
+ visRectDst
->top
,
1129 width
, height
, 0, 0 );
1138 image
= XGetImage( gdi_display
, physDev
->drawable
,
1139 physDev
->dc_rect
.left
+ visRectDst
->left
,
1140 physDev
->dc_rect
.top
+ visRectDst
->top
,
1141 width
, height
, AllPlanes
, ZPixmap
);
1144 /* Make sure we don't get a BadMatch error */
1145 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
1146 physDev
->dc_rect
.left
+ visRectDst
->left
,
1147 physDev
->dc_rect
.top
+ visRectDst
->top
,
1148 width
, height
, 0, 0);
1150 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1151 AllPlanes
, ZPixmap
);
1155 for (y
= 0; y
< height
; y
++)
1156 for (x
= 0; x
< width
; x
++)
1157 XPutPixel( image
, x
, y
,
1158 X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, x
, y
)]);
1159 XPutImage( gdi_display
, pixmap
, gc
, image
, 0, 0, 0, 0, width
, height
);
1160 XDestroyImage( image
);
1164 wine_tsx11_unlock();
1169 /***********************************************************************
1172 * Put an area back into the destination DC, mapping the pixel
1173 * colors to X pixels.
1175 static int BITBLT_PutDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, const RECT
*visRectDst
)
1178 INT width
= visRectDst
->right
- visRectDst
->left
;
1179 INT height
= visRectDst
->bottom
- visRectDst
->top
;
1181 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
1183 if (!X11DRV_PALETTE_PaletteToXPixel
|| (physDev
->depth
== 1) ||
1184 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
1186 XCopyArea( gdi_display
, pixmap
, physDev
->drawable
, physDev
->gc
, 0, 0, width
, height
,
1187 physDev
->dc_rect
.left
+ visRectDst
->left
,
1188 physDev
->dc_rect
.top
+ visRectDst
->top
);
1194 XImage
*image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1195 AllPlanes
, ZPixmap
);
1196 for (y
= 0; y
< height
; y
++)
1197 for (x
= 0; x
< width
; x
++)
1199 XPutPixel( image
, x
, y
,
1200 X11DRV_PALETTE_PaletteToXPixel
[XGetPixel( image
, x
, y
)]);
1202 XPutImage( gdi_display
, physDev
->drawable
, physDev
->gc
, image
, 0, 0,
1203 physDev
->dc_rect
.left
+ visRectDst
->left
,
1204 physDev
->dc_rect
.top
+ visRectDst
->top
, width
, height
);
1205 XDestroyImage( image
);
1211 /***********************************************************************
1212 * client_side_dib_copy
1214 static BOOL
client_side_dib_copy( X11DRV_PDEVICE
*physDevSrc
, INT xSrc
, INT ySrc
,
1215 X11DRV_PDEVICE
*physDevDst
, INT xDst
, INT yDst
,
1216 INT width
, INT height
)
1218 DIBSECTION srcDib
, dstDib
;
1219 BYTE
*srcPtr
, *dstPtr
;
1220 INT srcRowOffset
, dstRowOffset
;
1224 static RECT unusedRect
;
1226 if (GetObjectW(physDevSrc
->bitmap
->hbitmap
, sizeof(srcDib
), &srcDib
) != sizeof(srcDib
))
1228 if (GetObjectW(physDevDst
->bitmap
->hbitmap
, sizeof(dstDib
), &dstDib
) != sizeof(dstDib
))
1231 /* check for oversized values, just like X11DRV_DIB_CopyDIBSection() */
1232 if (xSrc
> srcDib
.dsBm
.bmWidth
|| ySrc
> srcDib
.dsBm
.bmHeight
)
1234 if (xSrc
+ width
> srcDib
.dsBm
.bmWidth
)
1235 width
= srcDib
.dsBm
.bmWidth
- xSrc
;
1236 if (ySrc
+ height
> srcDib
.dsBm
.bmHeight
)
1237 height
= srcDib
.dsBm
.bmHeight
- ySrc
;
1239 if (GetRgnBox(physDevDst
->region
, &unusedRect
) == COMPLEXREGION
)
1241 /* for simple regions, the clipping was already done by BITBLT_GetVisRectangles */
1242 FIXME("potential optimization: client-side complex region clipping\n");
1245 if (dstDib
.dsBm
.bmBitsPixel
<= 8)
1247 static BOOL fixme_once
;
1248 if(!fixme_once
++) FIXME("potential optimization: client-side color-index mode DIB copy\n");
1251 if (!(srcDib
.dsBmih
.biCompression
== BI_BITFIELDS
&&
1252 dstDib
.dsBmih
.biCompression
== BI_BITFIELDS
&&
1253 !memcmp(srcDib
.dsBitfields
, dstDib
.dsBitfields
, 3*sizeof(DWORD
)))
1254 && !(srcDib
.dsBmih
.biCompression
== BI_RGB
&&
1255 dstDib
.dsBmih
.biCompression
== BI_RGB
))
1257 FIXME("potential optimization: client-side compressed DIB copy\n");
1260 if (srcDib
.dsBm
.bmBitsPixel
!= dstDib
.dsBm
.bmBitsPixel
)
1262 FIXME("potential optimization: pixel format conversion\n");
1265 if (srcDib
.dsBmih
.biWidth
< 0 || dstDib
.dsBmih
.biWidth
< 0)
1267 FIXME("negative widths not yet implemented\n");
1271 switch (dstDib
.dsBm
.bmBitsPixel
)
1284 FIXME("don't know how to work with a depth of %d\n", physDevSrc
->depth
);
1288 bytesToCopy
= width
* bytesPerPixel
;
1290 if (physDevSrc
->bitmap
->topdown
)
1292 srcPtr
= &physDevSrc
->bitmap
->base
[ySrc
*srcDib
.dsBm
.bmWidthBytes
+ xSrc
*bytesPerPixel
];
1293 srcRowOffset
= srcDib
.dsBm
.bmWidthBytes
;
1297 srcPtr
= &physDevSrc
->bitmap
->base
[(srcDib
.dsBm
.bmHeight
-ySrc
-1)*srcDib
.dsBm
.bmWidthBytes
1298 + xSrc
*bytesPerPixel
];
1299 srcRowOffset
= -srcDib
.dsBm
.bmWidthBytes
;
1301 if (physDevDst
->bitmap
->topdown
)
1303 dstPtr
= &physDevDst
->bitmap
->base
[yDst
*dstDib
.dsBm
.bmWidthBytes
+ xDst
*bytesPerPixel
];
1304 dstRowOffset
= dstDib
.dsBm
.bmWidthBytes
;
1308 dstPtr
= &physDevDst
->bitmap
->base
[(dstDib
.dsBm
.bmHeight
-yDst
-1)*dstDib
.dsBm
.bmWidthBytes
1309 + xDst
*bytesPerPixel
];
1310 dstRowOffset
= -dstDib
.dsBm
.bmWidthBytes
;
1313 /* Handle overlapping regions on the same DIB */
1314 if (physDevSrc
== physDevDst
&& ySrc
< yDst
)
1316 srcPtr
+= srcRowOffset
* (height
- 1);
1317 srcRowOffset
= -srcRowOffset
;
1318 dstPtr
+= dstRowOffset
* (height
- 1);
1319 dstRowOffset
= -dstRowOffset
;
1322 for (y
= yDst
; y
< yDst
+ height
; ++y
)
1324 memmove(dstPtr
, srcPtr
, bytesToCopy
);
1325 srcPtr
+= srcRowOffset
;
1326 dstPtr
+= dstRowOffset
;
1332 static BOOL
same_format(X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
)
1334 if (physDevSrc
->depth
!= physDevDst
->depth
) return FALSE
;
1335 if (!physDevSrc
->color_shifts
&& !physDevDst
->color_shifts
) return TRUE
;
1336 if (physDevSrc
->color_shifts
&& physDevDst
->color_shifts
)
1337 return !memcmp(physDevSrc
->color_shifts
, physDevDst
->color_shifts
, sizeof(ColorShifts
));
1341 static void execute_rop( X11DRV_PDEVICE
*physdev
, Pixmap src_pixmap
, GC gc
,
1342 const RECT
*visrect
, DWORD rop
)
1345 Pixmap result
= src_pixmap
;
1347 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1348 BOOL use_pat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
1349 BOOL use_dst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
1350 int width
= visrect
->right
- visrect
->left
;
1351 int height
= visrect
->bottom
- visrect
->top
;
1353 pixmaps
[SRC
] = src_pixmap
;
1356 pixmaps
[DST
] = XCreatePixmap( gdi_display
, root_window
, width
, height
, physdev
->depth
);
1357 wine_tsx11_unlock();
1359 if (use_dst
) BITBLT_GetDstArea( physdev
, pixmaps
[DST
], gc
, visrect
);
1360 null_brush
= use_pat
&& !X11DRV_SetupGCForPatBlt( physdev
, gc
, TRUE
);
1363 for ( ; *opcode
; opcode
++)
1365 if (OP_DST(*opcode
) == DST
) result
= pixmaps
[DST
];
1366 XSetFunction( gdi_display
, gc
, OP_ROP(*opcode
) );
1367 switch(OP_SRCDST(*opcode
))
1369 case OP_ARGS(DST
,TMP
):
1370 case OP_ARGS(SRC
,TMP
):
1372 pixmaps
[TMP
] = XCreatePixmap( gdi_display
, root_window
, width
, height
, physdev
->depth
);
1374 case OP_ARGS(DST
,SRC
):
1375 case OP_ARGS(SRC
,DST
):
1376 case OP_ARGS(TMP
,SRC
):
1377 case OP_ARGS(TMP
,DST
):
1378 XCopyArea( gdi_display
, pixmaps
[OP_SRC(*opcode
)], pixmaps
[OP_DST(*opcode
)], gc
,
1379 0, 0, width
, height
, 0, 0 );
1381 case OP_ARGS(PAT
,DST
):
1382 case OP_ARGS(PAT
,SRC
):
1384 XFillRectangle( gdi_display
, pixmaps
[OP_DST(*opcode
)], gc
, 0, 0, width
, height
);
1388 XSetFunction( gdi_display
, physdev
->gc
, GXcopy
);
1389 physdev
->exposures
+= BITBLT_PutDstArea( physdev
, result
, visrect
);
1390 XFreePixmap( gdi_display
, pixmaps
[DST
] );
1391 if (pixmaps
[TMP
]) XFreePixmap( gdi_display
, pixmaps
[TMP
] );
1392 wine_tsx11_unlock();
1395 /***********************************************************************
1398 BOOL
X11DRV_PatBlt( PHYSDEV dev
, struct bitblt_coords
*dst
, DWORD rop
)
1400 X11DRV_PDEVICE
*physDev
= get_x11drv_dev( dev
);
1401 BOOL usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
1402 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1404 if (usePat
&& !X11DRV_SetupGCForBrush( physDev
)) return TRUE
;
1406 X11DRV_LockDIBSection( physDev
, DIB_Status_GdiMod
);
1409 XSetFunction( gdi_display
, physDev
->gc
, OP_ROP(*opcode
) );
1411 switch(rop
) /* a few special cases */
1413 case BLACKNESS
: /* 0x00 */
1414 case WHITENESS
: /* 0xff */
1415 if ((physDev
->depth
!= 1) && X11DRV_PALETTE_PaletteToXPixel
)
1417 XSetFunction( gdi_display
, physDev
->gc
, GXcopy
);
1418 if (rop
== BLACKNESS
)
1419 XSetForeground( gdi_display
, physDev
->gc
, X11DRV_PALETTE_PaletteToXPixel
[0] );
1421 XSetForeground( gdi_display
, physDev
->gc
,
1422 WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ));
1423 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
1426 case DSTINVERT
: /* 0x55 */
1427 if (!(X11DRV_PALETTE_PaletteFlags
& (X11DRV_PALETTE_PRIVATE
| X11DRV_PALETTE_VIRTUAL
)))
1429 /* Xor is much better when we do not have full colormap. */
1430 /* Using white^black ensures that we invert at least black */
1432 unsigned long xor_pix
= (WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ) ^
1433 BlackPixel( gdi_display
, DefaultScreen(gdi_display
) ));
1434 XSetFunction( gdi_display
, physDev
->gc
, GXxor
);
1435 XSetForeground( gdi_display
, physDev
->gc
, xor_pix
);
1436 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
1440 XFillRectangle( gdi_display
, physDev
->drawable
, physDev
->gc
,
1441 physDev
->dc_rect
.left
+ dst
->visrect
.left
,
1442 physDev
->dc_rect
.top
+ dst
->visrect
.top
,
1443 dst
->visrect
.right
- dst
->visrect
.left
,
1444 dst
->visrect
.bottom
- dst
->visrect
.top
);
1445 wine_tsx11_unlock();
1447 X11DRV_UnlockDIBSection( physDev
, TRUE
);
1452 /***********************************************************************
1455 BOOL
X11DRV_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
1456 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
1458 X11DRV_PDEVICE
*physDevDst
= get_x11drv_dev( dst_dev
);
1459 X11DRV_PDEVICE
*physDevSrc
= get_x11drv_dev( src_dev
); /* FIXME: check that it's really an x11 dev */
1462 INT sDst
, sSrc
= DIB_Status_None
;
1467 fStretch
= (src
->width
!= dst
->width
) || (src
->height
!= dst
->height
);
1469 if (physDevDst
!= physDevSrc
)
1470 sSrc
= X11DRV_LockDIBSection( physDevSrc
, DIB_Status_None
);
1472 width
= dst
->visrect
.right
- dst
->visrect
.left
;
1473 height
= dst
->visrect
.bottom
- dst
->visrect
.top
;
1475 sDst
= X11DRV_LockDIBSection( physDevDst
, DIB_Status_None
);
1476 if (physDevDst
== physDevSrc
) sSrc
= sDst
;
1478 /* try client-side DIB copy */
1479 if (!fStretch
&& rop
== SRCCOPY
&&
1480 sSrc
== DIB_Status_AppMod
&& sDst
== DIB_Status_AppMod
&&
1481 same_format(physDevSrc
, physDevDst
))
1483 if (client_side_dib_copy( physDevSrc
, src
->visrect
.left
, src
->visrect
.top
,
1484 physDevDst
, dst
->visrect
.left
, dst
->visrect
.top
, width
, height
))
1488 X11DRV_CoerceDIBSection( physDevDst
, DIB_Status_GdiMod
);
1490 opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1492 /* a few optimizations for single-op ROPs */
1493 if (!fStretch
&& !opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
))
1495 if (same_format(physDevSrc
, physDevDst
))
1498 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
1499 wine_tsx11_unlock();
1501 if (physDevSrc
!= physDevDst
)
1503 if (sSrc
== DIB_Status_AppMod
)
1505 X11DRV_DIB_CopyDIBSection( physDevSrc
, physDevDst
, src
->visrect
.left
, src
->visrect
.top
,
1506 dst
->visrect
.left
, dst
->visrect
.top
, width
, height
);
1509 X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
);
1512 XCopyArea( gdi_display
, physDevSrc
->drawable
,
1513 physDevDst
->drawable
, physDevDst
->gc
,
1514 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
1515 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
1517 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
1518 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
);
1519 physDevDst
->exposures
++;
1520 wine_tsx11_unlock();
1523 if (physDevSrc
->depth
== 1)
1527 X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
);
1528 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
1530 XSetBackground( gdi_display
, physDevDst
->gc
, fg
);
1531 XSetForeground( gdi_display
, physDevDst
->gc
, bg
);
1532 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
1533 XCopyPlane( gdi_display
, physDevSrc
->drawable
,
1534 physDevDst
->drawable
, physDevDst
->gc
,
1535 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
1536 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
1538 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
1539 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
, 1 );
1540 physDevDst
->exposures
++;
1541 wine_tsx11_unlock();
1547 tmpGC
= XCreateGC( gdi_display
, physDevDst
->drawable
, 0, NULL
);
1548 XSetSubwindowMode( gdi_display
, tmpGC
, IncludeInferiors
);
1549 XSetGraphicsExposures( gdi_display
, tmpGC
, False
);
1550 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, physDevDst
->depth
);
1551 wine_tsx11_unlock();
1553 if (physDevDst
!= physDevSrc
) X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
);
1555 if(!X11DRV_XRender_GetSrcAreaStretch( physDevSrc
, physDevDst
, src_pixmap
, tmpGC
, src
, dst
))
1558 BITBLT_GetSrcAreaStretch( physDevSrc
, physDevDst
, src_pixmap
, tmpGC
, src
, dst
);
1560 BITBLT_GetSrcArea( physDevSrc
, physDevDst
, src_pixmap
, tmpGC
, &src
->visrect
);
1563 execute_rop( physDevDst
, src_pixmap
, tmpGC
, &dst
->visrect
, rop
);
1566 XFreePixmap( gdi_display
, src_pixmap
);
1567 XFreeGC( gdi_display
, tmpGC
);
1568 wine_tsx11_unlock();
1571 if (physDevDst
!= physDevSrc
) X11DRV_UnlockDIBSection( physDevSrc
, FALSE
);
1572 X11DRV_UnlockDIBSection( physDevDst
, TRUE
);
1577 /***********************************************************************
1580 BOOL
X11DRV_AlphaBlend( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
1581 PHYSDEV src_dev
, struct bitblt_coords
*src
, BLENDFUNCTION blendfn
)
1583 X11DRV_PDEVICE
*physDevDst
= get_x11drv_dev( dst_dev
);
1584 X11DRV_PDEVICE
*physDevSrc
= get_x11drv_dev( src_dev
); /* FIXME: check that it's really an x11 dev */
1586 if (src
->x
< 0 || src
->y
< 0 || src
->width
< 0 || src
->height
< 0 ||
1587 src
->width
> physDevSrc
->drawable_rect
.right
- physDevSrc
->drawable_rect
.left
- src
->x
||
1588 src
->height
> physDevSrc
->drawable_rect
.bottom
- physDevSrc
->drawable_rect
.top
- src
->y
)
1590 WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src
->x
, src
->y
, src
->width
, src
->height
);
1591 SetLastError( ERROR_INVALID_PARAMETER
);
1595 return XRender_AlphaBlend( physDevDst
, dst
, physDevSrc
, src
, blendfn
);
1599 static void free_heap_bits( struct gdi_image_bits
*bits
)
1601 HeapFree( GetProcessHeap(), 0, bits
->ptr
);
1604 static void free_ximage_bits( struct gdi_image_bits
*bits
)
1608 wine_tsx11_unlock();
1611 /* store the palette or color mask data in the bitmap info structure */
1612 static void set_color_info( PHYSDEV dev
, const ColorShifts
*color_shifts
, BITMAPINFO
*info
)
1614 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1616 info
->bmiHeader
.biCompression
= BI_RGB
;
1617 info
->bmiHeader
.biClrUsed
= 0;
1619 switch (info
->bmiHeader
.biBitCount
)
1624 RGBQUAD
*rgb
= (RGBQUAD
*)colors
;
1625 PALETTEENTRY palette
[256];
1628 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1629 count
= X11DRV_GetSystemPaletteEntries( dev
, 0, info
->bmiHeader
.biClrUsed
, palette
);
1630 for (i
= 0; i
< count
; i
++)
1632 rgb
[i
].rgbRed
= palette
[i
].peRed
;
1633 rgb
[i
].rgbGreen
= palette
[i
].peGreen
;
1634 rgb
[i
].rgbBlue
= palette
[i
].peBlue
;
1635 rgb
[i
].rgbReserved
= 0;
1637 memset( &rgb
[count
], 0, (info
->bmiHeader
.biClrUsed
- count
) * sizeof(*rgb
) );
1641 colors
[0] = color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
;
1642 colors
[1] = color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
;
1643 colors
[2] = color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
;
1644 if (colors
[0] != 0x7c00 || colors
[1] != 0x03e0 || colors
[2] != 0x001f)
1645 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1648 colors
[0] = color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
;
1649 colors
[1] = color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
;
1650 colors
[2] = color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
;
1651 if (colors
[0] != 0xff0000 || colors
[1] != 0x00ff00 || colors
[2] != 0x0000ff)
1652 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1657 /* check if the specified color info is suitable for PutImage */
1658 static BOOL
matching_color_info( PHYSDEV dev
, const ColorShifts
*color_shifts
, const BITMAPINFO
*info
)
1660 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1662 switch (info
->bmiHeader
.biBitCount
)
1665 if (info
->bmiHeader
.biCompression
!= BI_RGB
) return FALSE
;
1666 return !info
->bmiHeader
.biClrUsed
; /* color map not allowed */
1670 RGBQUAD
*rgb
= (RGBQUAD
*)colors
;
1671 PALETTEENTRY palette
[256];
1674 if (info
->bmiHeader
.biCompression
!= BI_RGB
) return FALSE
;
1675 count
= X11DRV_GetSystemPaletteEntries( dev
, 0, 1 << info
->bmiHeader
.biBitCount
, palette
);
1676 if (count
!= info
->bmiHeader
.biClrUsed
) return FALSE
;
1677 for (i
= 0; i
< count
; i
++)
1679 if (rgb
[i
].rgbRed
!= palette
[i
].peRed
||
1680 rgb
[i
].rgbGreen
!= palette
[i
].peGreen
||
1681 rgb
[i
].rgbBlue
!= palette
[i
].peBlue
) return FALSE
;
1686 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1687 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== colors
[0] &&
1688 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== colors
[1] &&
1689 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== colors
[2]);
1690 if (info
->bmiHeader
.biCompression
== BI_RGB
)
1691 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== 0x7c00 &&
1692 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== 0x03e0 &&
1693 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== 0x001f);
1696 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1697 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== colors
[0] &&
1698 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== colors
[1] &&
1699 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== colors
[2]);
1702 if (info
->bmiHeader
.biCompression
== BI_RGB
)
1703 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== 0xff0000 &&
1704 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== 0x00ff00 &&
1705 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== 0x0000ff);
1711 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1712 static DWORD
copy_image_bits( BITMAPINFO
*info
, const ColorShifts
*color_shifts
, XImage
*image
,
1713 const struct gdi_image_bits
*src_bits
, struct gdi_image_bits
*dst_bits
,
1714 const int *mapping
, unsigned int zeropad_mask
)
1716 #ifdef WORDS_BIGENDIAN
1717 static const int client_byte_order
= MSBFirst
;
1719 static const int client_byte_order
= LSBFirst
;
1722 int x
, y
, height
= abs(info
->bmiHeader
.biHeight
);
1723 int width_bytes
= image
->bytes_per_line
;
1725 unsigned char *src
, *dst
;
1727 switch (info
->bmiHeader
.biBitCount
)
1730 need_byteswap
= (image
->bitmap_bit_order
!= MSBFirst
);
1733 need_byteswap
= (image
->byte_order
!= MSBFirst
);
1737 need_byteswap
= (image
->byte_order
!= client_byte_order
);
1740 need_byteswap
= ((image
->byte_order
== LSBFirst
&& color_shifts
->logicalBlue
.shift
== 16) ||
1741 (image
->byte_order
== MSBFirst
&& color_shifts
->logicalBlue
.shift
== 0));
1744 need_byteswap
= FALSE
;
1748 if ((need_byteswap
&& !src_bits
->is_copy
) || /* need to swap bytes */
1749 (zeropad_mask
!= ~0u && !src_bits
->is_copy
) || /* need to clear padding bytes */
1750 (mapping
&& !src_bits
->is_copy
) || /* need to remap pixels */
1751 (width_bytes
& 3) || /* need to fixup line alignment */
1752 (info
->bmiHeader
.biHeight
> 0)) /* need to flip vertically */
1754 width_bytes
= (width_bytes
+ 3) & ~3;
1755 info
->bmiHeader
.biSizeImage
= height
* width_bytes
;
1756 if (!(dst_bits
->ptr
= HeapAlloc( GetProcessHeap(), 0, info
->bmiHeader
.biSizeImage
)))
1757 return ERROR_OUTOFMEMORY
;
1758 dst_bits
->offset
= src_bits
->offset
;
1759 dst_bits
->is_copy
= TRUE
;
1760 dst_bits
->free
= free_heap_bits
;
1764 /* swap bits in place */
1765 dst_bits
->ptr
= src_bits
->ptr
;
1766 dst_bits
->offset
= src_bits
->offset
;
1767 dst_bits
->is_copy
= src_bits
->is_copy
;
1768 dst_bits
->free
= NULL
;
1769 if (!need_byteswap
&& zeropad_mask
== ~0u && !mapping
) return ERROR_SUCCESS
; /* nothing to do */
1772 src
= src_bits
->ptr
;
1773 dst
= dst_bits
->ptr
;
1774 padding_pos
= width_bytes
/sizeof(unsigned int) - 1;
1776 if (info
->bmiHeader
.biHeight
> 0)
1778 dst
+= (height
- 1) * width_bytes
;
1779 width_bytes
= -width_bytes
;
1782 if (need_byteswap
|| mapping
)
1784 switch (info
->bmiHeader
.biBitCount
)
1787 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1789 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1790 dst
[x
] = bit_swap
[src
[x
]];
1791 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1795 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1798 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1799 dst
[x
] = (mapping
[src
[x
] & 0x0f] << 4) | mapping
[src
[x
] >> 4];
1801 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1802 dst
[x
] = (src
[x
] << 4) | (src
[x
] >> 4);
1803 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1807 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1809 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1810 dst
[x
] = mapping
[src
[x
]];
1811 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1815 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1817 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1818 ((USHORT
*)dst
)[x
] = RtlUshortByteSwap( ((const USHORT
*)src
)[x
] );
1819 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1823 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1825 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1827 unsigned char tmp
= src
[3 * x
];
1828 dst
[3 * x
] = src
[3 * x
+ 2];
1829 dst
[3 * x
+ 1] = src
[3 * x
+ 1];
1830 dst
[3 * x
+ 2] = tmp
;
1832 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1836 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1837 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1838 ((ULONG
*)dst
)[x
] = RtlUlongByteSwap( ((const ULONG
*)src
)[x
] );
1842 else if (src
!= dst
)
1844 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1846 memcpy( dst
, src
, image
->bytes_per_line
);
1847 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1850 else /* only need to clear the padding */
1852 for (y
= 0; y
< height
; y
++, dst
+= width_bytes
)
1853 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1855 return ERROR_SUCCESS
;
1858 /***********************************************************************
1861 DWORD
X11DRV_PutImage( PHYSDEV dev
, HBITMAP hbitmap
, BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
1862 const RECT
*rect
, DWORD rop
)
1864 X11DRV_PDEVICE
*physdev
;
1865 X_PHYSBITMAP
*bitmap
;
1869 struct gdi_image_bits dst_bits
;
1870 const XPixmapFormatValues
*format
;
1871 const ColorShifts
*color_shifts
;
1872 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1873 const int *mapping
= NULL
;
1877 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
1879 depth
= bitmap
->pixmap_depth
;
1880 color_shifts
= &bitmap
->pixmap_color_shifts
;
1884 physdev
= get_x11drv_dev( dev
);
1886 depth
= physdev
->depth
;
1887 color_shifts
= physdev
->color_shifts
;
1889 format
= pixmap_formats
[depth
];
1891 if (info
->bmiHeader
.biPlanes
!= 1) goto update_format
;
1892 if (info
->bmiHeader
.biBitCount
!= format
->bits_per_pixel
) goto update_format
;
1893 /* FIXME: could try to handle 1-bpp using XCopyPlane */
1894 if (!matching_color_info( dev
, color_shifts
, info
)) goto update_format
;
1895 if (!bits
) return ERROR_SUCCESS
; /* just querying the format */
1898 image
= XCreateImage( gdi_display
, visual
, depth
, ZPixmap
, 0, NULL
,
1899 info
->bmiHeader
.biWidth
, abs(info
->bmiHeader
.biHeight
), 32, 0 );
1900 wine_tsx11_unlock();
1901 if (!image
) return ERROR_OUTOFMEMORY
;
1903 if (image
->bits_per_pixel
== 4 || image
->bits_per_pixel
== 8)
1905 if (bitmap
|| (!opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
)))
1906 mapping
= X11DRV_PALETTE_PaletteToXPixel
;
1909 ret
= copy_image_bits( info
, color_shifts
, image
, bits
, &dst_bits
, mapping
, ~0u );
1913 int width
= rect
->right
- rect
->left
;
1914 int height
= rect
->bottom
- rect
->top
;
1916 image
->data
= dst_bits
.ptr
;
1919 X11DRV_DIB_Lock( bitmap
, DIB_Status_GdiMod
);
1921 XPutImage( gdi_display
, bitmap
->pixmap
, get_bitmap_gc(depth
), image
, dst_bits
.offset
, 0,
1922 rect
->left
, rect
->top
, width
, height
);
1923 wine_tsx11_unlock();
1924 X11DRV_DIB_Unlock( bitmap
, TRUE
);
1928 X11DRV_LockDIBSection( physdev
, DIB_Status_GdiMod
);
1930 /* optimization for single-op ROPs */
1931 if (!opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
))
1934 XSetFunction( gdi_display
, physdev
->gc
, OP_ROP(*opcode
) );
1935 XPutImage( gdi_display
, physdev
->drawable
, physdev
->gc
, image
, dst_bits
.offset
, 0,
1936 physdev
->dc_rect
.left
+ rect
->left
, physdev
->dc_rect
.top
+ rect
->top
,
1938 wine_tsx11_unlock();
1946 gc
= XCreateGC( gdi_display
, physdev
->drawable
, 0, NULL
);
1947 XSetSubwindowMode( gdi_display
, gc
, IncludeInferiors
);
1948 XSetGraphicsExposures( gdi_display
, gc
, False
);
1949 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, depth
);
1950 XPutImage( gdi_display
, src_pixmap
, gc
, image
, dst_bits
.offset
, 0, 0, 0, width
, height
);
1951 wine_tsx11_unlock();
1953 execute_rop( physdev
, src_pixmap
, gc
, rect
, rop
);
1956 XFreePixmap( gdi_display
, src_pixmap
);
1957 XFreeGC( gdi_display
, gc
);
1958 wine_tsx11_unlock();
1961 X11DRV_UnlockDIBSection( physdev
, !ret
);
1967 XDestroyImage( image
);
1968 wine_tsx11_unlock();
1969 if (dst_bits
.free
) dst_bits
.free( &dst_bits
);
1973 info
->bmiHeader
.biPlanes
= 1;
1974 info
->bmiHeader
.biBitCount
= format
->bits_per_pixel
;
1975 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
1976 set_color_info( dev
, physdev
->color_shifts
, info
);
1977 return ERROR_BAD_FORMAT
;
1980 /***********************************************************************
1983 DWORD
X11DRV_GetImage( PHYSDEV dev
, HBITMAP hbitmap
, BITMAPINFO
*info
,
1984 struct gdi_image_bits
*bits
, const RECT
*rect
)
1986 X11DRV_PDEVICE
*physdev
;
1987 X_PHYSBITMAP
*bitmap
;
1988 DWORD ret
= ERROR_SUCCESS
;
1990 UINT align
, x
, y
, width
, height
;
1992 struct gdi_image_bits src_bits
;
1993 const XPixmapFormatValues
*format
;
1994 const ColorShifts
*color_shifts
;
1995 const int *mapping
= NULL
;
1999 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
2001 depth
= bitmap
->pixmap_depth
;
2002 color_shifts
= &bitmap
->pixmap_color_shifts
;
2006 physdev
= get_x11drv_dev( dev
);
2008 depth
= physdev
->depth
;
2009 color_shifts
= physdev
->color_shifts
;
2011 format
= pixmap_formats
[depth
];
2013 /* align start and width to 32-bit boundary */
2014 switch (format
->bits_per_pixel
)
2016 case 1: align
= 32; break;
2017 case 4: align
= 8; mapping
= X11DRV_PALETTE_XPixelToPalette
; break;
2018 case 8: align
= 4; mapping
= X11DRV_PALETTE_XPixelToPalette
; break;
2019 case 16: align
= 2; break;
2020 case 24: align
= 4; break;
2021 case 32: align
= 1; break;
2023 FIXME( "depth %u bpp %u not supported yet\n", depth
, format
->bits_per_pixel
);
2024 return ERROR_BAD_FORMAT
;
2026 src_bits
.offset
= rect
->left
& (align
- 1);
2027 x
= rect
->left
- src_bits
.offset
;
2029 width
= rect
->right
- x
;
2030 height
= rect
->bottom
- rect
->top
;
2031 if (format
->scanline_pad
!= 32) width
= (width
+ (align
- 1)) & ~(align
- 1);
2036 GetObjectW( hbitmap
, sizeof(bm
), &bm
);
2037 width
= min( width
, bm
.bmWidth
- x
);
2038 height
= min( height
, bm
.bmHeight
- y
);
2039 X11DRV_DIB_Lock( bitmap
, DIB_Status_GdiMod
);
2041 image
= XGetImage( gdi_display
, bitmap
->pixmap
, x
, y
, width
, height
, AllPlanes
, ZPixmap
);
2042 wine_tsx11_unlock();
2043 X11DRV_DIB_Unlock( bitmap
, TRUE
);
2045 else if (GetObjectType( dev
->hdc
) == OBJ_MEMDC
)
2047 X11DRV_LockDIBSection( physdev
, DIB_Status_GdiMod
);
2048 width
= min( width
, physdev
->dc_rect
.right
- physdev
->dc_rect
.left
- x
);
2049 height
= min( height
, physdev
->dc_rect
.bottom
- physdev
->dc_rect
.top
- y
);
2051 image
= XGetImage( gdi_display
, physdev
->drawable
,
2052 physdev
->dc_rect
.left
+ x
, physdev
->dc_rect
.top
+ y
,
2053 width
, height
, AllPlanes
, ZPixmap
);
2054 wine_tsx11_unlock();
2055 X11DRV_UnlockDIBSection( physdev
, FALSE
);
2062 /* use a temporary pixmap to avoid BadMatch errors */
2063 pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, depth
);
2064 XCopyArea( gdi_display
, physdev
->drawable
, pixmap
, get_bitmap_gc(depth
),
2065 physdev
->dc_rect
.left
+ x
, physdev
->dc_rect
.top
+ y
, width
, height
, 0, 0 );
2066 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
, AllPlanes
, ZPixmap
);
2067 XFreePixmap( gdi_display
, pixmap
);
2068 wine_tsx11_unlock();
2070 if (!image
) return ERROR_OUTOFMEMORY
;
2072 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
2073 info
->bmiHeader
.biWidth
= width
;
2074 info
->bmiHeader
.biHeight
= -height
;
2075 info
->bmiHeader
.biPlanes
= 1;
2076 info
->bmiHeader
.biBitCount
= image
->bits_per_pixel
;
2077 info
->bmiHeader
.biSizeImage
= height
* image
->bytes_per_line
;
2078 info
->bmiHeader
.biXPelsPerMeter
= 0;
2079 info
->bmiHeader
.biYPelsPerMeter
= 0;
2080 info
->bmiHeader
.biClrImportant
= 0;
2081 set_color_info( dev
, color_shifts
, info
);
2083 src_bits
.ptr
= image
->data
;
2084 src_bits
.is_copy
= TRUE
;
2085 ret
= copy_image_bits( info
, color_shifts
, image
, &src_bits
, bits
, mapping
,
2086 zeropad_masks
[(width
* image
->bits_per_pixel
) & 31] );
2088 if (!ret
&& bits
->ptr
== image
->data
)
2090 bits
->free
= free_ximage_bits
;
2094 XDestroyImage( image
);
2095 wine_tsx11_unlock();