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 static inline BOOL is_r8g8b8( int depth, const ColorShifts *color_shifts )
1539 return depth == 24 && color_shifts->logicalBlue.shift == 0 && color_shifts->logicalRed.shift == 16;
1542 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1543 DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
1544 const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
1545 struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
1547 #ifdef WORDS_BIGENDIAN
1548 static const int client_byte_order = MSBFirst;
1550 static const int client_byte_order = LSBFirst;
1553 int x, y, height = coords->visrect.bottom - coords->visrect.top;
1554 int width_bytes = image->bytes_per_line;
1556 unsigned char *src, *dst;
1558 switch (info->bmiHeader.biBitCount)
1561 need_byteswap = (image->bitmap_bit_order != MSBFirst);
1564 need_byteswap = (image->byte_order != MSBFirst);
1568 need_byteswap = (image->byte_order != client_byte_order);
1571 need_byteswap = (image->byte_order == MSBFirst) ^ !is_r8g8b8;
1574 need_byteswap = FALSE;
1578 src = src_bits->ptr;
1579 if (info->bmiHeader.biHeight > 0)
1580 src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes;
1582 src += coords->visrect.top * width_bytes;
1584 if ((need_byteswap && !src_bits->is_copy) || /* need to swap bytes */
1585 (zeropad_mask != ~0u && !src_bits->is_copy) || /* need to clear padding bytes */
1586 (mapping && !src_bits->is_copy) || /* need to remap pixels */
1587 (width_bytes & 3) || /* need to fixup line alignment */
1588 (info->bmiHeader.biHeight > 0)) /* need to flip vertically */
1590 width_bytes = (width_bytes + 3) & ~3;
1591 info->bmiHeader.biSizeImage = height * width_bytes;
1592 if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
1593 return ERROR_OUTOFMEMORY;
1594 dst_bits->is_copy = TRUE;
1595 dst_bits->free = free_heap_bits;
1599 /* swap bits in place */
1600 dst_bits->ptr = src;
1601 dst_bits->is_copy = src_bits->is_copy;
1602 dst_bits->free = NULL;
1603 if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS; /* nothing to do */
1606 dst = dst_bits->ptr;
1607 padding_pos = width_bytes/sizeof(unsigned int) - 1;
1609 if (info->bmiHeader.biHeight > 0)
1611 dst += (height - 1) * width_bytes;
1612 width_bytes = -width_bytes;
1615 if (need_byteswap || mapping)
1617 switch (info->bmiHeader.biBitCount)
1620 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1622 for (x = 0; x < image->bytes_per_line; x++)
1623 dst[x] = bit_swap[src[x]];
1624 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1628 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1631 for (x = 0; x < image->bytes_per_line; x++)
1632 dst[x] = (mapping[src[x] & 0x0f] << 4) | mapping[src[x] >> 4];
1634 for (x = 0; x < image->bytes_per_line; x++)
1635 dst[x] = (src[x] << 4) | (src[x] >> 4);
1636 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1640 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1642 for (x = 0; x < image->bytes_per_line; x++)
1643 dst[x] = mapping[src[x]];
1644 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1648 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1650 for (x = 0; x < info->bmiHeader.biWidth; x++)
1651 ((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] );
1652 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1656 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1658 for (x = 0; x < info->bmiHeader.biWidth; x++)
1660 unsigned char tmp = src[3 * x];
1661 dst[3 * x] = src[3 * x + 2];
1662 dst[3 * x + 1] = src[3 * x + 1];
1663 dst[3 * x + 2] = tmp;
1665 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1669 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1670 for (x = 0; x < info->bmiHeader.biWidth; x++)
1671 ((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] );
1675 else if (src != dst)
1677 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1679 memcpy( dst, src, image->bytes_per_line );
1680 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1683 else /* only need to clear the padding */
1685 for (y = 0; y < height; y++, dst += width_bytes)
1686 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1688 return ERROR_SUCCESS;
1691 /***********************************************************************
1694 DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
1695 const struct gdi_image_bits *bits, struct bitblt_coords *src,
1696 struct bitblt_coords *dst, DWORD rop )
1698 X11DRV_PDEVICE *physdev;
1699 X_PHYSBITMAP *bitmap;
1703 struct gdi_image_bits dst_bits;
1704 const XPixmapFormatValues *format;
1705 const ColorShifts *color_shifts;
1706 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1707 const int *mapping = NULL;
1711 if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
1713 depth = bitmap->pixmap_depth;
1714 color_shifts = &bitmap->pixmap_color_shifts;
1718 physdev = get_x11drv_dev( dev );
1720 depth = physdev->depth;
1721 color_shifts = physdev->color_shifts;
1723 format = pixmap_formats[depth];
1725 if (info->bmiHeader.biPlanes != 1) goto update_format;
1726 if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1727 /* FIXME: could try to handle 1-bpp using XCopyPlane */
1728 if (!matching_color_info( dev, color_shifts, info )) goto update_format;
1729 if (!bits) return ERROR_SUCCESS; /* just querying the format */
1730 if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
1733 image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0, NULL,
1734 info->bmiHeader.biWidth, src->visrect.bottom - src->visrect.top, 32, 0 );
1735 wine_tsx11_unlock();
1736 if (!image) return ERROR_OUTOFMEMORY;
1738 if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1740 if (bitmap || (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST)))
1741 mapping = X11DRV_PALETTE_PaletteToXPixel;
1744 ret = copy_image_bits( info, is_r8g8b8(depth,color_shifts), image, bits, &dst_bits, src, mapping, ~0u );
1748 int width = dst->visrect.right - dst->visrect.left;
1749 int height = dst->visrect.bottom - dst->visrect.top;
1751 image->data = dst_bits.ptr;
1752 /* hack: make sure the bits are readable if we are reading from a DIB section */
1753 /* to be removed once we get rid of DIB access protections */
1754 if (!dst_bits.is_copy) IsBadReadPtr( dst_bits.ptr, height * image->bytes_per_line );
1758 RGNDATA *clip_data = NULL;
1761 if (clip) clip_data = X11DRV_GetRegionData( clip, 0 );
1762 X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
1765 gc = XCreateGC( gdi_display, bitmap->pixmap, 0, NULL );
1766 XSetGraphicsExposures( gdi_display, gc, False );
1767 if (clip_data) XSetClipRectangles( gdi_display, gc, 0, 0, (XRectangle *)clip_data->Buffer,
1768 clip_data->rdh.nCount, YXBanded );
1769 XPutImage( gdi_display, bitmap->pixmap, gc, image, src->visrect.left, 0,
1770 dst->visrect.left, dst->visrect.top, width, height );
1771 XFreeGC( gdi_display, gc );
1772 wine_tsx11_unlock();
1774 X11DRV_DIB_Unlock( bitmap, TRUE );
1775 HeapFree( GetProcessHeap(), 0, clip_data );
1779 RGNDATA *saved_region = NULL;
1781 if (clip) saved_region = add_extra_clipping_region( physdev, clip );
1782 X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
1784 /* optimization for single-op ROPs */
1785 if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1788 XSetFunction( gdi_display, physdev->gc, OP_ROP(*opcode) );
1789 XPutImage( gdi_display, physdev->drawable, physdev->gc, image, src->visrect.left, 0,
1790 physdev->dc_rect.left + dst->visrect.left,
1791 physdev->dc_rect.top + dst->visrect.top, width, height );
1792 wine_tsx11_unlock();
1800 gc = XCreateGC( gdi_display, physdev->drawable, 0, NULL );
1801 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
1802 XSetGraphicsExposures( gdi_display, gc, False );
1803 src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1804 XPutImage( gdi_display, src_pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
1805 wine_tsx11_unlock();
1807 execute_rop( physdev, src_pixmap, gc, &dst->visrect, rop );
1810 XFreePixmap( gdi_display, src_pixmap );
1811 XFreeGC( gdi_display, gc );
1812 wine_tsx11_unlock();
1815 X11DRV_UnlockDIBSection( physdev, !ret );
1816 restore_clipping_region( physdev, saved_region );
1822 XDestroyImage( image );
1823 wine_tsx11_unlock();
1824 if (dst_bits.free) dst_bits.free( &dst_bits );
1828 info->bmiHeader.biPlanes = 1;
1829 info->bmiHeader.biBitCount = format->bits_per_pixel;
1830 if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1831 set_color_info( dev, color_shifts, info );
1832 return ERROR_BAD_FORMAT;
1835 /***********************************************************************
1838 DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
1839 struct gdi_image_bits *bits, struct bitblt_coords *src )
1841 X11DRV_PDEVICE *physdev;
1842 X_PHYSBITMAP *bitmap;
1843 DWORD ret = ERROR_SUCCESS;
1845 UINT align, x, y, width, height;
1847 struct gdi_image_bits src_bits;
1848 const XPixmapFormatValues *format;
1849 const ColorShifts *color_shifts;
1850 const int *mapping = NULL;
1854 if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
1856 depth = bitmap->pixmap_depth;
1857 color_shifts = &bitmap->pixmap_color_shifts;
1861 physdev = get_x11drv_dev( dev );
1863 depth = physdev->depth;
1864 color_shifts = physdev->color_shifts;
1866 format = pixmap_formats[depth];
1868 /* align start and width to 32-bit boundary */
1869 switch (format->bits_per_pixel)
1871 case 1: align = 32; break;
1872 case 4: align = 8; mapping = X11DRV_PALETTE_XPixelToPalette; break;
1873 case 8: align = 4; mapping = X11DRV_PALETTE_XPixelToPalette; break;
1874 case 16: align = 2; break;
1875 case 24: align = 4; break;
1876 case 32: align = 1; break;
1878 FIXME( "depth %u bpp %u not supported yet\n", depth, format->bits_per_pixel );
1879 return ERROR_BAD_FORMAT;
1882 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1883 info->bmiHeader.biPlanes = 1;
1884 info->bmiHeader.biBitCount = format->bits_per_pixel;
1885 info->bmiHeader.biXPelsPerMeter = 0;
1886 info->bmiHeader.biYPelsPerMeter = 0;
1887 info->bmiHeader.biClrImportant = 0;
1888 set_color_info( dev, color_shifts, info );
1890 if (!bits) return ERROR_SUCCESS; /* just querying the color information */
1892 x = src->visrect.left & ~(align - 1);
1893 y = src->visrect.top;
1894 width = src->visrect.right - x;
1895 height = src->visrect.bottom - src->visrect.top;
1896 if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
1897 /* make the source rectangle relative to the returned bits */
1900 OffsetRect( &src->visrect, -x, -y );
1905 GetObjectW( hbitmap, sizeof(bm), &bm );
1906 width = min( width, bm.bmWidth - x );
1907 height = min( height, bm.bmHeight - y );
1908 X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
1910 image = XGetImage( gdi_display, bitmap->pixmap, x, y, width, height, AllPlanes, ZPixmap );
1911 wine_tsx11_unlock();
1912 X11DRV_DIB_Unlock( bitmap, TRUE );
1914 else if (GetObjectType( dev->hdc ) == OBJ_MEMDC)
1916 X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
1917 width = min( width, physdev->dc_rect.right - physdev->dc_rect.left - x );
1918 height = min( height, physdev->dc_rect.bottom - physdev->dc_rect.top - y );
1920 image = XGetImage( gdi_display, physdev->drawable,
1921 physdev->dc_rect.left + x, physdev->dc_rect.top + y,
1922 width, height, AllPlanes, ZPixmap );
1923 wine_tsx11_unlock();
1924 X11DRV_UnlockDIBSection( physdev, FALSE );
1931 /* use a temporary pixmap to avoid BadMatch errors */
1932 pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1933 XCopyArea( gdi_display, physdev->drawable, pixmap, get_bitmap_gc(depth),
1934 physdev->dc_rect.left + x, physdev->dc_rect.top + y, width, height, 0, 0 );
1935 image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1936 XFreePixmap( gdi_display, pixmap );
1937 wine_tsx11_unlock();
1939 if (!image) return ERROR_OUTOFMEMORY;
1941 info->bmiHeader.biWidth = width;
1942 info->bmiHeader.biHeight = -height;
1943 info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1945 src_bits.ptr = image->data;
1946 src_bits.is_copy = TRUE;
1947 ret = copy_image_bits( info, is_r8g8b8(depth,color_shifts), image, &src_bits, bits, src, mapping,
1948 zeropad_masks[(width * image->bits_per_pixel) & 31] );
1950 if (!ret && bits->ptr == image->data)
1952 bits->free = free_ximage_bits;
1956 XDestroyImage( image );
1957 wine_tsx11_unlock();