2 * GDI bit-blit operations
4 * Copyright 1993, 1994 Alexandre Julliard
9 #include <X11/Intrinsic.h>
25 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(bitblt);
30 #define DST 0 /* Destination drawable */
31 #define SRC 1 /* Source drawable */
32 #define TMP 2 /* Temporary drawable */
33 #define PAT 3 /* Pattern (brush) in destination DC */
35 #define OP(src,dst,rop) (OP_ARGS(src,dst) << 4 | (rop))
36 #define OP_ARGS(src,dst) (((src) << 2) | (dst))
38 #define OP_SRC(opcode) ((opcode) >> 6)
39 #define OP_DST(opcode) (((opcode) >> 4) & 3)
40 #define OP_SRCDST(opcode) ((opcode) >> 4)
41 #define OP_ROP(opcode) ((opcode) & 0x0f)
43 #define MAX_OP_LEN 6 /* Longest opcode + 1 for the terminating 0 */
45 #define SWAP_INT32(i1,i2) \
46 do { INT __t = *(i1); *(i1) = *(i2); *(i2) = __t; } while(0)
48 static const unsigned char BITBLT_Opcodes[256][MAX_OP_LEN] =
50 { OP(PAT,DST,GXclear) }, /* 0x00 0 */
51 { OP(PAT,SRC,GXor), OP(SRC,DST,GXnor) }, /* 0x01 ~(D|(P|S)) */
52 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXand) }, /* 0x02 D&~(P|S) */
53 { OP(PAT,SRC,GXnor) }, /* 0x03 ~(P|S) */
54 { OP(PAT,DST,GXnor), OP(SRC,DST,GXand) }, /* 0x04 S&~(D|P) */
55 { OP(PAT,DST,GXnor) }, /* 0x05 ~(D|P) */
56 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnor), }, /* 0x06 ~(P|~(D^S)) */
57 { OP(SRC,DST,GXand), OP(PAT,DST,GXnor) }, /* 0x07 ~(P|(D&S)) */
58 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXand) },/* 0x08 S&D&~P */
59 { OP(SRC,DST,GXxor), OP(PAT,DST,GXnor) }, /* 0x09 ~(P|(D^S)) */
60 { OP(PAT,DST,GXandInverted) }, /* 0x0a D&~P */
61 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXnor) }, /* 0x0b ~(P|(S&~D)) */
62 { OP(PAT,SRC,GXandInverted) }, /* 0x0c S&~P */
63 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXnor) },/* 0x0d ~(P|(D&~S)) */
64 { OP(SRC,DST,GXnor), OP(PAT,DST,GXnor) }, /* 0x0e ~(P|~(D|S)) */
65 { OP(PAT,DST,GXcopyInverted) }, /* 0x0f ~P */
66 { OP(SRC,DST,GXnor), OP(PAT,DST,GXand) }, /* 0x10 P&~(S|D) */
67 { OP(SRC,DST,GXnor) }, /* 0x11 ~(D|S) */
68 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnor) }, /* 0x12 ~(S|~(D^P)) */
69 { OP(PAT,DST,GXand), OP(SRC,DST,GXnor) }, /* 0x13 ~(S|(D&P)) */
70 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnor) }, /* 0x14 ~(D|~(P^S)) */
71 { OP(PAT,SRC,GXand), OP(SRC,DST,GXnor) }, /* 0x15 ~(D|(P&S)) */
72 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXnand),
73 OP(TMP,DST,GXand), OP(SRC,DST,GXxor),
74 OP(PAT,DST,GXxor) }, /* 0x16 P^S^(D&~(P&S) */
75 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
76 OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
77 OP(TMP,DST,GXequiv) }, /* 0x17 ~S^((S^P)&(S^D))*/
78 { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
79 OP(SRC,DST,GXand) }, /* 0x18 (S^P)&(D^P) */
80 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXnand),
81 OP(TMP,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x19 ~S^(D&~(P&S)) */
82 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
83 OP(PAT,DST,GXxor) }, /* 0x1a P^(D|(S&P)) */
84 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXxor),
85 OP(TMP,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x1b ~S^(D&(P^S)) */
86 { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
87 OP(PAT,DST,GXxor) }, /* 0x1c P^(S|(D&P)) */
88 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
89 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x1d ~D^(S&(D^P)) */
90 { OP(SRC,DST,GXor), OP(PAT,DST,GXxor) }, /* 0x1e P^(D|S) */
91 { OP(SRC,DST,GXor), OP(PAT,DST,GXnand) }, /* 0x1f ~(P&(D|S)) */
92 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXand) }, /* 0x20 D&(P&~S) */
93 { OP(PAT,DST,GXxor), OP(SRC,DST,GXnor) }, /* 0x21 ~(S|(D^P)) */
94 { OP(SRC,DST,GXandInverted) }, /* 0x22 ~S&D */
95 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x23 ~(S|(P&~D)) */
96 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
97 OP(SRC,DST,GXand) }, /* 0x24 (S^P)&(S^D) */
98 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand),
99 OP(PAT,DST,GXequiv) }, /* 0x25 ~P^(D&~(S&P)) */
100 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXand),
101 OP(TMP,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x26 S^(D|(S&P)) */
102 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXequiv),
103 OP(TMP,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x27 S^(D|~(P^S)) */
104 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand) }, /* 0x28 D&(P^S) */
105 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXand),
106 OP(TMP,DST,GXor), OP(SRC,DST,GXxor),
107 OP(PAT,DST,GXequiv) }, /* 0x29 ~P^S^(D|(P&S)) */
108 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand) }, /* 0x2a D&~(P&S) */
109 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
110 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
111 OP(TMP,DST,GXequiv) }, /* 0x2b ~S^((P^S)&(P^D))*/
112 { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
113 OP(SRC,DST,GXxor) }, /* 0x2c S^(P&(S|D)) */
114 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXxor) }, /* 0x2d P^(S|~D) */
115 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
116 OP(PAT,DST,GXxor) }, /* 0x2e P^(S|(D^P)) */
117 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXnand) }, /* 0x2f ~(P&(S|~D)) */
118 { OP(PAT,SRC,GXandReverse) }, /* 0x30 P&~S */
119 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXnor) },/* 0x31 ~(S|(D&~P)) */
120 { OP(SRC,DST,GXor), OP(PAT,DST,GXor),
121 OP(SRC,DST,GXxor) }, /* 0x32 S^(D|P|S) */
122 { OP(SRC,DST,GXcopyInverted) }, /* 0x33 ~S */
123 { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
124 OP(SRC,DST,GXxor) }, /* 0x34 S^(P|(D&S)) */
125 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor),
126 OP(SRC,DST,GXxor) }, /* 0x35 S^(P|~(D^S)) */
127 { OP(PAT,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x36 S^(D|P) */
128 { OP(PAT,DST,GXor), OP(SRC,DST,GXnand) }, /* 0x37 ~(S&(D|P)) */
129 { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
130 OP(PAT,DST,GXxor) }, /* 0x38 P^(S&(D|P)) */
131 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXxor) }, /* 0x39 S^(P|~D) */
132 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
133 OP(SRC,DST,GXxor) }, /* 0x3a S^(P|(D^S)) */
134 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x3b ~(S&(P|~D)) */
135 { OP(PAT,SRC,GXxor) }, /* 0x3c P^S */
136 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
137 OP(SRC,DST,GXxor) }, /* 0x3d S^(P|~(D|S)) */
138 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
139 OP(SRC,DST,GXxor) }, /* 0x3e S^(P|(D&~S)) */
140 { OP(PAT,SRC,GXnand) }, /* 0x3f ~(P&S) */
141 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXand) }, /* 0x40 P&S&~D */
142 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnor) }, /* 0x41 ~(D|(P^S)) */
143 { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
144 OP(SRC,DST,GXand) }, /* 0x42 (S^D)&(P^D) */
145 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
146 OP(SRC,DST,GXequiv) }, /* 0x43 ~S^(P&~(D&S)) */
147 { OP(SRC,DST,GXandReverse) }, /* 0x44 S&~D */
148 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x45 ~(D|(P&~S)) */
149 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
150 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x46 D^(S|(P&D)) */
151 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
152 OP(PAT,DST,GXequiv) }, /* 0x47 ~P^(S&(D^P)) */
153 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand) }, /* 0x48 S&(P^D) */
154 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
155 OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
156 OP(PAT,DST,GXequiv) }, /* 0x49 ~P^D^(S|(P&D)) */
157 { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
158 OP(SRC,DST,GXxor) }, /* 0x4a D^(P&(S|D)) */
159 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXxor) }, /* 0x4b P^(D|~S) */
160 { OP(PAT,DST,GXnand), OP(SRC,DST,GXand) }, /* 0x4c S&~(D&P) */
161 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
162 OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
163 OP(TMP,DST,GXequiv) }, /* 0x4d ~S^((S^P)|(S^D))*/
164 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
165 OP(PAT,DST,GXxor) }, /* 0x4e P^(D|(S^P)) */
166 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXnand) },/* 0x4f ~(P&(D|~S)) */
167 { OP(PAT,DST,GXandReverse) }, /* 0x50 P&~D */
168 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXnor) },/* 0x51 ~(D|(S&~P)) */
169 { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
170 OP(SRC,DST,GXxor) }, /* 0x52 D^(P|(S&D)) */
171 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
172 OP(SRC,DST,GXequiv) }, /* 0x53 ~S^(P&(D^S)) */
173 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXnor) }, /* 0x54 ~(D|~(P|S)) */
174 { OP(PAT,DST,GXinvert) }, /* 0x55 ~D */
175 { OP(PAT,SRC,GXor), OP(SRC,DST,GXxor) }, /* 0x56 D^(P|S) */
176 { OP(PAT,SRC,GXor), OP(SRC,DST,GXnand) }, /* 0x57 ~(D&(P|S)) */
177 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
178 OP(PAT,DST,GXxor) }, /* 0x58 P^(D&(P|S)) */
179 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXxor) }, /* 0x59 D^(P|~S) */
180 { OP(PAT,DST,GXxor) }, /* 0x5a D^P */
181 { OP(DST,SRC,GXnor), OP(PAT,SRC,GXor),
182 OP(SRC,DST,GXxor) }, /* 0x5b D^(P|~(S|D)) */
183 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
184 OP(SRC,DST,GXxor) }, /* 0x5c D^(P|(S^D)) */
185 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x5d ~(D&(P|~S)) */
186 { OP(DST,SRC,GXandInverted), OP(PAT,SRC,GXor),
187 OP(SRC,DST,GXxor) }, /* 0x5e D^(P|(S&~D)) */
188 { OP(PAT,DST,GXnand) }, /* 0x5f ~(D&P) */
189 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand) }, /* 0x60 P&(D^S) */
190 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
191 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
192 OP(TMP,DST,GXequiv) }, /* 0x61 ~D^S^(P|(D&S)) */
193 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
194 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x62 D^(S&(P|D)) */
195 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x63 S^(D|~P) */
196 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
197 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x64 S^(D&(P|S)) */
198 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x65 D^(S|~P) */
199 { OP(SRC,DST,GXxor) }, /* 0x66 S^D */
200 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
201 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x67 S^(D|~(S|P) */
202 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnor),
203 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
204 OP(TMP,DST,GXequiv) }, /* 0x68 ~D^S^(P|~(D|S))*/
205 { OP(SRC,DST,GXxor), OP(PAT,DST,GXequiv) }, /* 0x69 ~P^(D^S) */
206 { OP(PAT,SRC,GXand), OP(SRC,DST,GXxor) }, /* 0x6a D^(P&S) */
207 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
208 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
209 OP(PAT,DST,GXequiv) }, /* 0x6b ~P^S^(D&(P|S)) */
210 { OP(PAT,DST,GXand), OP(SRC,DST,GXxor) }, /* 0x6c S^(D&P) */
211 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
212 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
213 OP(PAT,DST,GXequiv) }, /* 0x6d ~P^D^(S&(P|D)) */
214 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
215 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x6e S^(D&(P|~S)) */
216 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnand) }, /* 0x6f ~(P&~(S^D)) */
217 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand) }, /* 0x70 P&~(D&S) */
218 { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
219 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
220 OP(TMP,DST,GXequiv) }, /* 0x71 ~S^((S^D)&(P^D))*/
221 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
222 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x72 S^(D|(P^S)) */
223 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXnand) },/* 0x73 ~(S&(D|~P)) */
224 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
225 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x74 D^(S|(P^D)) */
226 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXnand) },/* 0x75 ~(D&(S|~P)) */
227 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
228 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x76 S^(D|(P&~S)) */
229 { OP(SRC,DST,GXnand) }, /* 0x77 ~(S&D) */
230 { OP(SRC,DST,GXand), OP(PAT,DST,GXxor) }, /* 0x78 P^(D&S) */
231 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
232 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
233 OP(TMP,DST,GXequiv) }, /* 0x79 ~D^S^(P&(D|S)) */
234 { OP(DST,SRC,GXorInverted), OP(PAT,SRC,GXand),
235 OP(SRC,DST,GXxor) }, /* 0x7a D^(P&(S|~D)) */
236 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnand) }, /* 0x7b ~(S&~(D^P)) */
237 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
238 OP(SRC,DST,GXxor) }, /* 0x7c S^(P&(D|~S)) */
239 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnand) }, /* 0x7d ~(D&~(P^S)) */
240 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
241 OP(SRC,DST,GXor) }, /* 0x7e (S^P)|(S^D) */
242 { OP(PAT,SRC,GXand), OP(SRC,DST,GXnand) }, /* 0x7f ~(D&P&S) */
243 { OP(PAT,SRC,GXand), OP(SRC,DST,GXand) }, /* 0x80 D&P&S */
244 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
245 OP(SRC,DST,GXnor) }, /* 0x81 ~((S^P)|(S^D)) */
246 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXand) }, /* 0x82 D&~(P^S) */
247 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
248 OP(SRC,DST,GXequiv) }, /* 0x83 ~S^(P&(D|~S)) */
249 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXand) }, /* 0x84 S&~(D^P) */
250 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand),
251 OP(PAT,DST,GXequiv) }, /* 0x85 ~P^(D&(S|~P)) */
252 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
253 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
254 OP(TMP,DST,GXxor) }, /* 0x86 D^S^(P&(D|S)) */
255 { OP(SRC,DST,GXand), OP(PAT,DST,GXequiv) }, /* 0x87 ~P^(D&S) */
256 { OP(SRC,DST,GXand) }, /* 0x88 S&D */
257 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
258 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x89 ~S^(D|(P&~S)) */
259 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8a D&(S|~P) */
260 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
261 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x8b ~D^(S|(P^D)) */
262 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8c S&(D|~P) */
263 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
264 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x8d ~S^(D|(P^S)) */
265 { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
266 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
267 OP(TMP,DST,GXxor) }, /* 0x8e S^((S^D)&(P^D))*/
268 { OP(SRC,DST,GXnand), OP(PAT,DST,GXnand) }, /* 0x8f ~(P&~(D&S)) */
269 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXand) }, /* 0x90 P&~(D^S) */
270 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
271 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x91 ~S^(D&(P|~S)) */
272 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
273 OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
274 OP(TMP,DST,GXxor) }, /* 0x92 D^P^(S&(D|P)) */
275 { OP(PAT,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x93 ~S^(P&D) */
276 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
277 OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
278 OP(TMP,DST,GXxor) }, /* 0x94 S^P^(D&(P|S)) */
279 { OP(PAT,SRC,GXand), OP(SRC,DST,GXequiv) }, /* 0x95 ~D^(P&S) */
280 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXxor) }, /* 0x96 D^P^S */
281 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
282 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
283 OP(TMP,DST,GXxor) }, /* 0x97 S^P^(D|~(P|S)) */
284 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
285 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x98 ~S^(D|~(P|S)) */
286 { OP(SRC,DST,GXequiv) }, /* 0x99 ~S^D */
287 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9a D^(P&~S) */
288 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
289 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x9b ~S^(D&(P|S)) */
290 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9c S^(P&~D) */
291 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
292 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x9d ~D^(S&(P|D)) */
293 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
294 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
295 OP(TMP,DST,GXxor) }, /* 0x9e D^S^(P|(D&S)) */
296 { OP(SRC,DST,GXxor), OP(PAT,DST,GXnand) }, /* 0x9f ~(P&(D^S)) */
297 { OP(PAT,DST,GXand) }, /* 0xa0 D&P */
298 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor),
299 OP(PAT,DST,GXequiv) }, /* 0xa1 ~P^(D|(S&~P)) */
300 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXand) }, /* 0xa2 D&(P|~S) */
301 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
302 OP(SRC,DST,GXequiv) }, /* 0xa3 ~D^(P|(S^D)) */
303 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor),
304 OP(PAT,DST,GXequiv) }, /* 0xa4 ~P^(D|~(S|P)) */
305 { OP(PAT,DST,GXequiv) }, /* 0xa5 ~P^D */
306 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXxor) },/* 0xa6 D^(S&~P) */
307 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
308 OP(PAT,DST,GXequiv) }, /* 0xa7 ~P^(D&(S|P)) */
309 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand) }, /* 0xa8 D&(P|S) */
310 { OP(PAT,SRC,GXor), OP(SRC,DST,GXequiv) }, /* 0xa9 ~D^(P|S) */
311 { OP(SRC,DST,GXnoop) }, /* 0xaa D */
312 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor) }, /* 0xab D|~(P|S) */
313 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
314 OP(SRC,DST,GXxor) }, /* 0xac S^(P&(D^S)) */
315 { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
316 OP(SRC,DST,GXequiv) }, /* 0xad ~D^(P|(S&D)) */
317 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor) }, /* 0xae D|(S&~P) */
318 { OP(PAT,DST,GXorInverted) }, /* 0xaf D|~P */
319 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand) }, /* 0xb0 P&(D|~S) */
320 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
321 OP(PAT,DST,GXequiv) }, /* 0xb1 ~P^(D|(S^P)) */
322 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
323 OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
324 OP(TMP,DST,GXxor) }, /* 0xb2 S^((S^P)|(S^D))*/
325 { OP(PAT,DST,GXnand), OP(SRC,DST,GXnand) }, /* 0xb3 ~(S&~(D&P)) */
326 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXxor) }, /* 0xb4 P^(S&~D) */
327 { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
328 OP(SRC,DST,GXequiv) }, /* 0xb5 ~D^(P&(S|D)) */
329 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
330 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
331 OP(TMP,DST,GXxor) }, /* 0xb6 D^P^(S|(D&P)) */
332 { OP(PAT,DST,GXxor), OP(SRC,DST,GXnand) }, /* 0xb7 ~(S&(D^P)) */
333 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
334 OP(PAT,DST,GXxor) }, /* 0xb8 P^(S&(D^P)) */
335 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
336 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0xb9 ~D^(S|(P&D)) */
337 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXor) }, /* 0xba D|(P&~S) */
338 { OP(SRC,DST,GXorInverted) }, /* 0xbb ~S|D */
339 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
340 OP(SRC,DST,GXxor) }, /* 0xbc S^(P&~(D&S)) */
341 { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
342 OP(SRC,DST,GXnand) }, /* 0xbd ~((S^D)&(P^D)) */
343 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor) }, /* 0xbe D|(P^S) */
344 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXor) }, /* 0xbf D|~(P&S) */
345 { OP(PAT,SRC,GXand) }, /* 0xc0 P&S */
346 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
347 OP(SRC,DST,GXequiv) }, /* 0xc1 ~S^(P|(D&~S)) */
348 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
349 OP(SRC,DST,GXequiv) }, /* 0xc2 ~S^(P|~(D|S)) */
350 { OP(PAT,SRC,GXequiv) }, /* 0xc3 ~P^S */
351 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXand) }, /* 0xc4 S&(P|~D) */
352 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
353 OP(SRC,DST,GXequiv) }, /* 0xc5 ~S^(P|(D^S)) */
354 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXxor) },/* 0xc6 S^(D&~P) */
355 { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
356 OP(PAT,DST,GXequiv) }, /* 0xc7 ~P^(S&(D|P)) */
357 { OP(PAT,DST,GXor), OP(SRC,DST,GXand) }, /* 0xc8 S&(D|P) */
358 { OP(PAT,DST,GXor), OP(SRC,DST,GXequiv) }, /* 0xc9 ~S^(P|D) */
359 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXand),
360 OP(SRC,DST,GXxor) }, /* 0xca D^(P&(S^D)) */
361 { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
362 OP(SRC,DST,GXequiv) }, /* 0xcb ~S^(P|(D&S)) */
363 { OP(SRC,DST,GXcopy) }, /* 0xcc S */
364 { OP(PAT,DST,GXnor), OP(SRC,DST,GXor) }, /* 0xcd S|~(D|P) */
365 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXor) }, /* 0xce S|(D&~P) */
366 { OP(PAT,SRC,GXorInverted) }, /* 0xcf S|~P */
367 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXand) }, /* 0xd0 P&(S|~D) */
368 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
369 OP(PAT,DST,GXequiv) }, /* 0xd1 ~P^(S|(D^P)) */
370 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXxor) },/* 0xd2 P^(D&~S) */
371 { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
372 OP(SRC,DST,GXequiv) }, /* 0xd3 ~S^(P&(D|S)) */
373 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
374 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
375 OP(TMP,DST,GXxor) }, /* 0xd4 S^((S^P)&(D^P))*/
376 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXnand) }, /* 0xd5 ~(D&~(P&S)) */
377 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
378 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
379 OP(TMP,DST,GXxor) }, /* 0xd6 S^P^(D|(P&S)) */
380 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnand) }, /* 0xd7 ~(D&(P^S)) */
381 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
382 OP(PAT,DST,GXxor) }, /* 0xd8 P^(D&(S^P)) */
383 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
384 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0xd9 ~S^(D|(P&S)) */
385 { OP(DST,SRC,GXnand), OP(PAT,SRC,GXand),
386 OP(SRC,DST,GXxor) }, /* 0xda D^(P&~(S&D)) */
387 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
388 OP(SRC,DST,GXnand) }, /* 0xdb ~((S^P)&(S^D)) */
389 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXor) }, /* 0xdc S|(P&~D) */
390 { OP(SRC,DST,GXorReverse) }, /* 0xdd S|~D */
391 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor) }, /* 0xde S|(D^P) */
392 { OP(PAT,DST,GXnand), OP(SRC,DST,GXor) }, /* 0xdf S|~(D&P) */
393 { OP(SRC,DST,GXor), OP(PAT,DST,GXand) }, /* 0xe0 P&(D|S) */
394 { OP(SRC,DST,GXor), OP(PAT,DST,GXequiv) }, /* 0xe1 ~P^(D|S) */
395 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
396 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe2 D^(S&(P^D)) */
397 { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
398 OP(PAT,DST,GXequiv) }, /* 0xe3 ~P^(S|(D&P)) */
399 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
400 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe4 S^(D&(P^S)) */
401 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
402 OP(PAT,DST,GXequiv) }, /* 0xe5 ~P^(D|(S&P)) */
403 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
404 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe6 S^(D&~(P&S)) */
405 { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
406 OP(SRC,DST,GXnand) }, /* 0xe7 ~((S^P)&(D^P)) */
407 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
408 OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
409 OP(TMP,DST,GXxor) }, /* 0xe8 S^((S^P)&(S^D))*/
410 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnand),
411 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
412 OP(TMP,DST,GXequiv) }, /* 0xe9 ~D^S^(P&~(S&D))*/
413 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor) }, /* 0xea D|(P&S) */
414 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXor) }, /* 0xeb D|~(P^S) */
415 { OP(PAT,DST,GXand), OP(SRC,DST,GXor) }, /* 0xec S|(D&P) */
416 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXor) }, /* 0xed S|~(D^P) */
417 { OP(SRC,DST,GXor) }, /* 0xee S|D */
418 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXor) }, /* 0xef S|D|~P */
419 { OP(PAT,DST,GXcopy) }, /* 0xf0 P */
420 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor) }, /* 0xf1 P|~(D|S) */
421 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor) }, /* 0xf2 P|(D&~S) */
422 { OP(PAT,SRC,GXorReverse) }, /* 0xf3 P|~S */
423 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXor) }, /* 0xf4 P|(S&~D) */
424 { OP(PAT,DST,GXorReverse) }, /* 0xf5 P|~D */
425 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor) }, /* 0xf6 P|(D^S) */
426 { OP(SRC,DST,GXnand), OP(PAT,DST,GXor) }, /* 0xf7 P|~(S&D) */
427 { OP(SRC,DST,GXand), OP(PAT,DST,GXor) }, /* 0xf8 P|(D&S) */
428 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor) }, /* 0xf9 P|~(D^S) */
429 { OP(PAT,DST,GXor) }, /* 0xfa D|P */
430 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXor) }, /* 0xfb D|P|~S */
431 { OP(PAT,SRC,GXor) }, /* 0xfc P|S */
432 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXor) }, /* 0xfd P|S|~D */
433 { OP(SRC,DST,GXor), OP(PAT,DST,GXor) }, /* 0xfe P|D|S */
434 { OP(PAT,DST,GXset) } /* 0xff 1 */
438 #ifdef BITBLT_TEST /* Opcodes test */
440 static int do_bitop( int s, int d, int rop )
445 case GXclear: res = 0; break;
446 case GXand: res = s & d; break;
447 case GXandReverse: res = s & ~d; break;
448 case GXcopy: res = s; break;
449 case GXandInverted: res = ~s & d; break;
450 case GXnoop: res = d; break;
451 case GXxor: res = s ^ d; break;
452 case GXor: res = s | d; break;
453 case GXnor: res = ~(s | d); break;
454 case GXequiv: res = ~s ^ d; break;
455 case GXinvert: res = ~d; break;
456 case GXorReverse: res = s | ~d; break;
457 case GXcopyInverted: res = ~s; break;
458 case GXorInverted: res = ~s | d; break;
459 case GXnand: res = ~(s & d); break;
460 case GXset: res = 1; break;
467 int rop, i, res, src, dst, pat, tmp, dstUsed;
470 for (rop = 0; rop < 256; rop++)
473 for (i = 0; i < 8; i++)
478 for (opcode = BITBLT_Opcodes[rop]; *opcode; opcode++)
482 case OP_ARGS(DST,TMP):
483 tmp = do_bitop( dst, tmp, *opcode & 0xf );
485 case OP_ARGS(DST,SRC):
486 src = do_bitop( dst, src, *opcode & 0xf );
488 case OP_ARGS(SRC,TMP):
489 tmp = do_bitop( src, tmp, *opcode & 0xf );
491 case OP_ARGS(SRC,DST):
492 dst = do_bitop( src, dst, *opcode & 0xf );
495 case OP_ARGS(PAT,TMP):
496 tmp = do_bitop( pat, tmp, *opcode & 0xf );
498 case OP_ARGS(PAT,DST):
499 dst = do_bitop( pat, dst, *opcode & 0xf );
502 case OP_ARGS(PAT,SRC):
503 src = do_bitop( pat, src, *opcode & 0xf );
505 case OP_ARGS(TMP,DST):
506 dst = do_bitop( tmp, dst, *opcode & 0xf );
509 case OP_ARGS(TMP,SRC):
510 src = do_bitop( tmp, src, *opcode & 0xf );
513 printf( "Invalid opcode %x\n", *opcode );
516 if (!dstUsed) dst = src;
517 if (dst) res |= 1 << i;
519 if (res != rop) printf( "%02x: ERROR, res=%02x\n", rop, res );
523 #endif /* BITBLT_TEST */
526 /***********************************************************************
529 * Favor correctness or speed?
531 static inline int perfect_graphics(void)
533 static int perfect = -1;
534 if (perfect == -1) perfect = PROFILE_GetWineIniBool( "x11drv", "PerfectGraphics", 0 );
538 /***********************************************************************
541 * Stretch a row of pixels. Helper function for BITBLT_StretchImage.
543 static void BITBLT_StretchRow( int *rowSrc, int *rowDst,
544 INT startDst, INT widthDst,
545 INT xinc, INT xoff, WORD mode )
547 register INT xsrc = xinc * startDst + xoff;
551 case STRETCH_ANDSCANS:
552 for(; widthDst > 0; widthDst--, xsrc += xinc)
553 *rowDst++ &= rowSrc[xsrc >> 16];
555 case STRETCH_ORSCANS:
556 for(; widthDst > 0; widthDst--, xsrc += xinc)
557 *rowDst++ |= rowSrc[xsrc >> 16];
559 case STRETCH_DELETESCANS:
560 for(; widthDst > 0; widthDst--, xsrc += xinc)
561 *rowDst++ = rowSrc[xsrc >> 16];
567 /***********************************************************************
570 * Shrink a row of pixels. Helper function for BITBLT_StretchImage.
572 static void BITBLT_ShrinkRow( int *rowSrc, int *rowDst,
573 INT startSrc, INT widthSrc,
574 INT xinc, INT xoff, WORD mode )
576 register INT xdst = xinc * startSrc + xoff;
580 case STRETCH_ORSCANS:
581 for(; widthSrc > 0; widthSrc--, xdst += xinc)
582 rowDst[xdst >> 16] |= *rowSrc++;
584 case STRETCH_ANDSCANS:
585 for(; widthSrc > 0; widthSrc--, xdst += xinc)
586 rowDst[xdst >> 16] &= *rowSrc++;
588 case STRETCH_DELETESCANS:
589 for(; widthSrc > 0; widthSrc--, xdst += xinc)
590 rowDst[xdst >> 16] = *rowSrc++;
596 /***********************************************************************
599 * Retrieve a row from an image. Helper function for BITBLT_StretchImage.
601 static void BITBLT_GetRow( XImage *image, int *pdata, INT row,
602 INT start, INT width, INT depthDst,
603 int fg, int bg, BOOL swap)
607 assert( (row >= 0) && (row < image->height) );
608 assert( (start >= 0) && (width <= image->width) );
610 pdata += swap ? start+width-1 : start;
611 if (image->depth == depthDst) /* color -> color */
613 if (X11DRV_PALETTE_XPixelToPalette && (depthDst != 1))
614 if (swap) for (i = 0; i < width; i++)
615 *pdata-- = X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, i, row )];
616 else for (i = 0; i < width; i++)
617 *pdata++ = X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, i, row )];
619 if (swap) for (i = 0; i < width; i++)
620 *pdata-- = XGetPixel( image, i, row );
621 else for (i = 0; i < width; i++)
622 *pdata++ = XGetPixel( image, i, row );
626 if (image->depth == 1) /* monochrome -> color */
628 if (X11DRV_PALETTE_XPixelToPalette)
630 fg = X11DRV_PALETTE_XPixelToPalette[fg];
631 bg = X11DRV_PALETTE_XPixelToPalette[bg];
633 if (swap) for (i = 0; i < width; i++)
634 *pdata-- = XGetPixel( image, i, row ) ? bg : fg;
635 else for (i = 0; i < width; i++)
636 *pdata++ = XGetPixel( image, i, row ) ? bg : fg;
638 else /* color -> monochrome */
640 if (swap) for (i = 0; i < width; i++)
641 *pdata-- = (XGetPixel( image, i, row ) == bg) ? 1 : 0;
642 else for (i = 0; i < width; i++)
643 *pdata++ = (XGetPixel( image, i, row ) == bg) ? 1 : 0;
649 /***********************************************************************
650 * BITBLT_StretchImage
652 * Stretch an X image.
653 * FIXME: does not work for full 32-bit coordinates.
655 static void BITBLT_StretchImage( XImage *srcImage, XImage *dstImage,
656 INT widthSrc, INT heightSrc,
657 INT widthDst, INT heightDst,
658 RECT *visRectSrc, RECT *visRectDst,
659 int foreground, int background, WORD mode )
661 int *rowSrc, *rowDst, *pixel;
663 INT xinc, xoff, yinc, ysrc, ydst;
665 BOOL hstretch, vstretch, hswap, vswap;
667 hswap = ((int)widthSrc * widthDst) < 0;
668 vswap = ((int)heightSrc * heightDst) < 0;
669 widthSrc = abs(widthSrc);
670 heightSrc = abs(heightSrc);
671 widthDst = abs(widthDst);
672 heightDst = abs(heightDst);
674 if (!(rowSrc = (int *)HeapAlloc( GetProcessHeap(), 0,
675 (widthSrc+widthDst)*sizeof(int) ))) return;
676 rowDst = rowSrc + widthSrc;
678 /* When stretching, all modes are the same, and DELETESCANS is faster */
679 if ((widthSrc < widthDst) && (heightSrc < heightDst))
680 mode = STRETCH_DELETESCANS;
682 if (mode != STRETCH_DELETESCANS)
683 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
684 widthDst*sizeof(int) );
686 hstretch = (widthSrc < widthDst);
687 vstretch = (heightSrc < heightDst);
691 xinc = ((int)widthSrc << 16) / widthDst;
692 xoff = ((widthSrc << 16) - (xinc * widthDst)) / 2;
696 xinc = ((int)widthDst << 16) / widthSrc;
697 xoff = ((widthDst << 16) - (xinc * widthSrc)) / 2;
702 yinc = ((int)heightSrc << 16) / heightDst;
703 ydst = visRectDst->top;
706 ysrc = yinc * (heightDst - ydst - 1);
712 for ( ; (ydst < visRectDst->bottom); ysrc += yinc, ydst++)
714 if (((ysrc >> 16) < visRectSrc->top) ||
715 ((ysrc >> 16) >= visRectSrc->bottom)) continue;
717 /* Retrieve a source row */
718 BITBLT_GetRow( srcImage, rowSrc, (ysrc >> 16) - visRectSrc->top,
719 hswap ? widthSrc - visRectSrc->right
721 visRectSrc->right - visRectSrc->left,
722 dstImage->depth, foreground, background, hswap );
724 /* Stretch or shrink it */
726 BITBLT_StretchRow( rowSrc, rowDst, visRectDst->left,
727 visRectDst->right - visRectDst->left,
729 else BITBLT_ShrinkRow( rowSrc, rowDst,
730 hswap ? widthSrc - visRectSrc->right
732 visRectSrc->right - visRectSrc->left,
735 /* Store the destination row */
736 pixel = rowDst + visRectDst->right - 1;
737 y = ydst - visRectDst->top;
738 for (x = visRectDst->right-visRectDst->left-1; x >= 0; x--)
739 XPutPixel( dstImage, x, y, *pixel-- );
740 if (mode != STRETCH_DELETESCANS)
741 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
742 widthDst*sizeof(int) );
744 /* Make copies of the destination row */
746 pdata = dstImage->data + dstImage->bytes_per_line * y;
747 while (((ysrc + yinc) >> 16 == ysrc >> 16) &&
748 (ydst < visRectDst->bottom-1))
750 memcpy( pdata + dstImage->bytes_per_line, pdata,
751 dstImage->bytes_per_line );
752 pdata += dstImage->bytes_per_line;
760 yinc = ((int)heightDst << 16) / heightSrc;
761 ysrc = visRectSrc->top;
762 ydst = ((heightDst << 16) - (yinc * heightSrc)) / 2;
765 ydst += yinc * (heightSrc - ysrc - 1);
771 for( ; (ysrc < visRectSrc->bottom); ydst += yinc, ysrc++)
773 if (((ydst >> 16) < visRectDst->top) ||
774 ((ydst >> 16) >= visRectDst->bottom)) continue;
776 /* Retrieve a source row */
777 BITBLT_GetRow( srcImage, rowSrc, ysrc - visRectSrc->top,
778 hswap ? widthSrc - visRectSrc->right
780 visRectSrc->right - visRectSrc->left,
781 dstImage->depth, foreground, background, hswap );
783 /* Stretch or shrink it */
785 BITBLT_StretchRow( rowSrc, rowDst, visRectDst->left,
786 visRectDst->right - visRectDst->left,
788 else BITBLT_ShrinkRow( rowSrc, rowDst,
789 hswap ? widthSrc - visRectSrc->right
791 visRectSrc->right - visRectSrc->left,
794 /* Merge several source rows into the destination */
795 if (mode == STRETCH_DELETESCANS)
797 /* Simply skip the overlapping rows */
798 while (((ydst + yinc) >> 16 == ydst >> 16) &&
799 (ysrc < visRectSrc->bottom-1))
805 else if (((ydst + yinc) >> 16 == ydst >> 16) &&
806 (ysrc < visRectSrc->bottom-1))
807 continue; /* Restart loop for next overlapping row */
809 /* Store the destination row */
810 pixel = rowDst + visRectDst->right - 1;
811 y = (ydst >> 16) - visRectDst->top;
812 for (x = visRectDst->right-visRectDst->left-1; x >= 0; x--)
813 XPutPixel( dstImage, x, y, *pixel-- );
814 if (mode != STRETCH_DELETESCANS)
815 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
816 widthDst*sizeof(int) );
819 HeapFree( GetProcessHeap(), 0, rowSrc );
823 /***********************************************************************
824 * BITBLT_GetSrcAreaStretch
826 * Retrieve an area from the source DC, stretching and mapping all the
827 * pixels to Windows colors.
829 static void BITBLT_GetSrcAreaStretch( DC *dcSrc, DC *dcDst,
830 Pixmap pixmap, GC gc,
832 INT widthSrc, INT heightSrc,
834 INT widthDst, INT heightDst,
835 RECT *visRectSrc, RECT *visRectDst )
837 XImage *imageSrc, *imageDst;
838 X11DRV_PDEVICE *physDevSrc = (X11DRV_PDEVICE *)dcSrc->physDev;
839 X11DRV_PDEVICE *physDevDst = (X11DRV_PDEVICE *)dcDst->physDev;
841 RECT rectSrc = *visRectSrc;
842 RECT rectDst = *visRectDst;
844 if (widthSrc < 0) xSrc += widthSrc;
845 if (widthDst < 0) xDst += widthDst;
846 if (heightSrc < 0) ySrc += heightSrc;
847 if (heightDst < 0) yDst += heightDst;
848 rectSrc.left -= xSrc;
849 rectSrc.right -= xSrc;
851 rectSrc.bottom -= ySrc;
852 rectDst.left -= xDst;
853 rectDst.right -= xDst;
855 rectDst.bottom -= yDst;
857 /* FIXME: avoid BadMatch errors */
858 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
859 visRectSrc->left, visRectSrc->top,
860 visRectSrc->right - visRectSrc->left,
861 visRectSrc->bottom - visRectSrc->top,
862 AllPlanes, ZPixmap );
863 imageDst = X11DRV_DIB_CreateXImage( rectDst.right - rectDst.left,
864 rectDst.bottom - rectDst.top, dcDst->bitsPerPixel );
865 BITBLT_StretchImage( imageSrc, imageDst, widthSrc, heightSrc,
866 widthDst, heightDst, &rectSrc, &rectDst,
867 physDevDst->textPixel, dcDst->bitsPerPixel != 1 ?
868 physDevDst->backgroundPixel :
869 physDevSrc->backgroundPixel,
870 dcDst->stretchBltMode );
871 XPutImage( gdi_display, pixmap, gc, imageDst, 0, 0, 0, 0,
872 rectDst.right - rectDst.left, rectDst.bottom - rectDst.top );
873 XDestroyImage( imageSrc );
874 XDestroyImage( imageDst );
878 /***********************************************************************
881 * Retrieve an area from the source DC, mapping all the
882 * pixels to Windows colors.
884 static void BITBLT_GetSrcArea( DC *dcSrc, DC *dcDst, Pixmap pixmap, GC gc,
885 INT xSrc, INT ySrc, RECT *visRectSrc )
887 XImage *imageSrc, *imageDst;
889 INT width = visRectSrc->right - visRectSrc->left;
890 INT height = visRectSrc->bottom - visRectSrc->top;
891 X11DRV_PDEVICE *physDevSrc = (X11DRV_PDEVICE *)dcSrc->physDev;
892 X11DRV_PDEVICE *physDevDst = (X11DRV_PDEVICE *)dcDst->physDev;
894 if (dcSrc->bitsPerPixel == dcDst->bitsPerPixel)
896 if (!X11DRV_PALETTE_XPixelToPalette ||
897 (dcDst->bitsPerPixel == 1)) /* monochrome -> monochrome */
899 if (dcDst->bitsPerPixel == 1)
901 /* MSDN says if StretchBlt must convert a bitmap from monochrome
902 to color or vice versa, the forground and background color of
903 the device context are used. In fact, it also applies to the
904 case when it is converted from mono to mono. */
905 XSetBackground( gdi_display, gc, physDevDst->textPixel );
906 XSetForeground( gdi_display, gc, physDevDst->backgroundPixel );
907 XCopyPlane( gdi_display, physDevSrc->drawable, pixmap, gc,
908 visRectSrc->left, visRectSrc->top,
909 width, height, 0, 0, 1);
912 XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc,
913 visRectSrc->left, visRectSrc->top, width, height, 0, 0);
915 else /* color -> color */
917 if (dcSrc->flags & DC_MEMORY)
918 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
919 visRectSrc->left, visRectSrc->top,
920 width, height, AllPlanes, ZPixmap );
923 /* Make sure we don't get a BadMatch error */
924 XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc,
925 visRectSrc->left, visRectSrc->top,
926 width, height, 0, 0);
927 imageSrc = XGetImage( gdi_display, pixmap, 0, 0, width, height,
928 AllPlanes, ZPixmap );
930 for (y = 0; y < height; y++)
931 for (x = 0; x < width; x++)
932 XPutPixel(imageSrc, x, y,
933 X11DRV_PALETTE_XPixelToPalette[XGetPixel(imageSrc, x, y)]);
934 XPutImage( gdi_display, pixmap, gc, imageSrc,
935 0, 0, 0, 0, width, height );
936 XDestroyImage( imageSrc );
941 if (dcSrc->bitsPerPixel == 1) /* monochrome -> color */
943 if (X11DRV_PALETTE_XPixelToPalette)
945 XSetBackground( gdi_display, gc,
946 X11DRV_PALETTE_XPixelToPalette[physDevDst->textPixel] );
947 XSetForeground( gdi_display, gc,
948 X11DRV_PALETTE_XPixelToPalette[physDevDst->backgroundPixel]);
952 XSetBackground( gdi_display, gc, physDevDst->textPixel );
953 XSetForeground( gdi_display, gc, physDevDst->backgroundPixel );
955 XCopyPlane( gdi_display, physDevSrc->drawable, pixmap, gc,
956 visRectSrc->left, visRectSrc->top,
957 width, height, 0, 0, 1 );
959 else /* color -> monochrome */
961 /* FIXME: avoid BadMatch error */
962 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
963 visRectSrc->left, visRectSrc->top,
964 width, height, AllPlanes, ZPixmap );
965 imageDst = X11DRV_DIB_CreateXImage( width, height, dcDst->bitsPerPixel );
966 for (y = 0; y < height; y++)
967 for (x = 0; x < width; x++)
968 XPutPixel(imageDst, x, y, (XGetPixel(imageSrc,x,y) ==
969 physDevSrc->backgroundPixel) );
970 XPutImage( gdi_display, pixmap, gc, imageDst,
971 0, 0, 0, 0, width, height );
972 XDestroyImage( imageSrc );
973 XDestroyImage( imageDst );
979 /***********************************************************************
982 * Retrieve an area from the destination DC, mapping all the
983 * pixels to Windows colors.
985 static void BITBLT_GetDstArea(DC *dc, Pixmap pixmap, GC gc, RECT *visRectDst)
987 INT width = visRectDst->right - visRectDst->left;
988 INT height = visRectDst->bottom - visRectDst->top;
989 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
991 if (!X11DRV_PALETTE_XPixelToPalette || (dc->bitsPerPixel == 1) ||
992 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
994 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
995 visRectDst->left, visRectDst->top, width, height, 0, 0 );
1002 if (dc->flags & DC_MEMORY)
1003 image = XGetImage( gdi_display, physDev->drawable,
1004 visRectDst->left, visRectDst->top,
1005 width, height, AllPlanes, ZPixmap );
1008 /* Make sure we don't get a BadMatch error */
1009 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
1010 visRectDst->left, visRectDst->top, width, height, 0, 0);
1011 image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
1012 AllPlanes, ZPixmap );
1014 for (y = 0; y < height; y++)
1015 for (x = 0; x < width; x++)
1016 XPutPixel( image, x, y,
1017 X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]);
1018 XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height );
1019 XDestroyImage( image );
1024 /***********************************************************************
1027 * Put an area back into the destination DC, mapping the pixel
1028 * colors to X pixels.
1030 static void BITBLT_PutDstArea(DC *dc, Pixmap pixmap, GC gc, RECT *visRectDst)
1032 INT width = visRectDst->right - visRectDst->left;
1033 INT height = visRectDst->bottom - visRectDst->top;
1034 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
1036 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
1038 if (!X11DRV_PALETTE_PaletteToXPixel || (dc->bitsPerPixel == 1) ||
1039 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
1041 XCopyArea( gdi_display, pixmap, physDev->drawable, gc, 0, 0,
1042 width, height, visRectDst->left, visRectDst->top );
1047 XImage *image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
1048 AllPlanes, ZPixmap );
1049 for (y = 0; y < height; y++)
1050 for (x = 0; x < width; x++)
1052 XPutPixel( image, x, y,
1053 X11DRV_PALETTE_PaletteToXPixel[XGetPixel( image, x, y )]);
1055 XPutImage( gdi_display, physDev->drawable, gc, image, 0, 0,
1056 visRectDst->left, visRectDst->top, width, height );
1057 XDestroyImage( image );
1062 /***********************************************************************
1063 * BITBLT_GetVisRectangles
1065 * Get the source and destination visible rectangles for StretchBlt().
1066 * Return FALSE if one of the rectangles is empty.
1068 static BOOL BITBLT_GetVisRectangles( DC *dcDst, INT xDst, INT yDst,
1069 INT widthDst, INT heightDst,
1070 DC *dcSrc, INT xSrc, INT ySrc,
1071 INT widthSrc, INT heightSrc,
1072 RECT *visRectSrc, RECT *visRectDst )
1074 RECT rect, clipRect;
1076 /* Get the destination visible rectangle */
1080 rect.right = xDst + widthDst;
1081 rect.bottom = yDst + heightDst;
1082 if (widthDst < 0) SWAP_INT32( &rect.left, &rect.right );
1083 if (heightDst < 0) SWAP_INT32( &rect.top, &rect.bottom );
1084 GetRgnBox( dcDst->hGCClipRgn, &clipRect );
1085 if (!IntersectRect( visRectDst, &rect, &clipRect )) return FALSE;
1087 /* Get the source visible rectangle */
1089 if (!dcSrc) return TRUE;
1092 rect.right = xSrc + widthSrc;
1093 rect.bottom = ySrc + heightSrc;
1094 if (widthSrc < 0) SWAP_INT32( &rect.left, &rect.right );
1095 if (heightSrc < 0) SWAP_INT32( &rect.top, &rect.bottom );
1096 /* Apparently the clipping and visible regions are only for output,
1097 so just check against totalExtent here to avoid BadMatch errors */
1098 if (!IntersectRect( visRectSrc, &rect, &dcSrc->totalExtent ))
1101 /* Intersect the rectangles */
1103 if ((widthSrc == widthDst) && (heightSrc == heightDst)) /* no stretching */
1105 visRectSrc->left += xDst - xSrc;
1106 visRectSrc->right += xDst - xSrc;
1107 visRectSrc->top += yDst - ySrc;
1108 visRectSrc->bottom += yDst - ySrc;
1109 if (!IntersectRect( &rect, visRectSrc, visRectDst )) return FALSE;
1110 *visRectSrc = *visRectDst = rect;
1111 visRectSrc->left += xSrc - xDst;
1112 visRectSrc->right += xSrc - xDst;
1113 visRectSrc->top += ySrc - yDst;
1114 visRectSrc->bottom += ySrc - yDst;
1116 else /* stretching */
1118 /* Map source rectangle into destination coordinates */
1119 rect.left = xDst + (visRectSrc->left - xSrc)*widthDst/widthSrc;
1120 rect.top = yDst + (visRectSrc->top - ySrc)*heightDst/heightSrc;
1121 rect.right = xDst + ((visRectSrc->right - xSrc)*widthDst)/widthSrc;
1122 rect.bottom = yDst + ((visRectSrc->bottom - ySrc)*heightDst)/heightSrc;
1123 if (rect.left > rect.right) SWAP_INT32( &rect.left, &rect.right );
1124 if (rect.top > rect.bottom) SWAP_INT32( &rect.top, &rect.bottom );
1126 /* Avoid rounding errors */
1131 if (!IntersectRect( visRectDst, &rect, visRectDst )) return FALSE;
1133 /* Map destination rectangle back to source coordinates */
1135 rect.left = xSrc + (visRectDst->left - xDst)*widthSrc/widthDst;
1136 rect.top = ySrc + (visRectDst->top - yDst)*heightSrc/heightDst;
1137 rect.right = xSrc + ((visRectDst->right - xDst)*widthSrc)/widthDst;
1138 rect.bottom = ySrc + ((visRectDst->bottom - yDst)*heightSrc)/heightDst;
1139 if (rect.left > rect.right) SWAP_INT32( &rect.left, &rect.right );
1140 if (rect.top > rect.bottom) SWAP_INT32( &rect.top, &rect.bottom );
1142 /* Avoid rounding errors */
1147 if (!IntersectRect( visRectSrc, &rect, visRectSrc )) return FALSE;
1153 /***********************************************************************
1154 * BITBLT_InternalStretchBlt
1156 * Implementation of PatBlt(), BitBlt() and StretchBlt().
1158 static BOOL BITBLT_InternalStretchBlt( DC *dcDst, INT xDst, INT yDst,
1159 INT widthDst, INT heightDst,
1160 DC *dcSrc, INT xSrc, INT ySrc,
1161 INT widthSrc, INT heightSrc,
1164 BOOL usePat, useSrc, useDst, destUsed, fStretch, fNullBrush;
1165 RECT visRectDst, visRectSrc;
1168 Pixmap pixmaps[3] = { 0, 0, 0 }; /* pixmaps for DST, SRC, TMP */
1170 X11DRV_PDEVICE *physDevSrc = NULL;
1171 X11DRV_PDEVICE *physDevDst = (X11DRV_PDEVICE *)dcDst->physDev;
1173 /* compensate for off-by-one shifting for negative widths and heights */
1183 if(dcSrc) physDevSrc = (X11DRV_PDEVICE *)dcSrc->physDev;
1184 usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
1185 useSrc = (((rop >> 2) & 0x330000) != (rop & 0x330000));
1186 useDst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
1187 if (!dcSrc && useSrc) return FALSE;
1189 /* Map the coordinates to device coords */
1191 xDst = dcDst->DCOrgX + XLPTODP( dcDst, xDst );
1192 yDst = dcDst->DCOrgY + YLPTODP( dcDst, yDst );
1194 /* Here we have to round to integers, not truncate */
1195 widthDst = MulDiv(widthDst, dcDst->vportExtX, dcDst->wndExtX);
1196 heightDst = MulDiv(heightDst, dcDst->vportExtY, dcDst->wndExtY);
1198 TRACE(" vportdst=%d,%d-%d,%d wnddst=%d,%d-%d,%d\n",
1199 dcDst->vportOrgX, dcDst->vportOrgY,
1200 dcDst->vportExtX, dcDst->vportExtY,
1201 dcDst->wndOrgX, dcDst->wndOrgY,
1202 dcDst->wndExtX, dcDst->wndExtY );
1203 TRACE(" rectdst=%d,%d-%d,%d orgdst=%d,%d\n",
1204 xDst, yDst, widthDst, heightDst,
1205 dcDst->DCOrgX, dcDst->DCOrgY );
1209 xSrc = dcSrc->DCOrgX + XLPTODP( dcSrc, xSrc );
1210 ySrc = dcSrc->DCOrgY + YLPTODP( dcSrc, ySrc );
1211 widthSrc = widthSrc * dcSrc->vportExtX / dcSrc->wndExtX;
1212 heightSrc = heightSrc * dcSrc->vportExtY / dcSrc->wndExtY;
1213 fStretch = (widthSrc != widthDst) || (heightSrc != heightDst);
1214 TRACE(" vportsrc=%d,%d-%d,%d wndsrc=%d,%d-%d,%d\n",
1215 dcSrc->vportOrgX, dcSrc->vportOrgY,
1216 dcSrc->vportExtX, dcSrc->vportExtY,
1217 dcSrc->wndOrgX, dcSrc->wndOrgY,
1218 dcSrc->wndExtX, dcSrc->wndExtY );
1219 TRACE(" rectsrc=%d,%d-%d,%d orgsrc=%d,%d\n",
1220 xSrc, ySrc, widthSrc, heightSrc,
1221 dcSrc->DCOrgX, dcSrc->DCOrgY );
1222 if (!BITBLT_GetVisRectangles( dcDst, xDst, yDst, widthDst, heightDst,
1223 dcSrc, xSrc, ySrc, widthSrc, heightSrc,
1224 &visRectSrc, &visRectDst ))
1226 TRACE(" vissrc=%d,%d-%d,%d visdst=%d,%d-%d,%d\n",
1227 visRectSrc.left, visRectSrc.top,
1228 visRectSrc.right, visRectSrc.bottom,
1229 visRectDst.left, visRectDst.top,
1230 visRectDst.right, visRectDst.bottom );
1235 if (!BITBLT_GetVisRectangles( dcDst, xDst, yDst, widthDst, heightDst,
1236 NULL, 0, 0, 0, 0, NULL, &visRectDst ))
1238 TRACE(" vissrc=none visdst=%d,%d-%d,%d\n",
1239 visRectDst.left, visRectDst.top,
1240 visRectDst.right, visRectDst.bottom );
1243 width = visRectDst.right - visRectDst.left;
1244 height = visRectDst.bottom - visRectDst.top;
1246 if (!fStretch) switch(rop) /* A few optimisations */
1248 case BLACKNESS: /* 0x00 */
1249 if ((dcDst->bitsPerPixel == 1) || !X11DRV_PALETTE_PaletteToXPixel)
1250 XSetFunction( gdi_display, physDevDst->gc, GXclear );
1253 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1254 XSetForeground( gdi_display, physDevDst->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
1255 XSetFillStyle( gdi_display, physDevDst->gc, FillSolid );
1257 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
1258 visRectDst.left, visRectDst.top, width, height );
1261 case DSTINVERT: /* 0x55 */
1262 if ((dcDst->bitsPerPixel == 1) || !X11DRV_PALETTE_PaletteToXPixel ||
1263 !perfect_graphics())
1265 XSetFunction( gdi_display, physDevDst->gc, GXinvert );
1267 if( X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL) )
1268 XSetFunction( gdi_display, physDevDst->gc, GXinvert);
1271 /* Xor is much better when we do not have full colormap. */
1272 /* Using white^black ensures that we invert at least black */
1274 Pixel xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
1275 BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
1276 XSetFunction( gdi_display, physDevDst->gc, GXxor );
1277 XSetForeground( gdi_display, physDevDst->gc, xor_pix);
1278 XSetFillStyle( gdi_display, physDevDst->gc, FillSolid );
1280 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
1281 visRectDst.left, visRectDst.top, width, height );
1286 case PATINVERT: /* 0x5a */
1287 if (perfect_graphics()) break;
1288 if (X11DRV_SetupGCForBrush( dcDst ))
1290 XSetFunction( gdi_display, physDevDst->gc, GXxor );
1291 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
1292 visRectDst.left, visRectDst.top, width, height );
1297 if (perfect_graphics()) break;
1298 if (X11DRV_SetupGCForBrush( dcDst ))
1300 XSetFunction( gdi_display, physDevDst->gc, GXequiv );
1301 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
1302 visRectDst.left, visRectDst.top, width, height );
1306 case SRCCOPY: /* 0xcc */
1307 if (dcSrc->bitsPerPixel == dcDst->bitsPerPixel)
1309 BOOL expose = !(dcSrc->flags & DC_MEMORY) && !(dcDst->flags & DC_MEMORY);
1310 if ( expose ) XSetGraphicsExposures( gdi_display, physDevDst->gc, True );
1311 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1312 XCopyArea( gdi_display, physDevSrc->drawable,
1313 physDevDst->drawable, physDevDst->gc,
1314 visRectSrc.left, visRectSrc.top,
1315 width, height, visRectDst.left, visRectDst.top );
1316 if ( expose ) XSetGraphicsExposures( gdi_display, physDevDst->gc, False );
1319 if (dcSrc->bitsPerPixel == 1)
1321 BOOL expose = !(dcSrc->flags & DC_MEMORY) && !(dcDst->flags & DC_MEMORY);
1322 XSetBackground( gdi_display, physDevDst->gc, physDevDst->textPixel );
1323 XSetForeground( gdi_display, physDevDst->gc, physDevDst->backgroundPixel );
1324 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1325 if ( expose ) XSetGraphicsExposures( gdi_display, physDevDst->gc, True );
1326 XCopyPlane( gdi_display, physDevSrc->drawable,
1327 physDevDst->drawable, physDevDst->gc,
1328 visRectSrc.left, visRectSrc.top,
1329 width, height, visRectDst.left, visRectDst.top, 1 );
1330 if ( expose ) XSetGraphicsExposures( gdi_display, physDevDst->gc, False );
1335 case PATCOPY: /* 0xf0 */
1336 if (!X11DRV_SetupGCForBrush( dcDst )) return TRUE;
1337 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1338 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
1339 visRectDst.left, visRectDst.top, width, height );
1342 case WHITENESS: /* 0xff */
1343 if ((dcDst->bitsPerPixel == 1) || !X11DRV_PALETTE_PaletteToXPixel)
1344 XSetFunction( gdi_display, physDevDst->gc, GXset );
1347 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1348 XSetForeground( gdi_display, physDevDst->gc,
1349 WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
1350 XSetFillStyle( gdi_display, physDevDst->gc, FillSolid );
1352 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
1353 visRectDst.left, visRectDst.top, width, height );
1357 tmpGC = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
1358 XSetGraphicsExposures( gdi_display, tmpGC, False );
1359 pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height,
1360 dcDst->bitsPerPixel );
1363 pixmaps[SRC] = XCreatePixmap( gdi_display, root_window, width, height,
1364 dcDst->bitsPerPixel );
1366 BITBLT_GetSrcAreaStretch( dcSrc, dcDst, pixmaps[SRC], tmpGC,
1367 xSrc, ySrc, widthSrc, heightSrc,
1368 xDst, yDst, widthDst, heightDst,
1369 &visRectSrc, &visRectDst );
1371 BITBLT_GetSrcArea( dcSrc, dcDst, pixmaps[SRC], tmpGC,
1372 xSrc, ySrc, &visRectSrc );
1374 if (useDst) BITBLT_GetDstArea( dcDst, pixmaps[DST], tmpGC, &visRectDst );
1375 if (usePat) fNullBrush = !X11DRV_SetupGCForPatBlt( dcDst, tmpGC, TRUE );
1376 else fNullBrush = FALSE;
1379 for (opcode = BITBLT_Opcodes[(rop >> 16) & 0xff]; *opcode; opcode++)
1381 if (OP_DST(*opcode) == DST) destUsed = TRUE;
1382 XSetFunction( gdi_display, tmpGC, OP_ROP(*opcode) );
1383 switch(OP_SRCDST(*opcode))
1385 case OP_ARGS(DST,TMP):
1386 case OP_ARGS(SRC,TMP):
1388 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window,
1390 dcDst->bitsPerPixel );
1392 case OP_ARGS(DST,SRC):
1393 case OP_ARGS(SRC,DST):
1394 case OP_ARGS(TMP,SRC):
1395 case OP_ARGS(TMP,DST):
1396 XCopyArea( gdi_display, pixmaps[OP_SRC(*opcode)],
1397 pixmaps[OP_DST(*opcode)], tmpGC,
1398 0, 0, width, height, 0, 0 );
1401 case OP_ARGS(PAT,TMP):
1402 if (!pixmaps[TMP] && !fNullBrush)
1403 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window,
1405 dcDst->bitsPerPixel );
1407 case OP_ARGS(PAT,DST):
1408 case OP_ARGS(PAT,SRC):
1410 XFillRectangle( gdi_display, pixmaps[OP_DST(*opcode)],
1411 tmpGC, 0, 0, width, height );
1415 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1416 BITBLT_PutDstArea( dcDst, pixmaps[destUsed ? DST : SRC],
1417 physDevDst->gc, &visRectDst );
1418 XFreePixmap( gdi_display, pixmaps[DST] );
1419 if (pixmaps[SRC]) XFreePixmap( gdi_display, pixmaps[SRC] );
1420 if (pixmaps[TMP]) XFreePixmap( gdi_display, pixmaps[TMP] );
1421 XFreeGC( gdi_display, tmpGC );
1426 /***********************************************************************
1429 BOOL X11DRV_PatBlt( DC *dc, INT left, INT top,
1430 INT width, INT height, DWORD rop )
1434 X11DRV_LockDIBSection( dc, DIB_Status_GdiMod, FALSE );
1436 result = BITBLT_InternalStretchBlt( dc, left, top, width, height, NULL, 0, 0, 0, 0, rop );
1437 wine_tsx11_unlock();
1438 X11DRV_UnlockDIBSection( dc, TRUE );
1443 /***********************************************************************
1446 BOOL X11DRV_BitBlt( DC *dcDst, INT xDst, INT yDst,
1447 INT width, INT height, DC *dcSrc,
1448 INT xSrc, INT ySrc, DWORD rop )
1450 BOOL result = FALSE;
1452 RECT visRectDst, visRectSrc;
1454 if (((rop >> 16) & 0x55) == ((rop >> 17) & 0x55)) {
1455 /* FIXME: seems the ROP doesn't include destination;
1456 * now if the destination area include the entire dcDst,
1457 * we can pass TRUE instead of FALSE to CoerceDIBSection(dcDst...),
1458 * which may avoid a copy in some situations */
1460 sDst = X11DRV_LockDIBSection( dcDst, DIB_Status_None, FALSE );
1461 sSrc = X11DRV_LockDIBSection( dcSrc, DIB_Status_None, FALSE );
1463 if ((sSrc == DIB_Status_AppMod) && (rop == SRCCOPY)) {
1464 /* do everything ourselves; map coordinates */
1465 xSrc = dcSrc->DCOrgX + XLPTODP( dcSrc, xSrc );
1466 ySrc = dcSrc->DCOrgY + YLPTODP( dcSrc, ySrc );
1467 xDst = dcDst->DCOrgX + XLPTODP( dcDst, xDst );
1468 yDst = dcDst->DCOrgY + YLPTODP( dcDst, yDst );
1469 width = MulDiv(width, dcDst->vportExtX, dcDst->wndExtX);
1470 height = MulDiv(height, dcDst->vportExtY, dcDst->wndExtY);
1472 /* Perform basic clipping */
1473 if (!BITBLT_GetVisRectangles( dcDst, xDst, yDst, width, height,
1474 dcSrc, xSrc, ySrc, width, height,
1475 &visRectSrc, &visRectDst ))
1478 xSrc = visRectSrc.left;
1479 ySrc = visRectSrc.top;
1480 xDst = visRectDst.left;
1481 yDst = visRectDst.top;
1482 width = visRectDst.right - visRectDst.left;
1483 height = visRectDst.bottom - visRectDst.top;
1485 if (sDst == DIB_Status_AppMod) {
1486 FIXME("potential optimization - client-side DIB copy\n");
1488 X11DRV_CoerceDIBSection( dcDst, DIB_Status_GdiMod, FALSE );
1490 X11DRV_DIB_CopyDIBSection( dcSrc, dcDst, xSrc, ySrc, xDst, yDst, width, height );
1495 X11DRV_CoerceDIBSection( dcDst, DIB_Status_GdiMod, FALSE );
1496 X11DRV_CoerceDIBSection( dcSrc, DIB_Status_GdiMod, FALSE );
1499 result = BITBLT_InternalStretchBlt( dcDst, xDst, yDst, width, height,
1500 dcSrc, xSrc, ySrc, width, height, rop );
1501 wine_tsx11_unlock();
1504 X11DRV_UnlockDIBSection( dcSrc, FALSE );
1505 X11DRV_UnlockDIBSection( dcDst, TRUE );
1511 /***********************************************************************
1514 BOOL X11DRV_StretchBlt( DC *dcDst, INT xDst, INT yDst,
1515 INT widthDst, INT heightDst,
1516 DC *dcSrc, INT xSrc, INT ySrc,
1517 INT widthSrc, INT heightSrc, DWORD rop )
1521 X11DRV_LockDIBSection( dcDst, DIB_Status_GdiMod, FALSE );
1522 X11DRV_LockDIBSection( dcSrc, DIB_Status_GdiMod, FALSE );
1525 result = BITBLT_InternalStretchBlt( dcDst, xDst, yDst, widthDst, heightDst,
1526 dcSrc, xSrc, ySrc, widthSrc, heightSrc, rop );
1527 wine_tsx11_unlock();
1529 X11DRV_UnlockDIBSection( dcSrc, FALSE );
1530 X11DRV_UnlockDIBSection( dcDst, TRUE );