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,TMP,GXnand),
83 OP(TMP,DST,GXand), OP(SRC,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,TMP,GXnand),
91 OP(TMP,DST,GXand), OP(SRC,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,TMP,GXxor),
95 OP(TMP,DST,GXand), OP(SRC,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,TMP,GXand),
111 OP(TMP,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x26 S^(D|(S&P)) */
112 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXequiv),
113 OP(TMP,DST,GXor), OP(SRC,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,TMP,GXand),
116 OP(TMP,DST,GXor), OP(SRC,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;
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,TMP):
559 tmp = do_bitop( pat, tmp, *opcode & 0xf );
561 case OP_ARGS(PAT,DST):
562 dst = do_bitop( pat, dst, *opcode & 0xf );
565 case OP_ARGS(PAT,SRC):
566 src = do_bitop( pat, src, *opcode & 0xf );
568 case OP_ARGS(TMP,DST):
569 dst = do_bitop( tmp, dst, *opcode & 0xf );
572 case OP_ARGS(TMP,SRC):
573 src = do_bitop( tmp, src, *opcode & 0xf );
576 printf( "Invalid opcode %x\n", *opcode );
579 if (!dstUsed) dst = src;
580 if (dst) res |= 1 << i;
582 if (res != rop) printf( "%02x: ERROR, res=%02x\n", rop, res );
588 #endif /* BITBLT_TEST */
591 static void get_colors(X11DRV_PDEVICE *physDevDst, X11DRV_PDEVICE *physDevSrc,
596 *fg = physDevDst->textPixel;
597 *bg = physDevDst->backgroundPixel;
598 if(physDevSrc->depth == 1) {
599 if(GetDIBColorTable(physDevSrc->dev.hdc, 0, 2, rgb) == 2) {
601 logcolor = RGB(rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue);
602 *fg = X11DRV_PALETTE_ToPhysical( physDevDst, logcolor );
603 logcolor = RGB(rgb[1].rgbRed, rgb[1].rgbGreen,rgb[1].rgbBlue);
604 *bg = X11DRV_PALETTE_ToPhysical( physDevDst, logcolor );
609 /* return a mask for meaningful bits when doing an XGetPixel on an image */
610 static unsigned long image_pixel_mask( X11DRV_PDEVICE *physDev )
613 ColorShifts *shifts = physDev->color_shifts;
615 if (!shifts) shifts = &X11DRV_PALETTE_default_shifts;
616 ret = (shifts->physicalRed.max << shifts->physicalRed.shift) |
617 (shifts->physicalGreen.max << shifts->physicalGreen.shift) |
618 (shifts->physicalBlue.max << shifts->physicalBlue.shift);
619 if (!ret) ret = (1 << physDev->depth) - 1;
624 /***********************************************************************
627 * Stretch a row of pixels. Helper function for BITBLT_StretchImage.
629 static void BITBLT_StretchRow( int *rowSrc, int *rowDst,
630 INT startDst, INT widthDst,
631 INT xinc, INT xoff, WORD mode )
633 register INT xsrc = xinc * startDst + xoff;
637 case STRETCH_ANDSCANS:
638 for(; widthDst > 0; widthDst--, xsrc += xinc)
639 *rowDst++ &= rowSrc[xsrc >> 16];
641 case STRETCH_ORSCANS:
642 for(; widthDst > 0; widthDst--, xsrc += xinc)
643 *rowDst++ |= rowSrc[xsrc >> 16];
645 case STRETCH_DELETESCANS:
646 for(; widthDst > 0; widthDst--, xsrc += xinc)
647 *rowDst++ = rowSrc[xsrc >> 16];
653 /***********************************************************************
656 * Shrink a row of pixels. Helper function for BITBLT_StretchImage.
658 static void BITBLT_ShrinkRow( int *rowSrc, int *rowDst,
659 INT startSrc, INT widthSrc,
660 INT xinc, INT xoff, WORD mode )
662 register INT xdst = xinc * startSrc + xoff;
666 case STRETCH_ORSCANS:
667 for(; widthSrc > 0; widthSrc--, xdst += xinc)
668 rowDst[xdst >> 16] |= *rowSrc++;
670 case STRETCH_ANDSCANS:
671 for(; widthSrc > 0; widthSrc--, xdst += xinc)
672 rowDst[xdst >> 16] &= *rowSrc++;
674 case STRETCH_DELETESCANS:
675 for(; widthSrc > 0; widthSrc--, xdst += xinc)
676 rowDst[xdst >> 16] = *rowSrc++;
682 /***********************************************************************
685 * Retrieve a row from an image. Helper function for BITBLT_StretchImage.
687 static void BITBLT_GetRow( XImage *image, int *pdata, INT row,
688 INT start, INT width, INT depthDst,
689 int fg, int bg, unsigned long pixel_mask, BOOL swap)
693 assert( (row >= 0) && (row < image->height) );
694 assert( (start >= 0) && (width <= image->width) );
696 pdata += swap ? start+width-1 : start;
697 if (image->depth == depthDst) /* color -> color */
699 if (X11DRV_PALETTE_XPixelToPalette && (depthDst != 1))
700 if (swap) for (i = 0; i < width; i++)
701 *pdata-- = X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, i, row )];
702 else for (i = 0; i < width; i++)
703 *pdata++ = X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, i, row )];
705 if (swap) for (i = 0; i < width; i++)
706 *pdata-- = XGetPixel( image, i, row );
707 else for (i = 0; i < width; i++)
708 *pdata++ = XGetPixel( image, i, row );
712 if (image->depth == 1) /* monochrome -> color */
714 if (X11DRV_PALETTE_XPixelToPalette)
716 fg = X11DRV_PALETTE_XPixelToPalette[fg];
717 bg = X11DRV_PALETTE_XPixelToPalette[bg];
719 if (swap) for (i = 0; i < width; i++)
720 *pdata-- = XGetPixel( image, i, row ) ? bg : fg;
721 else for (i = 0; i < width; i++)
722 *pdata++ = XGetPixel( image, i, row ) ? bg : fg;
724 else /* color -> monochrome */
726 if (swap) for (i = 0; i < width; i++)
727 *pdata-- = ((XGetPixel( image, i, row ) & pixel_mask) == bg) ? 1 : 0;
728 else for (i = 0; i < width; i++)
729 *pdata++ = ((XGetPixel( image, i, row ) & pixel_mask) == bg) ? 1 : 0;
735 /***********************************************************************
736 * BITBLT_StretchImage
738 * Stretch an X image.
739 * FIXME: does not work for full 32-bit coordinates.
741 static void BITBLT_StretchImage( XImage *srcImage, XImage *dstImage,
742 INT widthSrc, INT heightSrc,
743 INT widthDst, INT heightDst,
744 RECT *visRectSrc, RECT *visRectDst,
745 int foreground, int background,
746 unsigned long pixel_mask, WORD mode )
748 int *rowSrc, *rowDst, *pixel;
750 INT xinc, xoff, yinc, ysrc, ydst;
752 BOOL hstretch, vstretch, hswap, vswap;
754 hswap = widthSrc * widthDst < 0;
755 vswap = heightSrc * heightDst < 0;
756 widthSrc = abs(widthSrc);
757 heightSrc = abs(heightSrc);
758 widthDst = abs(widthDst);
759 heightDst = abs(heightDst);
761 if (!(rowSrc = HeapAlloc( GetProcessHeap(), 0,
762 (widthSrc+widthDst)*sizeof(int) ))) return;
763 rowDst = rowSrc + widthSrc;
765 /* When stretching, all modes are the same, and DELETESCANS is faster */
766 if ((widthSrc < widthDst) && (heightSrc < heightDst))
767 mode = STRETCH_DELETESCANS;
769 if (mode == STRETCH_HALFTONE) /* FIXME */
770 mode = STRETCH_DELETESCANS;
772 if (mode != STRETCH_DELETESCANS)
773 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
774 widthDst*sizeof(int) );
776 hstretch = (widthSrc < widthDst);
777 vstretch = (heightSrc < heightDst);
781 xinc = (widthSrc << 16) / widthDst;
782 xoff = ((widthSrc << 16) - (xinc * widthDst)) / 2;
786 xinc = ((int)widthDst << 16) / widthSrc;
787 xoff = ((widthDst << 16) - (xinc * widthSrc)) / 2;
793 yinc = (heightSrc << 16) / heightDst;
794 ydst = visRectDst->top;
797 ysrc = yinc * (heightDst - ydst - 1);
803 for ( ; (ydst < visRectDst->bottom); ysrc += yinc, ydst++)
805 if (((ysrc >> 16) < visRectSrc->top) ||
806 ((ysrc >> 16) >= visRectSrc->bottom)) continue;
808 /* Retrieve a source row */
809 BITBLT_GetRow( srcImage, rowSrc, (ysrc >> 16) - visRectSrc->top,
810 hswap ? widthSrc - visRectSrc->right
812 visRectSrc->right - visRectSrc->left,
813 dstImage->depth, foreground, background, pixel_mask, hswap );
815 /* Stretch or shrink it */
817 BITBLT_StretchRow( rowSrc, rowDst, visRectDst->left,
818 visRectDst->right - visRectDst->left,
820 else BITBLT_ShrinkRow( rowSrc, rowDst,
821 hswap ? widthSrc - visRectSrc->right
823 visRectSrc->right - visRectSrc->left,
826 /* Store the destination row */
827 pixel = rowDst + visRectDst->right - 1;
828 y = ydst - visRectDst->top;
829 for (x = visRectDst->right-visRectDst->left-1; x >= 0; x--)
830 XPutPixel( dstImage, x, y, *pixel-- );
831 if (mode != STRETCH_DELETESCANS)
832 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
833 widthDst*sizeof(int) );
835 /* Make copies of the destination row */
837 pdata = dstImage->data + dstImage->bytes_per_line * y;
838 while (((ysrc + yinc) >> 16 == ysrc >> 16) &&
839 (ydst < visRectDst->bottom-1))
841 memcpy( pdata + dstImage->bytes_per_line, pdata,
842 dstImage->bytes_per_line );
843 pdata += dstImage->bytes_per_line;
851 yinc = (heightDst << 16) / heightSrc;
852 ysrc = visRectSrc->top;
853 ydst = ((heightDst << 16) - (yinc * heightSrc)) / 2;
856 ydst += yinc * (heightSrc - ysrc - 1);
862 for( ; (ysrc < visRectSrc->bottom); ydst += yinc, ysrc++)
864 if (((ydst >> 16) < visRectDst->top) ||
865 ((ydst >> 16) >= visRectDst->bottom)) continue;
867 /* Retrieve a source row */
868 BITBLT_GetRow( srcImage, rowSrc, ysrc - visRectSrc->top,
869 hswap ? widthSrc - visRectSrc->right
871 visRectSrc->right - visRectSrc->left,
872 dstImage->depth, foreground, background, pixel_mask, hswap );
874 /* Stretch or shrink it */
876 BITBLT_StretchRow( rowSrc, rowDst, visRectDst->left,
877 visRectDst->right - visRectDst->left,
879 else BITBLT_ShrinkRow( rowSrc, rowDst,
880 hswap ? widthSrc - visRectSrc->right
882 visRectSrc->right - visRectSrc->left,
885 /* Merge several source rows into the destination */
886 if (mode == STRETCH_DELETESCANS)
888 /* Simply skip the overlapping rows */
889 while (((ydst + yinc) >> 16 == ydst >> 16) &&
890 (ysrc < visRectSrc->bottom-1))
896 else if (((ydst + yinc) >> 16 == ydst >> 16) &&
897 (ysrc < visRectSrc->bottom-1))
898 continue; /* Restart loop for next overlapping row */
900 /* Store the destination row */
901 pixel = rowDst + visRectDst->right - 1;
902 y = (ydst >> 16) - visRectDst->top;
903 for (x = visRectDst->right-visRectDst->left-1; x >= 0; x--)
904 XPutPixel( dstImage, x, y, *pixel-- );
905 if (mode != STRETCH_DELETESCANS)
906 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
907 widthDst*sizeof(int) );
911 HeapFree( GetProcessHeap(), 0, rowSrc );
915 /***********************************************************************
916 * BITBLT_GetSrcAreaStretch
918 * Retrieve an area from the source DC, stretching and mapping all the
919 * pixels to Windows colors.
921 static int BITBLT_GetSrcAreaStretch( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
922 Pixmap pixmap, GC gc,
923 const struct bitblt_coords *src, const struct bitblt_coords *dst )
925 XImage *imageSrc, *imageDst;
926 RECT rectSrc = src->visrect;
927 RECT rectDst = dst->visrect;
930 rectSrc.left -= src->x;
931 rectSrc.right -= src->x;
932 rectSrc.top -= src->y;
933 rectSrc.bottom -= src->y;
934 rectDst.left -= dst->x;
935 rectDst.right -= dst->x;
936 rectDst.top -= dst->y;
937 rectDst.bottom -= dst->y;
940 rectSrc.left -= src->width;
941 rectSrc.right -= src->width;
945 rectDst.left -= dst->width;
946 rectDst.right -= dst->width;
950 rectSrc.top -= src->height;
951 rectSrc.bottom -= src->height;
955 rectDst.top -= dst->height;
956 rectDst.bottom -= dst->height;
959 get_colors(physDevDst, physDevSrc, &fg, &bg);
961 /* FIXME: avoid BadMatch errors */
962 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
963 physDevSrc->dc_rect.left + src->visrect.left,
964 physDevSrc->dc_rect.top + src->visrect.top,
965 src->visrect.right - src->visrect.left,
966 src->visrect.bottom - src->visrect.top,
967 AllPlanes, ZPixmap );
970 imageDst = X11DRV_DIB_CreateXImage( rectDst.right - rectDst.left,
971 rectDst.bottom - rectDst.top, physDevDst->depth );
972 BITBLT_StretchImage( imageSrc, imageDst, src->width, src->height,
973 dst->width, dst->height, &rectSrc, &rectDst,
974 fg, physDevDst->depth != 1 ? bg : physDevSrc->backgroundPixel,
975 image_pixel_mask( physDevSrc ), GetStretchBltMode(physDevDst->dev.hdc) );
977 XPutImage( gdi_display, pixmap, gc, imageDst, 0, 0, 0, 0,
978 rectDst.right - rectDst.left, rectDst.bottom - rectDst.top );
979 XDestroyImage( imageSrc );
980 X11DRV_DIB_DestroyXImage( imageDst );
982 return 0; /* no exposure events generated */
986 /***********************************************************************
989 * Retrieve an area from the source DC, mapping all the
990 * pixels to Windows colors.
992 static int BITBLT_GetSrcArea( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
993 Pixmap pixmap, GC gc, RECT *visRectSrc )
995 XImage *imageSrc, *imageDst;
998 INT width = visRectSrc->right - visRectSrc->left;
999 INT height = visRectSrc->bottom - visRectSrc->top;
1001 BOOL memdc = (GetObjectType(physDevSrc->dev.hdc) == OBJ_MEMDC);
1003 if (physDevSrc->depth == physDevDst->depth)
1006 if (!X11DRV_PALETTE_XPixelToPalette ||
1007 (physDevDst->depth == 1)) /* monochrome -> monochrome */
1009 if (physDevDst->depth == 1)
1011 /* MSDN says if StretchBlt must convert a bitmap from monochrome
1012 to color or vice versa, the foreground and background color of
1013 the device context are used. In fact, it also applies to the
1014 case when it is converted from mono to mono. */
1015 XSetBackground( gdi_display, gc, physDevDst->textPixel );
1016 XSetForeground( gdi_display, gc, physDevDst->backgroundPixel );
1017 XCopyPlane( gdi_display, physDevSrc->drawable, pixmap, gc,
1018 physDevSrc->dc_rect.left + visRectSrc->left,
1019 physDevSrc->dc_rect.top + visRectSrc->top,
1020 width, height, 0, 0, 1);
1023 XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc,
1024 physDevSrc->dc_rect.left + visRectSrc->left,
1025 physDevSrc->dc_rect.top + visRectSrc->top,
1026 width, height, 0, 0);
1029 else /* color -> color */
1032 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
1033 physDevSrc->dc_rect.left + visRectSrc->left,
1034 physDevSrc->dc_rect.top + visRectSrc->top,
1035 width, height, AllPlanes, ZPixmap );
1038 /* Make sure we don't get a BadMatch error */
1039 XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc,
1040 physDevSrc->dc_rect.left + visRectSrc->left,
1041 physDevSrc->dc_rect.top + visRectSrc->top,
1042 width, height, 0, 0);
1044 imageSrc = XGetImage( gdi_display, pixmap, 0, 0, width, height,
1045 AllPlanes, ZPixmap );
1047 for (y = 0; y < height; y++)
1048 for (x = 0; x < width; x++)
1049 XPutPixel(imageSrc, x, y,
1050 X11DRV_PALETTE_XPixelToPalette[XGetPixel(imageSrc, x, y)]);
1051 XPutImage( gdi_display, pixmap, gc, imageSrc,
1052 0, 0, 0, 0, width, height );
1053 XDestroyImage( imageSrc );
1055 wine_tsx11_unlock();
1059 if (physDevSrc->depth == 1) /* monochrome -> color */
1061 get_colors(physDevDst, physDevSrc, &fg, &bg);
1064 if (X11DRV_PALETTE_XPixelToPalette)
1066 XSetBackground( gdi_display, gc,
1067 X11DRV_PALETTE_XPixelToPalette[fg] );
1068 XSetForeground( gdi_display, gc,
1069 X11DRV_PALETTE_XPixelToPalette[bg]);
1073 XSetBackground( gdi_display, gc, fg );
1074 XSetForeground( gdi_display, gc, bg );
1076 XCopyPlane( gdi_display, physDevSrc->drawable, pixmap, gc,
1077 physDevSrc->dc_rect.left + visRectSrc->left,
1078 physDevSrc->dc_rect.top + visRectSrc->top,
1079 width, height, 0, 0, 1 );
1081 wine_tsx11_unlock();
1083 else /* color -> monochrome */
1085 unsigned long pixel_mask;
1087 /* FIXME: avoid BadMatch error */
1088 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
1089 physDevSrc->dc_rect.left + visRectSrc->left,
1090 physDevSrc->dc_rect.top + visRectSrc->top,
1091 width, height, AllPlanes, ZPixmap );
1094 wine_tsx11_unlock();
1097 imageDst = X11DRV_DIB_CreateXImage( width, height, physDevDst->depth );
1100 XDestroyImage(imageSrc);
1101 wine_tsx11_unlock();
1104 pixel_mask = image_pixel_mask( physDevSrc );
1105 for (y = 0; y < height; y++)
1106 for (x = 0; x < width; x++)
1107 XPutPixel(imageDst, x, y,
1108 !((XGetPixel(imageSrc,x,y) ^ physDevSrc->backgroundPixel) & pixel_mask));
1109 XPutImage( gdi_display, pixmap, gc, imageDst,
1110 0, 0, 0, 0, width, height );
1111 XDestroyImage( imageSrc );
1112 X11DRV_DIB_DestroyXImage( imageDst );
1113 wine_tsx11_unlock();
1120 /***********************************************************************
1123 * Retrieve an area from the destination DC, mapping all the
1124 * pixels to Windows colors.
1126 static int BITBLT_GetDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, GC gc, const RECT *visRectDst)
1129 INT width = visRectDst->right - visRectDst->left;
1130 INT height = visRectDst->bottom - visRectDst->top;
1131 BOOL memdc = (GetObjectType( physDev->dev.hdc ) == OBJ_MEMDC);
1135 if (!X11DRV_PALETTE_XPixelToPalette || (physDev->depth == 1) ||
1136 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
1138 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
1139 physDev->dc_rect.left + visRectDst->left, physDev->dc_rect.top + visRectDst->top,
1140 width, height, 0, 0 );
1149 image = XGetImage( gdi_display, physDev->drawable,
1150 physDev->dc_rect.left + visRectDst->left,
1151 physDev->dc_rect.top + visRectDst->top,
1152 width, height, AllPlanes, ZPixmap );
1155 /* Make sure we don't get a BadMatch error */
1156 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
1157 physDev->dc_rect.left + visRectDst->left,
1158 physDev->dc_rect.top + visRectDst->top,
1159 width, height, 0, 0);
1161 image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
1162 AllPlanes, ZPixmap );
1166 for (y = 0; y < height; y++)
1167 for (x = 0; x < width; x++)
1168 XPutPixel( image, x, y,
1169 X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]);
1170 XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height );
1171 XDestroyImage( image );
1175 wine_tsx11_unlock();
1180 /***********************************************************************
1183 * Put an area back into the destination DC, mapping the pixel
1184 * colors to X pixels.
1186 static int BITBLT_PutDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, const RECT *visRectDst)
1189 INT width = visRectDst->right - visRectDst->left;
1190 INT height = visRectDst->bottom - visRectDst->top;
1192 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
1194 if (!X11DRV_PALETTE_PaletteToXPixel || (physDev->depth == 1) ||
1195 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
1197 XCopyArea( gdi_display, pixmap, physDev->drawable, physDev->gc, 0, 0, width, height,
1198 physDev->dc_rect.left + visRectDst->left,
1199 physDev->dc_rect.top + visRectDst->top );
1205 XImage *image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
1206 AllPlanes, ZPixmap );
1207 for (y = 0; y < height; y++)
1208 for (x = 0; x < width; x++)
1210 XPutPixel( image, x, y,
1211 X11DRV_PALETTE_PaletteToXPixel[XGetPixel( image, x, y )]);
1213 XPutImage( gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
1214 physDev->dc_rect.left + visRectDst->left,
1215 physDev->dc_rect.top + visRectDst->top, width, height );
1216 XDestroyImage( image );
1222 /***********************************************************************
1223 * client_side_dib_copy
1225 static BOOL client_side_dib_copy( X11DRV_PDEVICE *physDevSrc, INT xSrc, INT ySrc,
1226 X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst,
1227 INT width, INT height )
1229 DIBSECTION srcDib, dstDib;
1230 BYTE *srcPtr, *dstPtr;
1231 INT srcRowOffset, dstRowOffset;
1235 static RECT unusedRect;
1237 if (GetObjectW(physDevSrc->bitmap->hbitmap, sizeof(srcDib), &srcDib) != sizeof(srcDib))
1239 if (GetObjectW(physDevDst->bitmap->hbitmap, sizeof(dstDib), &dstDib) != sizeof(dstDib))
1242 /* check for oversized values, just like X11DRV_DIB_CopyDIBSection() */
1243 if (xSrc > srcDib.dsBm.bmWidth || ySrc > srcDib.dsBm.bmHeight)
1245 if (xSrc + width > srcDib.dsBm.bmWidth)
1246 width = srcDib.dsBm.bmWidth - xSrc;
1247 if (ySrc + height > srcDib.dsBm.bmHeight)
1248 height = srcDib.dsBm.bmHeight - ySrc;
1250 if (GetRgnBox(physDevDst->region, &unusedRect) == COMPLEXREGION)
1252 /* for simple regions, the clipping was already done by BITBLT_GetVisRectangles */
1253 FIXME("potential optimization: client-side complex region clipping\n");
1256 if (dstDib.dsBm.bmBitsPixel <= 8)
1258 static BOOL fixme_once;
1259 if(!fixme_once++) FIXME("potential optimization: client-side color-index mode DIB copy\n");
1262 if (!(srcDib.dsBmih.biCompression == BI_BITFIELDS &&
1263 dstDib.dsBmih.biCompression == BI_BITFIELDS &&
1264 !memcmp(srcDib.dsBitfields, dstDib.dsBitfields, 3*sizeof(DWORD)))
1265 && !(srcDib.dsBmih.biCompression == BI_RGB &&
1266 dstDib.dsBmih.biCompression == BI_RGB))
1268 FIXME("potential optimization: client-side compressed DIB copy\n");
1271 if (srcDib.dsBm.bmBitsPixel != dstDib.dsBm.bmBitsPixel)
1273 FIXME("potential optimization: pixel format conversion\n");
1276 if (srcDib.dsBmih.biWidth < 0 || dstDib.dsBmih.biWidth < 0)
1278 FIXME("negative widths not yet implemented\n");
1282 switch (dstDib.dsBm.bmBitsPixel)
1295 FIXME("don't know how to work with a depth of %d\n", physDevSrc->depth);
1299 bytesToCopy = width * bytesPerPixel;
1301 if (physDevSrc->bitmap->topdown)
1303 srcPtr = &physDevSrc->bitmap->base[ySrc*srcDib.dsBm.bmWidthBytes + xSrc*bytesPerPixel];
1304 srcRowOffset = srcDib.dsBm.bmWidthBytes;
1308 srcPtr = &physDevSrc->bitmap->base[(srcDib.dsBm.bmHeight-ySrc-1)*srcDib.dsBm.bmWidthBytes
1309 + xSrc*bytesPerPixel];
1310 srcRowOffset = -srcDib.dsBm.bmWidthBytes;
1312 if (physDevDst->bitmap->topdown)
1314 dstPtr = &physDevDst->bitmap->base[yDst*dstDib.dsBm.bmWidthBytes + xDst*bytesPerPixel];
1315 dstRowOffset = dstDib.dsBm.bmWidthBytes;
1319 dstPtr = &physDevDst->bitmap->base[(dstDib.dsBm.bmHeight-yDst-1)*dstDib.dsBm.bmWidthBytes
1320 + xDst*bytesPerPixel];
1321 dstRowOffset = -dstDib.dsBm.bmWidthBytes;
1324 /* Handle overlapping regions on the same DIB */
1325 if (physDevSrc == physDevDst && ySrc < yDst)
1327 srcPtr += srcRowOffset * (height - 1);
1328 srcRowOffset = -srcRowOffset;
1329 dstPtr += dstRowOffset * (height - 1);
1330 dstRowOffset = -dstRowOffset;
1333 for (y = yDst; y < yDst + height; ++y)
1335 memmove(dstPtr, srcPtr, bytesToCopy);
1336 srcPtr += srcRowOffset;
1337 dstPtr += dstRowOffset;
1343 static BOOL same_format(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst)
1345 if (physDevSrc->depth != physDevDst->depth) return FALSE;
1346 if (!physDevSrc->color_shifts && !physDevDst->color_shifts) return TRUE;
1347 if (physDevSrc->color_shifts && physDevDst->color_shifts)
1348 return !memcmp(physDevSrc->color_shifts, physDevDst->color_shifts, sizeof(ColorShifts));
1352 static void execute_rop( X11DRV_PDEVICE *physdev, Pixmap src_pixmap, GC gc,
1353 const RECT *visrect, DWORD rop )
1356 Pixmap result = src_pixmap;
1358 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1359 BOOL use_pat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
1360 BOOL use_dst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
1361 int width = visrect->right - visrect->left;
1362 int height = visrect->bottom - visrect->top;
1364 pixmaps[SRC] = src_pixmap;
1367 pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
1368 wine_tsx11_unlock();
1370 if (use_dst) BITBLT_GetDstArea( physdev, pixmaps[DST], gc, visrect );
1371 null_brush = use_pat && !X11DRV_SetupGCForPatBlt( physdev, gc, TRUE );
1374 for ( ; *opcode; opcode++)
1376 if (OP_DST(*opcode) == DST) result = pixmaps[DST];
1377 XSetFunction( gdi_display, gc, OP_ROP(*opcode) );
1378 switch(OP_SRCDST(*opcode))
1380 case OP_ARGS(DST,TMP):
1381 case OP_ARGS(SRC,TMP):
1383 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
1385 case OP_ARGS(DST,SRC):
1386 case OP_ARGS(SRC,DST):
1387 case OP_ARGS(TMP,SRC):
1388 case OP_ARGS(TMP,DST):
1389 XCopyArea( gdi_display, pixmaps[OP_SRC(*opcode)], pixmaps[OP_DST(*opcode)], gc,
1390 0, 0, width, height, 0, 0 );
1393 case OP_ARGS(PAT,TMP):
1394 if (!pixmaps[TMP] && !null_brush)
1395 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
1397 case OP_ARGS(PAT,DST):
1398 case OP_ARGS(PAT,SRC):
1400 XFillRectangle( gdi_display, pixmaps[OP_DST(*opcode)], gc, 0, 0, width, height );
1404 XSetFunction( gdi_display, physdev->gc, GXcopy );
1405 physdev->exposures += BITBLT_PutDstArea( physdev, result, visrect );
1406 XFreePixmap( gdi_display, pixmaps[DST] );
1407 if (pixmaps[TMP]) XFreePixmap( gdi_display, pixmaps[TMP] );
1408 wine_tsx11_unlock();
1411 /***********************************************************************
1414 BOOL X11DRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
1416 X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
1417 BOOL usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
1418 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1420 if (IsRectEmpty( &dst->visrect )) return TRUE;
1421 if (usePat && !X11DRV_SetupGCForBrush( physDev )) return TRUE;
1423 X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod );
1426 XSetFunction( gdi_display, physDev->gc, OP_ROP(*opcode) );
1428 switch(rop) /* a few special cases */
1430 case BLACKNESS: /* 0x00 */
1431 case WHITENESS: /* 0xff */
1432 if ((physDev->depth != 1) && X11DRV_PALETTE_PaletteToXPixel)
1434 XSetFunction( gdi_display, physDev->gc, GXcopy );
1435 if (rop == BLACKNESS)
1436 XSetForeground( gdi_display, physDev->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
1438 XSetForeground( gdi_display, physDev->gc,
1439 WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
1440 XSetFillStyle( gdi_display, physDev->gc, FillSolid );
1443 case DSTINVERT: /* 0x55 */
1444 if (!(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL)))
1446 /* Xor is much better when we do not have full colormap. */
1447 /* Using white^black ensures that we invert at least black */
1449 unsigned long xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
1450 BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
1451 XSetFunction( gdi_display, physDev->gc, GXxor );
1452 XSetForeground( gdi_display, physDev->gc, xor_pix);
1453 XSetFillStyle( gdi_display, physDev->gc, FillSolid );
1457 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
1458 physDev->dc_rect.left + dst->visrect.left,
1459 physDev->dc_rect.top + dst->visrect.top,
1460 dst->visrect.right - dst->visrect.left,
1461 dst->visrect.bottom - dst->visrect.top );
1462 wine_tsx11_unlock();
1464 X11DRV_UnlockDIBSection( physDev, TRUE );
1469 /***********************************************************************
1472 BOOL X11DRV_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
1473 PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
1475 X11DRV_PDEVICE *physDevDst = get_x11drv_dev( dst_dev );
1476 X11DRV_PDEVICE *physDevSrc = get_x11drv_dev( src_dev ); /* FIXME: check that it's really an x11 dev */
1479 INT sDst, sSrc = DIB_Status_None;
1484 if (IsRectEmpty( &dst->visrect )) return TRUE;
1486 fStretch = (src->width != dst->width) || (src->height != dst->height);
1488 if (physDevDst != physDevSrc)
1489 sSrc = X11DRV_LockDIBSection( physDevSrc, DIB_Status_None );
1491 width = dst->visrect.right - dst->visrect.left;
1492 height = dst->visrect.bottom - dst->visrect.top;
1494 sDst = X11DRV_LockDIBSection( physDevDst, DIB_Status_None );
1495 if (physDevDst == physDevSrc) sSrc = sDst;
1497 /* try client-side DIB copy */
1498 if (!fStretch && rop == SRCCOPY &&
1499 sSrc == DIB_Status_AppMod && sDst == DIB_Status_AppMod &&
1500 same_format(physDevSrc, physDevDst))
1502 if (client_side_dib_copy( physDevSrc, src->visrect.left, src->visrect.top,
1503 physDevDst, dst->visrect.left, dst->visrect.top, width, height ))
1507 X11DRV_CoerceDIBSection( physDevDst, DIB_Status_GdiMod );
1509 opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1511 /* a few optimizations for single-op ROPs */
1512 if (!fStretch && !opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1514 if (same_format(physDevSrc, physDevDst))
1517 XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
1518 wine_tsx11_unlock();
1520 if (physDevSrc != physDevDst)
1522 if (sSrc == DIB_Status_AppMod)
1524 X11DRV_DIB_CopyDIBSection( physDevSrc, physDevDst, src->visrect.left, src->visrect.top,
1525 dst->visrect.left, dst->visrect.top, width, height );
1528 X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod );
1531 XCopyArea( gdi_display, physDevSrc->drawable,
1532 physDevDst->drawable, physDevDst->gc,
1533 physDevSrc->dc_rect.left + src->visrect.left,
1534 physDevSrc->dc_rect.top + src->visrect.top,
1536 physDevDst->dc_rect.left + dst->visrect.left,
1537 physDevDst->dc_rect.top + dst->visrect.top );
1538 physDevDst->exposures++;
1539 wine_tsx11_unlock();
1542 if (physDevSrc->depth == 1)
1546 X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod );
1547 get_colors(physDevDst, physDevSrc, &fg, &bg);
1549 XSetBackground( gdi_display, physDevDst->gc, fg );
1550 XSetForeground( gdi_display, physDevDst->gc, bg );
1551 XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
1552 XCopyPlane( gdi_display, physDevSrc->drawable,
1553 physDevDst->drawable, physDevDst->gc,
1554 physDevSrc->dc_rect.left + src->visrect.left,
1555 physDevSrc->dc_rect.top + src->visrect.top,
1557 physDevDst->dc_rect.left + dst->visrect.left,
1558 physDevDst->dc_rect.top + dst->visrect.top, 1 );
1559 physDevDst->exposures++;
1560 wine_tsx11_unlock();
1566 tmpGC = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
1567 XSetSubwindowMode( gdi_display, tmpGC, IncludeInferiors );
1568 XSetGraphicsExposures( gdi_display, tmpGC, False );
1569 src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, physDevDst->depth );
1570 wine_tsx11_unlock();
1572 if (physDevDst != physDevSrc) X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod );
1574 if(!X11DRV_XRender_GetSrcAreaStretch( physDevSrc, physDevDst, src_pixmap, tmpGC, src, dst ))
1577 BITBLT_GetSrcAreaStretch( physDevSrc, physDevDst, src_pixmap, tmpGC, src, dst );
1579 BITBLT_GetSrcArea( physDevSrc, physDevDst, src_pixmap, tmpGC, &src->visrect );
1582 execute_rop( physDevDst, src_pixmap, tmpGC, &dst->visrect, rop );
1585 XFreePixmap( gdi_display, src_pixmap );
1586 XFreeGC( gdi_display, tmpGC );
1587 wine_tsx11_unlock();
1590 if (physDevDst != physDevSrc) X11DRV_UnlockDIBSection( physDevSrc, FALSE );
1591 X11DRV_UnlockDIBSection( physDevDst, TRUE );
1596 /***********************************************************************
1599 BOOL X11DRV_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst,
1600 PHYSDEV src_dev, struct bitblt_coords *src, BLENDFUNCTION blendfn )
1602 X11DRV_PDEVICE *physDevDst = get_x11drv_dev( dst_dev );
1603 X11DRV_PDEVICE *physDevSrc = get_x11drv_dev( src_dev ); /* FIXME: check that it's really an x11 dev */
1605 if (src->x < 0 || src->y < 0 || src->width < 0 || src->height < 0 ||
1606 src->width > physDevSrc->drawable_rect.right - physDevSrc->drawable_rect.left - src->x ||
1607 src->height > physDevSrc->drawable_rect.bottom - physDevSrc->drawable_rect.top - src->y)
1609 WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src->x, src->y, src->width, src->height );
1610 SetLastError( ERROR_INVALID_PARAMETER );
1613 if (IsRectEmpty( &dst->visrect )) return TRUE;
1615 return XRender_AlphaBlend( physDevDst, dst, physDevSrc, src, blendfn );
1619 static void free_heap_bits( struct gdi_image_bits *bits )
1621 HeapFree( GetProcessHeap(), 0, bits->ptr );
1624 static void free_ximage_bits( struct gdi_image_bits *bits )
1628 wine_tsx11_unlock();
1631 /* store the palette or color mask data in the bitmap info structure */
1632 static void set_color_info( const ColorShifts *color_shifts, BITMAPINFO *info )
1634 DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
1636 switch (info->bmiHeader.biBitCount)
1641 info->bmiHeader.biCompression = BI_RGB;
1642 /* FIXME: set color palette */
1646 info->bmiHeader.biCompression = BI_BITFIELDS;
1647 colors[0] = color_shifts->logicalRed.max << color_shifts->logicalRed.shift;
1648 colors[1] = color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift;
1649 colors[2] = color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift;
1652 info->bmiHeader.biCompression = BI_RGB;
1657 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1658 DWORD copy_image_bits( BITMAPINFO *info, const ColorShifts *color_shifts, XImage *image,
1659 const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
1660 unsigned int zeropad_mask )
1662 #ifdef WORDS_BIGENDIAN
1663 static const int client_byte_order = MSBFirst;
1665 static const int client_byte_order = LSBFirst;
1668 int x, y, height = abs(info->bmiHeader.biHeight);
1669 int width_bytes = image->bytes_per_line;
1671 unsigned char *src, *dst;
1673 switch (info->bmiHeader.biBitCount)
1676 need_byteswap = (image->bitmap_bit_order != MSBFirst);
1679 need_byteswap = (image->byte_order != MSBFirst);
1683 need_byteswap = (image->byte_order != client_byte_order);
1686 need_byteswap = ((image->byte_order == LSBFirst && color_shifts->logicalBlue.shift == 16) ||
1687 (image->byte_order == MSBFirst && color_shifts->logicalBlue.shift == 0));
1690 need_byteswap = FALSE;
1694 if ((need_byteswap && !src_bits->is_copy) || /* need to swap bytes */
1695 (zeropad_mask != ~0u && !src_bits->is_copy) || /* need to clear padding bytes */
1696 (width_bytes & 3) || /* need to fixup line alignment */
1697 (info->bmiHeader.biHeight > 0)) /* need to flip vertically */
1699 width_bytes = (width_bytes + 3) & ~3;
1700 info->bmiHeader.biSizeImage = height * width_bytes;
1701 if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
1702 return ERROR_OUTOFMEMORY;
1703 dst_bits->offset = src_bits->offset;
1704 dst_bits->is_copy = TRUE;
1705 dst_bits->free = free_heap_bits;
1709 /* swap bits in place */
1710 dst_bits->ptr = src_bits->ptr;
1711 dst_bits->offset = src_bits->offset;
1712 dst_bits->is_copy = src_bits->is_copy;
1713 dst_bits->free = NULL;
1714 if (!need_byteswap && zeropad_mask == ~0u) return ERROR_SUCCESS; /* nothing to do */
1717 src = src_bits->ptr;
1718 dst = dst_bits->ptr;
1719 padding_pos = width_bytes/sizeof(unsigned int) - 1;
1721 if (info->bmiHeader.biHeight > 0)
1723 dst += (height - 1) * width_bytes;
1724 width_bytes = -width_bytes;
1729 switch (info->bmiHeader.biBitCount)
1732 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1734 for (x = 0; x < image->bytes_per_line; x++)
1735 dst[x] = bit_swap[src[x]];
1736 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1740 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1742 for (x = 0; x < image->bytes_per_line; x++)
1743 dst[x] = (src[x] << 4) | (src[x] >> 4);
1744 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1748 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1750 for (x = 0; x < info->bmiHeader.biWidth; x++)
1751 ((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] );
1752 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1756 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1758 for (x = 0; x < info->bmiHeader.biWidth; x++)
1760 unsigned char tmp = src[3 * x];
1761 dst[3 * x] = src[3 * x + 2];
1762 dst[3 * x + 1] = src[3 * x + 1];
1763 dst[3 * x + 2] = tmp;
1765 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1769 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1770 for (x = 0; x < info->bmiHeader.biWidth; x++)
1771 ((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] );
1775 else if (src != dst)
1777 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1779 memcpy( dst, src, image->bytes_per_line );
1780 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1783 else /* only need to clear the padding */
1785 for (y = 0; y < height; y++, dst += width_bytes)
1786 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1788 return ERROR_SUCCESS;
1791 /***********************************************************************
1794 DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info, const struct gdi_image_bits *bits,
1795 const RECT *rect, DWORD rop )
1797 X11DRV_PDEVICE *physdev;
1798 X_PHYSBITMAP *bitmap;
1799 DWORD ret = ERROR_SUCCESS;
1802 struct gdi_image_bits dst_bits;
1803 const XPixmapFormatValues *format;
1804 const ColorShifts *color_shifts;
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 ret = copy_image_bits( info, color_shifts, image, bits, &dst_bits, ~0u );
1867 int width = rect->right - rect->left;
1868 int height = rect->bottom - rect->top;
1870 image->data = dst_bits.ptr;
1874 XPutImage( gdi_display, bitmap->pixmap, get_bitmap_gc(depth), image, dst_bits.offset, 0,
1875 rect->left, rect->top, width, height );
1876 wine_tsx11_unlock();
1880 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1882 X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
1884 /* optimization for single-op ROPs */
1885 if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1888 XSetFunction( gdi_display, physdev->gc, OP_ROP(*opcode) );
1889 XPutImage( gdi_display, physdev->drawable, physdev->gc, image, dst_bits.offset, 0,
1890 physdev->dc_rect.left + rect->left, physdev->dc_rect.top + rect->top,
1892 wine_tsx11_unlock();
1900 gc = XCreateGC( gdi_display, physdev->drawable, 0, NULL );
1901 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
1902 XSetGraphicsExposures( gdi_display, gc, False );
1903 src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1904 XPutImage( gdi_display, src_pixmap, gc, image, dst_bits.offset, 0, 0, 0, width, height );
1905 wine_tsx11_unlock();
1907 execute_rop( physdev, src_pixmap, gc, rect, rop );
1910 XFreePixmap( gdi_display, src_pixmap );
1911 XFreeGC( gdi_display, gc );
1912 wine_tsx11_unlock();
1915 X11DRV_UnlockDIBSection( physdev, !ret );
1921 XDestroyImage( image );
1922 wine_tsx11_unlock();
1923 if (dst_bits.free) dst_bits.free( &dst_bits );
1927 info->bmiHeader.biPlanes = 1;
1928 info->bmiHeader.biBitCount = format->bits_per_pixel;
1929 if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1930 set_color_info( physdev->color_shifts, info );
1931 return ERROR_BAD_FORMAT;
1934 /***********************************************************************
1937 DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
1938 struct gdi_image_bits *bits, const RECT *rect )
1940 X11DRV_PDEVICE *physdev;
1941 X_PHYSBITMAP *bitmap;
1942 DWORD ret = ERROR_SUCCESS;
1944 UINT align, x, y, width, height;
1946 struct gdi_image_bits src_bits;
1947 const XPixmapFormatValues *format;
1948 const ColorShifts *color_shifts;
1952 if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
1954 depth = bitmap->pixmap_depth;
1955 color_shifts = &bitmap->pixmap_color_shifts;
1959 physdev = get_x11drv_dev( dev );
1961 depth = physdev->depth;
1962 color_shifts = physdev->color_shifts;
1964 format = pixmap_formats[depth];
1966 /* align start and width to 32-bit boundary */
1967 switch (format->bits_per_pixel)
1969 case 1: align = 32; break;
1970 case 4: align = 8; break;
1971 case 8: align = 4; break;
1972 case 16: align = 2; break;
1973 case 24: align = 4; break;
1974 case 32: align = 1; break;
1976 FIXME( "depth %u bpp %u not supported yet\n", depth, format->bits_per_pixel );
1977 return ERROR_BAD_FORMAT;
1979 src_bits.offset = rect->left & (align - 1);
1980 x = rect->left - src_bits.offset;
1982 width = rect->right - x;
1983 height = rect->bottom - rect->top;
1984 if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
1989 GetObjectW( hbitmap, sizeof(bm), &bm );
1990 width = min( width, bm.bmWidth - x );
1991 height = min( height, bm.bmHeight - y );
1992 X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
1994 image = XGetImage( gdi_display, bitmap->pixmap, x, y, width, height, AllPlanes, ZPixmap );
1995 wine_tsx11_unlock();
1996 X11DRV_DIB_Unlock( bitmap, TRUE );
1998 else if (GetObjectType( dev->hdc ) == OBJ_MEMDC)
2000 X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
2001 width = min( width, physdev->dc_rect.right - physdev->dc_rect.left - x );
2002 height = min( height, physdev->dc_rect.bottom - physdev->dc_rect.top - y );
2004 image = XGetImage( gdi_display, physdev->drawable,
2005 physdev->dc_rect.left + x, physdev->dc_rect.top + y,
2006 width, height, AllPlanes, ZPixmap );
2007 wine_tsx11_unlock();
2008 X11DRV_UnlockDIBSection( physdev, FALSE );
2015 /* use a temporary pixmap to avoid BadMatch errors */
2016 pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
2017 XCopyArea( gdi_display, physdev->drawable, pixmap, get_bitmap_gc(depth),
2018 physdev->dc_rect.left + x, physdev->dc_rect.top + y, width, height, 0, 0 );
2019 image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
2020 XFreePixmap( gdi_display, pixmap );
2021 wine_tsx11_unlock();
2023 if (!image) return ERROR_OUTOFMEMORY;
2025 info->bmiHeader.biSize = sizeof(info->bmiHeader);
2026 info->bmiHeader.biWidth = width;
2027 info->bmiHeader.biHeight = -height;
2028 info->bmiHeader.biPlanes = 1;
2029 info->bmiHeader.biBitCount = image->bits_per_pixel;
2030 info->bmiHeader.biSizeImage = height * image->bytes_per_line;
2031 info->bmiHeader.biXPelsPerMeter = 0;
2032 info->bmiHeader.biYPelsPerMeter = 0;
2033 info->bmiHeader.biClrUsed = 0;
2034 info->bmiHeader.biClrImportant = 0;
2035 set_color_info( color_shifts, info );
2037 src_bits.ptr = image->data;
2038 src_bits.is_copy = TRUE;
2039 ret = copy_image_bits( info, color_shifts, image, &src_bits, bits,
2040 zeropad_masks[(width * image->bits_per_pixel) & 31] );
2042 if (!ret && bits->ptr == image->data)
2044 bits->free = free_ximage_bits;
2048 XDestroyImage( image );
2049 wine_tsx11_unlock();