2 * GDI bit-blit operations
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
39 #define DST 0 /* Destination drawable */
40 #define SRC 1 /* Source drawable */
41 #define TMP 2 /* Temporary drawable */
42 #define PAT 3 /* Pattern (brush) in destination DC */
44 #define OP(src,dst,rop) (OP_ARGS(src,dst) << 4 | (rop))
45 #define OP_ARGS(src,dst) (((src) << 2) | (dst))
47 #define OP_SRC(opcode) ((opcode) >> 6)
48 #define OP_DST(opcode) (((opcode) >> 4) & 3)
49 #define OP_SRCDST(opcode) ((opcode) >> 4)
50 #define OP_ROP(opcode) ((opcode) & 0x0f)
52 #define MAX_OP_LEN 6 /* Longest opcode + 1 for the terminating 0 */
54 #define SWAP_INT32(i1,i2) \
55 do { INT __t = *(i1); *(i1) = *(i2); *(i2) = __t; } while(0)
57 static const unsigned char BITBLT_Opcodes[256][MAX_OP_LEN] =
59 { OP(PAT,DST,GXclear) }, /* 0x00 0 */
60 { OP(PAT,SRC,GXor), OP(SRC,DST,GXnor) }, /* 0x01 ~(D|(P|S)) */
61 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXand) }, /* 0x02 D&~(P|S) */
62 { OP(PAT,SRC,GXnor) }, /* 0x03 ~(P|S) */
63 { OP(PAT,DST,GXnor), OP(SRC,DST,GXand) }, /* 0x04 S&~(D|P) */
64 { OP(PAT,DST,GXnor) }, /* 0x05 ~(D|P) */
65 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnor), }, /* 0x06 ~(P|~(D^S)) */
66 { OP(SRC,DST,GXand), OP(PAT,DST,GXnor) }, /* 0x07 ~(P|(D&S)) */
67 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXand) },/* 0x08 S&D&~P */
68 { OP(SRC,DST,GXxor), OP(PAT,DST,GXnor) }, /* 0x09 ~(P|(D^S)) */
69 { OP(PAT,DST,GXandInverted) }, /* 0x0a D&~P */
70 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXnor) }, /* 0x0b ~(P|(S&~D)) */
71 { OP(PAT,SRC,GXandInverted) }, /* 0x0c S&~P */
72 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXnor) },/* 0x0d ~(P|(D&~S)) */
73 { OP(SRC,DST,GXnor), OP(PAT,DST,GXnor) }, /* 0x0e ~(P|~(D|S)) */
74 { OP(PAT,DST,GXcopyInverted) }, /* 0x0f ~P */
75 { OP(SRC,DST,GXnor), OP(PAT,DST,GXand) }, /* 0x10 P&~(S|D) */
76 { OP(SRC,DST,GXnor) }, /* 0x11 ~(D|S) */
77 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnor) }, /* 0x12 ~(S|~(D^P)) */
78 { OP(PAT,DST,GXand), OP(SRC,DST,GXnor) }, /* 0x13 ~(S|(D&P)) */
79 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnor) }, /* 0x14 ~(D|~(P^S)) */
80 { OP(PAT,SRC,GXand), OP(SRC,DST,GXnor) }, /* 0x15 ~(D|(P&S)) */
81 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXnand),
82 OP(TMP,DST,GXand), OP(SRC,DST,GXxor),
83 OP(PAT,DST,GXxor) }, /* 0x16 P^S^(D&~(P&S) */
84 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
85 OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
86 OP(TMP,DST,GXequiv) }, /* 0x17 ~S^((S^P)&(S^D))*/
87 { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
88 OP(SRC,DST,GXand) }, /* 0x18 (S^P)&(D^P) */
89 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXnand),
90 OP(TMP,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x19 ~S^(D&~(P&S)) */
91 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
92 OP(PAT,DST,GXxor) }, /* 0x1a P^(D|(S&P)) */
93 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXxor),
94 OP(TMP,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x1b ~S^(D&(P^S)) */
95 { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
96 OP(PAT,DST,GXxor) }, /* 0x1c P^(S|(D&P)) */
97 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
98 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x1d ~D^(S&(D^P)) */
99 { OP(SRC,DST,GXor), OP(PAT,DST,GXxor) }, /* 0x1e P^(D|S) */
100 { OP(SRC,DST,GXor), OP(PAT,DST,GXnand) }, /* 0x1f ~(P&(D|S)) */
101 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXand) }, /* 0x20 D&(P&~S) */
102 { OP(PAT,DST,GXxor), OP(SRC,DST,GXnor) }, /* 0x21 ~(S|(D^P)) */
103 { OP(SRC,DST,GXandInverted) }, /* 0x22 ~S&D */
104 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x23 ~(S|(P&~D)) */
105 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
106 OP(SRC,DST,GXand) }, /* 0x24 (S^P)&(S^D) */
107 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand),
108 OP(PAT,DST,GXequiv) }, /* 0x25 ~P^(D&~(S&P)) */
109 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXand),
110 OP(TMP,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x26 S^(D|(S&P)) */
111 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXequiv),
112 OP(TMP,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x27 S^(D|~(P^S)) */
113 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand) }, /* 0x28 D&(P^S) */
114 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXand),
115 OP(TMP,DST,GXor), OP(SRC,DST,GXxor),
116 OP(PAT,DST,GXequiv) }, /* 0x29 ~P^S^(D|(P&S)) */
117 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand) }, /* 0x2a D&~(P&S) */
118 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
119 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
120 OP(TMP,DST,GXequiv) }, /* 0x2b ~S^((P^S)&(P^D))*/
121 { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
122 OP(SRC,DST,GXxor) }, /* 0x2c S^(P&(S|D)) */
123 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXxor) }, /* 0x2d P^(S|~D) */
124 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
125 OP(PAT,DST,GXxor) }, /* 0x2e P^(S|(D^P)) */
126 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXnand) }, /* 0x2f ~(P&(S|~D)) */
127 { OP(PAT,SRC,GXandReverse) }, /* 0x30 P&~S */
128 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXnor) },/* 0x31 ~(S|(D&~P)) */
129 { OP(SRC,DST,GXor), OP(PAT,DST,GXor),
130 OP(SRC,DST,GXxor) }, /* 0x32 S^(D|P|S) */
131 { OP(SRC,DST,GXcopyInverted) }, /* 0x33 ~S */
132 { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
133 OP(SRC,DST,GXxor) }, /* 0x34 S^(P|(D&S)) */
134 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor),
135 OP(SRC,DST,GXxor) }, /* 0x35 S^(P|~(D^S)) */
136 { OP(PAT,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x36 S^(D|P) */
137 { OP(PAT,DST,GXor), OP(SRC,DST,GXnand) }, /* 0x37 ~(S&(D|P)) */
138 { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
139 OP(PAT,DST,GXxor) }, /* 0x38 P^(S&(D|P)) */
140 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXxor) }, /* 0x39 S^(P|~D) */
141 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
142 OP(SRC,DST,GXxor) }, /* 0x3a S^(P|(D^S)) */
143 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x3b ~(S&(P|~D)) */
144 { OP(PAT,SRC,GXxor) }, /* 0x3c P^S */
145 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
146 OP(SRC,DST,GXxor) }, /* 0x3d S^(P|~(D|S)) */
147 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
148 OP(SRC,DST,GXxor) }, /* 0x3e S^(P|(D&~S)) */
149 { OP(PAT,SRC,GXnand) }, /* 0x3f ~(P&S) */
150 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXand) }, /* 0x40 P&S&~D */
151 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnor) }, /* 0x41 ~(D|(P^S)) */
152 { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
153 OP(SRC,DST,GXand) }, /* 0x42 (S^D)&(P^D) */
154 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
155 OP(SRC,DST,GXequiv) }, /* 0x43 ~S^(P&~(D&S)) */
156 { OP(SRC,DST,GXandReverse) }, /* 0x44 S&~D */
157 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x45 ~(D|(P&~S)) */
158 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
159 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x46 D^(S|(P&D)) */
160 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
161 OP(PAT,DST,GXequiv) }, /* 0x47 ~P^(S&(D^P)) */
162 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand) }, /* 0x48 S&(P^D) */
163 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
164 OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
165 OP(PAT,DST,GXequiv) }, /* 0x49 ~P^D^(S|(P&D)) */
166 { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
167 OP(SRC,DST,GXxor) }, /* 0x4a D^(P&(S|D)) */
168 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXxor) }, /* 0x4b P^(D|~S) */
169 { OP(PAT,DST,GXnand), OP(SRC,DST,GXand) }, /* 0x4c S&~(D&P) */
170 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
171 OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
172 OP(TMP,DST,GXequiv) }, /* 0x4d ~S^((S^P)|(S^D))*/
173 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
174 OP(PAT,DST,GXxor) }, /* 0x4e P^(D|(S^P)) */
175 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXnand) },/* 0x4f ~(P&(D|~S)) */
176 { OP(PAT,DST,GXandReverse) }, /* 0x50 P&~D */
177 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXnor) },/* 0x51 ~(D|(S&~P)) */
178 { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
179 OP(SRC,DST,GXxor) }, /* 0x52 D^(P|(S&D)) */
180 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
181 OP(SRC,DST,GXequiv) }, /* 0x53 ~S^(P&(D^S)) */
182 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXnor) }, /* 0x54 ~(D|~(P|S)) */
183 { OP(PAT,DST,GXinvert) }, /* 0x55 ~D */
184 { OP(PAT,SRC,GXor), OP(SRC,DST,GXxor) }, /* 0x56 D^(P|S) */
185 { OP(PAT,SRC,GXor), OP(SRC,DST,GXnand) }, /* 0x57 ~(D&(P|S)) */
186 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
187 OP(PAT,DST,GXxor) }, /* 0x58 P^(D&(P|S)) */
188 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXxor) }, /* 0x59 D^(P|~S) */
189 { OP(PAT,DST,GXxor) }, /* 0x5a D^P */
190 { OP(DST,SRC,GXnor), OP(PAT,SRC,GXor),
191 OP(SRC,DST,GXxor) }, /* 0x5b D^(P|~(S|D)) */
192 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
193 OP(SRC,DST,GXxor) }, /* 0x5c D^(P|(S^D)) */
194 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x5d ~(D&(P|~S)) */
195 { OP(DST,SRC,GXandInverted), OP(PAT,SRC,GXor),
196 OP(SRC,DST,GXxor) }, /* 0x5e D^(P|(S&~D)) */
197 { OP(PAT,DST,GXnand) }, /* 0x5f ~(D&P) */
198 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand) }, /* 0x60 P&(D^S) */
199 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
200 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
201 OP(TMP,DST,GXequiv) }, /* 0x61 ~D^S^(P|(D&S)) */
202 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
203 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x62 D^(S&(P|D)) */
204 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x63 S^(D|~P) */
205 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
206 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x64 S^(D&(P|S)) */
207 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x65 D^(S|~P) */
208 { OP(SRC,DST,GXxor) }, /* 0x66 S^D */
209 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
210 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x67 S^(D|~(S|P) */
211 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnor),
212 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
213 OP(TMP,DST,GXequiv) }, /* 0x68 ~D^S^(P|~(D|S))*/
214 { OP(SRC,DST,GXxor), OP(PAT,DST,GXequiv) }, /* 0x69 ~P^(D^S) */
215 { OP(PAT,SRC,GXand), OP(SRC,DST,GXxor) }, /* 0x6a D^(P&S) */
216 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
217 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
218 OP(PAT,DST,GXequiv) }, /* 0x6b ~P^S^(D&(P|S)) */
219 { OP(PAT,DST,GXand), OP(SRC,DST,GXxor) }, /* 0x6c S^(D&P) */
220 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
221 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
222 OP(PAT,DST,GXequiv) }, /* 0x6d ~P^D^(S&(P|D)) */
223 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
224 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x6e S^(D&(P|~S)) */
225 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnand) }, /* 0x6f ~(P&~(S^D)) */
226 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand) }, /* 0x70 P&~(D&S) */
227 { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
228 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
229 OP(TMP,DST,GXequiv) }, /* 0x71 ~S^((S^D)&(P^D))*/
230 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
231 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x72 S^(D|(P^S)) */
232 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXnand) },/* 0x73 ~(S&(D|~P)) */
233 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
234 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x74 D^(S|(P^D)) */
235 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXnand) },/* 0x75 ~(D&(S|~P)) */
236 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
237 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x76 S^(D|(P&~S)) */
238 { OP(SRC,DST,GXnand) }, /* 0x77 ~(S&D) */
239 { OP(SRC,DST,GXand), OP(PAT,DST,GXxor) }, /* 0x78 P^(D&S) */
240 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
241 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
242 OP(TMP,DST,GXequiv) }, /* 0x79 ~D^S^(P&(D|S)) */
243 { OP(DST,SRC,GXorInverted), OP(PAT,SRC,GXand),
244 OP(SRC,DST,GXxor) }, /* 0x7a D^(P&(S|~D)) */
245 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnand) }, /* 0x7b ~(S&~(D^P)) */
246 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
247 OP(SRC,DST,GXxor) }, /* 0x7c S^(P&(D|~S)) */
248 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnand) }, /* 0x7d ~(D&~(P^S)) */
249 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
250 OP(SRC,DST,GXor) }, /* 0x7e (S^P)|(S^D) */
251 { OP(PAT,SRC,GXand), OP(SRC,DST,GXnand) }, /* 0x7f ~(D&P&S) */
252 { OP(PAT,SRC,GXand), OP(SRC,DST,GXand) }, /* 0x80 D&P&S */
253 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
254 OP(SRC,DST,GXnor) }, /* 0x81 ~((S^P)|(S^D)) */
255 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXand) }, /* 0x82 D&~(P^S) */
256 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
257 OP(SRC,DST,GXequiv) }, /* 0x83 ~S^(P&(D|~S)) */
258 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXand) }, /* 0x84 S&~(D^P) */
259 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand),
260 OP(PAT,DST,GXequiv) }, /* 0x85 ~P^(D&(S|~P)) */
261 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
262 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
263 OP(TMP,DST,GXxor) }, /* 0x86 D^S^(P&(D|S)) */
264 { OP(SRC,DST,GXand), OP(PAT,DST,GXequiv) }, /* 0x87 ~P^(D&S) */
265 { OP(SRC,DST,GXand) }, /* 0x88 S&D */
266 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
267 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x89 ~S^(D|(P&~S)) */
268 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8a D&(S|~P) */
269 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
270 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x8b ~D^(S|(P^D)) */
271 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8c S&(D|~P) */
272 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
273 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x8d ~S^(D|(P^S)) */
274 { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
275 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
276 OP(TMP,DST,GXxor) }, /* 0x8e S^((S^D)&(P^D))*/
277 { OP(SRC,DST,GXnand), OP(PAT,DST,GXnand) }, /* 0x8f ~(P&~(D&S)) */
278 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXand) }, /* 0x90 P&~(D^S) */
279 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
280 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x91 ~S^(D&(P|~S)) */
281 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
282 OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
283 OP(TMP,DST,GXxor) }, /* 0x92 D^P^(S&(D|P)) */
284 { OP(PAT,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x93 ~S^(P&D) */
285 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
286 OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
287 OP(TMP,DST,GXxor) }, /* 0x94 S^P^(D&(P|S)) */
288 { OP(PAT,SRC,GXand), OP(SRC,DST,GXequiv) }, /* 0x95 ~D^(P&S) */
289 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXxor) }, /* 0x96 D^P^S */
290 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
291 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
292 OP(TMP,DST,GXxor) }, /* 0x97 S^P^(D|~(P|S)) */
293 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
294 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x98 ~S^(D|~(P|S)) */
295 { OP(SRC,DST,GXequiv) }, /* 0x99 ~S^D */
296 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9a D^(P&~S) */
297 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
298 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x9b ~S^(D&(P|S)) */
299 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9c S^(P&~D) */
300 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
301 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x9d ~D^(S&(P|D)) */
302 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
303 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
304 OP(TMP,DST,GXxor) }, /* 0x9e D^S^(P|(D&S)) */
305 { OP(SRC,DST,GXxor), OP(PAT,DST,GXnand) }, /* 0x9f ~(P&(D^S)) */
306 { OP(PAT,DST,GXand) }, /* 0xa0 D&P */
307 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor),
308 OP(PAT,DST,GXequiv) }, /* 0xa1 ~P^(D|(S&~P)) */
309 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXand) }, /* 0xa2 D&(P|~S) */
310 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
311 OP(SRC,DST,GXequiv) }, /* 0xa3 ~D^(P|(S^D)) */
312 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor),
313 OP(PAT,DST,GXequiv) }, /* 0xa4 ~P^(D|~(S|P)) */
314 { OP(PAT,DST,GXequiv) }, /* 0xa5 ~P^D */
315 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXxor) },/* 0xa6 D^(S&~P) */
316 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
317 OP(PAT,DST,GXequiv) }, /* 0xa7 ~P^(D&(S|P)) */
318 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand) }, /* 0xa8 D&(P|S) */
319 { OP(PAT,SRC,GXor), OP(SRC,DST,GXequiv) }, /* 0xa9 ~D^(P|S) */
320 { OP(SRC,DST,GXnoop) }, /* 0xaa D */
321 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor) }, /* 0xab D|~(P|S) */
322 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
323 OP(SRC,DST,GXxor) }, /* 0xac S^(P&(D^S)) */
324 { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
325 OP(SRC,DST,GXequiv) }, /* 0xad ~D^(P|(S&D)) */
326 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor) }, /* 0xae D|(S&~P) */
327 { OP(PAT,DST,GXorInverted) }, /* 0xaf D|~P */
328 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand) }, /* 0xb0 P&(D|~S) */
329 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
330 OP(PAT,DST,GXequiv) }, /* 0xb1 ~P^(D|(S^P)) */
331 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
332 OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
333 OP(TMP,DST,GXxor) }, /* 0xb2 S^((S^P)|(S^D))*/
334 { OP(PAT,DST,GXnand), OP(SRC,DST,GXnand) }, /* 0xb3 ~(S&~(D&P)) */
335 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXxor) }, /* 0xb4 P^(S&~D) */
336 { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
337 OP(SRC,DST,GXequiv) }, /* 0xb5 ~D^(P&(S|D)) */
338 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
339 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
340 OP(TMP,DST,GXxor) }, /* 0xb6 D^P^(S|(D&P)) */
341 { OP(PAT,DST,GXxor), OP(SRC,DST,GXnand) }, /* 0xb7 ~(S&(D^P)) */
342 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
343 OP(PAT,DST,GXxor) }, /* 0xb8 P^(S&(D^P)) */
344 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
345 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0xb9 ~D^(S|(P&D)) */
346 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXor) }, /* 0xba D|(P&~S) */
347 { OP(SRC,DST,GXorInverted) }, /* 0xbb ~S|D */
348 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
349 OP(SRC,DST,GXxor) }, /* 0xbc S^(P&~(D&S)) */
350 { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
351 OP(SRC,DST,GXnand) }, /* 0xbd ~((S^D)&(P^D)) */
352 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor) }, /* 0xbe D|(P^S) */
353 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXor) }, /* 0xbf D|~(P&S) */
354 { OP(PAT,SRC,GXand) }, /* 0xc0 P&S */
355 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
356 OP(SRC,DST,GXequiv) }, /* 0xc1 ~S^(P|(D&~S)) */
357 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
358 OP(SRC,DST,GXequiv) }, /* 0xc2 ~S^(P|~(D|S)) */
359 { OP(PAT,SRC,GXequiv) }, /* 0xc3 ~P^S */
360 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXand) }, /* 0xc4 S&(P|~D) */
361 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
362 OP(SRC,DST,GXequiv) }, /* 0xc5 ~S^(P|(D^S)) */
363 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXxor) },/* 0xc6 S^(D&~P) */
364 { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
365 OP(PAT,DST,GXequiv) }, /* 0xc7 ~P^(S&(D|P)) */
366 { OP(PAT,DST,GXor), OP(SRC,DST,GXand) }, /* 0xc8 S&(D|P) */
367 { OP(PAT,DST,GXor), OP(SRC,DST,GXequiv) }, /* 0xc9 ~S^(P|D) */
368 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXand),
369 OP(SRC,DST,GXxor) }, /* 0xca D^(P&(S^D)) */
370 { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
371 OP(SRC,DST,GXequiv) }, /* 0xcb ~S^(P|(D&S)) */
372 { OP(SRC,DST,GXcopy) }, /* 0xcc S */
373 { OP(PAT,DST,GXnor), OP(SRC,DST,GXor) }, /* 0xcd S|~(D|P) */
374 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXor) }, /* 0xce S|(D&~P) */
375 { OP(PAT,SRC,GXorInverted) }, /* 0xcf S|~P */
376 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXand) }, /* 0xd0 P&(S|~D) */
377 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
378 OP(PAT,DST,GXequiv) }, /* 0xd1 ~P^(S|(D^P)) */
379 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXxor) },/* 0xd2 P^(D&~S) */
380 { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
381 OP(SRC,DST,GXequiv) }, /* 0xd3 ~S^(P&(D|S)) */
382 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
383 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
384 OP(TMP,DST,GXxor) }, /* 0xd4 S^((S^P)&(D^P))*/
385 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXnand) }, /* 0xd5 ~(D&~(P&S)) */
386 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
387 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
388 OP(TMP,DST,GXxor) }, /* 0xd6 S^P^(D|(P&S)) */
389 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnand) }, /* 0xd7 ~(D&(P^S)) */
390 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
391 OP(PAT,DST,GXxor) }, /* 0xd8 P^(D&(S^P)) */
392 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
393 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0xd9 ~S^(D|(P&S)) */
394 { OP(DST,SRC,GXnand), OP(PAT,SRC,GXand),
395 OP(SRC,DST,GXxor) }, /* 0xda D^(P&~(S&D)) */
396 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
397 OP(SRC,DST,GXnand) }, /* 0xdb ~((S^P)&(S^D)) */
398 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXor) }, /* 0xdc S|(P&~D) */
399 { OP(SRC,DST,GXorReverse) }, /* 0xdd S|~D */
400 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor) }, /* 0xde S|(D^P) */
401 { OP(PAT,DST,GXnand), OP(SRC,DST,GXor) }, /* 0xdf S|~(D&P) */
402 { OP(SRC,DST,GXor), OP(PAT,DST,GXand) }, /* 0xe0 P&(D|S) */
403 { OP(SRC,DST,GXor), OP(PAT,DST,GXequiv) }, /* 0xe1 ~P^(D|S) */
404 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
405 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe2 D^(S&(P^D)) */
406 { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
407 OP(PAT,DST,GXequiv) }, /* 0xe3 ~P^(S|(D&P)) */
408 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
409 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe4 S^(D&(P^S)) */
410 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
411 OP(PAT,DST,GXequiv) }, /* 0xe5 ~P^(D|(S&P)) */
412 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
413 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe6 S^(D&~(P&S)) */
414 { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
415 OP(SRC,DST,GXnand) }, /* 0xe7 ~((S^P)&(D^P)) */
416 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
417 OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
418 OP(TMP,DST,GXxor) }, /* 0xe8 S^((S^P)&(S^D))*/
419 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnand),
420 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
421 OP(TMP,DST,GXequiv) }, /* 0xe9 ~D^S^(P&~(S&D))*/
422 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor) }, /* 0xea D|(P&S) */
423 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXor) }, /* 0xeb D|~(P^S) */
424 { OP(PAT,DST,GXand), OP(SRC,DST,GXor) }, /* 0xec S|(D&P) */
425 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXor) }, /* 0xed S|~(D^P) */
426 { OP(SRC,DST,GXor) }, /* 0xee S|D */
427 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXor) }, /* 0xef S|D|~P */
428 { OP(PAT,DST,GXcopy) }, /* 0xf0 P */
429 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor) }, /* 0xf1 P|~(D|S) */
430 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor) }, /* 0xf2 P|(D&~S) */
431 { OP(PAT,SRC,GXorReverse) }, /* 0xf3 P|~S */
432 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXor) }, /* 0xf4 P|(S&~D) */
433 { OP(PAT,DST,GXorReverse) }, /* 0xf5 P|~D */
434 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor) }, /* 0xf6 P|(D^S) */
435 { OP(SRC,DST,GXnand), OP(PAT,DST,GXor) }, /* 0xf7 P|~(S&D) */
436 { OP(SRC,DST,GXand), OP(PAT,DST,GXor) }, /* 0xf8 P|(D&S) */
437 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor) }, /* 0xf9 P|~(D^S) */
438 { OP(PAT,DST,GXor) }, /* 0xfa D|P */
439 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXor) }, /* 0xfb D|P|~S */
440 { OP(PAT,SRC,GXor) }, /* 0xfc P|S */
441 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXor) }, /* 0xfd P|S|~D */
442 { OP(SRC,DST,GXor), OP(PAT,DST,GXor) }, /* 0xfe P|D|S */
443 { OP(PAT,DST,GXset) } /* 0xff 1 */
447 #ifdef BITBLT_TEST /* Opcodes test */
449 static int do_bitop( int s, int d, int rop )
454 case GXclear: res = 0; break;
455 case GXand: res = s & d; break;
456 case GXandReverse: res = s & ~d; break;
457 case GXcopy: res = s; break;
458 case GXandInverted: res = ~s & d; break;
459 case GXnoop: res = d; break;
460 case GXxor: res = s ^ d; break;
461 case GXor: res = s | d; break;
462 case GXnor: res = ~(s | d); break;
463 case GXequiv: res = ~s ^ d; break;
464 case GXinvert: res = ~d; break;
465 case GXorReverse: res = s | ~d; break;
466 case GXcopyInverted: res = ~s; break;
467 case GXorInverted: res = ~s | d; break;
468 case GXnand: res = ~(s & d); break;
469 case GXset: res = 1; break;
476 int rop, i, res, src, dst, pat, tmp, dstUsed;
479 for (rop = 0; rop < 256; rop++)
482 for (i = 0; i < 8; i++)
487 for (opcode = BITBLT_Opcodes[rop]; *opcode; opcode++)
491 case OP_ARGS(DST,TMP):
492 tmp = do_bitop( dst, tmp, *opcode & 0xf );
494 case OP_ARGS(DST,SRC):
495 src = do_bitop( dst, src, *opcode & 0xf );
497 case OP_ARGS(SRC,TMP):
498 tmp = do_bitop( src, tmp, *opcode & 0xf );
500 case OP_ARGS(SRC,DST):
501 dst = do_bitop( src, dst, *opcode & 0xf );
504 case OP_ARGS(PAT,TMP):
505 tmp = do_bitop( pat, tmp, *opcode & 0xf );
507 case OP_ARGS(PAT,DST):
508 dst = do_bitop( pat, dst, *opcode & 0xf );
511 case OP_ARGS(PAT,SRC):
512 src = do_bitop( pat, src, *opcode & 0xf );
514 case OP_ARGS(TMP,DST):
515 dst = do_bitop( tmp, dst, *opcode & 0xf );
518 case OP_ARGS(TMP,SRC):
519 src = do_bitop( tmp, src, *opcode & 0xf );
522 printf( "Invalid opcode %x\n", *opcode );
525 if (!dstUsed) dst = src;
526 if (dst) res |= 1 << i;
528 if (res != rop) printf( "%02x: ERROR, res=%02x\n", rop, res );
534 #endif /* BITBLT_TEST */
537 static void get_colors(X11DRV_PDEVICE *physDevDst, X11DRV_PDEVICE *physDevSrc,
542 *fg = physDevDst->textPixel;
543 *bg = physDevDst->backgroundPixel;
544 if(physDevSrc->depth == 1) {
545 if(GetDIBColorTable(physDevSrc->hdc, 0, 2, rgb) == 2) {
547 logcolor = RGB(rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue);
548 *fg = X11DRV_PALETTE_ToPhysical( physDevDst, logcolor );
549 logcolor = RGB(rgb[1].rgbRed, rgb[1].rgbGreen,rgb[1].rgbBlue);
550 *bg = X11DRV_PALETTE_ToPhysical( physDevDst, logcolor );
555 /***********************************************************************
558 * Stretch a row of pixels. Helper function for BITBLT_StretchImage.
560 static void BITBLT_StretchRow( int *rowSrc, int *rowDst,
561 INT startDst, INT widthDst,
562 INT xinc, INT xoff, WORD mode )
564 register INT xsrc = xinc * startDst + xoff;
568 case STRETCH_ANDSCANS:
569 for(; widthDst > 0; widthDst--, xsrc += xinc)
570 *rowDst++ &= rowSrc[xsrc >> 16];
572 case STRETCH_ORSCANS:
573 for(; widthDst > 0; widthDst--, xsrc += xinc)
574 *rowDst++ |= rowSrc[xsrc >> 16];
576 case STRETCH_DELETESCANS:
577 for(; widthDst > 0; widthDst--, xsrc += xinc)
578 *rowDst++ = rowSrc[xsrc >> 16];
584 /***********************************************************************
587 * Shrink a row of pixels. Helper function for BITBLT_StretchImage.
589 static void BITBLT_ShrinkRow( int *rowSrc, int *rowDst,
590 INT startSrc, INT widthSrc,
591 INT xinc, INT xoff, WORD mode )
593 register INT xdst = xinc * startSrc + xoff;
597 case STRETCH_ORSCANS:
598 for(; widthSrc > 0; widthSrc--, xdst += xinc)
599 rowDst[xdst >> 16] |= *rowSrc++;
601 case STRETCH_ANDSCANS:
602 for(; widthSrc > 0; widthSrc--, xdst += xinc)
603 rowDst[xdst >> 16] &= *rowSrc++;
605 case STRETCH_DELETESCANS:
606 for(; widthSrc > 0; widthSrc--, xdst += xinc)
607 rowDst[xdst >> 16] = *rowSrc++;
613 /***********************************************************************
616 * Retrieve a row from an image. Helper function for BITBLT_StretchImage.
618 static void BITBLT_GetRow( XImage *image, int *pdata, INT row,
619 INT start, INT width, INT depthDst,
620 int fg, int bg, BOOL swap)
624 assert( (row >= 0) && (row < image->height) );
625 assert( (start >= 0) && (width <= image->width) );
627 pdata += swap ? start+width-1 : start;
628 if (image->depth == depthDst) /* color -> color */
630 if (X11DRV_PALETTE_XPixelToPalette && (depthDst != 1))
631 if (swap) for (i = 0; i < width; i++)
632 *pdata-- = X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, i, row )];
633 else for (i = 0; i < width; i++)
634 *pdata++ = X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, i, row )];
636 if (swap) for (i = 0; i < width; i++)
637 *pdata-- = XGetPixel( image, i, row );
638 else for (i = 0; i < width; i++)
639 *pdata++ = XGetPixel( image, i, row );
643 if (image->depth == 1) /* monochrome -> color */
645 if (X11DRV_PALETTE_XPixelToPalette)
647 fg = X11DRV_PALETTE_XPixelToPalette[fg];
648 bg = X11DRV_PALETTE_XPixelToPalette[bg];
650 if (swap) for (i = 0; i < width; i++)
651 *pdata-- = XGetPixel( image, i, row ) ? bg : fg;
652 else for (i = 0; i < width; i++)
653 *pdata++ = XGetPixel( image, i, row ) ? bg : fg;
655 else /* color -> monochrome */
657 if (swap) for (i = 0; i < width; i++)
658 *pdata-- = (XGetPixel( image, i, row ) == bg) ? 1 : 0;
659 else for (i = 0; i < width; i++)
660 *pdata++ = (XGetPixel( image, i, row ) == bg) ? 1 : 0;
666 /***********************************************************************
667 * BITBLT_StretchImage
669 * Stretch an X image.
670 * FIXME: does not work for full 32-bit coordinates.
672 static void BITBLT_StretchImage( XImage *srcImage, XImage *dstImage,
673 INT widthSrc, INT heightSrc,
674 INT widthDst, INT heightDst,
675 RECT *visRectSrc, RECT *visRectDst,
676 int foreground, int background, WORD mode )
678 int *rowSrc, *rowDst, *pixel;
680 INT xinc, xoff, yinc, ysrc, ydst;
682 BOOL hstretch, vstretch, hswap, vswap;
684 hswap = ((int)widthSrc * widthDst) < 0;
685 vswap = ((int)heightSrc * heightDst) < 0;
686 widthSrc = abs(widthSrc);
687 heightSrc = abs(heightSrc);
688 widthDst = abs(widthDst);
689 heightDst = abs(heightDst);
691 if (!(rowSrc = HeapAlloc( GetProcessHeap(), 0,
692 (widthSrc+widthDst)*sizeof(int) ))) return;
693 rowDst = rowSrc + widthSrc;
695 /* When stretching, all modes are the same, and DELETESCANS is faster */
696 if ((widthSrc < widthDst) && (heightSrc < heightDst))
697 mode = STRETCH_DELETESCANS;
699 if (mode == STRETCH_HALFTONE) /* FIXME */
700 mode = STRETCH_DELETESCANS;
702 if (mode != STRETCH_DELETESCANS)
703 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
704 widthDst*sizeof(int) );
706 hstretch = (widthSrc < widthDst);
707 vstretch = (heightSrc < heightDst);
711 xinc = ((int)widthSrc << 16) / widthDst;
712 xoff = ((widthSrc << 16) - (xinc * widthDst)) / 2;
716 xinc = ((int)widthDst << 16) / widthSrc;
717 xoff = ((widthDst << 16) - (xinc * widthSrc)) / 2;
722 yinc = ((int)heightSrc << 16) / heightDst;
723 ydst = visRectDst->top;
726 ysrc = yinc * (heightDst - ydst - 1);
732 for ( ; (ydst < visRectDst->bottom); ysrc += yinc, ydst++)
734 if (((ysrc >> 16) < visRectSrc->top) ||
735 ((ysrc >> 16) >= visRectSrc->bottom)) continue;
737 /* Retrieve a source row */
738 BITBLT_GetRow( srcImage, rowSrc, (ysrc >> 16) - visRectSrc->top,
739 hswap ? widthSrc - visRectSrc->right
741 visRectSrc->right - visRectSrc->left,
742 dstImage->depth, foreground, background, hswap );
744 /* Stretch or shrink it */
746 BITBLT_StretchRow( rowSrc, rowDst, visRectDst->left,
747 visRectDst->right - visRectDst->left,
749 else BITBLT_ShrinkRow( rowSrc, rowDst,
750 hswap ? widthSrc - visRectSrc->right
752 visRectSrc->right - visRectSrc->left,
755 /* Store the destination row */
756 pixel = rowDst + visRectDst->right - 1;
757 y = ydst - visRectDst->top;
758 for (x = visRectDst->right-visRectDst->left-1; x >= 0; x--)
759 XPutPixel( dstImage, x, y, *pixel-- );
760 if (mode != STRETCH_DELETESCANS)
761 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
762 widthDst*sizeof(int) );
764 /* Make copies of the destination row */
766 pdata = dstImage->data + dstImage->bytes_per_line * y;
767 while (((ysrc + yinc) >> 16 == ysrc >> 16) &&
768 (ydst < visRectDst->bottom-1))
770 memcpy( pdata + dstImage->bytes_per_line, pdata,
771 dstImage->bytes_per_line );
772 pdata += dstImage->bytes_per_line;
780 yinc = ((int)heightDst << 16) / heightSrc;
781 ysrc = visRectSrc->top;
782 ydst = ((heightDst << 16) - (yinc * heightSrc)) / 2;
785 ydst += yinc * (heightSrc - ysrc - 1);
791 for( ; (ysrc < visRectSrc->bottom); ydst += yinc, ysrc++)
793 if (((ydst >> 16) < visRectDst->top) ||
794 ((ydst >> 16) >= visRectDst->bottom)) continue;
796 /* Retrieve a source row */
797 BITBLT_GetRow( srcImage, rowSrc, ysrc - visRectSrc->top,
798 hswap ? widthSrc - visRectSrc->right
800 visRectSrc->right - visRectSrc->left,
801 dstImage->depth, foreground, background, hswap );
803 /* Stretch or shrink it */
805 BITBLT_StretchRow( rowSrc, rowDst, visRectDst->left,
806 visRectDst->right - visRectDst->left,
808 else BITBLT_ShrinkRow( rowSrc, rowDst,
809 hswap ? widthSrc - visRectSrc->right
811 visRectSrc->right - visRectSrc->left,
814 /* Merge several source rows into the destination */
815 if (mode == STRETCH_DELETESCANS)
817 /* Simply skip the overlapping rows */
818 while (((ydst + yinc) >> 16 == ydst >> 16) &&
819 (ysrc < visRectSrc->bottom-1))
825 else if (((ydst + yinc) >> 16 == ydst >> 16) &&
826 (ysrc < visRectSrc->bottom-1))
827 continue; /* Restart loop for next overlapping row */
829 /* Store the destination row */
830 pixel = rowDst + visRectDst->right - 1;
831 y = (ydst >> 16) - visRectDst->top;
832 for (x = visRectDst->right-visRectDst->left-1; x >= 0; x--)
833 XPutPixel( dstImage, x, y, *pixel-- );
834 if (mode != STRETCH_DELETESCANS)
835 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
836 widthDst*sizeof(int) );
839 HeapFree( GetProcessHeap(), 0, rowSrc );
843 /***********************************************************************
844 * BITBLT_GetSrcAreaStretch
846 * Retrieve an area from the source DC, stretching and mapping all the
847 * pixels to Windows colors.
849 static int BITBLT_GetSrcAreaStretch( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
850 Pixmap pixmap, GC gc,
852 INT widthSrc, INT heightSrc,
854 INT widthDst, INT heightDst,
855 RECT *visRectSrc, RECT *visRectDst )
857 XImage *imageSrc, *imageDst;
858 RECT rectSrc = *visRectSrc;
859 RECT rectDst = *visRectDst;
862 if (widthSrc < 0) xSrc += widthSrc;
863 if (widthDst < 0) xDst += widthDst;
864 if (heightSrc < 0) ySrc += heightSrc;
865 if (heightDst < 0) yDst += heightDst;
866 rectSrc.left -= xSrc;
867 rectSrc.right -= xSrc;
869 rectSrc.bottom -= ySrc;
870 rectDst.left -= xDst;
871 rectDst.right -= xDst;
873 rectDst.bottom -= yDst;
875 get_colors(physDevDst, physDevSrc, &fg, &bg);
876 /* FIXME: avoid BadMatch errors */
877 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
878 physDevSrc->org.x + visRectSrc->left,
879 physDevSrc->org.y + visRectSrc->top,
880 visRectSrc->right - visRectSrc->left,
881 visRectSrc->bottom - visRectSrc->top,
882 AllPlanes, ZPixmap );
883 imageDst = X11DRV_DIB_CreateXImage( rectDst.right - rectDst.left,
884 rectDst.bottom - rectDst.top, physDevDst->depth );
885 BITBLT_StretchImage( imageSrc, imageDst, widthSrc, heightSrc,
886 widthDst, heightDst, &rectSrc, &rectDst,
887 fg, physDevDst->depth != 1 ?
888 bg : physDevSrc->backgroundPixel,
889 GetStretchBltMode(physDevDst->hdc) );
890 XPutImage( gdi_display, pixmap, gc, imageDst, 0, 0, 0, 0,
891 rectDst.right - rectDst.left, rectDst.bottom - rectDst.top );
892 XDestroyImage( imageSrc );
893 XDestroyImage( imageDst );
894 return 0; /* no exposure events generated */
898 /***********************************************************************
901 * Retrieve an area from the source DC, mapping all the
902 * pixels to Windows colors.
904 static int BITBLT_GetSrcArea( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
905 Pixmap pixmap, GC gc, INT xSrc, INT ySrc, RECT *visRectSrc )
907 XImage *imageSrc, *imageDst;
910 INT width = visRectSrc->right - visRectSrc->left;
911 INT height = visRectSrc->bottom - visRectSrc->top;
914 if (physDevSrc->depth == physDevDst->depth)
916 if (!X11DRV_PALETTE_XPixelToPalette ||
917 (physDevDst->depth == 1)) /* monochrome -> monochrome */
919 if (physDevDst->depth == 1)
921 /* MSDN says if StretchBlt must convert a bitmap from monochrome
922 to color or vice versa, the forground and background color of
923 the device context are used. In fact, it also applies to the
924 case when it is converted from mono to mono. */
925 XSetBackground( gdi_display, gc, physDevDst->textPixel );
926 XSetForeground( gdi_display, gc, physDevDst->backgroundPixel );
927 XCopyPlane( gdi_display, physDevSrc->drawable, pixmap, gc,
928 physDevSrc->org.x + visRectSrc->left,
929 physDevSrc->org.y + visRectSrc->top,
930 width, height, 0, 0, 1);
933 XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc,
934 physDevSrc->org.x + visRectSrc->left,
935 physDevSrc->org.y + visRectSrc->top,
936 width, height, 0, 0);
939 else /* color -> color */
941 if (GetObjectType(physDevSrc->hdc) == OBJ_MEMDC)
942 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
943 physDevSrc->org.x + visRectSrc->left,
944 physDevSrc->org.y + visRectSrc->top,
945 width, height, AllPlanes, ZPixmap );
948 /* Make sure we don't get a BadMatch error */
949 XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc,
950 physDevSrc->org.x + visRectSrc->left,
951 physDevSrc->org.y + visRectSrc->top,
952 width, height, 0, 0);
954 imageSrc = XGetImage( gdi_display, pixmap, 0, 0, width, height,
955 AllPlanes, ZPixmap );
957 for (y = 0; y < height; y++)
958 for (x = 0; x < width; x++)
959 XPutPixel(imageSrc, x, y,
960 X11DRV_PALETTE_XPixelToPalette[XGetPixel(imageSrc, x, y)]);
961 XPutImage( gdi_display, pixmap, gc, imageSrc,
962 0, 0, 0, 0, width, height );
963 XDestroyImage( imageSrc );
968 if (physDevSrc->depth == 1) /* monochrome -> color */
970 get_colors(physDevDst, physDevSrc, &fg, &bg);
972 if (X11DRV_PALETTE_XPixelToPalette)
974 XSetBackground( gdi_display, gc,
975 X11DRV_PALETTE_XPixelToPalette[fg] );
976 XSetForeground( gdi_display, gc,
977 X11DRV_PALETTE_XPixelToPalette[bg]);
981 XSetBackground( gdi_display, gc, fg );
982 XSetForeground( gdi_display, gc, bg );
984 XCopyPlane( gdi_display, physDevSrc->drawable, pixmap, gc,
985 physDevSrc->org.x + visRectSrc->left,
986 physDevSrc->org.y + visRectSrc->top,
987 width, height, 0, 0, 1 );
990 else /* color -> monochrome */
992 /* FIXME: avoid BadMatch error */
993 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
994 physDevSrc->org.x + visRectSrc->left,
995 physDevSrc->org.y + visRectSrc->top,
996 width, height, AllPlanes, ZPixmap );
1001 imageDst = X11DRV_DIB_CreateXImage( width, height, physDevDst->depth );
1004 XDestroyImage(imageSrc);
1007 for (y = 0; y < height; y++)
1008 for (x = 0; x < width; x++)
1009 XPutPixel(imageDst, x, y, (XGetPixel(imageSrc,x,y) ==
1010 physDevSrc->backgroundPixel) );
1011 XPutImage( gdi_display, pixmap, gc, imageDst,
1012 0, 0, 0, 0, width, height );
1013 XDestroyImage( imageSrc );
1014 XDestroyImage( imageDst );
1021 /***********************************************************************
1024 * Retrieve an area from the destination DC, mapping all the
1025 * pixels to Windows colors.
1027 static int BITBLT_GetDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, GC gc, RECT *visRectDst)
1030 INT width = visRectDst->right - visRectDst->left;
1031 INT height = visRectDst->bottom - visRectDst->top;
1033 if (!X11DRV_PALETTE_XPixelToPalette || (physDev->depth == 1) ||
1034 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
1036 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
1037 physDev->org.x + visRectDst->left, physDev->org.y + visRectDst->top,
1038 width, height, 0, 0 );
1046 if (GetObjectType( physDev->hdc ) == OBJ_MEMDC)
1047 image = XGetImage( gdi_display, physDev->drawable,
1048 physDev->org.x + visRectDst->left,
1049 physDev->org.y + visRectDst->top,
1050 width, height, AllPlanes, ZPixmap );
1053 /* Make sure we don't get a BadMatch error */
1054 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
1055 physDev->org.x + visRectDst->left,
1056 physDev->org.y + visRectDst->top,
1057 width, height, 0, 0);
1059 image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
1060 AllPlanes, ZPixmap );
1062 for (y = 0; y < height; y++)
1063 for (x = 0; x < width; x++)
1064 XPutPixel( image, x, y,
1065 X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]);
1066 XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height );
1067 XDestroyImage( image );
1073 /***********************************************************************
1076 * Put an area back into the destination DC, mapping the pixel
1077 * colors to X pixels.
1079 static int BITBLT_PutDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, RECT *visRectDst)
1082 INT width = visRectDst->right - visRectDst->left;
1083 INT height = visRectDst->bottom - visRectDst->top;
1085 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
1087 if (!X11DRV_PALETTE_PaletteToXPixel || (physDev->depth == 1) ||
1088 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
1090 XCopyArea( gdi_display, pixmap, physDev->drawable, physDev->gc, 0, 0, width, height,
1091 physDev->org.x + visRectDst->left,
1092 physDev->org.y + visRectDst->top );
1098 XImage *image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
1099 AllPlanes, ZPixmap );
1100 for (y = 0; y < height; y++)
1101 for (x = 0; x < width; x++)
1103 XPutPixel( image, x, y,
1104 X11DRV_PALETTE_PaletteToXPixel[XGetPixel( image, x, y )]);
1106 XPutImage( gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
1107 physDev->org.x + visRectDst->left,
1108 physDev->org.y + visRectDst->top, width, height );
1109 XDestroyImage( image );
1115 /***********************************************************************
1116 * BITBLT_GetVisRectangles
1118 * Get the source and destination visible rectangles for StretchBlt().
1119 * Return FALSE if one of the rectangles is empty.
1121 static BOOL BITBLT_GetVisRectangles( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst,
1122 INT widthDst, INT heightDst,
1123 X11DRV_PDEVICE *physDevSrc, INT xSrc, INT ySrc,
1124 INT widthSrc, INT heightSrc,
1125 RECT *visRectSrc, RECT *visRectDst )
1127 RECT rect, clipRect;
1129 /* Get the destination visible rectangle */
1133 rect.right = xDst + widthDst;
1134 rect.bottom = yDst + heightDst;
1135 if (widthDst < 0) SWAP_INT32( &rect.left, &rect.right );
1136 if (heightDst < 0) SWAP_INT32( &rect.top, &rect.bottom );
1137 GetRgnBox( physDevDst->region, &clipRect );
1138 if (!IntersectRect( visRectDst, &rect, &clipRect )) return FALSE;
1140 /* Get the source visible rectangle */
1142 if (!physDevSrc) return TRUE;
1145 rect.right = xSrc + widthSrc;
1146 rect.bottom = ySrc + heightSrc;
1147 if (widthSrc < 0) SWAP_INT32( &rect.left, &rect.right );
1148 if (heightSrc < 0) SWAP_INT32( &rect.top, &rect.bottom );
1149 /* Apparently the clipping and visible regions are only for output,
1150 so just check against dc extent here to avoid BadMatch errors */
1151 if (physDevSrc->bitmap)
1154 GetObjectW( physDevSrc->bitmap->hbitmap, sizeof(bm), &bm );
1155 SetRect( &clipRect, 0, 0, bm.bmWidth, bm.bmHeight );
1157 else SetRect( &clipRect, 0, 0, screen_width, screen_height );
1158 if (!IntersectRect( visRectSrc, &rect, &clipRect ))
1161 /* Intersect the rectangles */
1163 if ((widthSrc == widthDst) && (heightSrc == heightDst)) /* no stretching */
1165 visRectSrc->left += xDst - xSrc;
1166 visRectSrc->right += xDst - xSrc;
1167 visRectSrc->top += yDst - ySrc;
1168 visRectSrc->bottom += yDst - ySrc;
1169 if (!IntersectRect( &rect, visRectSrc, visRectDst )) return FALSE;
1170 *visRectSrc = *visRectDst = rect;
1171 visRectSrc->left += xSrc - xDst;
1172 visRectSrc->right += xSrc - xDst;
1173 visRectSrc->top += ySrc - yDst;
1174 visRectSrc->bottom += ySrc - yDst;
1176 else /* stretching */
1178 /* Map source rectangle into destination coordinates */
1179 rect.left = xDst + (visRectSrc->left - xSrc)*widthDst/widthSrc;
1180 rect.top = yDst + (visRectSrc->top - ySrc)*heightDst/heightSrc;
1181 rect.right = xDst + ((visRectSrc->right - xSrc)*widthDst)/widthSrc;
1182 rect.bottom = yDst + ((visRectSrc->bottom - ySrc)*heightDst)/heightSrc;
1183 if (rect.left > rect.right) SWAP_INT32( &rect.left, &rect.right );
1184 if (rect.top > rect.bottom) SWAP_INT32( &rect.top, &rect.bottom );
1186 /* Avoid rounding errors */
1191 if (!IntersectRect( visRectDst, &rect, visRectDst )) return FALSE;
1193 /* Map destination rectangle back to source coordinates */
1195 rect.left = xSrc + (visRectDst->left - xDst)*widthSrc/widthDst;
1196 rect.top = ySrc + (visRectDst->top - yDst)*heightSrc/heightDst;
1197 rect.right = xSrc + ((visRectDst->right - xDst)*widthSrc)/widthDst;
1198 rect.bottom = ySrc + ((visRectDst->bottom - yDst)*heightSrc)/heightDst;
1199 if (rect.left > rect.right) SWAP_INT32( &rect.left, &rect.right );
1200 if (rect.top > rect.bottom) SWAP_INT32( &rect.top, &rect.bottom );
1202 /* Avoid rounding errors */
1207 if (!IntersectRect( visRectSrc, &rect, visRectSrc )) return FALSE;
1213 /***********************************************************************
1214 * BITBLT_InternalStretchBlt
1216 * Implementation of PatBlt(), BitBlt() and StretchBlt().
1218 static BOOL BITBLT_InternalStretchBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst,
1219 INT widthDst, INT heightDst,
1220 X11DRV_PDEVICE *physDevSrc, INT xSrc, INT ySrc,
1221 INT widthSrc, INT heightSrc,
1224 BOOL usePat, useSrc, useDst, destUsed, fStretch, fNullBrush;
1225 RECT visRectDst, visRectSrc;
1228 Pixmap pixmaps[3] = { 0, 0, 0 }; /* pixmaps for DST, SRC, TMP */
1232 /* compensate for off-by-one shifting for negative widths and heights */
1242 usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
1243 useSrc = (((rop >> 2) & 0x330000) != (rop & 0x330000));
1244 useDst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
1245 if (!physDevSrc && useSrc) return FALSE;
1247 /* Map the coordinates to device coords */
1251 pts[1].x = xDst + widthDst;
1252 pts[1].y = yDst + heightDst;
1253 LPtoDP(physDevDst->hdc, pts, 2);
1256 widthDst = pts[1].x - pts[0].x;
1257 heightDst = pts[1].y - pts[0].y;
1259 TRACE(" rectdst=%d,%d-%d,%d orgdst=%ld,%ld\n",
1260 xDst, yDst, widthDst, heightDst,
1261 physDevDst->org.x, physDevDst->org.y );
1267 pts[1].x = xSrc + widthSrc;
1268 pts[1].y = ySrc + heightSrc;
1269 LPtoDP(physDevSrc->hdc, pts, 2);
1272 widthSrc = pts[1].x - pts[0].x;
1273 heightSrc = pts[1].y - pts[0].y;
1275 fStretch = (widthSrc != widthDst) || (heightSrc != heightDst);
1276 TRACE(" rectsrc=%d,%d-%d,%d orgsrc=%ld,%ld\n",
1277 xSrc, ySrc, widthSrc, heightSrc,
1278 physDevSrc->org.x, physDevSrc->org.y );
1279 if (!BITBLT_GetVisRectangles( physDevDst, xDst, yDst, widthDst, heightDst,
1280 physDevSrc, xSrc, ySrc, widthSrc, heightSrc,
1281 &visRectSrc, &visRectDst ))
1283 TRACE(" vissrc=%ld,%ld-%ld,%ld visdst=%ld,%ld-%ld,%ld\n",
1284 visRectSrc.left, visRectSrc.top,
1285 visRectSrc.right, visRectSrc.bottom,
1286 visRectDst.left, visRectDst.top,
1287 visRectDst.right, visRectDst.bottom );
1292 if (!BITBLT_GetVisRectangles( physDevDst, xDst, yDst, widthDst, heightDst,
1293 NULL, 0, 0, 0, 0, NULL, &visRectDst ))
1295 TRACE(" vissrc=none visdst=%ld,%ld-%ld,%ld\n",
1296 visRectDst.left, visRectDst.top,
1297 visRectDst.right, visRectDst.bottom );
1300 width = visRectDst.right - visRectDst.left;
1301 height = visRectDst.bottom - visRectDst.top;
1303 if (!fStretch) switch(rop) /* A few optimisations */
1305 case BLACKNESS: /* 0x00 */
1307 if ((physDevDst->depth == 1) || !X11DRV_PALETTE_PaletteToXPixel)
1308 XSetFunction( gdi_display, physDevDst->gc, GXclear );
1311 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1312 XSetForeground( gdi_display, physDevDst->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
1313 XSetFillStyle( gdi_display, physDevDst->gc, FillSolid );
1315 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
1316 physDevDst->org.x + visRectDst.left,
1317 physDevDst->org.y + visRectDst.top,
1319 wine_tsx11_unlock();
1322 case DSTINVERT: /* 0x55 */
1324 XSetFunction( gdi_display, physDevDst->gc, GXinvert );
1326 if( X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL) )
1327 XSetFunction( gdi_display, physDevDst->gc, GXinvert);
1330 /* Xor is much better when we do not have full colormap. */
1331 /* Using white^black ensures that we invert at least black */
1333 unsigned long xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
1334 BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
1335 XSetFunction( gdi_display, physDevDst->gc, GXxor );
1336 XSetForeground( gdi_display, physDevDst->gc, xor_pix);
1337 XSetFillStyle( gdi_display, physDevDst->gc, FillSolid );
1339 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
1340 physDevDst->org.x + visRectDst.left,
1341 physDevDst->org.y + visRectDst.top,
1343 wine_tsx11_unlock();
1346 case PATINVERT: /* 0x5a */
1347 if (X11DRV_SetupGCForBrush( physDevDst ))
1350 XSetFunction( gdi_display, physDevDst->gc, GXxor );
1351 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
1352 physDevDst->org.x + visRectDst.left,
1353 physDevDst->org.y + visRectDst.top,
1355 wine_tsx11_unlock();
1360 if (X11DRV_SetupGCForBrush( physDevDst ))
1363 XSetFunction( gdi_display, physDevDst->gc, GXequiv );
1364 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
1365 physDevDst->org.x + visRectDst.left,
1366 physDevDst->org.y + visRectDst.top,
1368 wine_tsx11_unlock();
1372 case SRCCOPY: /* 0xcc */
1373 if (physDevSrc->depth == physDevDst->depth)
1376 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1377 XCopyArea( gdi_display, physDevSrc->drawable,
1378 physDevDst->drawable, physDevDst->gc,
1379 physDevSrc->org.x + visRectSrc.left,
1380 physDevSrc->org.y + visRectSrc.top,
1382 physDevDst->org.x + visRectDst.left,
1383 physDevDst->org.y + visRectDst.top );
1384 physDevDst->exposures++;
1385 wine_tsx11_unlock();
1389 if (physDevSrc->depth == 1)
1392 get_colors(physDevDst, physDevSrc, &fg, &bg);
1395 XSetBackground( gdi_display, physDevDst->gc, fg );
1396 XSetForeground( gdi_display, physDevDst->gc, bg );
1397 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1398 XCopyPlane( gdi_display, physDevSrc->drawable,
1399 physDevDst->drawable, physDevDst->gc,
1400 physDevSrc->org.x + visRectSrc.left,
1401 physDevSrc->org.y + visRectSrc.top,
1403 physDevDst->org.x + visRectDst.left,
1404 physDevDst->org.y + visRectDst.top, 1 );
1405 physDevDst->exposures++;
1406 wine_tsx11_unlock();
1411 case PATCOPY: /* 0xf0 */
1412 if (!X11DRV_SetupGCForBrush( physDevDst )) return TRUE;
1414 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1415 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
1416 physDevDst->org.x + visRectDst.left,
1417 physDevDst->org.y + visRectDst.top,
1419 wine_tsx11_unlock();
1422 case WHITENESS: /* 0xff */
1424 if ((physDevDst->depth == 1) || !X11DRV_PALETTE_PaletteToXPixel)
1425 XSetFunction( gdi_display, physDevDst->gc, GXset );
1428 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1429 XSetForeground( gdi_display, physDevDst->gc,
1430 WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
1431 XSetFillStyle( gdi_display, physDevDst->gc, FillSolid );
1433 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
1434 physDevDst->org.x + visRectDst.left,
1435 physDevDst->org.y + visRectDst.top,
1437 wine_tsx11_unlock();
1443 tmpGC = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
1444 XSetSubwindowMode( gdi_display, tmpGC, IncludeInferiors );
1445 XSetGraphicsExposures( gdi_display, tmpGC, False );
1446 pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height,
1447 physDevDst->depth );
1450 pixmaps[SRC] = XCreatePixmap( gdi_display, root_window, width, height,
1451 physDevDst->depth );
1453 BITBLT_GetSrcAreaStretch( physDevSrc, physDevDst, pixmaps[SRC], tmpGC,
1454 xSrc, ySrc, widthSrc, heightSrc,
1455 xDst, yDst, widthDst, heightDst,
1456 &visRectSrc, &visRectDst );
1458 BITBLT_GetSrcArea( physDevSrc, physDevDst, pixmaps[SRC], tmpGC,
1459 xSrc, ySrc, &visRectSrc );
1462 if (useDst) BITBLT_GetDstArea( physDevDst, pixmaps[DST], tmpGC, &visRectDst );
1463 if (usePat) fNullBrush = !X11DRV_SetupGCForPatBlt( physDevDst, tmpGC, TRUE );
1464 else fNullBrush = FALSE;
1467 for (opcode = BITBLT_Opcodes[(rop >> 16) & 0xff]; *opcode; opcode++)
1469 if (OP_DST(*opcode) == DST) destUsed = TRUE;
1470 XSetFunction( gdi_display, tmpGC, OP_ROP(*opcode) );
1471 switch(OP_SRCDST(*opcode))
1473 case OP_ARGS(DST,TMP):
1474 case OP_ARGS(SRC,TMP):
1476 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window,
1477 width, height, physDevDst->depth );
1479 case OP_ARGS(DST,SRC):
1480 case OP_ARGS(SRC,DST):
1481 case OP_ARGS(TMP,SRC):
1482 case OP_ARGS(TMP,DST):
1484 XCopyArea( gdi_display, pixmaps[OP_SRC(*opcode)],
1485 pixmaps[OP_DST(*opcode)], tmpGC,
1486 0, 0, width, height, 0, 0 );
1489 case OP_ARGS(PAT,TMP):
1490 if (!pixmaps[TMP] && !fNullBrush)
1491 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window,
1492 width, height, physDevDst->depth );
1494 case OP_ARGS(PAT,DST):
1495 case OP_ARGS(PAT,SRC):
1497 XFillRectangle( gdi_display, pixmaps[OP_DST(*opcode)],
1498 tmpGC, 0, 0, width, height );
1502 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1503 physDevDst->exposures += BITBLT_PutDstArea( physDevDst, pixmaps[destUsed ? DST : SRC],
1505 XFreePixmap( gdi_display, pixmaps[DST] );
1506 if (pixmaps[SRC]) XFreePixmap( gdi_display, pixmaps[SRC] );
1507 if (pixmaps[TMP]) XFreePixmap( gdi_display, pixmaps[TMP] );
1508 XFreeGC( gdi_display, tmpGC );
1509 wine_tsx11_unlock();
1514 /***********************************************************************
1517 BOOL X11DRV_PatBlt( X11DRV_PDEVICE *physDev, INT left, INT top, INT width, INT height, DWORD rop )
1521 X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod, FALSE );
1522 result = BITBLT_InternalStretchBlt( physDev, left, top, width, height, NULL, 0, 0, 0, 0, rop );
1523 X11DRV_UnlockDIBSection( physDev, TRUE );
1528 /***********************************************************************
1531 BOOL X11DRV_BitBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst,
1532 INT width, INT height, X11DRV_PDEVICE *physDevSrc,
1533 INT xSrc, INT ySrc, DWORD rop )
1535 BOOL result = FALSE;
1537 RECT visRectDst, visRectSrc;
1539 if (((rop >> 16) & 0x55) == ((rop >> 17) & 0x55)) {
1540 /* FIXME: seems the ROP doesn't include destination;
1541 * now if the destination area include the entire dcDst,
1542 * we can pass TRUE instead of FALSE to CoerceDIBSection(dcDst...),
1543 * which may avoid a copy in some situations */
1546 sDst = X11DRV_LockDIBSection( physDevDst, DIB_Status_None, FALSE );
1547 if (physDevDst != physDevSrc)
1548 sSrc = X11DRV_LockDIBSection( physDevSrc, DIB_Status_None, FALSE );
1552 if ((sSrc == DIB_Status_AppMod) && (rop == SRCCOPY) &&
1553 (physDevSrc->depth == physDevDst->depth))
1556 /* do everything ourselves; map coordinates */
1560 pts[1].x = xSrc + width;
1561 pts[1].y = ySrc + height;
1563 LPtoDP(physDevSrc->hdc, pts, 2);
1564 width = pts[1].x - pts[0].x;
1565 height = pts[1].y - pts[0].y;
1571 LPtoDP(physDevDst->hdc, pts, 1);
1576 /* Perform basic clipping */
1577 if (!BITBLT_GetVisRectangles( physDevDst, xDst, yDst, width, height,
1578 physDevSrc, xSrc, ySrc, width, height,
1579 &visRectSrc, &visRectDst ))
1582 xSrc = visRectSrc.left;
1583 ySrc = visRectSrc.top;
1584 xDst = visRectDst.left;
1585 yDst = visRectDst.top;
1586 width = visRectDst.right - visRectDst.left;
1587 height = visRectDst.bottom - visRectDst.top;
1589 if (sDst == DIB_Status_AppMod) {
1590 FIXME("potential optimization - client-side DIB copy\n");
1592 X11DRV_CoerceDIBSection( physDevDst, DIB_Status_GdiMod, FALSE );
1595 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1596 wine_tsx11_unlock();
1598 X11DRV_DIB_CopyDIBSection( physDevSrc, physDevDst, xSrc, ySrc, xDst, yDst, width, height );
1603 X11DRV_CoerceDIBSection( physDevDst, DIB_Status_GdiMod, FALSE );
1604 if (physDevDst != physDevSrc)
1605 X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod, FALSE );
1607 result = BITBLT_InternalStretchBlt( physDevDst, xDst, yDst, width, height,
1608 physDevSrc, xSrc, ySrc, width, height, rop );
1611 if (physDevDst != physDevSrc)
1612 X11DRV_UnlockDIBSection( physDevSrc, FALSE );
1613 X11DRV_UnlockDIBSection( physDevDst, TRUE );
1619 /***********************************************************************
1622 BOOL X11DRV_StretchBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst,
1623 INT widthDst, INT heightDst,
1624 X11DRV_PDEVICE *physDevSrc, INT xSrc, INT ySrc,
1625 INT widthSrc, INT heightSrc, DWORD rop )
1629 X11DRV_LockDIBSection( physDevDst, DIB_Status_GdiMod, FALSE );
1630 if (physDevDst != physDevSrc)
1631 X11DRV_LockDIBSection( physDevSrc, DIB_Status_GdiMod, FALSE );
1633 result = BITBLT_InternalStretchBlt( physDevDst, xDst, yDst, widthDst, heightDst,
1634 physDevSrc, xSrc, ySrc, widthSrc, heightSrc, rop );
1636 if (physDevDst != physDevSrc)
1637 X11DRV_UnlockDIBSection( physDevSrc, FALSE );
1638 X11DRV_UnlockDIBSection( physDevDst, TRUE );