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 OffsetRect( &rectSrc, -src->x, -src->y );
920 OffsetRect( &rectDst, -dst->x, -dst->y );
922 if (src->width < 0) OffsetRect( &rectSrc, -src->width, 0 );
923 if (dst->width < 0) OffsetRect( &rectDst, -dst->width, 0 );
924 if (src->height < 0) OffsetRect( &rectSrc, 0, -src->height );
925 if (dst->height < 0) OffsetRect( &rectDst, 0, -dst->height );
927 get_colors(physDevDst, physDevSrc, &fg, &bg);
929 /* FIXME: avoid BadMatch errors */
930 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
931 physDevSrc->dc_rect.left + src->visrect.left,
932 physDevSrc->dc_rect.top + src->visrect.top,
933 src->visrect.right - src->visrect.left,
934 src->visrect.bottom - src->visrect.top,
935 AllPlanes, ZPixmap );
938 imageDst = X11DRV_DIB_CreateXImage( rectDst.right - rectDst.left,
939 rectDst.bottom - rectDst.top, physDevDst->depth );
940 BITBLT_StretchImage( imageSrc, imageDst, src->width, src->height,
941 dst->width, dst->height, &rectSrc, &rectDst,
942 fg, physDevDst->depth != 1 ? bg : physDevSrc->backgroundPixel,
943 image_pixel_mask( physDevSrc ), GetStretchBltMode(physDevDst->dev.hdc) );
945 XPutImage( gdi_display, pixmap, gc, imageDst, 0, 0, 0, 0,
946 rectDst.right - rectDst.left, rectDst.bottom - rectDst.top );
947 XDestroyImage( imageSrc );
948 X11DRV_DIB_DestroyXImage( imageDst );
950 return 0; /* no exposure events generated */
954 /***********************************************************************
957 * Retrieve an area from the source DC, mapping all the
958 * pixels to Windows colors.
960 static int BITBLT_GetSrcArea( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
961 Pixmap pixmap, GC gc, RECT *visRectSrc )
963 XImage *imageSrc, *imageDst;
966 INT width = visRectSrc->right - visRectSrc->left;
967 INT height = visRectSrc->bottom - visRectSrc->top;
969 BOOL memdc = (GetObjectType(physDevSrc->dev.hdc) == OBJ_MEMDC);
971 if (physDevSrc->depth == physDevDst->depth)
974 if (!X11DRV_PALETTE_XPixelToPalette ||
975 (physDevDst->depth == 1)) /* monochrome -> monochrome */
977 if (physDevDst->depth == 1)
979 /* MSDN says if StretchBlt must convert a bitmap from monochrome
980 to color or vice versa, the foreground and background color of
981 the device context are used. In fact, it also applies to the
982 case when it is converted from mono to mono. */
983 XSetBackground( gdi_display, gc, physDevDst->textPixel );
984 XSetForeground( gdi_display, gc, physDevDst->backgroundPixel );
985 XCopyPlane( gdi_display, physDevSrc->drawable, pixmap, gc,
986 physDevSrc->dc_rect.left + visRectSrc->left,
987 physDevSrc->dc_rect.top + visRectSrc->top,
988 width, height, 0, 0, 1);
991 XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc,
992 physDevSrc->dc_rect.left + visRectSrc->left,
993 physDevSrc->dc_rect.top + visRectSrc->top,
994 width, height, 0, 0);
997 else /* color -> color */
1000 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
1001 physDevSrc->dc_rect.left + visRectSrc->left,
1002 physDevSrc->dc_rect.top + visRectSrc->top,
1003 width, height, AllPlanes, ZPixmap );
1006 /* Make sure we don't get a BadMatch error */
1007 XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc,
1008 physDevSrc->dc_rect.left + visRectSrc->left,
1009 physDevSrc->dc_rect.top + visRectSrc->top,
1010 width, height, 0, 0);
1012 imageSrc = XGetImage( gdi_display, pixmap, 0, 0, width, height,
1013 AllPlanes, ZPixmap );
1015 for (y = 0; y < height; y++)
1016 for (x = 0; x < width; x++)
1017 XPutPixel(imageSrc, x, y,
1018 X11DRV_PALETTE_XPixelToPalette[XGetPixel(imageSrc, x, y)]);
1019 XPutImage( gdi_display, pixmap, gc, imageSrc,
1020 0, 0, 0, 0, width, height );
1021 XDestroyImage( imageSrc );
1023 wine_tsx11_unlock();
1027 if (physDevSrc->depth == 1) /* monochrome -> color */
1029 get_colors(physDevDst, physDevSrc, &fg, &bg);
1032 if (X11DRV_PALETTE_XPixelToPalette)
1034 XSetBackground( gdi_display, gc,
1035 X11DRV_PALETTE_XPixelToPalette[fg] );
1036 XSetForeground( gdi_display, gc,
1037 X11DRV_PALETTE_XPixelToPalette[bg]);
1041 XSetBackground( gdi_display, gc, fg );
1042 XSetForeground( gdi_display, gc, bg );
1044 XCopyPlane( gdi_display, physDevSrc->drawable, pixmap, gc,
1045 physDevSrc->dc_rect.left + visRectSrc->left,
1046 physDevSrc->dc_rect.top + visRectSrc->top,
1047 width, height, 0, 0, 1 );
1049 wine_tsx11_unlock();
1051 else /* color -> monochrome */
1053 unsigned long pixel_mask;
1055 /* FIXME: avoid BadMatch error */
1056 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
1057 physDevSrc->dc_rect.left + visRectSrc->left,
1058 physDevSrc->dc_rect.top + visRectSrc->top,
1059 width, height, AllPlanes, ZPixmap );
1062 wine_tsx11_unlock();
1065 imageDst = X11DRV_DIB_CreateXImage( width, height, physDevDst->depth );
1068 XDestroyImage(imageSrc);
1069 wine_tsx11_unlock();
1072 pixel_mask = image_pixel_mask( physDevSrc );
1073 for (y = 0; y < height; y++)
1074 for (x = 0; x < width; x++)
1075 XPutPixel(imageDst, x, y,
1076 !((XGetPixel(imageSrc,x,y) ^ physDevSrc->backgroundPixel) & pixel_mask));
1077 XPutImage( gdi_display, pixmap, gc, imageDst,
1078 0, 0, 0, 0, width, height );
1079 XDestroyImage( imageSrc );
1080 X11DRV_DIB_DestroyXImage( imageDst );
1081 wine_tsx11_unlock();
1088 /***********************************************************************
1091 * Retrieve an area from the destination DC, mapping all the
1092 * pixels to Windows colors.
1094 static int BITBLT_GetDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, GC gc, const RECT *visRectDst)
1097 INT width = visRectDst->right - visRectDst->left;
1098 INT height = visRectDst->bottom - visRectDst->top;
1099 BOOL memdc = (GetObjectType( physDev->dev.hdc ) == OBJ_MEMDC);
1103 if (!X11DRV_PALETTE_XPixelToPalette || (physDev->depth == 1) ||
1104 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
1106 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
1107 physDev->dc_rect.left + visRectDst->left, physDev->dc_rect.top + visRectDst->top,
1108 width, height, 0, 0 );
1117 image = XGetImage( gdi_display, physDev->drawable,
1118 physDev->dc_rect.left + visRectDst->left,
1119 physDev->dc_rect.top + visRectDst->top,
1120 width, height, AllPlanes, ZPixmap );
1123 /* Make sure we don't get a BadMatch error */
1124 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
1125 physDev->dc_rect.left + visRectDst->left,
1126 physDev->dc_rect.top + visRectDst->top,
1127 width, height, 0, 0);
1129 image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
1130 AllPlanes, ZPixmap );
1134 for (y = 0; y < height; y++)
1135 for (x = 0; x < width; x++)
1136 XPutPixel( image, x, y,
1137 X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]);
1138 XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height );
1139 XDestroyImage( image );
1143 wine_tsx11_unlock();
1148 /***********************************************************************
1151 * Put an area back into the destination DC, mapping the pixel
1152 * colors to X pixels.
1154 static int BITBLT_PutDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, const RECT *visRectDst)
1157 INT width = visRectDst->right - visRectDst->left;
1158 INT height = visRectDst->bottom - visRectDst->top;
1160 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
1162 if (!X11DRV_PALETTE_PaletteToXPixel || (physDev->depth == 1) ||
1163 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
1165 XCopyArea( gdi_display, pixmap, physDev->drawable, physDev->gc, 0, 0, width, height,
1166 physDev->dc_rect.left + visRectDst->left,
1167 physDev->dc_rect.top + visRectDst->top );
1173 XImage *image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
1174 AllPlanes, ZPixmap );
1175 for (y = 0; y < height; y++)
1176 for (x = 0; x < width; x++)
1178 XPutPixel( image, x, y,
1179 X11DRV_PALETTE_PaletteToXPixel[XGetPixel( image, x, y )]);
1181 XPutImage( gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
1182 physDev->dc_rect.left + visRectDst->left,
1183 physDev->dc_rect.top + visRectDst->top, width, height );
1184 XDestroyImage( image );
1189 static BOOL same_format(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst)
1191 if (physDevSrc->depth != physDevDst->depth) return FALSE;
1192 if (!physDevSrc->color_shifts && !physDevDst->color_shifts) return TRUE;
1193 if (physDevSrc->color_shifts && physDevDst->color_shifts)
1194 return !memcmp(physDevSrc->color_shifts, physDevDst->color_shifts, sizeof(ColorShifts));
1198 void execute_rop( X11DRV_PDEVICE *physdev, Pixmap src_pixmap, GC gc, const RECT *visrect, DWORD rop )
1201 Pixmap result = src_pixmap;
1203 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1204 BOOL use_pat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
1205 BOOL use_dst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
1206 int width = visrect->right - visrect->left;
1207 int height = visrect->bottom - visrect->top;
1209 pixmaps[SRC] = src_pixmap;
1212 pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
1213 wine_tsx11_unlock();
1215 if (use_dst) BITBLT_GetDstArea( physdev, pixmaps[DST], gc, visrect );
1216 null_brush = use_pat && !X11DRV_SetupGCForPatBlt( physdev, gc, TRUE );
1219 for ( ; *opcode; opcode++)
1221 if (OP_DST(*opcode) == DST) result = pixmaps[DST];
1222 XSetFunction( gdi_display, gc, OP_ROP(*opcode) );
1223 switch(OP_SRCDST(*opcode))
1225 case OP_ARGS(DST,TMP):
1226 case OP_ARGS(SRC,TMP):
1228 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
1230 case OP_ARGS(DST,SRC):
1231 case OP_ARGS(SRC,DST):
1232 case OP_ARGS(TMP,SRC):
1233 case OP_ARGS(TMP,DST):
1234 XCopyArea( gdi_display, pixmaps[OP_SRC(*opcode)], pixmaps[OP_DST(*opcode)], gc,
1235 0, 0, width, height, 0, 0 );
1237 case OP_ARGS(PAT,DST):
1238 case OP_ARGS(PAT,SRC):
1240 XFillRectangle( gdi_display, pixmaps[OP_DST(*opcode)], gc, 0, 0, width, height );
1244 XSetFunction( gdi_display, physdev->gc, GXcopy );
1245 physdev->exposures += BITBLT_PutDstArea( physdev, result, visrect );
1246 XFreePixmap( gdi_display, pixmaps[DST] );
1247 if (pixmaps[TMP]) XFreePixmap( gdi_display, pixmaps[TMP] );
1248 wine_tsx11_unlock();
1251 /***********************************************************************
1254 BOOL X11DRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
1256 X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
1257 BOOL usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
1258 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1260 if (usePat && !X11DRV_SetupGCForBrush( physDev )) return TRUE;
1262 X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod );
1265 XSetFunction( gdi_display, physDev->gc, OP_ROP(*opcode) );
1267 switch(rop) /* a few special cases */
1269 case BLACKNESS: /* 0x00 */
1270 case WHITENESS: /* 0xff */
1271 if ((physDev->depth != 1) && X11DRV_PALETTE_PaletteToXPixel)
1273 XSetFunction( gdi_display, physDev->gc, GXcopy );
1274 if (rop == BLACKNESS)
1275 XSetForeground( gdi_display, physDev->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
1277 XSetForeground( gdi_display, physDev->gc,
1278 WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
1279 XSetFillStyle( gdi_display, physDev->gc, FillSolid );
1282 case DSTINVERT: /* 0x55 */
1283 if (!(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL)))
1285 /* Xor is much better when we do not have full colormap. */
1286 /* Using white^black ensures that we invert at least black */
1288 unsigned long xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
1289 BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
1290 XSetFunction( gdi_display, physDev->gc, GXxor );
1291 XSetForeground( gdi_display, physDev->gc, xor_pix);
1292 XSetFillStyle( gdi_display, physDev->gc, FillSolid );
1296 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
1297 physDev->dc_rect.left + dst->visrect.left,
1298 physDev->dc_rect.top + dst->visrect.top,
1299 dst->visrect.right - dst->visrect.left,
1300 dst->visrect.bottom - dst->visrect.top );
1301 wine_tsx11_unlock();
1303 X11DRV_UnlockDIBSection( physDev, TRUE );
1308 /***********************************************************************
1311 BOOL X11DRV_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
1312 PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
1314 X11DRV_PDEVICE *physDevDst = get_x11drv_dev( dst_dev );
1315 X11DRV_PDEVICE *physDevSrc = get_x11drv_dev( src_dev );
1318 INT sDst, sSrc = DIB_Status_None;
1323 if (src_dev->funcs != dst_dev->funcs)
1325 dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
1326 return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
1329 fStretch = (src->width != dst->width) || (src->height != dst->height);
1331 if (physDevDst != physDevSrc)
1332 sSrc = X11DRV_LockDIBSection( physDevSrc, DIB_Status_None );
1334 width = dst->visrect.right - dst->visrect.left;
1335 height = dst->visrect.bottom - dst->visrect.top;
1337 sDst = X11DRV_LockDIBSection( physDevDst, DIB_Status_None );
1338 if (physDevDst == physDevSrc) sSrc = sDst;
1340 /* try client-side DIB copy */
1341 if (!fStretch && sSrc == DIB_Status_AppMod)
1343 if (physDevDst != physDevSrc) X11DRV_UnlockDIBSection( physDevSrc, FALSE );
1344 X11DRV_UnlockDIBSection( physDevDst, TRUE );
1345 dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
1346 return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
1349 X11DRV_CoerceDIBSection( physDevDst, DIB_Status_GdiMod );
1351 opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1353 /* a few optimizations for single-op ROPs */
1354 if (!fStretch && !opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1356 if (same_format(physDevSrc, physDevDst))
1359 XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
1360 wine_tsx11_unlock();
1362 if (physDevSrc != physDevDst) X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod );
1364 XCopyArea( gdi_display, physDevSrc->drawable,
1365 physDevDst->drawable, physDevDst->gc,
1366 physDevSrc->dc_rect.left + src->visrect.left,
1367 physDevSrc->dc_rect.top + src->visrect.top,
1369 physDevDst->dc_rect.left + dst->visrect.left,
1370 physDevDst->dc_rect.top + dst->visrect.top );
1371 physDevDst->exposures++;
1372 wine_tsx11_unlock();
1375 if (physDevSrc->depth == 1)
1379 X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod );
1380 get_colors(physDevDst, physDevSrc, &fg, &bg);
1382 XSetBackground( gdi_display, physDevDst->gc, fg );
1383 XSetForeground( gdi_display, physDevDst->gc, bg );
1384 XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
1385 XCopyPlane( gdi_display, physDevSrc->drawable,
1386 physDevDst->drawable, physDevDst->gc,
1387 physDevSrc->dc_rect.left + src->visrect.left,
1388 physDevSrc->dc_rect.top + src->visrect.top,
1390 physDevDst->dc_rect.left + dst->visrect.left,
1391 physDevDst->dc_rect.top + dst->visrect.top, 1 );
1392 physDevDst->exposures++;
1393 wine_tsx11_unlock();
1399 tmpGC = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
1400 XSetSubwindowMode( gdi_display, tmpGC, IncludeInferiors );
1401 XSetGraphicsExposures( gdi_display, tmpGC, False );
1402 src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, physDevDst->depth );
1403 wine_tsx11_unlock();
1405 if (physDevDst != physDevSrc) X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod );
1408 BITBLT_GetSrcAreaStretch( physDevSrc, physDevDst, src_pixmap, tmpGC, src, dst );
1410 BITBLT_GetSrcArea( physDevSrc, physDevDst, src_pixmap, tmpGC, &src->visrect );
1412 execute_rop( physDevDst, src_pixmap, tmpGC, &dst->visrect, rop );
1415 XFreePixmap( gdi_display, src_pixmap );
1416 XFreeGC( gdi_display, tmpGC );
1417 wine_tsx11_unlock();
1420 if (physDevDst != physDevSrc) X11DRV_UnlockDIBSection( physDevSrc, FALSE );
1421 X11DRV_UnlockDIBSection( physDevDst, TRUE );
1426 static void free_heap_bits( struct gdi_image_bits *bits )
1428 HeapFree( GetProcessHeap(), 0, bits->ptr );
1431 static void free_ximage_bits( struct gdi_image_bits *bits )
1435 wine_tsx11_unlock();
1438 /* store the palette or color mask data in the bitmap info structure */
1439 static void set_color_info( PHYSDEV dev, const ColorShifts *color_shifts, BITMAPINFO *info )
1441 DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
1443 info->bmiHeader.biCompression = BI_RGB;
1444 info->bmiHeader.biClrUsed = 0;
1446 switch (info->bmiHeader.biBitCount)
1451 RGBQUAD *rgb = (RGBQUAD *)colors;
1452 PALETTEENTRY palette[256];
1455 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1456 count = X11DRV_GetSystemPaletteEntries( dev, 0, info->bmiHeader.biClrUsed, palette );
1457 for (i = 0; i < count; i++)
1459 rgb[i].rgbRed = palette[i].peRed;
1460 rgb[i].rgbGreen = palette[i].peGreen;
1461 rgb[i].rgbBlue = palette[i].peBlue;
1462 rgb[i].rgbReserved = 0;
1464 memset( &rgb[count], 0, (info->bmiHeader.biClrUsed - count) * sizeof(*rgb) );
1468 colors[0] = color_shifts->logicalRed.max << color_shifts->logicalRed.shift;
1469 colors[1] = color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift;
1470 colors[2] = color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift;
1471 info->bmiHeader.biCompression = BI_BITFIELDS;
1474 colors[0] = color_shifts->logicalRed.max << color_shifts->logicalRed.shift;
1475 colors[1] = color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift;
1476 colors[2] = color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift;
1477 if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff)
1478 info->bmiHeader.biCompression = BI_BITFIELDS;
1483 /* check if the specified color info is suitable for PutImage */
1484 static BOOL matching_color_info( PHYSDEV dev, const ColorShifts *color_shifts, const BITMAPINFO *info )
1486 DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
1488 switch (info->bmiHeader.biBitCount)
1491 if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
1492 return !info->bmiHeader.biClrUsed; /* color map not allowed */
1496 RGBQUAD *rgb = (RGBQUAD *)colors;
1497 PALETTEENTRY palette[256];
1500 if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
1501 count = X11DRV_GetSystemPaletteEntries( dev, 0, 1 << info->bmiHeader.biBitCount, palette );
1502 if (count != info->bmiHeader.biClrUsed) return FALSE;
1503 for (i = 0; i < count; i++)
1505 if (rgb[i].rgbRed != palette[i].peRed ||
1506 rgb[i].rgbGreen != palette[i].peGreen ||
1507 rgb[i].rgbBlue != palette[i].peBlue) return FALSE;
1512 if (info->bmiHeader.biCompression == BI_BITFIELDS)
1513 return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == colors[0] &&
1514 color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == colors[1] &&
1515 color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == colors[2]);
1516 if (info->bmiHeader.biCompression == BI_RGB)
1517 return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == 0x7c00 &&
1518 color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == 0x03e0 &&
1519 color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == 0x001f);
1522 if (info->bmiHeader.biCompression == BI_BITFIELDS)
1523 return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == colors[0] &&
1524 color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == colors[1] &&
1525 color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == colors[2]);
1528 if (info->bmiHeader.biCompression == BI_RGB)
1529 return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == 0xff0000 &&
1530 color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == 0x00ff00 &&
1531 color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == 0x0000ff);
1537 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1538 static DWORD copy_image_bits( BITMAPINFO *info, const ColorShifts *color_shifts, XImage *image,
1539 const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
1540 struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
1542 #ifdef WORDS_BIGENDIAN
1543 static const int client_byte_order = MSBFirst;
1545 static const int client_byte_order = LSBFirst;
1548 int x, y, height = coords->visrect.bottom - coords->visrect.top;
1549 int width_bytes = image->bytes_per_line;
1551 unsigned char *src, *dst;
1553 switch (info->bmiHeader.biBitCount)
1556 need_byteswap = (image->bitmap_bit_order != MSBFirst);
1559 need_byteswap = (image->byte_order != MSBFirst);
1563 need_byteswap = (image->byte_order != client_byte_order);
1566 need_byteswap = ((image->byte_order == LSBFirst && color_shifts->logicalBlue.shift == 16) ||
1567 (image->byte_order == MSBFirst && color_shifts->logicalBlue.shift == 0));
1570 need_byteswap = FALSE;
1574 src = src_bits->ptr;
1575 if (info->bmiHeader.biHeight > 0)
1576 src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes;
1578 src += coords->visrect.top * width_bytes;
1580 if ((need_byteswap && !src_bits->is_copy) || /* need to swap bytes */
1581 (zeropad_mask != ~0u && !src_bits->is_copy) || /* need to clear padding bytes */
1582 (mapping && !src_bits->is_copy) || /* need to remap pixels */
1583 (width_bytes & 3) || /* need to fixup line alignment */
1584 (info->bmiHeader.biHeight > 0)) /* need to flip vertically */
1586 width_bytes = (width_bytes + 3) & ~3;
1587 info->bmiHeader.biSizeImage = height * width_bytes;
1588 if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
1589 return ERROR_OUTOFMEMORY;
1590 dst_bits->is_copy = TRUE;
1591 dst_bits->free = free_heap_bits;
1595 /* swap bits in place */
1596 dst_bits->ptr = src;
1597 dst_bits->is_copy = src_bits->is_copy;
1598 dst_bits->free = NULL;
1599 if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS; /* nothing to do */
1602 dst = dst_bits->ptr;
1603 padding_pos = width_bytes/sizeof(unsigned int) - 1;
1605 if (info->bmiHeader.biHeight > 0)
1607 dst += (height - 1) * width_bytes;
1608 width_bytes = -width_bytes;
1611 if (need_byteswap || mapping)
1613 switch (info->bmiHeader.biBitCount)
1616 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1618 for (x = 0; x < image->bytes_per_line; x++)
1619 dst[x] = bit_swap[src[x]];
1620 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1624 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1627 for (x = 0; x < image->bytes_per_line; x++)
1628 dst[x] = (mapping[src[x] & 0x0f] << 4) | mapping[src[x] >> 4];
1630 for (x = 0; x < image->bytes_per_line; x++)
1631 dst[x] = (src[x] << 4) | (src[x] >> 4);
1632 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1636 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1638 for (x = 0; x < image->bytes_per_line; x++)
1639 dst[x] = mapping[src[x]];
1640 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1644 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1646 for (x = 0; x < info->bmiHeader.biWidth; x++)
1647 ((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] );
1648 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1652 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1654 for (x = 0; x < info->bmiHeader.biWidth; x++)
1656 unsigned char tmp = src[3 * x];
1657 dst[3 * x] = src[3 * x + 2];
1658 dst[3 * x + 1] = src[3 * x + 1];
1659 dst[3 * x + 2] = tmp;
1661 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1665 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1666 for (x = 0; x < info->bmiHeader.biWidth; x++)
1667 ((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] );
1671 else if (src != dst)
1673 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1675 memcpy( dst, src, image->bytes_per_line );
1676 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1679 else /* only need to clear the padding */
1681 for (y = 0; y < height; y++, dst += width_bytes)
1682 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1684 return ERROR_SUCCESS;
1687 /***********************************************************************
1690 DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
1691 const struct gdi_image_bits *bits, struct bitblt_coords *src,
1692 struct bitblt_coords *dst, DWORD rop )
1694 X11DRV_PDEVICE *physdev;
1695 X_PHYSBITMAP *bitmap;
1699 struct gdi_image_bits dst_bits;
1700 const XPixmapFormatValues *format;
1701 const ColorShifts *color_shifts;
1702 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1703 const int *mapping = NULL;
1707 if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
1709 depth = bitmap->pixmap_depth;
1710 color_shifts = &bitmap->pixmap_color_shifts;
1714 physdev = get_x11drv_dev( dev );
1716 depth = physdev->depth;
1717 color_shifts = physdev->color_shifts;
1719 format = pixmap_formats[depth];
1721 if (info->bmiHeader.biPlanes != 1) goto update_format;
1722 if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1723 /* FIXME: could try to handle 1-bpp using XCopyPlane */
1724 if (!matching_color_info( dev, color_shifts, info )) goto update_format;
1725 if (!bits) return ERROR_SUCCESS; /* just querying the format */
1726 if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
1729 image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0, NULL,
1730 info->bmiHeader.biWidth, src->visrect.bottom - src->visrect.top, 32, 0 );
1731 wine_tsx11_unlock();
1732 if (!image) return ERROR_OUTOFMEMORY;
1734 if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1736 if (bitmap || (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST)))
1737 mapping = X11DRV_PALETTE_PaletteToXPixel;
1740 ret = copy_image_bits( info, color_shifts, image, bits, &dst_bits, src, mapping, ~0u );
1744 int width = dst->visrect.right - dst->visrect.left;
1745 int height = dst->visrect.bottom - dst->visrect.top;
1747 image->data = dst_bits.ptr;
1748 /* hack: make sure the bits are readable if we are reading from a DIB section */
1749 /* to be removed once we get rid of DIB access protections */
1750 if (!dst_bits.is_copy) IsBadReadPtr( dst_bits.ptr, height * image->bytes_per_line );
1754 RGNDATA *clip_data = NULL;
1757 if (clip) clip_data = X11DRV_GetRegionData( clip, 0 );
1758 X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
1761 gc = XCreateGC( gdi_display, bitmap->pixmap, 0, NULL );
1762 XSetGraphicsExposures( gdi_display, gc, False );
1763 if (clip_data) XSetClipRectangles( gdi_display, gc, 0, 0, (XRectangle *)clip_data->Buffer,
1764 clip_data->rdh.nCount, YXBanded );
1765 XPutImage( gdi_display, bitmap->pixmap, gc, image, src->visrect.left, 0,
1766 dst->visrect.left, dst->visrect.top, width, height );
1767 XFreeGC( gdi_display, gc );
1768 wine_tsx11_unlock();
1770 X11DRV_DIB_Unlock( bitmap, TRUE );
1771 HeapFree( GetProcessHeap(), 0, clip_data );
1775 RGNDATA *saved_region = NULL;
1777 if (clip) saved_region = add_extra_clipping_region( physdev, clip );
1778 X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
1780 /* optimization for single-op ROPs */
1781 if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1784 XSetFunction( gdi_display, physdev->gc, OP_ROP(*opcode) );
1785 XPutImage( gdi_display, physdev->drawable, physdev->gc, image, src->visrect.left, 0,
1786 physdev->dc_rect.left + dst->visrect.left,
1787 physdev->dc_rect.top + dst->visrect.top, width, height );
1788 wine_tsx11_unlock();
1796 gc = XCreateGC( gdi_display, physdev->drawable, 0, NULL );
1797 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
1798 XSetGraphicsExposures( gdi_display, gc, False );
1799 src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1800 XPutImage( gdi_display, src_pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
1801 wine_tsx11_unlock();
1803 execute_rop( physdev, src_pixmap, gc, &dst->visrect, rop );
1806 XFreePixmap( gdi_display, src_pixmap );
1807 XFreeGC( gdi_display, gc );
1808 wine_tsx11_unlock();
1811 X11DRV_UnlockDIBSection( physdev, !ret );
1812 restore_clipping_region( physdev, saved_region );
1818 XDestroyImage( image );
1819 wine_tsx11_unlock();
1820 if (dst_bits.free) dst_bits.free( &dst_bits );
1824 info->bmiHeader.biPlanes = 1;
1825 info->bmiHeader.biBitCount = format->bits_per_pixel;
1826 if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1827 set_color_info( dev, color_shifts, info );
1828 return ERROR_BAD_FORMAT;
1831 /***********************************************************************
1834 DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
1835 struct gdi_image_bits *bits, struct bitblt_coords *src )
1837 X11DRV_PDEVICE *physdev;
1838 X_PHYSBITMAP *bitmap;
1839 DWORD ret = ERROR_SUCCESS;
1841 UINT align, x, y, width, height;
1843 struct gdi_image_bits src_bits;
1844 const XPixmapFormatValues *format;
1845 const ColorShifts *color_shifts;
1846 const int *mapping = NULL;
1850 if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
1852 depth = bitmap->pixmap_depth;
1853 color_shifts = &bitmap->pixmap_color_shifts;
1857 physdev = get_x11drv_dev( dev );
1859 depth = physdev->depth;
1860 color_shifts = physdev->color_shifts;
1862 format = pixmap_formats[depth];
1864 /* align start and width to 32-bit boundary */
1865 switch (format->bits_per_pixel)
1867 case 1: align = 32; break;
1868 case 4: align = 8; mapping = X11DRV_PALETTE_XPixelToPalette; break;
1869 case 8: align = 4; mapping = X11DRV_PALETTE_XPixelToPalette; break;
1870 case 16: align = 2; break;
1871 case 24: align = 4; break;
1872 case 32: align = 1; break;
1874 FIXME( "depth %u bpp %u not supported yet\n", depth, format->bits_per_pixel );
1875 return ERROR_BAD_FORMAT;
1878 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1879 info->bmiHeader.biPlanes = 1;
1880 info->bmiHeader.biBitCount = format->bits_per_pixel;
1881 info->bmiHeader.biXPelsPerMeter = 0;
1882 info->bmiHeader.biYPelsPerMeter = 0;
1883 info->bmiHeader.biClrImportant = 0;
1884 set_color_info( dev, color_shifts, info );
1886 if (!bits) return ERROR_SUCCESS; /* just querying the color information */
1888 x = src->visrect.left & ~(align - 1);
1889 y = src->visrect.top;
1890 width = src->visrect.right - x;
1891 height = src->visrect.bottom - src->visrect.top;
1892 if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
1893 /* make the source rectangle relative to the returned bits */
1896 OffsetRect( &src->visrect, -x, -y );
1901 GetObjectW( hbitmap, sizeof(bm), &bm );
1902 width = min( width, bm.bmWidth - x );
1903 height = min( height, bm.bmHeight - y );
1904 X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
1906 image = XGetImage( gdi_display, bitmap->pixmap, x, y, width, height, AllPlanes, ZPixmap );
1907 wine_tsx11_unlock();
1908 X11DRV_DIB_Unlock( bitmap, TRUE );
1910 else if (GetObjectType( dev->hdc ) == OBJ_MEMDC)
1912 X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
1913 width = min( width, physdev->dc_rect.right - physdev->dc_rect.left - x );
1914 height = min( height, physdev->dc_rect.bottom - physdev->dc_rect.top - y );
1916 image = XGetImage( gdi_display, physdev->drawable,
1917 physdev->dc_rect.left + x, physdev->dc_rect.top + y,
1918 width, height, AllPlanes, ZPixmap );
1919 wine_tsx11_unlock();
1920 X11DRV_UnlockDIBSection( physdev, FALSE );
1927 /* use a temporary pixmap to avoid BadMatch errors */
1928 pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1929 XCopyArea( gdi_display, physdev->drawable, pixmap, get_bitmap_gc(depth),
1930 physdev->dc_rect.left + x, physdev->dc_rect.top + y, width, height, 0, 0 );
1931 image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1932 XFreePixmap( gdi_display, pixmap );
1933 wine_tsx11_unlock();
1935 if (!image) return ERROR_OUTOFMEMORY;
1937 info->bmiHeader.biWidth = width;
1938 info->bmiHeader.biHeight = -height;
1939 info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1941 src_bits.ptr = image->data;
1942 src_bits.is_copy = TRUE;
1943 ret = copy_image_bits( info, color_shifts, image, &src_bits, bits, src, mapping,
1944 zeropad_masks[(width * image->bits_per_pixel) & 31] );
1946 if (!ret && bits->ptr == image->data)
1948 bits->free = free_ximage_bits;
1952 XDestroyImage( image );
1953 wine_tsx11_unlock();