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 static const unsigned char BITBLT_Opcodes[256][MAX_OP_LEN] =
57 { OP(PAT,DST,GXclear) }, /* 0x00 0 */
58 { OP(PAT,SRC,GXor), OP(SRC,DST,GXnor) }, /* 0x01 ~(D|(P|S)) */
59 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXand) }, /* 0x02 D&~(P|S) */
60 { OP(PAT,SRC,GXnor) }, /* 0x03 ~(P|S) */
61 { OP(PAT,DST,GXnor), OP(SRC,DST,GXand) }, /* 0x04 S&~(D|P) */
62 { OP(PAT,DST,GXnor) }, /* 0x05 ~(D|P) */
63 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnor), }, /* 0x06 ~(P|~(D^S)) */
64 { OP(SRC,DST,GXand), OP(PAT,DST,GXnor) }, /* 0x07 ~(P|(D&S)) */
65 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXand) },/* 0x08 S&D&~P */
66 { OP(SRC,DST,GXxor), OP(PAT,DST,GXnor) }, /* 0x09 ~(P|(D^S)) */
67 { OP(PAT,DST,GXandInverted) }, /* 0x0a D&~P */
68 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXnor) }, /* 0x0b ~(P|(S&~D)) */
69 { OP(PAT,SRC,GXandInverted) }, /* 0x0c S&~P */
70 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXnor) },/* 0x0d ~(P|(D&~S)) */
71 { OP(SRC,DST,GXnor), OP(PAT,DST,GXnor) }, /* 0x0e ~(P|~(D|S)) */
72 { OP(PAT,DST,GXcopyInverted) }, /* 0x0f ~P */
73 { OP(SRC,DST,GXnor), OP(PAT,DST,GXand) }, /* 0x10 P&~(S|D) */
74 { OP(SRC,DST,GXnor) }, /* 0x11 ~(D|S) */
75 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnor) }, /* 0x12 ~(S|~(D^P)) */
76 { OP(PAT,DST,GXand), OP(SRC,DST,GXnor) }, /* 0x13 ~(S|(D&P)) */
77 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnor) }, /* 0x14 ~(D|~(P^S)) */
78 { OP(PAT,SRC,GXand), OP(SRC,DST,GXnor) }, /* 0x15 ~(D|(P&S)) */
79 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
80 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
81 OP(PAT,DST,GXxor) }, /* 0x16 P^S^(D&~(P&S) */
82 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
83 OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
84 OP(TMP,DST,GXequiv) }, /* 0x17 ~S^((S^P)&(S^D))*/
85 { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
86 OP(SRC,DST,GXand) }, /* 0x18 (S^P)&(D^P) */
87 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
88 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x19 ~S^(D&~(P&S)) */
89 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
90 OP(PAT,DST,GXxor) }, /* 0x1a P^(D|(S&P)) */
91 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
92 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x1b ~S^(D&(P^S)) */
93 { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
94 OP(PAT,DST,GXxor) }, /* 0x1c P^(S|(D&P)) */
95 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
96 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x1d ~D^(S&(D^P)) */
97 { OP(SRC,DST,GXor), OP(PAT,DST,GXxor) }, /* 0x1e P^(D|S) */
98 { OP(SRC,DST,GXor), OP(PAT,DST,GXnand) }, /* 0x1f ~(P&(D|S)) */
99 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXand) }, /* 0x20 D&(P&~S) */
100 { OP(PAT,DST,GXxor), OP(SRC,DST,GXnor) }, /* 0x21 ~(S|(D^P)) */
101 { OP(SRC,DST,GXandInverted) }, /* 0x22 ~S&D */
102 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x23 ~(S|(P&~D)) */
103 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
104 OP(SRC,DST,GXand) }, /* 0x24 (S^P)&(S^D) */
105 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand),
106 OP(PAT,DST,GXequiv) }, /* 0x25 ~P^(D&~(S&P)) */
107 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
108 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x26 S^(D|(S&P)) */
109 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXequiv),
110 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x27 S^(D|~(P^S)) */
111 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand) }, /* 0x28 D&(P^S) */
112 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
113 OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
114 OP(PAT,DST,GXequiv) }, /* 0x29 ~P^S^(D|(P&S)) */
115 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand) }, /* 0x2a D&~(P&S) */
116 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
117 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
118 OP(TMP,DST,GXequiv) }, /* 0x2b ~S^((P^S)&(P^D))*/
119 { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
120 OP(SRC,DST,GXxor) }, /* 0x2c S^(P&(S|D)) */
121 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXxor) }, /* 0x2d P^(S|~D) */
122 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
123 OP(PAT,DST,GXxor) }, /* 0x2e P^(S|(D^P)) */
124 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXnand) }, /* 0x2f ~(P&(S|~D)) */
125 { OP(PAT,SRC,GXandReverse) }, /* 0x30 P&~S */
126 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXnor) },/* 0x31 ~(S|(D&~P)) */
127 { OP(SRC,DST,GXor), OP(PAT,DST,GXor),
128 OP(SRC,DST,GXxor) }, /* 0x32 S^(D|P|S) */
129 { OP(SRC,DST,GXcopyInverted) }, /* 0x33 ~S */
130 { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
131 OP(SRC,DST,GXxor) }, /* 0x34 S^(P|(D&S)) */
132 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor),
133 OP(SRC,DST,GXxor) }, /* 0x35 S^(P|~(D^S)) */
134 { OP(PAT,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x36 S^(D|P) */
135 { OP(PAT,DST,GXor), OP(SRC,DST,GXnand) }, /* 0x37 ~(S&(D|P)) */
136 { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
137 OP(PAT,DST,GXxor) }, /* 0x38 P^(S&(D|P)) */
138 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXxor) }, /* 0x39 S^(P|~D) */
139 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
140 OP(SRC,DST,GXxor) }, /* 0x3a S^(P|(D^S)) */
141 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x3b ~(S&(P|~D)) */
142 { OP(PAT,SRC,GXxor) }, /* 0x3c P^S */
143 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
144 OP(SRC,DST,GXxor) }, /* 0x3d S^(P|~(D|S)) */
145 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
146 OP(SRC,DST,GXxor) }, /* 0x3e S^(P|(D&~S)) */
147 { OP(PAT,SRC,GXnand) }, /* 0x3f ~(P&S) */
148 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXand) }, /* 0x40 P&S&~D */
149 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnor) }, /* 0x41 ~(D|(P^S)) */
150 { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
151 OP(SRC,DST,GXand) }, /* 0x42 (S^D)&(P^D) */
152 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
153 OP(SRC,DST,GXequiv) }, /* 0x43 ~S^(P&~(D&S)) */
154 { OP(SRC,DST,GXandReverse) }, /* 0x44 S&~D */
155 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x45 ~(D|(P&~S)) */
156 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
157 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x46 D^(S|(P&D)) */
158 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
159 OP(PAT,DST,GXequiv) }, /* 0x47 ~P^(S&(D^P)) */
160 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand) }, /* 0x48 S&(P^D) */
161 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
162 OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
163 OP(PAT,DST,GXequiv) }, /* 0x49 ~P^D^(S|(P&D)) */
164 { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
165 OP(SRC,DST,GXxor) }, /* 0x4a D^(P&(S|D)) */
166 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXxor) }, /* 0x4b P^(D|~S) */
167 { OP(PAT,DST,GXnand), OP(SRC,DST,GXand) }, /* 0x4c S&~(D&P) */
168 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
169 OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
170 OP(TMP,DST,GXequiv) }, /* 0x4d ~S^((S^P)|(S^D))*/
171 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
172 OP(PAT,DST,GXxor) }, /* 0x4e P^(D|(S^P)) */
173 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXnand) },/* 0x4f ~(P&(D|~S)) */
174 { OP(PAT,DST,GXandReverse) }, /* 0x50 P&~D */
175 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXnor) },/* 0x51 ~(D|(S&~P)) */
176 { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
177 OP(SRC,DST,GXxor) }, /* 0x52 D^(P|(S&D)) */
178 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
179 OP(SRC,DST,GXequiv) }, /* 0x53 ~S^(P&(D^S)) */
180 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXnor) }, /* 0x54 ~(D|~(P|S)) */
181 { OP(PAT,DST,GXinvert) }, /* 0x55 ~D */
182 { OP(PAT,SRC,GXor), OP(SRC,DST,GXxor) }, /* 0x56 D^(P|S) */
183 { OP(PAT,SRC,GXor), OP(SRC,DST,GXnand) }, /* 0x57 ~(D&(P|S)) */
184 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
185 OP(PAT,DST,GXxor) }, /* 0x58 P^(D&(P|S)) */
186 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXxor) }, /* 0x59 D^(P|~S) */
187 { OP(PAT,DST,GXxor) }, /* 0x5a D^P */
188 { OP(DST,SRC,GXnor), OP(PAT,SRC,GXor),
189 OP(SRC,DST,GXxor) }, /* 0x5b D^(P|~(S|D)) */
190 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
191 OP(SRC,DST,GXxor) }, /* 0x5c D^(P|(S^D)) */
192 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x5d ~(D&(P|~S)) */
193 { OP(DST,SRC,GXandInverted), OP(PAT,SRC,GXor),
194 OP(SRC,DST,GXxor) }, /* 0x5e D^(P|(S&~D)) */
195 { OP(PAT,DST,GXnand) }, /* 0x5f ~(D&P) */
196 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand) }, /* 0x60 P&(D^S) */
197 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
198 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
199 OP(TMP,DST,GXequiv) }, /* 0x61 ~D^S^(P|(D&S)) */
200 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
201 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x62 D^(S&(P|D)) */
202 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x63 S^(D|~P) */
203 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
204 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x64 S^(D&(P|S)) */
205 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x65 D^(S|~P) */
206 { OP(SRC,DST,GXxor) }, /* 0x66 S^D */
207 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
208 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x67 S^(D|~(S|P) */
209 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnor),
210 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
211 OP(TMP,DST,GXequiv) }, /* 0x68 ~D^S^(P|~(D|S))*/
212 { OP(SRC,DST,GXxor), OP(PAT,DST,GXequiv) }, /* 0x69 ~P^(D^S) */
213 { OP(PAT,SRC,GXand), OP(SRC,DST,GXxor) }, /* 0x6a D^(P&S) */
214 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
215 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
216 OP(PAT,DST,GXequiv) }, /* 0x6b ~P^S^(D&(P|S)) */
217 { OP(PAT,DST,GXand), OP(SRC,DST,GXxor) }, /* 0x6c S^(D&P) */
218 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
219 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
220 OP(PAT,DST,GXequiv) }, /* 0x6d ~P^D^(S&(P|D)) */
221 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
222 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x6e S^(D&(P|~S)) */
223 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnand) }, /* 0x6f ~(P&~(S^D)) */
224 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand) }, /* 0x70 P&~(D&S) */
225 { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
226 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
227 OP(TMP,DST,GXequiv) }, /* 0x71 ~S^((S^D)&(P^D))*/
228 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
229 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x72 S^(D|(P^S)) */
230 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXnand) },/* 0x73 ~(S&(D|~P)) */
231 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
232 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x74 D^(S|(P^D)) */
233 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXnand) },/* 0x75 ~(D&(S|~P)) */
234 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
235 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x76 S^(D|(P&~S)) */
236 { OP(SRC,DST,GXnand) }, /* 0x77 ~(S&D) */
237 { OP(SRC,DST,GXand), OP(PAT,DST,GXxor) }, /* 0x78 P^(D&S) */
238 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
239 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
240 OP(TMP,DST,GXequiv) }, /* 0x79 ~D^S^(P&(D|S)) */
241 { OP(DST,SRC,GXorInverted), OP(PAT,SRC,GXand),
242 OP(SRC,DST,GXxor) }, /* 0x7a D^(P&(S|~D)) */
243 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnand) }, /* 0x7b ~(S&~(D^P)) */
244 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
245 OP(SRC,DST,GXxor) }, /* 0x7c S^(P&(D|~S)) */
246 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnand) }, /* 0x7d ~(D&~(P^S)) */
247 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
248 OP(SRC,DST,GXor) }, /* 0x7e (S^P)|(S^D) */
249 { OP(PAT,SRC,GXand), OP(SRC,DST,GXnand) }, /* 0x7f ~(D&P&S) */
250 { OP(PAT,SRC,GXand), OP(SRC,DST,GXand) }, /* 0x80 D&P&S */
251 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
252 OP(SRC,DST,GXnor) }, /* 0x81 ~((S^P)|(S^D)) */
253 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXand) }, /* 0x82 D&~(P^S) */
254 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
255 OP(SRC,DST,GXequiv) }, /* 0x83 ~S^(P&(D|~S)) */
256 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXand) }, /* 0x84 S&~(D^P) */
257 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand),
258 OP(PAT,DST,GXequiv) }, /* 0x85 ~P^(D&(S|~P)) */
259 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
260 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
261 OP(TMP,DST,GXxor) }, /* 0x86 D^S^(P&(D|S)) */
262 { OP(SRC,DST,GXand), OP(PAT,DST,GXequiv) }, /* 0x87 ~P^(D&S) */
263 { OP(SRC,DST,GXand) }, /* 0x88 S&D */
264 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
265 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x89 ~S^(D|(P&~S)) */
266 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8a D&(S|~P) */
267 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
268 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x8b ~D^(S|(P^D)) */
269 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8c S&(D|~P) */
270 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
271 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x8d ~S^(D|(P^S)) */
272 { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
273 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
274 OP(TMP,DST,GXxor) }, /* 0x8e S^((S^D)&(P^D))*/
275 { OP(SRC,DST,GXnand), OP(PAT,DST,GXnand) }, /* 0x8f ~(P&~(D&S)) */
276 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXand) }, /* 0x90 P&~(D^S) */
277 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
278 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x91 ~S^(D&(P|~S)) */
279 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
280 OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
281 OP(TMP,DST,GXxor) }, /* 0x92 D^P^(S&(D|P)) */
282 { OP(PAT,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x93 ~S^(P&D) */
283 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
284 OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
285 OP(TMP,DST,GXxor) }, /* 0x94 S^P^(D&(P|S)) */
286 { OP(PAT,SRC,GXand), OP(SRC,DST,GXequiv) }, /* 0x95 ~D^(P&S) */
287 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXxor) }, /* 0x96 D^P^S */
288 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
289 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
290 OP(TMP,DST,GXxor) }, /* 0x97 S^P^(D|~(P|S)) */
291 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
292 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x98 ~S^(D|~(P|S)) */
293 { OP(SRC,DST,GXequiv) }, /* 0x99 ~S^D */
294 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9a D^(P&~S) */
295 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
296 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x9b ~S^(D&(P|S)) */
297 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9c S^(P&~D) */
298 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
299 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x9d ~D^(S&(P|D)) */
300 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
301 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
302 OP(TMP,DST,GXxor) }, /* 0x9e D^S^(P|(D&S)) */
303 { OP(SRC,DST,GXxor), OP(PAT,DST,GXnand) }, /* 0x9f ~(P&(D^S)) */
304 { OP(PAT,DST,GXand) }, /* 0xa0 D&P */
305 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor),
306 OP(PAT,DST,GXequiv) }, /* 0xa1 ~P^(D|(S&~P)) */
307 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXand) }, /* 0xa2 D&(P|~S) */
308 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
309 OP(SRC,DST,GXequiv) }, /* 0xa3 ~D^(P|(S^D)) */
310 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor),
311 OP(PAT,DST,GXequiv) }, /* 0xa4 ~P^(D|~(S|P)) */
312 { OP(PAT,DST,GXequiv) }, /* 0xa5 ~P^D */
313 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXxor) },/* 0xa6 D^(S&~P) */
314 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
315 OP(PAT,DST,GXequiv) }, /* 0xa7 ~P^(D&(S|P)) */
316 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand) }, /* 0xa8 D&(P|S) */
317 { OP(PAT,SRC,GXor), OP(SRC,DST,GXequiv) }, /* 0xa9 ~D^(P|S) */
318 { OP(PAT,DST,GXnoop) }, /* 0xaa D */
319 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor) }, /* 0xab D|~(P|S) */
320 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
321 OP(SRC,DST,GXxor) }, /* 0xac S^(P&(D^S)) */
322 { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
323 OP(SRC,DST,GXequiv) }, /* 0xad ~D^(P|(S&D)) */
324 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor) }, /* 0xae D|(S&~P) */
325 { OP(PAT,DST,GXorInverted) }, /* 0xaf D|~P */
326 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand) }, /* 0xb0 P&(D|~S) */
327 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
328 OP(PAT,DST,GXequiv) }, /* 0xb1 ~P^(D|(S^P)) */
329 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
330 OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
331 OP(TMP,DST,GXxor) }, /* 0xb2 S^((S^P)|(S^D))*/
332 { OP(PAT,DST,GXnand), OP(SRC,DST,GXnand) }, /* 0xb3 ~(S&~(D&P)) */
333 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXxor) }, /* 0xb4 P^(S&~D) */
334 { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
335 OP(SRC,DST,GXequiv) }, /* 0xb5 ~D^(P&(S|D)) */
336 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
337 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
338 OP(TMP,DST,GXxor) }, /* 0xb6 D^P^(S|(D&P)) */
339 { OP(PAT,DST,GXxor), OP(SRC,DST,GXnand) }, /* 0xb7 ~(S&(D^P)) */
340 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
341 OP(PAT,DST,GXxor) }, /* 0xb8 P^(S&(D^P)) */
342 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
343 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0xb9 ~D^(S|(P&D)) */
344 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXor) }, /* 0xba D|(P&~S) */
345 { OP(SRC,DST,GXorInverted) }, /* 0xbb ~S|D */
346 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
347 OP(SRC,DST,GXxor) }, /* 0xbc S^(P&~(D&S)) */
348 { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
349 OP(SRC,DST,GXnand) }, /* 0xbd ~((S^D)&(P^D)) */
350 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor) }, /* 0xbe D|(P^S) */
351 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXor) }, /* 0xbf D|~(P&S) */
352 { OP(PAT,SRC,GXand) }, /* 0xc0 P&S */
353 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
354 OP(SRC,DST,GXequiv) }, /* 0xc1 ~S^(P|(D&~S)) */
355 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
356 OP(SRC,DST,GXequiv) }, /* 0xc2 ~S^(P|~(D|S)) */
357 { OP(PAT,SRC,GXequiv) }, /* 0xc3 ~P^S */
358 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXand) }, /* 0xc4 S&(P|~D) */
359 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
360 OP(SRC,DST,GXequiv) }, /* 0xc5 ~S^(P|(D^S)) */
361 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXxor) },/* 0xc6 S^(D&~P) */
362 { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
363 OP(PAT,DST,GXequiv) }, /* 0xc7 ~P^(S&(D|P)) */
364 { OP(PAT,DST,GXor), OP(SRC,DST,GXand) }, /* 0xc8 S&(D|P) */
365 { OP(PAT,DST,GXor), OP(SRC,DST,GXequiv) }, /* 0xc9 ~S^(P|D) */
366 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXand),
367 OP(SRC,DST,GXxor) }, /* 0xca D^(P&(S^D)) */
368 { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
369 OP(SRC,DST,GXequiv) }, /* 0xcb ~S^(P|(D&S)) */
370 { OP(SRC,DST,GXcopy) }, /* 0xcc S */
371 { OP(PAT,DST,GXnor), OP(SRC,DST,GXor) }, /* 0xcd S|~(D|P) */
372 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXor) }, /* 0xce S|(D&~P) */
373 { OP(PAT,SRC,GXorInverted) }, /* 0xcf S|~P */
374 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXand) }, /* 0xd0 P&(S|~D) */
375 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
376 OP(PAT,DST,GXequiv) }, /* 0xd1 ~P^(S|(D^P)) */
377 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXxor) },/* 0xd2 P^(D&~S) */
378 { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
379 OP(SRC,DST,GXequiv) }, /* 0xd3 ~S^(P&(D|S)) */
380 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
381 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
382 OP(TMP,DST,GXxor) }, /* 0xd4 S^((S^P)&(D^P))*/
383 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXnand) }, /* 0xd5 ~(D&~(P&S)) */
384 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
385 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
386 OP(TMP,DST,GXxor) }, /* 0xd6 S^P^(D|(P&S)) */
387 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnand) }, /* 0xd7 ~(D&(P^S)) */
388 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
389 OP(PAT,DST,GXxor) }, /* 0xd8 P^(D&(S^P)) */
390 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
391 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0xd9 ~S^(D|(P&S)) */
392 { OP(DST,SRC,GXnand), OP(PAT,SRC,GXand),
393 OP(SRC,DST,GXxor) }, /* 0xda D^(P&~(S&D)) */
394 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
395 OP(SRC,DST,GXnand) }, /* 0xdb ~((S^P)&(S^D)) */
396 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXor) }, /* 0xdc S|(P&~D) */
397 { OP(SRC,DST,GXorReverse) }, /* 0xdd S|~D */
398 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor) }, /* 0xde S|(D^P) */
399 { OP(PAT,DST,GXnand), OP(SRC,DST,GXor) }, /* 0xdf S|~(D&P) */
400 { OP(SRC,DST,GXor), OP(PAT,DST,GXand) }, /* 0xe0 P&(D|S) */
401 { OP(SRC,DST,GXor), OP(PAT,DST,GXequiv) }, /* 0xe1 ~P^(D|S) */
402 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
403 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe2 D^(S&(P^D)) */
404 { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
405 OP(PAT,DST,GXequiv) }, /* 0xe3 ~P^(S|(D&P)) */
406 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
407 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe4 S^(D&(P^S)) */
408 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
409 OP(PAT,DST,GXequiv) }, /* 0xe5 ~P^(D|(S&P)) */
410 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
411 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe6 S^(D&~(P&S)) */
412 { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
413 OP(SRC,DST,GXnand) }, /* 0xe7 ~((S^P)&(D^P)) */
414 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
415 OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
416 OP(TMP,DST,GXxor) }, /* 0xe8 S^((S^P)&(S^D))*/
417 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnand),
418 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
419 OP(TMP,DST,GXequiv) }, /* 0xe9 ~D^S^(P&~(S&D))*/
420 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor) }, /* 0xea D|(P&S) */
421 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXor) }, /* 0xeb D|~(P^S) */
422 { OP(PAT,DST,GXand), OP(SRC,DST,GXor) }, /* 0xec S|(D&P) */
423 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXor) }, /* 0xed S|~(D^P) */
424 { OP(SRC,DST,GXor) }, /* 0xee S|D */
425 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXor) }, /* 0xef S|D|~P */
426 { OP(PAT,DST,GXcopy) }, /* 0xf0 P */
427 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor) }, /* 0xf1 P|~(D|S) */
428 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor) }, /* 0xf2 P|(D&~S) */
429 { OP(PAT,SRC,GXorReverse) }, /* 0xf3 P|~S */
430 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXor) }, /* 0xf4 P|(S&~D) */
431 { OP(PAT,DST,GXorReverse) }, /* 0xf5 P|~D */
432 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor) }, /* 0xf6 P|(D^S) */
433 { OP(SRC,DST,GXnand), OP(PAT,DST,GXor) }, /* 0xf7 P|~(S&D) */
434 { OP(SRC,DST,GXand), OP(PAT,DST,GXor) }, /* 0xf8 P|(D&S) */
435 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor) }, /* 0xf9 P|~(D^S) */
436 { OP(PAT,DST,GXor) }, /* 0xfa D|P */
437 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXor) }, /* 0xfb D|P|~S */
438 { OP(PAT,SRC,GXor) }, /* 0xfc P|S */
439 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXor) }, /* 0xfd P|S|~D */
440 { OP(SRC,DST,GXor), OP(PAT,DST,GXor) }, /* 0xfe P|D|S */
441 { OP(PAT,DST,GXset) } /* 0xff 1 */
444 static const unsigned char bit_swap[256] =
446 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
447 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
448 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
449 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
450 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
451 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
452 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
453 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
454 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
455 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
456 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
457 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
458 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
459 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
460 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
461 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
462 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
463 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
464 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
465 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
466 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
467 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
468 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
469 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
470 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
471 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
472 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
473 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
474 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
475 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
476 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
477 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
480 #ifdef WORDS_BIGENDIAN
481 static const unsigned int zeropad_masks[32] =
483 0xffffffff, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
484 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
485 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
486 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe
489 static const unsigned int zeropad_masks[32] =
491 0xffffffff, 0x00000080, 0x000000c0, 0x000000e0, 0x000000f0, 0x000000f8, 0x000000fc, 0x000000fe,
492 0x000000ff, 0x000080ff, 0x0000c0ff, 0x0000e0ff, 0x0000f0ff, 0x0000f8ff, 0x0000fcff, 0x0000feff,
493 0x0000ffff, 0x0080ffff, 0x00c0ffff, 0x00e0ffff, 0x00f0ffff, 0x00f8ffff, 0x00fcffff, 0x00feffff,
494 0x00ffffff, 0x80ffffff, 0xc0ffffff, 0xe0ffffff, 0xf0ffffff, 0xf8ffffff, 0xfcffffff, 0xfeffffff
498 #ifdef BITBLT_TEST /* Opcodes test */
500 static int do_bitop( int s, int d, int rop )
505 case GXclear: res = 0; break;
506 case GXand: res = s & d; break;
507 case GXandReverse: res = s & ~d; break;
508 case GXcopy: res = s; break;
509 case GXandInverted: res = ~s & d; break;
510 case GXnoop: res = d; break;
511 case GXxor: res = s ^ d; break;
512 case GXor: res = s | d; break;
513 case GXnor: res = ~(s | d); break;
514 case GXequiv: res = ~s ^ d; break;
515 case GXinvert: res = ~d; break;
516 case GXorReverse: res = s | ~d; break;
517 case GXcopyInverted: res = ~s; break;
518 case GXorInverted: res = ~s | d; break;
519 case GXnand: res = ~(s & d); break;
520 case GXset: res = 1; break;
527 int rop, i, res, src, dst, pat, tmp, dstUsed;
528 const unsigned char *opcode;
530 for (rop = 0; rop < 256; rop++)
533 for (i = 0; i < 8; i++)
538 for (opcode = BITBLT_Opcodes[rop]; *opcode; opcode++)
542 case OP_ARGS(DST,TMP):
543 tmp = do_bitop( dst, tmp, *opcode & 0xf );
545 case OP_ARGS(DST,SRC):
546 src = do_bitop( dst, src, *opcode & 0xf );
548 case OP_ARGS(SRC,TMP):
549 tmp = do_bitop( src, tmp, *opcode & 0xf );
551 case OP_ARGS(SRC,DST):
552 dst = do_bitop( src, dst, *opcode & 0xf );
555 case OP_ARGS(PAT,DST):
556 dst = do_bitop( pat, dst, *opcode & 0xf );
559 case OP_ARGS(PAT,SRC):
560 src = do_bitop( pat, src, *opcode & 0xf );
562 case OP_ARGS(TMP,DST):
563 dst = do_bitop( tmp, dst, *opcode & 0xf );
566 case OP_ARGS(TMP,SRC):
567 src = do_bitop( tmp, src, *opcode & 0xf );
570 printf( "Invalid opcode %x\n", *opcode );
573 if (!dstUsed) dst = src;
574 if (dst) res |= 1 << i;
576 if (res != rop) printf( "%02x: ERROR, res=%02x\n", rop, res );
582 #endif /* BITBLT_TEST */
585 /***********************************************************************
588 * Retrieve an area from the destination DC, mapping all the
589 * pixels to Windows colors.
591 static int BITBLT_GetDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, GC gc, const RECT *visRectDst)
594 INT width = visRectDst->right - visRectDst->left;
595 INT height = visRectDst->bottom - visRectDst->top;
596 BOOL memdc = (GetObjectType( physDev->dev.hdc ) == OBJ_MEMDC);
600 if (!X11DRV_PALETTE_XPixelToPalette || (physDev->depth == 1) ||
601 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
603 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
604 physDev->dc_rect.left + visRectDst->left, physDev->dc_rect.top + visRectDst->top,
605 width, height, 0, 0 );
614 image = XGetImage( gdi_display, physDev->drawable,
615 physDev->dc_rect.left + visRectDst->left,
616 physDev->dc_rect.top + visRectDst->top,
617 width, height, AllPlanes, ZPixmap );
620 /* Make sure we don't get a BadMatch error */
621 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
622 physDev->dc_rect.left + visRectDst->left,
623 physDev->dc_rect.top + visRectDst->top,
624 width, height, 0, 0);
626 image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
627 AllPlanes, ZPixmap );
631 for (y = 0; y < height; y++)
632 for (x = 0; x < width; x++)
633 XPutPixel( image, x, y,
634 X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]);
635 XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height );
636 XDestroyImage( image );
645 /***********************************************************************
648 * Put an area back into the destination DC, mapping the pixel
649 * colors to X pixels.
651 static int BITBLT_PutDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, const RECT *visRectDst)
654 INT width = visRectDst->right - visRectDst->left;
655 INT height = visRectDst->bottom - visRectDst->top;
657 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
659 if (!X11DRV_PALETTE_PaletteToXPixel || (physDev->depth == 1) ||
660 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
662 XCopyArea( gdi_display, pixmap, physDev->drawable, physDev->gc, 0, 0, width, height,
663 physDev->dc_rect.left + visRectDst->left,
664 physDev->dc_rect.top + visRectDst->top );
670 XImage *image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
671 AllPlanes, ZPixmap );
672 for (y = 0; y < height; y++)
673 for (x = 0; x < width; x++)
675 XPutPixel( image, x, y,
676 X11DRV_PALETTE_PaletteToXPixel[XGetPixel( image, x, y )]);
678 XPutImage( gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
679 physDev->dc_rect.left + visRectDst->left,
680 physDev->dc_rect.top + visRectDst->top, width, height );
681 XDestroyImage( image );
686 static BOOL same_format(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst)
688 if (physDevSrc->depth != physDevDst->depth) return FALSE;
689 if (!physDevSrc->color_shifts && !physDevDst->color_shifts) return TRUE;
690 if (physDevSrc->color_shifts && physDevDst->color_shifts)
691 return !memcmp(physDevSrc->color_shifts, physDevDst->color_shifts, sizeof(ColorShifts));
695 void execute_rop( X11DRV_PDEVICE *physdev, Pixmap src_pixmap, GC gc, const RECT *visrect, DWORD rop )
698 Pixmap result = src_pixmap;
700 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
701 BOOL use_pat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
702 BOOL use_dst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
703 int width = visrect->right - visrect->left;
704 int height = visrect->bottom - visrect->top;
706 pixmaps[SRC] = src_pixmap;
709 pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
712 if (use_dst) BITBLT_GetDstArea( physdev, pixmaps[DST], gc, visrect );
713 null_brush = use_pat && !X11DRV_SetupGCForPatBlt( physdev, gc, TRUE );
716 for ( ; *opcode; opcode++)
718 if (OP_DST(*opcode) == DST) result = pixmaps[DST];
719 XSetFunction( gdi_display, gc, OP_ROP(*opcode) );
720 switch(OP_SRCDST(*opcode))
722 case OP_ARGS(DST,TMP):
723 case OP_ARGS(SRC,TMP):
725 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
727 case OP_ARGS(DST,SRC):
728 case OP_ARGS(SRC,DST):
729 case OP_ARGS(TMP,SRC):
730 case OP_ARGS(TMP,DST):
731 XCopyArea( gdi_display, pixmaps[OP_SRC(*opcode)], pixmaps[OP_DST(*opcode)], gc,
732 0, 0, width, height, 0, 0 );
734 case OP_ARGS(PAT,DST):
735 case OP_ARGS(PAT,SRC):
737 XFillRectangle( gdi_display, pixmaps[OP_DST(*opcode)], gc, 0, 0, width, height );
741 XSetFunction( gdi_display, physdev->gc, GXcopy );
742 physdev->exposures += BITBLT_PutDstArea( physdev, result, visrect );
743 XFreePixmap( gdi_display, pixmaps[DST] );
744 if (pixmaps[TMP]) XFreePixmap( gdi_display, pixmaps[TMP] );
748 /***********************************************************************
751 BOOL X11DRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
753 X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
754 BOOL usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
755 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
757 if (usePat && !X11DRV_SetupGCForBrush( physDev )) return TRUE;
759 X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod );
762 XSetFunction( gdi_display, physDev->gc, OP_ROP(*opcode) );
764 switch(rop) /* a few special cases */
766 case BLACKNESS: /* 0x00 */
767 case WHITENESS: /* 0xff */
768 if ((physDev->depth != 1) && X11DRV_PALETTE_PaletteToXPixel)
770 XSetFunction( gdi_display, physDev->gc, GXcopy );
771 if (rop == BLACKNESS)
772 XSetForeground( gdi_display, physDev->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
774 XSetForeground( gdi_display, physDev->gc,
775 WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
776 XSetFillStyle( gdi_display, physDev->gc, FillSolid );
779 case DSTINVERT: /* 0x55 */
780 if (!(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL)))
782 /* Xor is much better when we do not have full colormap. */
783 /* Using white^black ensures that we invert at least black */
785 unsigned long xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
786 BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
787 XSetFunction( gdi_display, physDev->gc, GXxor );
788 XSetForeground( gdi_display, physDev->gc, xor_pix);
789 XSetFillStyle( gdi_display, physDev->gc, FillSolid );
793 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
794 physDev->dc_rect.left + dst->visrect.left,
795 physDev->dc_rect.top + dst->visrect.top,
796 dst->visrect.right - dst->visrect.left,
797 dst->visrect.bottom - dst->visrect.top );
800 X11DRV_UnlockDIBSection( physDev, TRUE );
805 /***********************************************************************
808 BOOL X11DRV_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
809 PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
811 X11DRV_PDEVICE *physDevDst = get_x11drv_dev( dst_dev );
812 X11DRV_PDEVICE *physDevSrc = get_x11drv_dev( src_dev );
818 if (src_dev->funcs != dst_dev->funcs ||
819 src->width != dst->width || src->height != dst->height || /* no stretching with core X11 */
820 (physDevDst->depth == 1 && physDevSrc->depth != 1) || /* color -> mono done by hand */
821 (X11DRV_PALETTE_XPixelToPalette && physDevSrc->depth != 1)) /* needs palette mapping */
823 dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
824 return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
827 width = dst->visrect.right - dst->visrect.left;
828 height = dst->visrect.bottom - dst->visrect.top;
830 X11DRV_LockDIBSection( physDevDst, DIB_Status_GdiMod );
831 if (physDevDst != physDevSrc) X11DRV_LockDIBSection( physDevSrc, DIB_Status_GdiMod );
833 opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
835 /* a few optimizations for single-op ROPs */
836 if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
838 if (same_format(physDevSrc, physDevDst))
841 XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
842 XCopyArea( gdi_display, physDevSrc->drawable,
843 physDevDst->drawable, physDevDst->gc,
844 physDevSrc->dc_rect.left + src->visrect.left,
845 physDevSrc->dc_rect.top + src->visrect.top,
847 physDevDst->dc_rect.left + dst->visrect.left,
848 physDevDst->dc_rect.top + dst->visrect.top );
849 physDevDst->exposures++;
853 if (physDevSrc->depth == 1)
856 XSetBackground( gdi_display, physDevDst->gc, physDevDst->textPixel );
857 XSetForeground( gdi_display, physDevDst->gc, physDevDst->backgroundPixel );
858 XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
859 XCopyPlane( gdi_display, physDevSrc->drawable,
860 physDevDst->drawable, physDevDst->gc,
861 physDevSrc->dc_rect.left + src->visrect.left,
862 physDevSrc->dc_rect.top + src->visrect.top,
864 physDevDst->dc_rect.left + dst->visrect.left,
865 physDevDst->dc_rect.top + dst->visrect.top, 1 );
866 physDevDst->exposures++;
873 gc = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
874 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
875 XSetGraphicsExposures( gdi_display, gc, False );
877 /* retrieve the source */
879 src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, physDevDst->depth );
880 if (physDevSrc->depth == 1)
882 /* MSDN says if StretchBlt must convert a bitmap from monochrome
883 to color or vice versa, the foreground and background color of
884 the device context are used. In fact, it also applies to the
885 case when it is converted from mono to mono. */
886 if (X11DRV_PALETTE_XPixelToPalette && physDevDst->depth != 1)
888 XSetBackground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[physDevDst->textPixel] );
889 XSetForeground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[physDevDst->backgroundPixel]);
893 XSetBackground( gdi_display, gc, physDevDst->textPixel );
894 XSetForeground( gdi_display, gc, physDevDst->backgroundPixel );
896 XCopyPlane( gdi_display, physDevSrc->drawable, src_pixmap, gc,
897 physDevSrc->dc_rect.left + src->visrect.left,
898 physDevSrc->dc_rect.top + src->visrect.top,
899 width, height, 0, 0, 1 );
901 else /* color -> color */
903 XCopyArea( gdi_display, physDevSrc->drawable, src_pixmap, gc,
904 physDevSrc->dc_rect.left + src->visrect.left,
905 physDevSrc->dc_rect.top + src->visrect.top,
906 width, height, 0, 0 );
910 execute_rop( physDevDst, src_pixmap, gc, &dst->visrect, rop );
913 XFreePixmap( gdi_display, src_pixmap );
914 XFreeGC( gdi_display, gc );
918 if (physDevDst != physDevSrc) X11DRV_UnlockDIBSection( physDevSrc, FALSE );
919 X11DRV_UnlockDIBSection( physDevDst, TRUE );
924 static void free_heap_bits( struct gdi_image_bits *bits )
926 HeapFree( GetProcessHeap(), 0, bits->ptr );
929 static void free_ximage_bits( struct gdi_image_bits *bits )
936 /* store the palette or color mask data in the bitmap info structure */
937 static void set_color_info( PHYSDEV dev, const ColorShifts *color_shifts, BITMAPINFO *info )
939 DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
941 info->bmiHeader.biCompression = BI_RGB;
942 info->bmiHeader.biClrUsed = 0;
944 switch (info->bmiHeader.biBitCount)
949 RGBQUAD *rgb = (RGBQUAD *)colors;
950 PALETTEENTRY palette[256];
953 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
954 count = X11DRV_GetSystemPaletteEntries( dev, 0, info->bmiHeader.biClrUsed, palette );
955 for (i = 0; i < count; i++)
957 rgb[i].rgbRed = palette[i].peRed;
958 rgb[i].rgbGreen = palette[i].peGreen;
959 rgb[i].rgbBlue = palette[i].peBlue;
960 rgb[i].rgbReserved = 0;
962 memset( &rgb[count], 0, (info->bmiHeader.biClrUsed - count) * sizeof(*rgb) );
966 colors[0] = color_shifts->logicalRed.max << color_shifts->logicalRed.shift;
967 colors[1] = color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift;
968 colors[2] = color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift;
969 info->bmiHeader.biCompression = BI_BITFIELDS;
972 colors[0] = color_shifts->logicalRed.max << color_shifts->logicalRed.shift;
973 colors[1] = color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift;
974 colors[2] = color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift;
975 if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff)
976 info->bmiHeader.biCompression = BI_BITFIELDS;
981 /* check if the specified color info is suitable for PutImage */
982 static BOOL matching_color_info( PHYSDEV dev, const ColorShifts *color_shifts, const BITMAPINFO *info )
984 DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
986 switch (info->bmiHeader.biBitCount)
989 if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
990 return !info->bmiHeader.biClrUsed; /* color map not allowed */
994 RGBQUAD *rgb = (RGBQUAD *)colors;
995 PALETTEENTRY palette[256];
998 if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
999 count = X11DRV_GetSystemPaletteEntries( dev, 0, 1 << info->bmiHeader.biBitCount, palette );
1000 if (count != info->bmiHeader.biClrUsed) return FALSE;
1001 for (i = 0; i < count; i++)
1003 if (rgb[i].rgbRed != palette[i].peRed ||
1004 rgb[i].rgbGreen != palette[i].peGreen ||
1005 rgb[i].rgbBlue != palette[i].peBlue) return FALSE;
1010 if (info->bmiHeader.biCompression == BI_BITFIELDS)
1011 return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == colors[0] &&
1012 color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == colors[1] &&
1013 color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == colors[2]);
1014 if (info->bmiHeader.biCompression == BI_RGB)
1015 return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == 0x7c00 &&
1016 color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == 0x03e0 &&
1017 color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == 0x001f);
1020 if (info->bmiHeader.biCompression == BI_BITFIELDS)
1021 return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == colors[0] &&
1022 color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == colors[1] &&
1023 color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == colors[2]);
1026 if (info->bmiHeader.biCompression == BI_RGB)
1027 return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == 0xff0000 &&
1028 color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == 0x00ff00 &&
1029 color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == 0x0000ff);
1035 static inline BOOL is_r8g8b8( int depth, const ColorShifts *color_shifts )
1037 return depth == 24 && color_shifts->logicalBlue.shift == 0 && color_shifts->logicalRed.shift == 16;
1040 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1041 DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
1042 const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
1043 struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
1045 #ifdef WORDS_BIGENDIAN
1046 static const int client_byte_order = MSBFirst;
1048 static const int client_byte_order = LSBFirst;
1051 int x, y, height = coords->visrect.bottom - coords->visrect.top;
1052 int width_bytes = image->bytes_per_line;
1054 unsigned char *src, *dst;
1056 switch (info->bmiHeader.biBitCount)
1059 need_byteswap = (image->bitmap_bit_order != MSBFirst);
1062 need_byteswap = (image->byte_order != MSBFirst);
1066 need_byteswap = (image->byte_order != client_byte_order);
1069 need_byteswap = (image->byte_order == MSBFirst) ^ !is_r8g8b8;
1072 need_byteswap = FALSE;
1076 src = src_bits->ptr;
1077 if (info->bmiHeader.biHeight > 0)
1078 src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes;
1080 src += coords->visrect.top * width_bytes;
1082 if ((need_byteswap && !src_bits->is_copy) || /* need to swap bytes */
1083 (zeropad_mask != ~0u && !src_bits->is_copy) || /* need to clear padding bytes */
1084 (mapping && !src_bits->is_copy) || /* need to remap pixels */
1085 (width_bytes & 3) || /* need to fixup line alignment */
1086 (info->bmiHeader.biHeight > 0)) /* need to flip vertically */
1088 width_bytes = (width_bytes + 3) & ~3;
1089 info->bmiHeader.biSizeImage = height * width_bytes;
1090 if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
1091 return ERROR_OUTOFMEMORY;
1092 dst_bits->is_copy = TRUE;
1093 dst_bits->free = free_heap_bits;
1097 /* swap bits in place */
1098 dst_bits->ptr = src;
1099 dst_bits->is_copy = src_bits->is_copy;
1100 dst_bits->free = NULL;
1101 if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS; /* nothing to do */
1104 dst = dst_bits->ptr;
1105 padding_pos = width_bytes/sizeof(unsigned int) - 1;
1107 if (info->bmiHeader.biHeight > 0)
1109 dst += (height - 1) * width_bytes;
1110 width_bytes = -width_bytes;
1113 if (need_byteswap || mapping)
1115 switch (info->bmiHeader.biBitCount)
1118 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1120 for (x = 0; x < image->bytes_per_line; x++)
1121 dst[x] = bit_swap[src[x]];
1122 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1126 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1129 for (x = 0; x < image->bytes_per_line; x++)
1130 dst[x] = (mapping[src[x] & 0x0f] << 4) | mapping[src[x] >> 4];
1132 for (x = 0; x < image->bytes_per_line; x++)
1133 dst[x] = (src[x] << 4) | (src[x] >> 4);
1134 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1138 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1140 for (x = 0; x < image->bytes_per_line; x++)
1141 dst[x] = mapping[src[x]];
1142 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1146 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1148 for (x = 0; x < info->bmiHeader.biWidth; x++)
1149 ((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] );
1150 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1154 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1156 for (x = 0; x < info->bmiHeader.biWidth; x++)
1158 unsigned char tmp = src[3 * x];
1159 dst[3 * x] = src[3 * x + 2];
1160 dst[3 * x + 1] = src[3 * x + 1];
1161 dst[3 * x + 2] = tmp;
1163 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1167 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1168 for (x = 0; x < info->bmiHeader.biWidth; x++)
1169 ((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] );
1173 else if (src != dst)
1175 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1177 memcpy( dst, src, image->bytes_per_line );
1178 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1181 else /* only need to clear the padding */
1183 for (y = 0; y < height; y++, dst += width_bytes)
1184 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1186 return ERROR_SUCCESS;
1189 /***********************************************************************
1192 DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
1193 const struct gdi_image_bits *bits, struct bitblt_coords *src,
1194 struct bitblt_coords *dst, DWORD rop )
1196 X11DRV_PDEVICE *physdev;
1197 X_PHYSBITMAP *bitmap;
1201 struct gdi_image_bits dst_bits;
1202 const XPixmapFormatValues *format;
1203 const ColorShifts *color_shifts;
1204 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1205 const int *mapping = NULL;
1209 if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
1211 depth = bitmap->depth;
1212 color_shifts = &bitmap->color_shifts;
1216 physdev = get_x11drv_dev( dev );
1218 depth = physdev->depth;
1219 color_shifts = physdev->color_shifts;
1221 format = pixmap_formats[depth];
1223 if (info->bmiHeader.biPlanes != 1) goto update_format;
1224 if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1225 /* FIXME: could try to handle 1-bpp using XCopyPlane */
1226 if (!matching_color_info( dev, color_shifts, info )) goto update_format;
1227 if (!bits) return ERROR_SUCCESS; /* just querying the format */
1228 if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
1231 image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0, NULL,
1232 info->bmiHeader.biWidth, src->visrect.bottom - src->visrect.top, 32, 0 );
1233 wine_tsx11_unlock();
1234 if (!image) return ERROR_OUTOFMEMORY;
1236 if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1238 if (bitmap || (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST)))
1239 mapping = X11DRV_PALETTE_PaletteToXPixel;
1242 ret = copy_image_bits( info, is_r8g8b8(depth,color_shifts), image, bits, &dst_bits, src, mapping, ~0u );
1246 int width = dst->visrect.right - dst->visrect.left;
1247 int height = dst->visrect.bottom - dst->visrect.top;
1249 image->data = dst_bits.ptr;
1250 /* hack: make sure the bits are readable if we are reading from a DIB section */
1251 /* to be removed once we get rid of DIB access protections */
1252 if (!dst_bits.is_copy) IsBadReadPtr( dst_bits.ptr, height * image->bytes_per_line );
1256 RGNDATA *clip_data = NULL;
1259 if (clip) clip_data = X11DRV_GetRegionData( clip, 0 );
1260 X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
1263 gc = XCreateGC( gdi_display, bitmap->pixmap, 0, NULL );
1264 XSetGraphicsExposures( gdi_display, gc, False );
1265 if (clip_data) XSetClipRectangles( gdi_display, gc, 0, 0, (XRectangle *)clip_data->Buffer,
1266 clip_data->rdh.nCount, YXBanded );
1267 XPutImage( gdi_display, bitmap->pixmap, gc, image, src->visrect.left, 0,
1268 dst->visrect.left, dst->visrect.top, width, height );
1269 XFreeGC( gdi_display, gc );
1270 wine_tsx11_unlock();
1272 X11DRV_DIB_Unlock( bitmap, TRUE );
1273 HeapFree( GetProcessHeap(), 0, clip_data );
1277 RGNDATA *saved_region = NULL;
1279 if (clip) saved_region = add_extra_clipping_region( physdev, clip );
1280 X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
1282 /* optimization for single-op ROPs */
1283 if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1286 XSetFunction( gdi_display, physdev->gc, OP_ROP(*opcode) );
1287 XPutImage( gdi_display, physdev->drawable, physdev->gc, image, src->visrect.left, 0,
1288 physdev->dc_rect.left + dst->visrect.left,
1289 physdev->dc_rect.top + dst->visrect.top, width, height );
1290 wine_tsx11_unlock();
1298 gc = XCreateGC( gdi_display, physdev->drawable, 0, NULL );
1299 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
1300 XSetGraphicsExposures( gdi_display, gc, False );
1301 src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1302 XPutImage( gdi_display, src_pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
1303 wine_tsx11_unlock();
1305 execute_rop( physdev, src_pixmap, gc, &dst->visrect, rop );
1308 XFreePixmap( gdi_display, src_pixmap );
1309 XFreeGC( gdi_display, gc );
1310 wine_tsx11_unlock();
1313 X11DRV_UnlockDIBSection( physdev, !ret );
1314 restore_clipping_region( physdev, saved_region );
1320 XDestroyImage( image );
1321 wine_tsx11_unlock();
1322 if (dst_bits.free) dst_bits.free( &dst_bits );
1326 info->bmiHeader.biPlanes = 1;
1327 info->bmiHeader.biBitCount = format->bits_per_pixel;
1328 if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1329 set_color_info( dev, color_shifts, info );
1330 return ERROR_BAD_FORMAT;
1333 /***********************************************************************
1336 DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
1337 struct gdi_image_bits *bits, struct bitblt_coords *src )
1339 X11DRV_PDEVICE *physdev;
1340 X_PHYSBITMAP *bitmap;
1341 DWORD ret = ERROR_SUCCESS;
1343 UINT align, x, y, width, height;
1345 struct gdi_image_bits src_bits;
1346 const XPixmapFormatValues *format;
1347 const ColorShifts *color_shifts;
1348 const int *mapping = NULL;
1352 if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
1354 depth = bitmap->depth;
1355 color_shifts = &bitmap->color_shifts;
1359 physdev = get_x11drv_dev( dev );
1361 depth = physdev->depth;
1362 color_shifts = physdev->color_shifts;
1364 format = pixmap_formats[depth];
1366 /* align start and width to 32-bit boundary */
1367 switch (format->bits_per_pixel)
1369 case 1: align = 32; break;
1370 case 4: align = 8; mapping = X11DRV_PALETTE_XPixelToPalette; break;
1371 case 8: align = 4; mapping = X11DRV_PALETTE_XPixelToPalette; break;
1372 case 16: align = 2; break;
1373 case 24: align = 4; break;
1374 case 32: align = 1; break;
1376 FIXME( "depth %u bpp %u not supported yet\n", depth, format->bits_per_pixel );
1377 return ERROR_BAD_FORMAT;
1380 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1381 info->bmiHeader.biPlanes = 1;
1382 info->bmiHeader.biBitCount = format->bits_per_pixel;
1383 info->bmiHeader.biXPelsPerMeter = 0;
1384 info->bmiHeader.biYPelsPerMeter = 0;
1385 info->bmiHeader.biClrImportant = 0;
1386 set_color_info( dev, color_shifts, info );
1388 if (!bits) return ERROR_SUCCESS; /* just querying the color information */
1390 x = src->visrect.left & ~(align - 1);
1391 y = src->visrect.top;
1392 width = src->visrect.right - x;
1393 height = src->visrect.bottom - src->visrect.top;
1394 if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
1395 /* make the source rectangle relative to the returned bits */
1398 OffsetRect( &src->visrect, -x, -y );
1403 GetObjectW( hbitmap, sizeof(bm), &bm );
1404 width = min( width, bm.bmWidth - x );
1405 height = min( height, bm.bmHeight - y );
1406 X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
1408 image = XGetImage( gdi_display, bitmap->pixmap, x, y, width, height, AllPlanes, ZPixmap );
1409 wine_tsx11_unlock();
1410 X11DRV_DIB_Unlock( bitmap, TRUE );
1412 else if (GetObjectType( dev->hdc ) == OBJ_MEMDC)
1414 X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
1415 width = min( width, physdev->dc_rect.right - physdev->dc_rect.left - x );
1416 height = min( height, physdev->dc_rect.bottom - physdev->dc_rect.top - y );
1418 image = XGetImage( gdi_display, physdev->drawable,
1419 physdev->dc_rect.left + x, physdev->dc_rect.top + y,
1420 width, height, AllPlanes, ZPixmap );
1421 wine_tsx11_unlock();
1422 X11DRV_UnlockDIBSection( physdev, FALSE );
1429 /* use a temporary pixmap to avoid BadMatch errors */
1430 pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1431 XCopyArea( gdi_display, physdev->drawable, pixmap, get_bitmap_gc(depth),
1432 physdev->dc_rect.left + x, physdev->dc_rect.top + y, width, height, 0, 0 );
1433 image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1434 XFreePixmap( gdi_display, pixmap );
1435 wine_tsx11_unlock();
1437 if (!image) return ERROR_OUTOFMEMORY;
1439 info->bmiHeader.biWidth = width;
1440 info->bmiHeader.biHeight = -height;
1441 info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1443 src_bits.ptr = image->data;
1444 src_bits.is_copy = TRUE;
1445 ret = copy_image_bits( info, is_r8g8b8(depth,color_shifts), image, &src_bits, bits, src, mapping,
1446 zeropad_masks[(width * image->bits_per_pixel) & 31] );
1448 if (!ret && bits->ptr == image->data)
1450 bits->free = free_ximage_bits;
1454 XDestroyImage( image );
1455 wine_tsx11_unlock();