2 * GDI bit-blit operations
4 * Copyright 1993, 1994 Alexandre Julliard
5 * Copyright 2006 Damjan Jovanovic
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(bitblt
);
40 #define DST 0 /* Destination drawable */
41 #define SRC 1 /* Source drawable */
42 #define TMP 2 /* Temporary drawable */
43 #define PAT 3 /* Pattern (brush) in destination DC */
45 #define OP(src,dst,rop) (OP_ARGS(src,dst) << 4 | (rop))
46 #define OP_ARGS(src,dst) (((src) << 2) | (dst))
48 #define OP_SRC(opcode) ((opcode) >> 6)
49 #define OP_DST(opcode) (((opcode) >> 4) & 3)
50 #define OP_SRCDST(opcode) ((opcode) >> 4)
51 #define OP_ROP(opcode) ((opcode) & 0x0f)
53 #define MAX_OP_LEN 6 /* Longest opcode + 1 for the terminating 0 */
55 #define SWAP_INT32(i1,i2) \
56 do { INT __t = *(i1); *(i1) = *(i2); *(i2) = __t; } while(0)
58 static const unsigned char BITBLT_Opcodes
[256][MAX_OP_LEN
] =
60 { OP(PAT
,DST
,GXclear
) }, /* 0x00 0 */
61 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXnor
) }, /* 0x01 ~(D|(P|S)) */
62 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXand
) }, /* 0x02 D&~(P|S) */
63 { OP(PAT
,SRC
,GXnor
) }, /* 0x03 ~(P|S) */
64 { OP(PAT
,DST
,GXnor
), OP(SRC
,DST
,GXand
) }, /* 0x04 S&~(D|P) */
65 { OP(PAT
,DST
,GXnor
) }, /* 0x05 ~(D|P) */
66 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXnor
), }, /* 0x06 ~(P|~(D^S)) */
67 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXnor
) }, /* 0x07 ~(P|(D&S)) */
68 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXand
) },/* 0x08 S&D&~P */
69 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXnor
) }, /* 0x09 ~(P|(D^S)) */
70 { OP(PAT
,DST
,GXandInverted
) }, /* 0x0a D&~P */
71 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXnor
) }, /* 0x0b ~(P|(S&~D)) */
72 { OP(PAT
,SRC
,GXandInverted
) }, /* 0x0c S&~P */
73 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXnor
) },/* 0x0d ~(P|(D&~S)) */
74 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXnor
) }, /* 0x0e ~(P|~(D|S)) */
75 { OP(PAT
,DST
,GXcopyInverted
) }, /* 0x0f ~P */
76 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXand
) }, /* 0x10 P&~(S|D) */
77 { OP(SRC
,DST
,GXnor
) }, /* 0x11 ~(D|S) */
78 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXnor
) }, /* 0x12 ~(S|~(D^P)) */
79 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXnor
) }, /* 0x13 ~(S|(D&P)) */
80 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXnor
) }, /* 0x14 ~(D|~(P^S)) */
81 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXnor
) }, /* 0x15 ~(D|(P&S)) */
82 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,TMP
,GXnand
),
83 OP(TMP
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
84 OP(PAT
,DST
,GXxor
) }, /* 0x16 P^S^(D&~(P&S) */
85 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
86 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
87 OP(TMP
,DST
,GXequiv
) }, /* 0x17 ~S^((S^P)&(S^D))*/
88 { OP(PAT
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
89 OP(SRC
,DST
,GXand
) }, /* 0x18 (S^P)&(D^P) */
90 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,TMP
,GXnand
),
91 OP(TMP
,DST
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x19 ~S^(D&~(P&S)) */
92 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
),
93 OP(PAT
,DST
,GXxor
) }, /* 0x1a P^(D|(S&P)) */
94 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,TMP
,GXxor
),
95 OP(TMP
,DST
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x1b ~S^(D&(P^S)) */
96 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
),
97 OP(PAT
,DST
,GXxor
) }, /* 0x1c P^(S|(D&P)) */
98 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
99 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x1d ~D^(S&(D^P)) */
100 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
) }, /* 0x1e P^(D|S) */
101 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXnand
) }, /* 0x1f ~(P&(D|S)) */
102 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXand
) }, /* 0x20 D&(P&~S) */
103 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXnor
) }, /* 0x21 ~(S|(D^P)) */
104 { OP(SRC
,DST
,GXandInverted
) }, /* 0x22 ~S&D */
105 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXnor
) }, /* 0x23 ~(S|(P&~D)) */
106 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
107 OP(SRC
,DST
,GXand
) }, /* 0x24 (S^P)&(S^D) */
108 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXand
),
109 OP(PAT
,DST
,GXequiv
) }, /* 0x25 ~P^(D&~(S&P)) */
110 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,TMP
,GXand
),
111 OP(TMP
,DST
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x26 S^(D|(S&P)) */
112 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,TMP
,GXequiv
),
113 OP(TMP
,DST
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x27 S^(D|~(P^S)) */
114 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
) }, /* 0x28 D&(P^S) */
115 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,TMP
,GXand
),
116 OP(TMP
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
117 OP(PAT
,DST
,GXequiv
) }, /* 0x29 ~P^S^(D|(P&S)) */
118 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXand
) }, /* 0x2a D&~(P&S) */
119 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
120 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
121 OP(TMP
,DST
,GXequiv
) }, /* 0x2b ~S^((P^S)&(P^D))*/
122 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
),
123 OP(SRC
,DST
,GXxor
) }, /* 0x2c S^(P&(S|D)) */
124 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXxor
) }, /* 0x2d P^(S|~D) */
125 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
),
126 OP(PAT
,DST
,GXxor
) }, /* 0x2e P^(S|(D^P)) */
127 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXnand
) }, /* 0x2f ~(P&(S|~D)) */
128 { OP(PAT
,SRC
,GXandReverse
) }, /* 0x30 P&~S */
129 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXnor
) },/* 0x31 ~(S|(D&~P)) */
130 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXor
),
131 OP(SRC
,DST
,GXxor
) }, /* 0x32 S^(D|P|S) */
132 { OP(SRC
,DST
,GXcopyInverted
) }, /* 0x33 ~S */
133 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
),
134 OP(SRC
,DST
,GXxor
) }, /* 0x34 S^(P|(D&S)) */
135 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXor
),
136 OP(SRC
,DST
,GXxor
) }, /* 0x35 S^(P|~(D^S)) */
137 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x36 S^(D|P) */
138 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXnand
) }, /* 0x37 ~(S&(D|P)) */
139 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
),
140 OP(PAT
,DST
,GXxor
) }, /* 0x38 P^(S&(D|P)) */
141 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x39 S^(P|~D) */
142 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
),
143 OP(SRC
,DST
,GXxor
) }, /* 0x3a S^(P|(D^S)) */
144 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXnand
) }, /* 0x3b ~(S&(P|~D)) */
145 { OP(PAT
,SRC
,GXxor
) }, /* 0x3c P^S */
146 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
),
147 OP(SRC
,DST
,GXxor
) }, /* 0x3d S^(P|~(D|S)) */
148 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
),
149 OP(SRC
,DST
,GXxor
) }, /* 0x3e S^(P|(D&~S)) */
150 { OP(PAT
,SRC
,GXnand
) }, /* 0x3f ~(P&S) */
151 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXand
) }, /* 0x40 P&S&~D */
152 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXnor
) }, /* 0x41 ~(D|(P^S)) */
153 { OP(DST
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
154 OP(SRC
,DST
,GXand
) }, /* 0x42 (S^D)&(P^D) */
155 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
),
156 OP(SRC
,DST
,GXequiv
) }, /* 0x43 ~S^(P&~(D&S)) */
157 { OP(SRC
,DST
,GXandReverse
) }, /* 0x44 S&~D */
158 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXnor
) }, /* 0x45 ~(D|(P&~S)) */
159 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
160 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x46 D^(S|(P&D)) */
161 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
162 OP(PAT
,DST
,GXequiv
) }, /* 0x47 ~P^(S&(D^P)) */
163 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
) }, /* 0x48 S&(P^D) */
164 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
165 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
),
166 OP(PAT
,DST
,GXequiv
) }, /* 0x49 ~P^D^(S|(P&D)) */
167 { OP(DST
,SRC
,GXor
), OP(PAT
,SRC
,GXand
),
168 OP(SRC
,DST
,GXxor
) }, /* 0x4a D^(P&(S|D)) */
169 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXxor
) }, /* 0x4b P^(D|~S) */
170 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXand
) }, /* 0x4c S&~(D&P) */
171 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
172 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
173 OP(TMP
,DST
,GXequiv
) }, /* 0x4d ~S^((S^P)|(S^D))*/
174 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
175 OP(PAT
,DST
,GXxor
) }, /* 0x4e P^(D|(S^P)) */
176 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXnand
) },/* 0x4f ~(P&(D|~S)) */
177 { OP(PAT
,DST
,GXandReverse
) }, /* 0x50 P&~D */
178 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXnor
) },/* 0x51 ~(D|(S&~P)) */
179 { OP(DST
,SRC
,GXand
), OP(PAT
,SRC
,GXor
),
180 OP(SRC
,DST
,GXxor
) }, /* 0x52 D^(P|(S&D)) */
181 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
),
182 OP(SRC
,DST
,GXequiv
) }, /* 0x53 ~S^(P&(D^S)) */
183 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXnor
) }, /* 0x54 ~(D|~(P|S)) */
184 { OP(PAT
,DST
,GXinvert
) }, /* 0x55 ~D */
185 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x56 D^(P|S) */
186 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXnand
) }, /* 0x57 ~(D&(P|S)) */
187 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
),
188 OP(PAT
,DST
,GXxor
) }, /* 0x58 P^(D&(P|S)) */
189 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x59 D^(P|~S) */
190 { OP(PAT
,DST
,GXxor
) }, /* 0x5a D^P */
191 { OP(DST
,SRC
,GXnor
), OP(PAT
,SRC
,GXor
),
192 OP(SRC
,DST
,GXxor
) }, /* 0x5b D^(P|~(S|D)) */
193 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXor
),
194 OP(SRC
,DST
,GXxor
) }, /* 0x5c D^(P|(S^D)) */
195 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXnand
) }, /* 0x5d ~(D&(P|~S)) */
196 { OP(DST
,SRC
,GXandInverted
), OP(PAT
,SRC
,GXor
),
197 OP(SRC
,DST
,GXxor
) }, /* 0x5e D^(P|(S&~D)) */
198 { OP(PAT
,DST
,GXnand
) }, /* 0x5f ~(D&P) */
199 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
) }, /* 0x60 P&(D^S) */
200 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXand
),
201 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
202 OP(TMP
,DST
,GXequiv
) }, /* 0x61 ~D^S^(P|(D&S)) */
203 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
204 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x62 D^(S&(P|D)) */
205 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXxor
) }, /* 0x63 S^(D|~P) */
206 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
207 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x64 S^(D&(P|S)) */
208 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXxor
) }, /* 0x65 D^(S|~P) */
209 { OP(SRC
,DST
,GXxor
) }, /* 0x66 S^D */
210 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
211 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x67 S^(D|~(S|P) */
212 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXnor
),
213 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
214 OP(TMP
,DST
,GXequiv
) }, /* 0x68 ~D^S^(P|~(D|S))*/
215 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXequiv
) }, /* 0x69 ~P^(D^S) */
216 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXxor
) }, /* 0x6a D^(P&S) */
217 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
218 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
),
219 OP(PAT
,DST
,GXequiv
) }, /* 0x6b ~P^S^(D&(P|S)) */
220 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
) }, /* 0x6c S^(D&P) */
221 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
222 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
),
223 OP(PAT
,DST
,GXequiv
) }, /* 0x6d ~P^D^(S&(P|D)) */
224 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXorReverse
),
225 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x6e S^(D&(P|~S)) */
226 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXnand
) }, /* 0x6f ~(P&~(S^D)) */
227 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
) }, /* 0x70 P&~(D&S) */
228 { OP(SRC
,TMP
,GXcopy
), OP(DST
,SRC
,GXxor
),
229 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
230 OP(TMP
,DST
,GXequiv
) }, /* 0x71 ~S^((S^D)&(P^D))*/
231 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
232 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x72 S^(D|(P^S)) */
233 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXnand
) },/* 0x73 ~(S&(D|~P)) */
234 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
235 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x74 D^(S|(P^D)) */
236 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXnand
) },/* 0x75 ~(D&(S|~P)) */
237 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXandReverse
),
238 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x76 S^(D|(P&~S)) */
239 { OP(SRC
,DST
,GXnand
) }, /* 0x77 ~(S&D) */
240 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
) }, /* 0x78 P^(D&S) */
241 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXor
),
242 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
243 OP(TMP
,DST
,GXequiv
) }, /* 0x79 ~D^S^(P&(D|S)) */
244 { OP(DST
,SRC
,GXorInverted
), OP(PAT
,SRC
,GXand
),
245 OP(SRC
,DST
,GXxor
) }, /* 0x7a D^(P&(S|~D)) */
246 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXnand
) }, /* 0x7b ~(S&~(D^P)) */
247 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
),
248 OP(SRC
,DST
,GXxor
) }, /* 0x7c S^(P&(D|~S)) */
249 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXnand
) }, /* 0x7d ~(D&~(P^S)) */
250 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
251 OP(SRC
,DST
,GXor
) }, /* 0x7e (S^P)|(S^D) */
252 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXnand
) }, /* 0x7f ~(D&P&S) */
253 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXand
) }, /* 0x80 D&P&S */
254 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
255 OP(SRC
,DST
,GXnor
) }, /* 0x81 ~((S^P)|(S^D)) */
256 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXand
) }, /* 0x82 D&~(P^S) */
257 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
),
258 OP(SRC
,DST
,GXequiv
) }, /* 0x83 ~S^(P&(D|~S)) */
259 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXand
) }, /* 0x84 S&~(D^P) */
260 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXand
),
261 OP(PAT
,DST
,GXequiv
) }, /* 0x85 ~P^(D&(S|~P)) */
262 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXor
),
263 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
264 OP(TMP
,DST
,GXxor
) }, /* 0x86 D^S^(P&(D|S)) */
265 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXequiv
) }, /* 0x87 ~P^(D&S) */
266 { OP(SRC
,DST
,GXand
) }, /* 0x88 S&D */
267 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXandReverse
),
268 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x89 ~S^(D|(P&~S)) */
269 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXand
) }, /* 0x8a D&(S|~P) */
270 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
271 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x8b ~D^(S|(P^D)) */
272 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXand
) }, /* 0x8c S&(D|~P) */
273 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
274 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x8d ~S^(D|(P^S)) */
275 { OP(SRC
,TMP
,GXcopy
), OP(DST
,SRC
,GXxor
),
276 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
277 OP(TMP
,DST
,GXxor
) }, /* 0x8e S^((S^D)&(P^D))*/
278 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXnand
) }, /* 0x8f ~(P&~(D&S)) */
279 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXand
) }, /* 0x90 P&~(D^S) */
280 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXorReverse
),
281 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x91 ~S^(D&(P|~S)) */
282 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
283 OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
),
284 OP(TMP
,DST
,GXxor
) }, /* 0x92 D^P^(S&(D|P)) */
285 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x93 ~S^(P&D) */
286 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
287 OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
),
288 OP(TMP
,DST
,GXxor
) }, /* 0x94 S^P^(D&(P|S)) */
289 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x95 ~D^(P&S) */
290 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXxor
) }, /* 0x96 D^P^S */
291 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
292 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
293 OP(TMP
,DST
,GXxor
) }, /* 0x97 S^P^(D|~(P|S)) */
294 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
295 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x98 ~S^(D|~(P|S)) */
296 { OP(SRC
,DST
,GXequiv
) }, /* 0x99 ~S^D */
297 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x9a D^(P&~S) */
298 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
299 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x9b ~S^(D&(P|S)) */
300 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x9c S^(P&~D) */
301 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
302 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x9d ~D^(S&(P|D)) */
303 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXand
),
304 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
305 OP(TMP
,DST
,GXxor
) }, /* 0x9e D^S^(P|(D&S)) */
306 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXnand
) }, /* 0x9f ~(P&(D^S)) */
307 { OP(PAT
,DST
,GXand
) }, /* 0xa0 D&P */
308 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXor
),
309 OP(PAT
,DST
,GXequiv
) }, /* 0xa1 ~P^(D|(S&~P)) */
310 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXand
) }, /* 0xa2 D&(P|~S) */
311 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXor
),
312 OP(SRC
,DST
,GXequiv
) }, /* 0xa3 ~D^(P|(S^D)) */
313 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXor
),
314 OP(PAT
,DST
,GXequiv
) }, /* 0xa4 ~P^(D|~(S|P)) */
315 { OP(PAT
,DST
,GXequiv
) }, /* 0xa5 ~P^D */
316 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXxor
) },/* 0xa6 D^(S&~P) */
317 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
),
318 OP(PAT
,DST
,GXequiv
) }, /* 0xa7 ~P^(D&(S|P)) */
319 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
) }, /* 0xa8 D&(P|S) */
320 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXequiv
) }, /* 0xa9 ~D^(P|S) */
321 { OP(SRC
,DST
,GXnoop
) }, /* 0xaa D */
322 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXor
) }, /* 0xab D|~(P|S) */
323 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
),
324 OP(SRC
,DST
,GXxor
) }, /* 0xac S^(P&(D^S)) */
325 { OP(DST
,SRC
,GXand
), OP(PAT
,SRC
,GXor
),
326 OP(SRC
,DST
,GXequiv
) }, /* 0xad ~D^(P|(S&D)) */
327 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXor
) }, /* 0xae D|(S&~P) */
328 { OP(PAT
,DST
,GXorInverted
) }, /* 0xaf D|~P */
329 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
) }, /* 0xb0 P&(D|~S) */
330 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
331 OP(PAT
,DST
,GXequiv
) }, /* 0xb1 ~P^(D|(S^P)) */
332 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
333 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
334 OP(TMP
,DST
,GXxor
) }, /* 0xb2 S^((S^P)|(S^D))*/
335 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXnand
) }, /* 0xb3 ~(S&~(D&P)) */
336 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXxor
) }, /* 0xb4 P^(S&~D) */
337 { OP(DST
,SRC
,GXor
), OP(PAT
,SRC
,GXand
),
338 OP(SRC
,DST
,GXequiv
) }, /* 0xb5 ~D^(P&(S|D)) */
339 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
340 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
341 OP(TMP
,DST
,GXxor
) }, /* 0xb6 D^P^(S|(D&P)) */
342 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXnand
) }, /* 0xb7 ~(S&(D^P)) */
343 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
344 OP(PAT
,DST
,GXxor
) }, /* 0xb8 P^(S&(D^P)) */
345 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
346 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0xb9 ~D^(S|(P&D)) */
347 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXor
) }, /* 0xba D|(P&~S) */
348 { OP(SRC
,DST
,GXorInverted
) }, /* 0xbb ~S|D */
349 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
),
350 OP(SRC
,DST
,GXxor
) }, /* 0xbc S^(P&~(D&S)) */
351 { OP(DST
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
352 OP(SRC
,DST
,GXnand
) }, /* 0xbd ~((S^D)&(P^D)) */
353 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
) }, /* 0xbe D|(P^S) */
354 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXor
) }, /* 0xbf D|~(P&S) */
355 { OP(PAT
,SRC
,GXand
) }, /* 0xc0 P&S */
356 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
),
357 OP(SRC
,DST
,GXequiv
) }, /* 0xc1 ~S^(P|(D&~S)) */
358 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
),
359 OP(SRC
,DST
,GXequiv
) }, /* 0xc2 ~S^(P|~(D|S)) */
360 { OP(PAT
,SRC
,GXequiv
) }, /* 0xc3 ~P^S */
361 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXand
) }, /* 0xc4 S&(P|~D) */
362 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
),
363 OP(SRC
,DST
,GXequiv
) }, /* 0xc5 ~S^(P|(D^S)) */
364 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXxor
) },/* 0xc6 S^(D&~P) */
365 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
),
366 OP(PAT
,DST
,GXequiv
) }, /* 0xc7 ~P^(S&(D|P)) */
367 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
) }, /* 0xc8 S&(D|P) */
368 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXequiv
) }, /* 0xc9 ~S^(P|D) */
369 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXand
),
370 OP(SRC
,DST
,GXxor
) }, /* 0xca D^(P&(S^D)) */
371 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
),
372 OP(SRC
,DST
,GXequiv
) }, /* 0xcb ~S^(P|(D&S)) */
373 { OP(SRC
,DST
,GXcopy
) }, /* 0xcc S */
374 { OP(PAT
,DST
,GXnor
), OP(SRC
,DST
,GXor
) }, /* 0xcd S|~(D|P) */
375 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXor
) }, /* 0xce S|(D&~P) */
376 { OP(PAT
,SRC
,GXorInverted
) }, /* 0xcf S|~P */
377 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXand
) }, /* 0xd0 P&(S|~D) */
378 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
),
379 OP(PAT
,DST
,GXequiv
) }, /* 0xd1 ~P^(S|(D^P)) */
380 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXxor
) },/* 0xd2 P^(D&~S) */
381 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
),
382 OP(SRC
,DST
,GXequiv
) }, /* 0xd3 ~S^(P&(D|S)) */
383 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
384 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
385 OP(TMP
,DST
,GXxor
) }, /* 0xd4 S^((S^P)&(D^P))*/
386 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXnand
) }, /* 0xd5 ~(D&~(P&S)) */
387 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
388 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
389 OP(TMP
,DST
,GXxor
) }, /* 0xd6 S^P^(D|(P&S)) */
390 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXnand
) }, /* 0xd7 ~(D&(P^S)) */
391 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
392 OP(PAT
,DST
,GXxor
) }, /* 0xd8 P^(D&(S^P)) */
393 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
394 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0xd9 ~S^(D|(P&S)) */
395 { OP(DST
,SRC
,GXnand
), OP(PAT
,SRC
,GXand
),
396 OP(SRC
,DST
,GXxor
) }, /* 0xda D^(P&~(S&D)) */
397 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
398 OP(SRC
,DST
,GXnand
) }, /* 0xdb ~((S^P)&(S^D)) */
399 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXor
) }, /* 0xdc S|(P&~D) */
400 { OP(SRC
,DST
,GXorReverse
) }, /* 0xdd S|~D */
401 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
) }, /* 0xde S|(D^P) */
402 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXor
) }, /* 0xdf S|~(D&P) */
403 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
) }, /* 0xe0 P&(D|S) */
404 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXequiv
) }, /* 0xe1 ~P^(D|S) */
405 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
406 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe2 D^(S&(P^D)) */
407 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
),
408 OP(PAT
,DST
,GXequiv
) }, /* 0xe3 ~P^(S|(D&P)) */
409 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
410 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe4 S^(D&(P^S)) */
411 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
),
412 OP(PAT
,DST
,GXequiv
) }, /* 0xe5 ~P^(D|(S&P)) */
413 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnand
),
414 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe6 S^(D&~(P&S)) */
415 { OP(PAT
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
416 OP(SRC
,DST
,GXnand
) }, /* 0xe7 ~((S^P)&(D^P)) */
417 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
418 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
419 OP(TMP
,DST
,GXxor
) }, /* 0xe8 S^((S^P)&(S^D))*/
420 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXnand
),
421 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
422 OP(TMP
,DST
,GXequiv
) }, /* 0xe9 ~D^S^(P&~(S&D))*/
423 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
) }, /* 0xea D|(P&S) */
424 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXor
) }, /* 0xeb D|~(P^S) */
425 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
) }, /* 0xec S|(D&P) */
426 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXor
) }, /* 0xed S|~(D^P) */
427 { OP(SRC
,DST
,GXor
) }, /* 0xee S|D */
428 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXor
) }, /* 0xef S|D|~P */
429 { OP(PAT
,DST
,GXcopy
) }, /* 0xf0 P */
430 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
) }, /* 0xf1 P|~(D|S) */
431 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
) }, /* 0xf2 P|(D&~S) */
432 { OP(PAT
,SRC
,GXorReverse
) }, /* 0xf3 P|~S */
433 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXor
) }, /* 0xf4 P|(S&~D) */
434 { OP(PAT
,DST
,GXorReverse
) }, /* 0xf5 P|~D */
435 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
) }, /* 0xf6 P|(D^S) */
436 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXor
) }, /* 0xf7 P|~(S&D) */
437 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
) }, /* 0xf8 P|(D&S) */
438 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXor
) }, /* 0xf9 P|~(D^S) */
439 { OP(PAT
,DST
,GXor
) }, /* 0xfa D|P */
440 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXor
) }, /* 0xfb D|P|~S */
441 { OP(PAT
,SRC
,GXor
) }, /* 0xfc P|S */
442 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXor
) }, /* 0xfd P|S|~D */
443 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXor
) }, /* 0xfe P|D|S */
444 { OP(PAT
,DST
,GXset
) } /* 0xff 1 */
448 #ifdef BITBLT_TEST /* Opcodes test */
450 static int do_bitop( int s
, int d
, int rop
)
455 case GXclear
: res
= 0; break;
456 case GXand
: res
= s
& d
; break;
457 case GXandReverse
: res
= s
& ~d
; break;
458 case GXcopy
: res
= s
; break;
459 case GXandInverted
: res
= ~s
& d
; break;
460 case GXnoop
: res
= d
; break;
461 case GXxor
: res
= s
^ d
; break;
462 case GXor
: res
= s
| d
; break;
463 case GXnor
: res
= ~(s
| d
); break;
464 case GXequiv
: res
= ~s
^ d
; break;
465 case GXinvert
: res
= ~d
; break;
466 case GXorReverse
: res
= s
| ~d
; break;
467 case GXcopyInverted
: res
= ~s
; break;
468 case GXorInverted
: res
= ~s
| d
; break;
469 case GXnand
: res
= ~(s
& d
); break;
470 case GXset
: res
= 1; break;
477 int rop
, i
, res
, src
, dst
, pat
, tmp
, dstUsed
;
480 for (rop
= 0; rop
< 256; rop
++)
483 for (i
= 0; i
< 8; i
++)
488 for (opcode
= BITBLT_Opcodes
[rop
]; *opcode
; opcode
++)
492 case OP_ARGS(DST
,TMP
):
493 tmp
= do_bitop( dst
, tmp
, *opcode
& 0xf );
495 case OP_ARGS(DST
,SRC
):
496 src
= do_bitop( dst
, src
, *opcode
& 0xf );
498 case OP_ARGS(SRC
,TMP
):
499 tmp
= do_bitop( src
, tmp
, *opcode
& 0xf );
501 case OP_ARGS(SRC
,DST
):
502 dst
= do_bitop( src
, dst
, *opcode
& 0xf );
505 case OP_ARGS(PAT
,TMP
):
506 tmp
= do_bitop( pat
, tmp
, *opcode
& 0xf );
508 case OP_ARGS(PAT
,DST
):
509 dst
= do_bitop( pat
, dst
, *opcode
& 0xf );
512 case OP_ARGS(PAT
,SRC
):
513 src
= do_bitop( pat
, src
, *opcode
& 0xf );
515 case OP_ARGS(TMP
,DST
):
516 dst
= do_bitop( tmp
, dst
, *opcode
& 0xf );
519 case OP_ARGS(TMP
,SRC
):
520 src
= do_bitop( tmp
, src
, *opcode
& 0xf );
523 printf( "Invalid opcode %x\n", *opcode
);
526 if (!dstUsed
) dst
= src
;
527 if (dst
) res
|= 1 << i
;
529 if (res
!= rop
) printf( "%02x: ERROR, res=%02x\n", rop
, res
);
535 #endif /* BITBLT_TEST */
538 static void get_colors(X11DRV_PDEVICE
*physDevDst
, X11DRV_PDEVICE
*physDevSrc
,
543 *fg
= physDevDst
->textPixel
;
544 *bg
= physDevDst
->backgroundPixel
;
545 if(physDevSrc
->depth
== 1) {
546 if(GetDIBColorTable(physDevSrc
->hdc
, 0, 2, rgb
) == 2) {
548 logcolor
= RGB(rgb
[0].rgbRed
, rgb
[0].rgbGreen
, rgb
[0].rgbBlue
);
549 *fg
= X11DRV_PALETTE_ToPhysical( physDevDst
, logcolor
);
550 logcolor
= RGB(rgb
[1].rgbRed
, rgb
[1].rgbGreen
,rgb
[1].rgbBlue
);
551 *bg
= X11DRV_PALETTE_ToPhysical( physDevDst
, logcolor
);
556 /***********************************************************************
559 * Stretch a row of pixels. Helper function for BITBLT_StretchImage.
561 static void BITBLT_StretchRow( int *rowSrc
, int *rowDst
,
562 INT startDst
, INT widthDst
,
563 INT xinc
, INT xoff
, WORD mode
)
565 register INT xsrc
= xinc
* startDst
+ xoff
;
569 case STRETCH_ANDSCANS
:
570 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
571 *rowDst
++ &= rowSrc
[xsrc
>> 16];
573 case STRETCH_ORSCANS
:
574 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
575 *rowDst
++ |= rowSrc
[xsrc
>> 16];
577 case STRETCH_DELETESCANS
:
578 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
579 *rowDst
++ = rowSrc
[xsrc
>> 16];
585 /***********************************************************************
588 * Shrink a row of pixels. Helper function for BITBLT_StretchImage.
590 static void BITBLT_ShrinkRow( int *rowSrc
, int *rowDst
,
591 INT startSrc
, INT widthSrc
,
592 INT xinc
, INT xoff
, WORD mode
)
594 register INT xdst
= xinc
* startSrc
+ xoff
;
598 case STRETCH_ORSCANS
:
599 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
600 rowDst
[xdst
>> 16] |= *rowSrc
++;
602 case STRETCH_ANDSCANS
:
603 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
604 rowDst
[xdst
>> 16] &= *rowSrc
++;
606 case STRETCH_DELETESCANS
:
607 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
608 rowDst
[xdst
>> 16] = *rowSrc
++;
614 /***********************************************************************
617 * Retrieve a row from an image. Helper function for BITBLT_StretchImage.
619 static void BITBLT_GetRow( XImage
*image
, int *pdata
, INT row
,
620 INT start
, INT width
, INT depthDst
,
621 int fg
, int bg
, BOOL swap
)
625 assert( (row
>= 0) && (row
< image
->height
) );
626 assert( (start
>= 0) && (width
<= image
->width
) );
628 pdata
+= swap
? start
+width
-1 : start
;
629 if (image
->depth
== depthDst
) /* color -> color */
631 if (X11DRV_PALETTE_XPixelToPalette
&& (depthDst
!= 1))
632 if (swap
) for (i
= 0; i
< width
; i
++)
633 *pdata
-- = X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, i
, row
)];
634 else for (i
= 0; i
< width
; i
++)
635 *pdata
++ = X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, i
, row
)];
637 if (swap
) for (i
= 0; i
< width
; i
++)
638 *pdata
-- = XGetPixel( image
, i
, row
);
639 else for (i
= 0; i
< width
; i
++)
640 *pdata
++ = XGetPixel( image
, i
, row
);
644 if (image
->depth
== 1) /* monochrome -> color */
646 if (X11DRV_PALETTE_XPixelToPalette
)
648 fg
= X11DRV_PALETTE_XPixelToPalette
[fg
];
649 bg
= X11DRV_PALETTE_XPixelToPalette
[bg
];
651 if (swap
) for (i
= 0; i
< width
; i
++)
652 *pdata
-- = XGetPixel( image
, i
, row
) ? bg
: fg
;
653 else for (i
= 0; i
< width
; i
++)
654 *pdata
++ = XGetPixel( image
, i
, row
) ? bg
: fg
;
656 else /* color -> monochrome */
658 if (swap
) for (i
= 0; i
< width
; i
++)
659 *pdata
-- = (XGetPixel( image
, i
, row
) == bg
) ? 1 : 0;
660 else for (i
= 0; i
< width
; i
++)
661 *pdata
++ = (XGetPixel( image
, i
, row
) == bg
) ? 1 : 0;
667 /***********************************************************************
668 * BITBLT_StretchImage
670 * Stretch an X image.
671 * FIXME: does not work for full 32-bit coordinates.
673 static void BITBLT_StretchImage( XImage
*srcImage
, XImage
*dstImage
,
674 INT widthSrc
, INT heightSrc
,
675 INT widthDst
, INT heightDst
,
676 RECT
*visRectSrc
, RECT
*visRectDst
,
677 int foreground
, int background
, WORD mode
)
679 int *rowSrc
, *rowDst
, *pixel
;
681 INT xinc
, xoff
, yinc
, ysrc
, ydst
;
683 BOOL hstretch
, vstretch
, hswap
, vswap
;
685 hswap
= ((int)widthSrc
* widthDst
) < 0;
686 vswap
= ((int)heightSrc
* heightDst
) < 0;
687 widthSrc
= abs(widthSrc
);
688 heightSrc
= abs(heightSrc
);
689 widthDst
= abs(widthDst
);
690 heightDst
= abs(heightDst
);
692 if (!(rowSrc
= HeapAlloc( GetProcessHeap(), 0,
693 (widthSrc
+widthDst
)*sizeof(int) ))) return;
694 rowDst
= rowSrc
+ widthSrc
;
696 /* When stretching, all modes are the same, and DELETESCANS is faster */
697 if ((widthSrc
< widthDst
) && (heightSrc
< heightDst
))
698 mode
= STRETCH_DELETESCANS
;
700 if (mode
== STRETCH_HALFTONE
) /* FIXME */
701 mode
= STRETCH_DELETESCANS
;
703 if (mode
!= STRETCH_DELETESCANS
)
704 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
705 widthDst
*sizeof(int) );
707 hstretch
= (widthSrc
< widthDst
);
708 vstretch
= (heightSrc
< heightDst
);
712 xinc
= ((int)widthSrc
<< 16) / widthDst
;
713 xoff
= ((widthSrc
<< 16) - (xinc
* widthDst
)) / 2;
717 xinc
= ((int)widthDst
<< 16) / widthSrc
;
718 xoff
= ((widthDst
<< 16) - (xinc
* widthSrc
)) / 2;
723 yinc
= ((int)heightSrc
<< 16) / heightDst
;
724 ydst
= visRectDst
->top
;
727 ysrc
= yinc
* (heightDst
- ydst
- 1);
733 for ( ; (ydst
< visRectDst
->bottom
); ysrc
+= yinc
, ydst
++)
735 if (((ysrc
>> 16) < visRectSrc
->top
) ||
736 ((ysrc
>> 16) >= visRectSrc
->bottom
)) continue;
738 /* Retrieve a source row */
739 BITBLT_GetRow( srcImage
, rowSrc
, (ysrc
>> 16) - visRectSrc
->top
,
740 hswap
? widthSrc
- visRectSrc
->right
742 visRectSrc
->right
- visRectSrc
->left
,
743 dstImage
->depth
, foreground
, background
, hswap
);
745 /* Stretch or shrink it */
747 BITBLT_StretchRow( rowSrc
, rowDst
, visRectDst
->left
,
748 visRectDst
->right
- visRectDst
->left
,
750 else BITBLT_ShrinkRow( rowSrc
, rowDst
,
751 hswap
? widthSrc
- visRectSrc
->right
753 visRectSrc
->right
- visRectSrc
->left
,
756 /* Store the destination row */
757 pixel
= rowDst
+ visRectDst
->right
- 1;
758 y
= ydst
- visRectDst
->top
;
759 for (x
= visRectDst
->right
-visRectDst
->left
-1; x
>= 0; x
--)
760 XPutPixel( dstImage
, x
, y
, *pixel
-- );
761 if (mode
!= STRETCH_DELETESCANS
)
762 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
763 widthDst
*sizeof(int) );
765 /* Make copies of the destination row */
767 pdata
= dstImage
->data
+ dstImage
->bytes_per_line
* y
;
768 while (((ysrc
+ yinc
) >> 16 == ysrc
>> 16) &&
769 (ydst
< visRectDst
->bottom
-1))
771 memcpy( pdata
+ dstImage
->bytes_per_line
, pdata
,
772 dstImage
->bytes_per_line
);
773 pdata
+= dstImage
->bytes_per_line
;
781 yinc
= ((int)heightDst
<< 16) / heightSrc
;
782 ysrc
= visRectSrc
->top
;
783 ydst
= ((heightDst
<< 16) - (yinc
* heightSrc
)) / 2;
786 ydst
+= yinc
* (heightSrc
- ysrc
- 1);
792 for( ; (ysrc
< visRectSrc
->bottom
); ydst
+= yinc
, ysrc
++)
794 if (((ydst
>> 16) < visRectDst
->top
) ||
795 ((ydst
>> 16) >= visRectDst
->bottom
)) continue;
797 /* Retrieve a source row */
798 BITBLT_GetRow( srcImage
, rowSrc
, ysrc
- visRectSrc
->top
,
799 hswap
? widthSrc
- visRectSrc
->right
801 visRectSrc
->right
- visRectSrc
->left
,
802 dstImage
->depth
, foreground
, background
, hswap
);
804 /* Stretch or shrink it */
806 BITBLT_StretchRow( rowSrc
, rowDst
, visRectDst
->left
,
807 visRectDst
->right
- visRectDst
->left
,
809 else BITBLT_ShrinkRow( rowSrc
, rowDst
,
810 hswap
? widthSrc
- visRectSrc
->right
812 visRectSrc
->right
- visRectSrc
->left
,
815 /* Merge several source rows into the destination */
816 if (mode
== STRETCH_DELETESCANS
)
818 /* Simply skip the overlapping rows */
819 while (((ydst
+ yinc
) >> 16 == ydst
>> 16) &&
820 (ysrc
< visRectSrc
->bottom
-1))
826 else if (((ydst
+ yinc
) >> 16 == ydst
>> 16) &&
827 (ysrc
< visRectSrc
->bottom
-1))
828 continue; /* Restart loop for next overlapping row */
830 /* Store the destination row */
831 pixel
= rowDst
+ visRectDst
->right
- 1;
832 y
= (ydst
>> 16) - visRectDst
->top
;
833 for (x
= visRectDst
->right
-visRectDst
->left
-1; x
>= 0; x
--)
834 XPutPixel( dstImage
, x
, y
, *pixel
-- );
835 if (mode
!= STRETCH_DELETESCANS
)
836 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
837 widthDst
*sizeof(int) );
840 HeapFree( GetProcessHeap(), 0, rowSrc
);
844 /***********************************************************************
845 * BITBLT_GetSrcAreaStretch
847 * Retrieve an area from the source DC, stretching and mapping all the
848 * pixels to Windows colors.
850 static int BITBLT_GetSrcAreaStretch( X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
851 Pixmap pixmap
, GC gc
,
853 INT widthSrc
, INT heightSrc
,
855 INT widthDst
, INT heightDst
,
856 RECT
*visRectSrc
, RECT
*visRectDst
)
858 XImage
*imageSrc
, *imageDst
;
859 RECT rectSrc
= *visRectSrc
;
860 RECT rectDst
= *visRectDst
;
863 if (widthSrc
< 0) xSrc
+= widthSrc
;
864 if (widthDst
< 0) xDst
+= widthDst
;
865 if (heightSrc
< 0) ySrc
+= heightSrc
;
866 if (heightDst
< 0) yDst
+= heightDst
;
867 rectSrc
.left
-= xSrc
;
868 rectSrc
.right
-= xSrc
;
870 rectSrc
.bottom
-= ySrc
;
871 rectDst
.left
-= xDst
;
872 rectDst
.right
-= xDst
;
874 rectDst
.bottom
-= yDst
;
876 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
877 /* FIXME: avoid BadMatch errors */
878 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
879 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
880 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
881 visRectSrc
->right
- visRectSrc
->left
,
882 visRectSrc
->bottom
- visRectSrc
->top
,
883 AllPlanes
, ZPixmap
);
889 imageDst
= X11DRV_DIB_CreateXImage( rectDst
.right
- rectDst
.left
,
890 rectDst
.bottom
- rectDst
.top
, physDevDst
->depth
);
891 BITBLT_StretchImage( imageSrc
, imageDst
, widthSrc
, heightSrc
,
892 widthDst
, heightDst
, &rectSrc
, &rectDst
,
893 fg
, physDevDst
->depth
!= 1 ?
894 bg
: physDevSrc
->backgroundPixel
,
895 GetStretchBltMode(physDevDst
->hdc
) );
896 XPutImage( gdi_display
, pixmap
, gc
, imageDst
, 0, 0, 0, 0,
897 rectDst
.right
- rectDst
.left
, rectDst
.bottom
- rectDst
.top
);
898 XDestroyImage( imageSrc
);
899 XDestroyImage( imageDst
);
900 return 0; /* no exposure events generated */
904 /***********************************************************************
907 * Retrieve an area from the source DC, mapping all the
908 * pixels to Windows colors.
910 static int BITBLT_GetSrcArea( X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
911 Pixmap pixmap
, GC gc
, INT xSrc
, INT ySrc
, RECT
*visRectSrc
)
913 XImage
*imageSrc
, *imageDst
;
916 INT width
= visRectSrc
->right
- visRectSrc
->left
;
917 INT height
= visRectSrc
->bottom
- visRectSrc
->top
;
920 if (physDevSrc
->depth
== physDevDst
->depth
)
922 if (!X11DRV_PALETTE_XPixelToPalette
||
923 (physDevDst
->depth
== 1)) /* monochrome -> monochrome */
925 if (physDevDst
->depth
== 1)
927 /* MSDN says if StretchBlt must convert a bitmap from monochrome
928 to color or vice versa, the forground and background color of
929 the device context are used. In fact, it also applies to the
930 case when it is converted from mono to mono. */
931 XSetBackground( gdi_display
, gc
, physDevDst
->textPixel
);
932 XSetForeground( gdi_display
, gc
, physDevDst
->backgroundPixel
);
933 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
934 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
935 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
936 width
, height
, 0, 0, 1);
939 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
940 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
941 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
942 width
, height
, 0, 0);
945 else /* color -> color */
947 if (GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
948 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
949 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
950 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
951 width
, height
, AllPlanes
, ZPixmap
);
954 /* Make sure we don't get a BadMatch error */
955 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
956 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
957 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
958 width
, height
, 0, 0);
960 imageSrc
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
961 AllPlanes
, ZPixmap
);
963 for (y
= 0; y
< height
; y
++)
964 for (x
= 0; x
< width
; x
++)
965 XPutPixel(imageSrc
, x
, y
,
966 X11DRV_PALETTE_XPixelToPalette
[XGetPixel(imageSrc
, x
, y
)]);
967 XPutImage( gdi_display
, pixmap
, gc
, imageSrc
,
968 0, 0, 0, 0, width
, height
);
969 XDestroyImage( imageSrc
);
974 if (physDevSrc
->depth
== 1) /* monochrome -> color */
976 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
978 if (X11DRV_PALETTE_XPixelToPalette
)
980 XSetBackground( gdi_display
, gc
,
981 X11DRV_PALETTE_XPixelToPalette
[fg
] );
982 XSetForeground( gdi_display
, gc
,
983 X11DRV_PALETTE_XPixelToPalette
[bg
]);
987 XSetBackground( gdi_display
, gc
, fg
);
988 XSetForeground( gdi_display
, gc
, bg
);
990 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
991 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
992 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
993 width
, height
, 0, 0, 1 );
996 else /* color -> monochrome */
998 /* FIXME: avoid BadMatch error */
999 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
1000 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1001 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1002 width
, height
, AllPlanes
, ZPixmap
);
1007 imageDst
= X11DRV_DIB_CreateXImage( width
, height
, physDevDst
->depth
);
1010 XDestroyImage(imageSrc
);
1013 for (y
= 0; y
< height
; y
++)
1014 for (x
= 0; x
< width
; x
++)
1015 XPutPixel(imageDst
, x
, y
, (XGetPixel(imageSrc
,x
,y
) ==
1016 physDevSrc
->backgroundPixel
) );
1017 XPutImage( gdi_display
, pixmap
, gc
, imageDst
,
1018 0, 0, 0, 0, width
, height
);
1019 XDestroyImage( imageSrc
);
1020 XDestroyImage( imageDst
);
1027 /***********************************************************************
1030 * Retrieve an area from the destination DC, mapping all the
1031 * pixels to Windows colors.
1033 static int BITBLT_GetDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, GC gc
, RECT
*visRectDst
)
1036 INT width
= visRectDst
->right
- visRectDst
->left
;
1037 INT height
= visRectDst
->bottom
- visRectDst
->top
;
1039 if (!X11DRV_PALETTE_XPixelToPalette
|| (physDev
->depth
== 1) ||
1040 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
1042 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
1043 physDev
->dc_rect
.left
+ visRectDst
->left
, physDev
->dc_rect
.top
+ visRectDst
->top
,
1044 width
, height
, 0, 0 );
1052 if (GetObjectType( physDev
->hdc
) == OBJ_MEMDC
)
1053 image
= XGetImage( gdi_display
, physDev
->drawable
,
1054 physDev
->dc_rect
.left
+ visRectDst
->left
,
1055 physDev
->dc_rect
.top
+ visRectDst
->top
,
1056 width
, height
, AllPlanes
, ZPixmap
);
1059 /* Make sure we don't get a BadMatch error */
1060 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
1061 physDev
->dc_rect
.left
+ visRectDst
->left
,
1062 physDev
->dc_rect
.top
+ visRectDst
->top
,
1063 width
, height
, 0, 0);
1065 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1066 AllPlanes
, ZPixmap
);
1068 for (y
= 0; y
< height
; y
++)
1069 for (x
= 0; x
< width
; x
++)
1070 XPutPixel( image
, x
, y
,
1071 X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, x
, y
)]);
1072 XPutImage( gdi_display
, pixmap
, gc
, image
, 0, 0, 0, 0, width
, height
);
1073 XDestroyImage( image
);
1079 /***********************************************************************
1082 * Put an area back into the destination DC, mapping the pixel
1083 * colors to X pixels.
1085 static int BITBLT_PutDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, RECT
*visRectDst
)
1088 INT width
= visRectDst
->right
- visRectDst
->left
;
1089 INT height
= visRectDst
->bottom
- visRectDst
->top
;
1091 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
1093 if (!X11DRV_PALETTE_PaletteToXPixel
|| (physDev
->depth
== 1) ||
1094 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
1096 XCopyArea( gdi_display
, pixmap
, physDev
->drawable
, physDev
->gc
, 0, 0, width
, height
,
1097 physDev
->dc_rect
.left
+ visRectDst
->left
,
1098 physDev
->dc_rect
.top
+ visRectDst
->top
);
1104 XImage
*image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1105 AllPlanes
, ZPixmap
);
1106 for (y
= 0; y
< height
; y
++)
1107 for (x
= 0; x
< width
; x
++)
1109 XPutPixel( image
, x
, y
,
1110 X11DRV_PALETTE_PaletteToXPixel
[XGetPixel( image
, x
, y
)]);
1112 XPutImage( gdi_display
, physDev
->drawable
, physDev
->gc
, image
, 0, 0,
1113 physDev
->dc_rect
.left
+ visRectDst
->left
,
1114 physDev
->dc_rect
.top
+ visRectDst
->top
, width
, height
);
1115 XDestroyImage( image
);
1121 /***********************************************************************
1122 * BITBLT_GetVisRectangles
1124 * Get the source and destination visible rectangles for StretchBlt().
1125 * Return FALSE if one of the rectangles is empty.
1127 static BOOL
BITBLT_GetVisRectangles( X11DRV_PDEVICE
*physDevDst
, INT xDst
, INT yDst
,
1128 INT widthDst
, INT heightDst
,
1129 X11DRV_PDEVICE
*physDevSrc
, INT xSrc
, INT ySrc
,
1130 INT widthSrc
, INT heightSrc
,
1131 RECT
*visRectSrc
, RECT
*visRectDst
)
1133 RECT rect
, clipRect
;
1135 /* Get the destination visible rectangle */
1139 rect
.right
= xDst
+ widthDst
;
1140 rect
.bottom
= yDst
+ heightDst
;
1141 if (widthDst
< 0) SWAP_INT32( &rect
.left
, &rect
.right
);
1142 if (heightDst
< 0) SWAP_INT32( &rect
.top
, &rect
.bottom
);
1143 GetRgnBox( physDevDst
->region
, &clipRect
);
1144 if (!IntersectRect( visRectDst
, &rect
, &clipRect
)) return FALSE
;
1146 /* Get the source visible rectangle */
1148 if (!physDevSrc
) return TRUE
;
1151 rect
.right
= xSrc
+ widthSrc
;
1152 rect
.bottom
= ySrc
+ heightSrc
;
1153 if (widthSrc
< 0) SWAP_INT32( &rect
.left
, &rect
.right
);
1154 if (heightSrc
< 0) SWAP_INT32( &rect
.top
, &rect
.bottom
);
1155 /* Apparently the clipping and visible regions are only for output,
1156 so just check against dc extent here to avoid BadMatch errors */
1157 clipRect
= physDevSrc
->drawable_rect
;
1158 OffsetRect( &clipRect
, -(physDevSrc
->drawable_rect
.left
+ physDevSrc
->dc_rect
.left
),
1159 -(physDevSrc
->drawable_rect
.top
+ physDevSrc
->dc_rect
.top
) );
1160 if (!IntersectRect( visRectSrc
, &rect
, &clipRect
))
1163 /* Intersect the rectangles */
1165 if ((widthSrc
== widthDst
) && (heightSrc
== heightDst
)) /* no stretching */
1167 visRectSrc
->left
+= xDst
- xSrc
;
1168 visRectSrc
->right
+= xDst
- xSrc
;
1169 visRectSrc
->top
+= yDst
- ySrc
;
1170 visRectSrc
->bottom
+= yDst
- ySrc
;
1171 if (!IntersectRect( &rect
, visRectSrc
, visRectDst
)) return FALSE
;
1172 *visRectSrc
= *visRectDst
= rect
;
1173 visRectSrc
->left
+= xSrc
- xDst
;
1174 visRectSrc
->right
+= xSrc
- xDst
;
1175 visRectSrc
->top
+= ySrc
- yDst
;
1176 visRectSrc
->bottom
+= ySrc
- yDst
;
1178 else /* stretching */
1180 /* Map source rectangle into destination coordinates */
1181 rect
.left
= xDst
+ (visRectSrc
->left
- xSrc
)*widthDst
/widthSrc
;
1182 rect
.top
= yDst
+ (visRectSrc
->top
- ySrc
)*heightDst
/heightSrc
;
1183 rect
.right
= xDst
+ ((visRectSrc
->right
- xSrc
)*widthDst
)/widthSrc
;
1184 rect
.bottom
= yDst
+ ((visRectSrc
->bottom
- ySrc
)*heightDst
)/heightSrc
;
1185 if (rect
.left
> rect
.right
) SWAP_INT32( &rect
.left
, &rect
.right
);
1186 if (rect
.top
> rect
.bottom
) SWAP_INT32( &rect
.top
, &rect
.bottom
);
1188 /* Avoid rounding errors */
1193 if (!IntersectRect( visRectDst
, &rect
, visRectDst
)) return FALSE
;
1195 /* Map destination rectangle back to source coordinates */
1197 rect
.left
= xSrc
+ (visRectDst
->left
- xDst
)*widthSrc
/widthDst
;
1198 rect
.top
= ySrc
+ (visRectDst
->top
- yDst
)*heightSrc
/heightDst
;
1199 rect
.right
= xSrc
+ ((visRectDst
->right
- xDst
)*widthSrc
)/widthDst
;
1200 rect
.bottom
= ySrc
+ ((visRectDst
->bottom
- yDst
)*heightSrc
)/heightDst
;
1201 if (rect
.left
> rect
.right
) SWAP_INT32( &rect
.left
, &rect
.right
);
1202 if (rect
.top
> rect
.bottom
) SWAP_INT32( &rect
.top
, &rect
.bottom
);
1204 /* Avoid rounding errors */
1209 if (!IntersectRect( visRectSrc
, &rect
, visRectSrc
)) return FALSE
;
1215 /***********************************************************************
1216 * BITBLT_InternalStretchBlt
1218 * Implementation of PatBlt(), BitBlt() and StretchBlt().
1220 static BOOL
BITBLT_InternalStretchBlt( X11DRV_PDEVICE
*physDevDst
, INT xDst
, INT yDst
,
1221 INT widthDst
, INT heightDst
,
1222 X11DRV_PDEVICE
*physDevSrc
, INT xSrc
, INT ySrc
,
1223 INT widthSrc
, INT heightSrc
,
1226 BOOL usePat
, useSrc
, useDst
, destUsed
, fStretch
, fNullBrush
;
1227 RECT visRectDst
, visRectSrc
;
1230 Pixmap pixmaps
[3] = { 0, 0, 0 }; /* pixmaps for DST, SRC, TMP */
1234 /* compensate for off-by-one shifting for negative widths and heights */
1244 usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
1245 useSrc
= (((rop
>> 2) & 0x330000) != (rop
& 0x330000));
1246 useDst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
1247 if (!physDevSrc
&& useSrc
) return FALSE
;
1249 /* Map the coordinates to device coords */
1253 pts
[1].x
= xDst
+ widthDst
;
1254 pts
[1].y
= yDst
+ heightDst
;
1255 LPtoDP(physDevDst
->hdc
, pts
, 2);
1258 widthDst
= pts
[1].x
- pts
[0].x
;
1259 heightDst
= pts
[1].y
- pts
[0].y
;
1261 TRACE(" rectdst=%d,%d-%d,%d orgdst=%d,%d\n",
1262 xDst
, yDst
, widthDst
, heightDst
,
1263 physDevDst
->dc_rect
.left
, physDevDst
->dc_rect
.top
);
1269 pts
[1].x
= xSrc
+ widthSrc
;
1270 pts
[1].y
= ySrc
+ heightSrc
;
1271 LPtoDP(physDevSrc
->hdc
, pts
, 2);
1274 widthSrc
= pts
[1].x
- pts
[0].x
;
1275 heightSrc
= pts
[1].y
- pts
[0].y
;
1277 fStretch
= (widthSrc
!= widthDst
) || (heightSrc
!= heightDst
);
1278 TRACE(" rectsrc=%d,%d-%d,%d orgsrc=%d,%d\n",
1279 xSrc
, ySrc
, widthSrc
, heightSrc
,
1280 physDevSrc
->dc_rect
.left
, physDevSrc
->dc_rect
.top
);
1281 if (!BITBLT_GetVisRectangles( physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
1282 physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
,
1283 &visRectSrc
, &visRectDst
))
1285 TRACE(" vissrc=%d,%d-%d,%d visdst=%d,%d-%d,%d\n",
1286 visRectSrc
.left
, visRectSrc
.top
,
1287 visRectSrc
.right
, visRectSrc
.bottom
,
1288 visRectDst
.left
, visRectDst
.top
,
1289 visRectDst
.right
, visRectDst
.bottom
);
1294 if (!BITBLT_GetVisRectangles( physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
1295 NULL
, 0, 0, 0, 0, NULL
, &visRectDst
))
1297 TRACE(" vissrc=none visdst=%d,%d-%d,%d\n",
1298 visRectDst
.left
, visRectDst
.top
,
1299 visRectDst
.right
, visRectDst
.bottom
);
1302 width
= visRectDst
.right
- visRectDst
.left
;
1303 height
= visRectDst
.bottom
- visRectDst
.top
;
1305 if (!fStretch
) switch(rop
) /* A few optimisations */
1307 case BLACKNESS
: /* 0x00 */
1309 if ((physDevDst
->depth
== 1) || !X11DRV_PALETTE_PaletteToXPixel
)
1310 XSetFunction( gdi_display
, physDevDst
->gc
, GXclear
);
1313 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1314 XSetForeground( gdi_display
, physDevDst
->gc
, X11DRV_PALETTE_PaletteToXPixel
[0] );
1315 XSetFillStyle( gdi_display
, physDevDst
->gc
, FillSolid
);
1317 XFillRectangle( gdi_display
, physDevDst
->drawable
, physDevDst
->gc
,
1318 physDevDst
->dc_rect
.left
+ visRectDst
.left
,
1319 physDevDst
->dc_rect
.top
+ visRectDst
.top
,
1321 wine_tsx11_unlock();
1324 case DSTINVERT
: /* 0x55 */
1326 XSetFunction( gdi_display
, physDevDst
->gc
, GXinvert
);
1328 if( X11DRV_PALETTE_PaletteFlags
& (X11DRV_PALETTE_PRIVATE
| X11DRV_PALETTE_VIRTUAL
) )
1329 XSetFunction( gdi_display
, physDevDst
->gc
, GXinvert
);
1332 /* Xor is much better when we do not have full colormap. */
1333 /* Using white^black ensures that we invert at least black */
1335 unsigned long xor_pix
= (WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ) ^
1336 BlackPixel( gdi_display
, DefaultScreen(gdi_display
) ));
1337 XSetFunction( gdi_display
, physDevDst
->gc
, GXxor
);
1338 XSetForeground( gdi_display
, physDevDst
->gc
, xor_pix
);
1339 XSetFillStyle( gdi_display
, physDevDst
->gc
, FillSolid
);
1341 XFillRectangle( gdi_display
, physDevDst
->drawable
, physDevDst
->gc
,
1342 physDevDst
->dc_rect
.left
+ visRectDst
.left
,
1343 physDevDst
->dc_rect
.top
+ visRectDst
.top
,
1345 wine_tsx11_unlock();
1348 case PATINVERT
: /* 0x5a */
1349 if (X11DRV_SetupGCForBrush( physDevDst
))
1352 XSetFunction( gdi_display
, physDevDst
->gc
, GXxor
);
1353 XFillRectangle( gdi_display
, physDevDst
->drawable
, physDevDst
->gc
,
1354 physDevDst
->dc_rect
.left
+ visRectDst
.left
,
1355 physDevDst
->dc_rect
.top
+ visRectDst
.top
,
1357 wine_tsx11_unlock();
1362 if (X11DRV_SetupGCForBrush( physDevDst
))
1365 XSetFunction( gdi_display
, physDevDst
->gc
, GXequiv
);
1366 XFillRectangle( gdi_display
, physDevDst
->drawable
, physDevDst
->gc
,
1367 physDevDst
->dc_rect
.left
+ visRectDst
.left
,
1368 physDevDst
->dc_rect
.top
+ visRectDst
.top
,
1370 wine_tsx11_unlock();
1374 case SRCCOPY
: /* 0xcc */
1375 if (physDevSrc
->depth
== physDevDst
->depth
)
1378 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1379 XCopyArea( gdi_display
, physDevSrc
->drawable
,
1380 physDevDst
->drawable
, physDevDst
->gc
,
1381 physDevSrc
->dc_rect
.left
+ visRectSrc
.left
,
1382 physDevSrc
->dc_rect
.top
+ visRectSrc
.top
,
1384 physDevDst
->dc_rect
.left
+ visRectDst
.left
,
1385 physDevDst
->dc_rect
.top
+ visRectDst
.top
);
1386 physDevDst
->exposures
++;
1387 wine_tsx11_unlock();
1391 if (physDevSrc
->depth
== 1)
1394 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
1397 XSetBackground( gdi_display
, physDevDst
->gc
, fg
);
1398 XSetForeground( gdi_display
, physDevDst
->gc
, bg
);
1399 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1400 XCopyPlane( gdi_display
, physDevSrc
->drawable
,
1401 physDevDst
->drawable
, physDevDst
->gc
,
1402 physDevSrc
->dc_rect
.left
+ visRectSrc
.left
,
1403 physDevSrc
->dc_rect
.top
+ visRectSrc
.top
,
1405 physDevDst
->dc_rect
.left
+ visRectDst
.left
,
1406 physDevDst
->dc_rect
.top
+ visRectDst
.top
, 1 );
1407 physDevDst
->exposures
++;
1408 wine_tsx11_unlock();
1413 case PATCOPY
: /* 0xf0 */
1414 if (!X11DRV_SetupGCForBrush( physDevDst
)) return TRUE
;
1416 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1417 XFillRectangle( gdi_display
, physDevDst
->drawable
, physDevDst
->gc
,
1418 physDevDst
->dc_rect
.left
+ visRectDst
.left
,
1419 physDevDst
->dc_rect
.top
+ visRectDst
.top
,
1421 wine_tsx11_unlock();
1424 case WHITENESS
: /* 0xff */
1426 if ((physDevDst
->depth
== 1) || !X11DRV_PALETTE_PaletteToXPixel
)
1427 XSetFunction( gdi_display
, physDevDst
->gc
, GXset
);
1430 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1431 XSetForeground( gdi_display
, physDevDst
->gc
,
1432 WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ));
1433 XSetFillStyle( gdi_display
, physDevDst
->gc
, FillSolid
);
1435 XFillRectangle( gdi_display
, physDevDst
->drawable
, physDevDst
->gc
,
1436 physDevDst
->dc_rect
.left
+ visRectDst
.left
,
1437 physDevDst
->dc_rect
.top
+ visRectDst
.top
,
1439 wine_tsx11_unlock();
1445 tmpGC
= XCreateGC( gdi_display
, physDevDst
->drawable
, 0, NULL
);
1446 XSetSubwindowMode( gdi_display
, tmpGC
, IncludeInferiors
);
1447 XSetGraphicsExposures( gdi_display
, tmpGC
, False
);
1448 pixmaps
[DST
] = XCreatePixmap( gdi_display
, root_window
, width
, height
,
1449 physDevDst
->depth
);
1452 pixmaps
[SRC
] = XCreatePixmap( gdi_display
, root_window
, width
, height
,
1453 physDevDst
->depth
);
1455 BITBLT_GetSrcAreaStretch( physDevSrc
, physDevDst
, pixmaps
[SRC
], tmpGC
,
1456 xSrc
, ySrc
, widthSrc
, heightSrc
,
1457 xDst
, yDst
, widthDst
, heightDst
,
1458 &visRectSrc
, &visRectDst
);
1460 BITBLT_GetSrcArea( physDevSrc
, physDevDst
, pixmaps
[SRC
], tmpGC
,
1461 xSrc
, ySrc
, &visRectSrc
);
1464 if (useDst
) BITBLT_GetDstArea( physDevDst
, pixmaps
[DST
], tmpGC
, &visRectDst
);
1465 if (usePat
) fNullBrush
= !X11DRV_SetupGCForPatBlt( physDevDst
, tmpGC
, TRUE
);
1466 else fNullBrush
= FALSE
;
1469 for (opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff]; *opcode
; opcode
++)
1471 if (OP_DST(*opcode
) == DST
) destUsed
= TRUE
;
1472 XSetFunction( gdi_display
, tmpGC
, OP_ROP(*opcode
) );
1473 switch(OP_SRCDST(*opcode
))
1475 case OP_ARGS(DST
,TMP
):
1476 case OP_ARGS(SRC
,TMP
):
1478 pixmaps
[TMP
] = XCreatePixmap( gdi_display
, root_window
,
1479 width
, height
, physDevDst
->depth
);
1481 case OP_ARGS(DST
,SRC
):
1482 case OP_ARGS(SRC
,DST
):
1483 case OP_ARGS(TMP
,SRC
):
1484 case OP_ARGS(TMP
,DST
):
1486 XCopyArea( gdi_display
, pixmaps
[OP_SRC(*opcode
)],
1487 pixmaps
[OP_DST(*opcode
)], tmpGC
,
1488 0, 0, width
, height
, 0, 0 );
1491 case OP_ARGS(PAT
,TMP
):
1492 if (!pixmaps
[TMP
] && !fNullBrush
)
1493 pixmaps
[TMP
] = XCreatePixmap( gdi_display
, root_window
,
1494 width
, height
, physDevDst
->depth
);
1496 case OP_ARGS(PAT
,DST
):
1497 case OP_ARGS(PAT
,SRC
):
1499 XFillRectangle( gdi_display
, pixmaps
[OP_DST(*opcode
)],
1500 tmpGC
, 0, 0, width
, height
);
1504 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1505 physDevDst
->exposures
+= BITBLT_PutDstArea( physDevDst
, pixmaps
[destUsed
? DST
: SRC
],
1507 XFreePixmap( gdi_display
, pixmaps
[DST
] );
1508 if (pixmaps
[SRC
]) XFreePixmap( gdi_display
, pixmaps
[SRC
] );
1509 if (pixmaps
[TMP
]) XFreePixmap( gdi_display
, pixmaps
[TMP
] );
1510 XFreeGC( gdi_display
, tmpGC
);
1511 wine_tsx11_unlock();
1516 /***********************************************************************
1519 BOOL
X11DRV_PatBlt( X11DRV_PDEVICE
*physDev
, INT left
, INT top
, INT width
, INT height
, DWORD rop
)
1523 X11DRV_LockDIBSection( physDev
, DIB_Status_GdiMod
, FALSE
);
1524 result
= BITBLT_InternalStretchBlt( physDev
, left
, top
, width
, height
, NULL
, 0, 0, 0, 0, rop
);
1525 X11DRV_UnlockDIBSection( physDev
, TRUE
);
1530 /***********************************************************************
1531 * X11DRV_ClientSideDIBCopy
1533 static BOOL
X11DRV_ClientSideDIBCopy( X11DRV_PDEVICE
*physDevSrc
, INT xSrc
, INT ySrc
,
1534 X11DRV_PDEVICE
*physDevDst
, INT xDst
, INT yDst
,
1535 INT width
, INT height
)
1537 DIBSECTION srcDib
, dstDib
;
1538 BYTE
*srcPtr
, *dstPtr
;
1539 INT srcRowOffset
, dstRowOffset
;
1543 static RECT unusedRect
;
1545 if (GetObjectW(physDevSrc
->bitmap
->hbitmap
, sizeof(srcDib
), &srcDib
) != sizeof(srcDib
))
1547 if (GetObjectW(physDevDst
->bitmap
->hbitmap
, sizeof(dstDib
), &dstDib
) != sizeof(dstDib
))
1550 /* check for oversized values, just like X11DRV_DIB_CopyDIBSection() */
1551 if (xSrc
> srcDib
.dsBm
.bmWidth
|| ySrc
> srcDib
.dsBm
.bmHeight
)
1553 if (xSrc
+ width
> srcDib
.dsBm
.bmWidth
)
1554 width
= srcDib
.dsBm
.bmWidth
- xSrc
;
1555 if (ySrc
+ height
> srcDib
.dsBm
.bmHeight
)
1556 height
= srcDib
.dsBm
.bmHeight
- ySrc
;
1558 if (GetRgnBox(physDevSrc
->region
, &unusedRect
) == COMPLEXREGION
||
1559 GetRgnBox(physDevDst
->region
, &unusedRect
) == COMPLEXREGION
)
1561 /* for simple regions, the clipping was already done by BITBLT_GetVisRectangles */
1562 FIXME("potential optimization: client-side complex region clipping\n");
1565 if (dstDib
.dsBm
.bmBitsPixel
<= 8)
1567 FIXME("potential optimization: client-side color-index mode DIB copy\n");
1570 if (!(srcDib
.dsBmih
.biCompression
== BI_BITFIELDS
&&
1571 dstDib
.dsBmih
.biCompression
== BI_BITFIELDS
&&
1572 !memcmp(srcDib
.dsBitfields
, dstDib
.dsBitfields
, 3*sizeof(DWORD
)))
1573 && !(srcDib
.dsBmih
.biCompression
== BI_RGB
&&
1574 dstDib
.dsBmih
.biCompression
== BI_RGB
))
1576 FIXME("potential optimization: client-side compressed DIB copy\n");
1579 if (srcDib
.dsBm
.bmBitsPixel
!= dstDib
.dsBm
.bmBitsPixel
)
1581 FIXME("potential optimization: pixel format conversion\n");
1584 if (srcDib
.dsBmih
.biWidth
< 0 || dstDib
.dsBmih
.biWidth
< 0)
1586 FIXME("negative widths not yet implemented\n");
1590 switch (dstDib
.dsBm
.bmBitsPixel
)
1603 FIXME("don't know how to work with a depth of %d\n", physDevSrc
->depth
);
1607 bytesToCopy
= width
* bytesPerPixel
;
1609 if (srcDib
.dsBmih
.biHeight
< 0)
1611 srcPtr
= &physDevSrc
->bitmap
->base
[ySrc
*srcDib
.dsBm
.bmWidthBytes
+ xSrc
*bytesPerPixel
];
1612 srcRowOffset
= srcDib
.dsBm
.bmWidthBytes
;
1616 srcPtr
= &physDevSrc
->bitmap
->base
[(srcDib
.dsBm
.bmHeight
-ySrc
-1)*srcDib
.dsBm
.bmWidthBytes
1617 + xSrc
*bytesPerPixel
];
1618 srcRowOffset
= -srcDib
.dsBm
.bmWidthBytes
;
1620 if (dstDib
.dsBmih
.biHeight
< 0)
1622 dstPtr
= &physDevDst
->bitmap
->base
[yDst
*dstDib
.dsBm
.bmWidthBytes
+ xDst
*bytesPerPixel
];
1623 dstRowOffset
= dstDib
.dsBm
.bmWidthBytes
;
1627 dstPtr
= &physDevDst
->bitmap
->base
[(dstDib
.dsBm
.bmHeight
-yDst
-1)*dstDib
.dsBm
.bmWidthBytes
1628 + xDst
*bytesPerPixel
];
1629 dstRowOffset
= -dstDib
.dsBm
.bmWidthBytes
;
1632 for (y
= yDst
; y
< yDst
+ height
; ++y
)
1634 memcpy(dstPtr
, srcPtr
, bytesToCopy
);
1635 srcPtr
+= srcRowOffset
;
1636 dstPtr
+= dstRowOffset
;
1643 /***********************************************************************
1646 BOOL
X11DRV_BitBlt( X11DRV_PDEVICE
*physDevDst
, INT xDst
, INT yDst
,
1647 INT width
, INT height
, X11DRV_PDEVICE
*physDevSrc
,
1648 INT xSrc
, INT ySrc
, DWORD rop
)
1650 BOOL result
= FALSE
;
1652 RECT visRectDst
, visRectSrc
;
1654 if (((rop
>> 16) & 0x55) == ((rop
>> 17) & 0x55)) {
1655 /* FIXME: seems the ROP doesn't include destination;
1656 * now if the destination area include the entire dcDst,
1657 * we can pass TRUE instead of FALSE to CoerceDIBSection(dcDst...),
1658 * which may avoid a copy in some situations */
1661 sDst
= X11DRV_LockDIBSection( physDevDst
, DIB_Status_None
, FALSE
);
1662 if (physDevDst
!= physDevSrc
)
1663 sSrc
= X11DRV_LockDIBSection( physDevSrc
, DIB_Status_None
, FALSE
);
1667 if ((sSrc
== DIB_Status_AppMod
) && (rop
== SRCCOPY
) &&
1668 (physDevSrc
->depth
== physDevDst
->depth
))
1671 /* do everything ourselves; map coordinates */
1675 pts
[1].x
= xSrc
+ width
;
1676 pts
[1].y
= ySrc
+ height
;
1678 LPtoDP(physDevSrc
->hdc
, pts
, 2);
1679 width
= pts
[1].x
- pts
[0].x
;
1680 height
= pts
[1].y
- pts
[0].y
;
1686 LPtoDP(physDevDst
->hdc
, pts
, 1);
1691 /* Perform basic clipping */
1692 if (!BITBLT_GetVisRectangles( physDevDst
, xDst
, yDst
, width
, height
,
1693 physDevSrc
, xSrc
, ySrc
, width
, height
,
1694 &visRectSrc
, &visRectDst
))
1697 xSrc
= visRectSrc
.left
;
1698 ySrc
= visRectSrc
.top
;
1699 xDst
= visRectDst
.left
;
1700 yDst
= visRectDst
.top
;
1701 width
= visRectDst
.right
- visRectDst
.left
;
1702 height
= visRectDst
.bottom
- visRectDst
.top
;
1704 if (sDst
== DIB_Status_AppMod
) {
1705 result
= X11DRV_ClientSideDIBCopy( physDevSrc
, xSrc
, ySrc
,
1706 physDevDst
, xDst
, yDst
,
1710 /* fall back to X server copying */
1712 X11DRV_CoerceDIBSection( physDevDst
, DIB_Status_GdiMod
, FALSE
);
1715 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1716 wine_tsx11_unlock();
1718 X11DRV_DIB_CopyDIBSection( physDevSrc
, physDevDst
, xSrc
, ySrc
, xDst
, yDst
, width
, height
);
1723 X11DRV_CoerceDIBSection( physDevDst
, DIB_Status_GdiMod
, FALSE
);
1724 if (physDevDst
!= physDevSrc
)
1725 X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
, FALSE
);
1727 result
= BITBLT_InternalStretchBlt( physDevDst
, xDst
, yDst
, width
, height
,
1728 physDevSrc
, xSrc
, ySrc
, width
, height
, rop
);
1731 if (physDevDst
!= physDevSrc
)
1732 X11DRV_UnlockDIBSection( physDevSrc
, FALSE
);
1733 X11DRV_UnlockDIBSection( physDevDst
, TRUE
);
1739 /***********************************************************************
1742 BOOL
X11DRV_StretchBlt( X11DRV_PDEVICE
*physDevDst
, INT xDst
, INT yDst
,
1743 INT widthDst
, INT heightDst
,
1744 X11DRV_PDEVICE
*physDevSrc
, INT xSrc
, INT ySrc
,
1745 INT widthSrc
, INT heightSrc
, DWORD rop
)
1749 X11DRV_LockDIBSection( physDevDst
, DIB_Status_GdiMod
, FALSE
);
1750 if (physDevDst
!= physDevSrc
)
1751 X11DRV_LockDIBSection( physDevSrc
, DIB_Status_GdiMod
, FALSE
);
1753 result
= BITBLT_InternalStretchBlt( physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
1754 physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
1756 if (physDevDst
!= physDevSrc
)
1757 X11DRV_UnlockDIBSection( physDevSrc
, FALSE
);
1758 X11DRV_UnlockDIBSection( physDevDst
, TRUE
);