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