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 );
1407 if(!X11DRV_XRender_GetSrcAreaStretch( physDevSrc, physDevDst, src_pixmap, tmpGC, src, dst ))
1410 BITBLT_GetSrcAreaStretch( physDevSrc, physDevDst, src_pixmap, tmpGC, src, dst );
1412 BITBLT_GetSrcArea( physDevSrc, physDevDst, src_pixmap, tmpGC, &src->visrect );
1415 execute_rop( physDevDst, src_pixmap, tmpGC, &dst->visrect, rop );
1418 XFreePixmap( gdi_display, src_pixmap );
1419 XFreeGC( gdi_display, tmpGC );
1420 wine_tsx11_unlock();
1423 if (physDevDst != physDevSrc) X11DRV_UnlockDIBSection( physDevSrc, FALSE );
1424 X11DRV_UnlockDIBSection( physDevDst, TRUE );
1429 static void free_heap_bits( struct gdi_image_bits *bits )
1431 HeapFree( GetProcessHeap(), 0, bits->ptr );
1434 static void free_ximage_bits( struct gdi_image_bits *bits )
1438 wine_tsx11_unlock();
1441 /* store the palette or color mask data in the bitmap info structure */
1442 static void set_color_info( PHYSDEV dev, const ColorShifts *color_shifts, BITMAPINFO *info )
1444 DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
1446 info->bmiHeader.biCompression = BI_RGB;
1447 info->bmiHeader.biClrUsed = 0;
1449 switch (info->bmiHeader.biBitCount)
1454 RGBQUAD *rgb = (RGBQUAD *)colors;
1455 PALETTEENTRY palette[256];
1458 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
1459 count = X11DRV_GetSystemPaletteEntries( dev, 0, info->bmiHeader.biClrUsed, palette );
1460 for (i = 0; i < count; i++)
1462 rgb[i].rgbRed = palette[i].peRed;
1463 rgb[i].rgbGreen = palette[i].peGreen;
1464 rgb[i].rgbBlue = palette[i].peBlue;
1465 rgb[i].rgbReserved = 0;
1467 memset( &rgb[count], 0, (info->bmiHeader.biClrUsed - count) * sizeof(*rgb) );
1471 colors[0] = color_shifts->logicalRed.max << color_shifts->logicalRed.shift;
1472 colors[1] = color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift;
1473 colors[2] = color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift;
1474 info->bmiHeader.biCompression = BI_BITFIELDS;
1477 colors[0] = color_shifts->logicalRed.max << color_shifts->logicalRed.shift;
1478 colors[1] = color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift;
1479 colors[2] = color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift;
1480 if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff)
1481 info->bmiHeader.biCompression = BI_BITFIELDS;
1486 /* check if the specified color info is suitable for PutImage */
1487 static BOOL matching_color_info( PHYSDEV dev, const ColorShifts *color_shifts, const BITMAPINFO *info )
1489 DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
1491 switch (info->bmiHeader.biBitCount)
1494 if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
1495 return !info->bmiHeader.biClrUsed; /* color map not allowed */
1499 RGBQUAD *rgb = (RGBQUAD *)colors;
1500 PALETTEENTRY palette[256];
1503 if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
1504 count = X11DRV_GetSystemPaletteEntries( dev, 0, 1 << info->bmiHeader.biBitCount, palette );
1505 if (count != info->bmiHeader.biClrUsed) return FALSE;
1506 for (i = 0; i < count; i++)
1508 if (rgb[i].rgbRed != palette[i].peRed ||
1509 rgb[i].rgbGreen != palette[i].peGreen ||
1510 rgb[i].rgbBlue != palette[i].peBlue) return FALSE;
1515 if (info->bmiHeader.biCompression == BI_BITFIELDS)
1516 return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == colors[0] &&
1517 color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == colors[1] &&
1518 color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == colors[2]);
1519 if (info->bmiHeader.biCompression == BI_RGB)
1520 return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == 0x7c00 &&
1521 color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == 0x03e0 &&
1522 color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == 0x001f);
1525 if (info->bmiHeader.biCompression == BI_BITFIELDS)
1526 return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == colors[0] &&
1527 color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == colors[1] &&
1528 color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == colors[2]);
1531 if (info->bmiHeader.biCompression == BI_RGB)
1532 return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == 0xff0000 &&
1533 color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == 0x00ff00 &&
1534 color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == 0x0000ff);
1540 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1541 static DWORD copy_image_bits( BITMAPINFO *info, const ColorShifts *color_shifts, XImage *image,
1542 const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
1543 struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
1545 #ifdef WORDS_BIGENDIAN
1546 static const int client_byte_order = MSBFirst;
1548 static const int client_byte_order = LSBFirst;
1551 int x, y, height = coords->visrect.bottom - coords->visrect.top;
1552 int width_bytes = image->bytes_per_line;
1554 unsigned char *src, *dst;
1556 switch (info->bmiHeader.biBitCount)
1559 need_byteswap = (image->bitmap_bit_order != MSBFirst);
1562 need_byteswap = (image->byte_order != MSBFirst);
1566 need_byteswap = (image->byte_order != client_byte_order);
1569 need_byteswap = ((image->byte_order == LSBFirst && color_shifts->logicalBlue.shift == 16) ||
1570 (image->byte_order == MSBFirst && color_shifts->logicalBlue.shift == 0));
1573 need_byteswap = FALSE;
1577 src = src_bits->ptr;
1578 if (info->bmiHeader.biHeight > 0)
1579 src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes;
1581 src += coords->visrect.top * width_bytes;
1583 if ((need_byteswap && !src_bits->is_copy) || /* need to swap bytes */
1584 (zeropad_mask != ~0u && !src_bits->is_copy) || /* need to clear padding bytes */
1585 (mapping && !src_bits->is_copy) || /* need to remap pixels */
1586 (width_bytes & 3) || /* need to fixup line alignment */
1587 (info->bmiHeader.biHeight > 0)) /* need to flip vertically */
1589 width_bytes = (width_bytes + 3) & ~3;
1590 info->bmiHeader.biSizeImage = height * width_bytes;
1591 if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
1592 return ERROR_OUTOFMEMORY;
1593 dst_bits->is_copy = TRUE;
1594 dst_bits->free = free_heap_bits;
1598 /* swap bits in place */
1599 dst_bits->ptr = src;
1600 dst_bits->is_copy = src_bits->is_copy;
1601 dst_bits->free = NULL;
1602 if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS; /* nothing to do */
1605 dst = dst_bits->ptr;
1606 padding_pos = width_bytes/sizeof(unsigned int) - 1;
1608 if (info->bmiHeader.biHeight > 0)
1610 dst += (height - 1) * width_bytes;
1611 width_bytes = -width_bytes;
1614 if (need_byteswap || mapping)
1616 switch (info->bmiHeader.biBitCount)
1619 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1621 for (x = 0; x < image->bytes_per_line; x++)
1622 dst[x] = bit_swap[src[x]];
1623 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1627 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1630 for (x = 0; x < image->bytes_per_line; x++)
1631 dst[x] = (mapping[src[x] & 0x0f] << 4) | mapping[src[x] >> 4];
1633 for (x = 0; x < image->bytes_per_line; x++)
1634 dst[x] = (src[x] << 4) | (src[x] >> 4);
1635 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1639 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1641 for (x = 0; x < image->bytes_per_line; x++)
1642 dst[x] = mapping[src[x]];
1643 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1647 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1649 for (x = 0; x < info->bmiHeader.biWidth; x++)
1650 ((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] );
1651 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1655 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1657 for (x = 0; x < info->bmiHeader.biWidth; x++)
1659 unsigned char tmp = src[3 * x];
1660 dst[3 * x] = src[3 * x + 2];
1661 dst[3 * x + 1] = src[3 * x + 1];
1662 dst[3 * x + 2] = tmp;
1664 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1668 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1669 for (x = 0; x < info->bmiHeader.biWidth; x++)
1670 ((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] );
1674 else if (src != dst)
1676 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1678 memcpy( dst, src, image->bytes_per_line );
1679 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1682 else /* only need to clear the padding */
1684 for (y = 0; y < height; y++, dst += width_bytes)
1685 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1687 return ERROR_SUCCESS;
1690 /***********************************************************************
1693 DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
1694 const struct gdi_image_bits *bits, struct bitblt_coords *src,
1695 struct bitblt_coords *dst, DWORD rop )
1697 X11DRV_PDEVICE *physdev;
1698 X_PHYSBITMAP *bitmap;
1702 struct gdi_image_bits dst_bits;
1703 const XPixmapFormatValues *format;
1704 const ColorShifts *color_shifts;
1705 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1706 const int *mapping = NULL;
1710 if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
1712 depth = bitmap->pixmap_depth;
1713 color_shifts = &bitmap->pixmap_color_shifts;
1717 physdev = get_x11drv_dev( dev );
1719 depth = physdev->depth;
1720 color_shifts = physdev->color_shifts;
1722 format = pixmap_formats[depth];
1724 if (info->bmiHeader.biPlanes != 1) goto update_format;
1725 if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1726 /* FIXME: could try to handle 1-bpp using XCopyPlane */
1727 if (!matching_color_info( dev, color_shifts, info )) goto update_format;
1728 if (!bits) return ERROR_SUCCESS; /* just querying the format */
1729 if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
1732 image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0, NULL,
1733 info->bmiHeader.biWidth, src->visrect.bottom - src->visrect.top, 32, 0 );
1734 wine_tsx11_unlock();
1735 if (!image) return ERROR_OUTOFMEMORY;
1737 if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1739 if (bitmap || (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST)))
1740 mapping = X11DRV_PALETTE_PaletteToXPixel;
1743 ret = copy_image_bits( info, color_shifts, image, bits, &dst_bits, src, mapping, ~0u );
1747 int width = dst->visrect.right - dst->visrect.left;
1748 int height = dst->visrect.bottom - dst->visrect.top;
1750 image->data = dst_bits.ptr;
1751 /* hack: make sure the bits are readable if we are reading from a DIB section */
1752 /* to be removed once we get rid of DIB access protections */
1753 if (!dst_bits.is_copy) IsBadReadPtr( dst_bits.ptr, height * image->bytes_per_line );
1757 RGNDATA *clip_data = NULL;
1760 if (clip) clip_data = X11DRV_GetRegionData( clip, 0 );
1761 X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
1764 gc = XCreateGC( gdi_display, bitmap->pixmap, 0, NULL );
1765 XSetGraphicsExposures( gdi_display, gc, False );
1766 if (clip_data) XSetClipRectangles( gdi_display, gc, 0, 0, (XRectangle *)clip_data->Buffer,
1767 clip_data->rdh.nCount, YXBanded );
1768 XPutImage( gdi_display, bitmap->pixmap, gc, image, src->visrect.left, 0,
1769 dst->visrect.left, dst->visrect.top, width, height );
1770 XFreeGC( gdi_display, gc );
1771 wine_tsx11_unlock();
1773 X11DRV_DIB_Unlock( bitmap, TRUE );
1774 HeapFree( GetProcessHeap(), 0, clip_data );
1778 RGNDATA *saved_region = NULL;
1780 if (clip) saved_region = add_extra_clipping_region( physdev, clip );
1781 X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
1783 /* optimization for single-op ROPs */
1784 if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1787 XSetFunction( gdi_display, physdev->gc, OP_ROP(*opcode) );
1788 XPutImage( gdi_display, physdev->drawable, physdev->gc, image, src->visrect.left, 0,
1789 physdev->dc_rect.left + dst->visrect.left,
1790 physdev->dc_rect.top + dst->visrect.top, width, height );
1791 wine_tsx11_unlock();
1799 gc = XCreateGC( gdi_display, physdev->drawable, 0, NULL );
1800 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
1801 XSetGraphicsExposures( gdi_display, gc, False );
1802 src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1803 XPutImage( gdi_display, src_pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
1804 wine_tsx11_unlock();
1806 execute_rop( physdev, src_pixmap, gc, &dst->visrect, rop );
1809 XFreePixmap( gdi_display, src_pixmap );
1810 XFreeGC( gdi_display, gc );
1811 wine_tsx11_unlock();
1814 X11DRV_UnlockDIBSection( physdev, !ret );
1815 restore_clipping_region( physdev, saved_region );
1821 XDestroyImage( image );
1822 wine_tsx11_unlock();
1823 if (dst_bits.free) dst_bits.free( &dst_bits );
1827 info->bmiHeader.biPlanes = 1;
1828 info->bmiHeader.biBitCount = format->bits_per_pixel;
1829 if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1830 set_color_info( dev, color_shifts, info );
1831 return ERROR_BAD_FORMAT;
1834 /***********************************************************************
1837 DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
1838 struct gdi_image_bits *bits, struct bitblt_coords *src )
1840 X11DRV_PDEVICE *physdev;
1841 X_PHYSBITMAP *bitmap;
1842 DWORD ret = ERROR_SUCCESS;
1844 UINT align, x, y, width, height;
1846 struct gdi_image_bits src_bits;
1847 const XPixmapFormatValues *format;
1848 const ColorShifts *color_shifts;
1849 const int *mapping = NULL;
1853 if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
1855 depth = bitmap->pixmap_depth;
1856 color_shifts = &bitmap->pixmap_color_shifts;
1860 physdev = get_x11drv_dev( dev );
1862 depth = physdev->depth;
1863 color_shifts = physdev->color_shifts;
1865 format = pixmap_formats[depth];
1867 /* align start and width to 32-bit boundary */
1868 switch (format->bits_per_pixel)
1870 case 1: align = 32; break;
1871 case 4: align = 8; mapping = X11DRV_PALETTE_XPixelToPalette; break;
1872 case 8: align = 4; mapping = X11DRV_PALETTE_XPixelToPalette; break;
1873 case 16: align = 2; break;
1874 case 24: align = 4; break;
1875 case 32: align = 1; break;
1877 FIXME( "depth %u bpp %u not supported yet\n", depth, format->bits_per_pixel );
1878 return ERROR_BAD_FORMAT;
1881 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1882 info->bmiHeader.biPlanes = 1;
1883 info->bmiHeader.biBitCount = format->bits_per_pixel;
1884 info->bmiHeader.biXPelsPerMeter = 0;
1885 info->bmiHeader.biYPelsPerMeter = 0;
1886 info->bmiHeader.biClrImportant = 0;
1887 set_color_info( dev, color_shifts, info );
1889 if (!bits) return ERROR_SUCCESS; /* just querying the color information */
1891 x = src->visrect.left & ~(align - 1);
1892 y = src->visrect.top;
1893 width = src->visrect.right - x;
1894 height = src->visrect.bottom - src->visrect.top;
1895 if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
1896 /* make the source rectangle relative to the returned bits */
1899 OffsetRect( &src->visrect, -x, -y );
1904 GetObjectW( hbitmap, sizeof(bm), &bm );
1905 width = min( width, bm.bmWidth - x );
1906 height = min( height, bm.bmHeight - y );
1907 X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
1909 image = XGetImage( gdi_display, bitmap->pixmap, x, y, width, height, AllPlanes, ZPixmap );
1910 wine_tsx11_unlock();
1911 X11DRV_DIB_Unlock( bitmap, TRUE );
1913 else if (GetObjectType( dev->hdc ) == OBJ_MEMDC)
1915 X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
1916 width = min( width, physdev->dc_rect.right - physdev->dc_rect.left - x );
1917 height = min( height, physdev->dc_rect.bottom - physdev->dc_rect.top - y );
1919 image = XGetImage( gdi_display, physdev->drawable,
1920 physdev->dc_rect.left + x, physdev->dc_rect.top + y,
1921 width, height, AllPlanes, ZPixmap );
1922 wine_tsx11_unlock();
1923 X11DRV_UnlockDIBSection( physdev, FALSE );
1930 /* use a temporary pixmap to avoid BadMatch errors */
1931 pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1932 XCopyArea( gdi_display, physdev->drawable, pixmap, get_bitmap_gc(depth),
1933 physdev->dc_rect.left + x, physdev->dc_rect.top + y, width, height, 0, 0 );
1934 image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1935 XFreePixmap( gdi_display, pixmap );
1936 wine_tsx11_unlock();
1938 if (!image) return ERROR_OUTOFMEMORY;
1940 info->bmiHeader.biWidth = width;
1941 info->bmiHeader.biHeight = -height;
1942 info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1944 src_bits.ptr = image->data;
1945 src_bits.is_copy = TRUE;
1946 ret = copy_image_bits( info, color_shifts, image, &src_bits, bits, src, mapping,
1947 zeropad_masks[(width * image->bits_per_pixel) & 31] );
1949 if (!ret && bits->ptr == image->data)
1951 bits->free = free_ximage_bits;
1955 XDestroyImage( image );
1956 wine_tsx11_unlock();