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
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(bitblt
);
39 #define DST 0 /* Destination drawable */
40 #define SRC 1 /* Source drawable */
41 #define TMP 2 /* Temporary drawable */
42 #define PAT 3 /* Pattern (brush) in destination DC */
44 #define OP(src,dst,rop) (OP_ARGS(src,dst) << 4 | (rop))
45 #define OP_ARGS(src,dst) (((src) << 2) | (dst))
47 #define OP_SRC(opcode) ((opcode) >> 6)
48 #define OP_DST(opcode) (((opcode) >> 4) & 3)
49 #define OP_SRCDST(opcode) ((opcode) >> 4)
50 #define OP_ROP(opcode) ((opcode) & 0x0f)
52 #define MAX_OP_LEN 6 /* Longest opcode + 1 for the terminating 0 */
54 #define SWAP_INT32(i1,i2) \
55 do { INT __t = *(i1); *(i1) = *(i2); *(i2) = __t; } while(0)
57 static const unsigned char BITBLT_Opcodes
[256][MAX_OP_LEN
] =
59 { OP(PAT
,DST
,GXclear
) }, /* 0x00 0 */
60 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXnor
) }, /* 0x01 ~(D|(P|S)) */
61 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXand
) }, /* 0x02 D&~(P|S) */
62 { OP(PAT
,SRC
,GXnor
) }, /* 0x03 ~(P|S) */
63 { OP(PAT
,DST
,GXnor
), OP(SRC
,DST
,GXand
) }, /* 0x04 S&~(D|P) */
64 { OP(PAT
,DST
,GXnor
) }, /* 0x05 ~(D|P) */
65 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXnor
), }, /* 0x06 ~(P|~(D^S)) */
66 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXnor
) }, /* 0x07 ~(P|(D&S)) */
67 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXand
) },/* 0x08 S&D&~P */
68 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXnor
) }, /* 0x09 ~(P|(D^S)) */
69 { OP(PAT
,DST
,GXandInverted
) }, /* 0x0a D&~P */
70 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXnor
) }, /* 0x0b ~(P|(S&~D)) */
71 { OP(PAT
,SRC
,GXandInverted
) }, /* 0x0c S&~P */
72 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXnor
) },/* 0x0d ~(P|(D&~S)) */
73 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXnor
) }, /* 0x0e ~(P|~(D|S)) */
74 { OP(PAT
,DST
,GXcopyInverted
) }, /* 0x0f ~P */
75 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXand
) }, /* 0x10 P&~(S|D) */
76 { OP(SRC
,DST
,GXnor
) }, /* 0x11 ~(D|S) */
77 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXnor
) }, /* 0x12 ~(S|~(D^P)) */
78 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXnor
) }, /* 0x13 ~(S|(D&P)) */
79 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXnor
) }, /* 0x14 ~(D|~(P^S)) */
80 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXnor
) }, /* 0x15 ~(D|(P&S)) */
81 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,TMP
,GXnand
),
82 OP(TMP
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
83 OP(PAT
,DST
,GXxor
) }, /* 0x16 P^S^(D&~(P&S) */
84 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
85 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
86 OP(TMP
,DST
,GXequiv
) }, /* 0x17 ~S^((S^P)&(S^D))*/
87 { OP(PAT
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
88 OP(SRC
,DST
,GXand
) }, /* 0x18 (S^P)&(D^P) */
89 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,TMP
,GXnand
),
90 OP(TMP
,DST
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x19 ~S^(D&~(P&S)) */
91 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
),
92 OP(PAT
,DST
,GXxor
) }, /* 0x1a P^(D|(S&P)) */
93 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,TMP
,GXxor
),
94 OP(TMP
,DST
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x1b ~S^(D&(P^S)) */
95 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
),
96 OP(PAT
,DST
,GXxor
) }, /* 0x1c P^(S|(D&P)) */
97 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
98 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x1d ~D^(S&(D^P)) */
99 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
) }, /* 0x1e P^(D|S) */
100 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXnand
) }, /* 0x1f ~(P&(D|S)) */
101 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXand
) }, /* 0x20 D&(P&~S) */
102 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXnor
) }, /* 0x21 ~(S|(D^P)) */
103 { OP(SRC
,DST
,GXandInverted
) }, /* 0x22 ~S&D */
104 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXnor
) }, /* 0x23 ~(S|(P&~D)) */
105 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
106 OP(SRC
,DST
,GXand
) }, /* 0x24 (S^P)&(S^D) */
107 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXand
),
108 OP(PAT
,DST
,GXequiv
) }, /* 0x25 ~P^(D&~(S&P)) */
109 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,TMP
,GXand
),
110 OP(TMP
,DST
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x26 S^(D|(S&P)) */
111 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,TMP
,GXequiv
),
112 OP(TMP
,DST
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x27 S^(D|~(P^S)) */
113 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
) }, /* 0x28 D&(P^S) */
114 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,TMP
,GXand
),
115 OP(TMP
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
116 OP(PAT
,DST
,GXequiv
) }, /* 0x29 ~P^S^(D|(P&S)) */
117 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXand
) }, /* 0x2a D&~(P&S) */
118 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
119 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
120 OP(TMP
,DST
,GXequiv
) }, /* 0x2b ~S^((P^S)&(P^D))*/
121 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
),
122 OP(SRC
,DST
,GXxor
) }, /* 0x2c S^(P&(S|D)) */
123 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXxor
) }, /* 0x2d P^(S|~D) */
124 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
),
125 OP(PAT
,DST
,GXxor
) }, /* 0x2e P^(S|(D^P)) */
126 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXnand
) }, /* 0x2f ~(P&(S|~D)) */
127 { OP(PAT
,SRC
,GXandReverse
) }, /* 0x30 P&~S */
128 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXnor
) },/* 0x31 ~(S|(D&~P)) */
129 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXor
),
130 OP(SRC
,DST
,GXxor
) }, /* 0x32 S^(D|P|S) */
131 { OP(SRC
,DST
,GXcopyInverted
) }, /* 0x33 ~S */
132 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
),
133 OP(SRC
,DST
,GXxor
) }, /* 0x34 S^(P|(D&S)) */
134 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXor
),
135 OP(SRC
,DST
,GXxor
) }, /* 0x35 S^(P|~(D^S)) */
136 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x36 S^(D|P) */
137 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXnand
) }, /* 0x37 ~(S&(D|P)) */
138 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
),
139 OP(PAT
,DST
,GXxor
) }, /* 0x38 P^(S&(D|P)) */
140 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x39 S^(P|~D) */
141 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
),
142 OP(SRC
,DST
,GXxor
) }, /* 0x3a S^(P|(D^S)) */
143 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXnand
) }, /* 0x3b ~(S&(P|~D)) */
144 { OP(PAT
,SRC
,GXxor
) }, /* 0x3c P^S */
145 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
),
146 OP(SRC
,DST
,GXxor
) }, /* 0x3d S^(P|~(D|S)) */
147 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
),
148 OP(SRC
,DST
,GXxor
) }, /* 0x3e S^(P|(D&~S)) */
149 { OP(PAT
,SRC
,GXnand
) }, /* 0x3f ~(P&S) */
150 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXand
) }, /* 0x40 P&S&~D */
151 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXnor
) }, /* 0x41 ~(D|(P^S)) */
152 { OP(DST
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
153 OP(SRC
,DST
,GXand
) }, /* 0x42 (S^D)&(P^D) */
154 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
),
155 OP(SRC
,DST
,GXequiv
) }, /* 0x43 ~S^(P&~(D&S)) */
156 { OP(SRC
,DST
,GXandReverse
) }, /* 0x44 S&~D */
157 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXnor
) }, /* 0x45 ~(D|(P&~S)) */
158 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
159 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x46 D^(S|(P&D)) */
160 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
161 OP(PAT
,DST
,GXequiv
) }, /* 0x47 ~P^(S&(D^P)) */
162 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
) }, /* 0x48 S&(P^D) */
163 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
164 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
),
165 OP(PAT
,DST
,GXequiv
) }, /* 0x49 ~P^D^(S|(P&D)) */
166 { OP(DST
,SRC
,GXor
), OP(PAT
,SRC
,GXand
),
167 OP(SRC
,DST
,GXxor
) }, /* 0x4a D^(P&(S|D)) */
168 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXxor
) }, /* 0x4b P^(D|~S) */
169 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXand
) }, /* 0x4c S&~(D&P) */
170 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
171 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
172 OP(TMP
,DST
,GXequiv
) }, /* 0x4d ~S^((S^P)|(S^D))*/
173 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
174 OP(PAT
,DST
,GXxor
) }, /* 0x4e P^(D|(S^P)) */
175 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXnand
) },/* 0x4f ~(P&(D|~S)) */
176 { OP(PAT
,DST
,GXandReverse
) }, /* 0x50 P&~D */
177 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXnor
) },/* 0x51 ~(D|(S&~P)) */
178 { OP(DST
,SRC
,GXand
), OP(PAT
,SRC
,GXor
),
179 OP(SRC
,DST
,GXxor
) }, /* 0x52 D^(P|(S&D)) */
180 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
),
181 OP(SRC
,DST
,GXequiv
) }, /* 0x53 ~S^(P&(D^S)) */
182 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXnor
) }, /* 0x54 ~(D|~(P|S)) */
183 { OP(PAT
,DST
,GXinvert
) }, /* 0x55 ~D */
184 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x56 D^(P|S) */
185 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXnand
) }, /* 0x57 ~(D&(P|S)) */
186 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
),
187 OP(PAT
,DST
,GXxor
) }, /* 0x58 P^(D&(P|S)) */
188 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x59 D^(P|~S) */
189 { OP(PAT
,DST
,GXxor
) }, /* 0x5a D^P */
190 { OP(DST
,SRC
,GXnor
), OP(PAT
,SRC
,GXor
),
191 OP(SRC
,DST
,GXxor
) }, /* 0x5b D^(P|~(S|D)) */
192 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXor
),
193 OP(SRC
,DST
,GXxor
) }, /* 0x5c D^(P|(S^D)) */
194 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXnand
) }, /* 0x5d ~(D&(P|~S)) */
195 { OP(DST
,SRC
,GXandInverted
), OP(PAT
,SRC
,GXor
),
196 OP(SRC
,DST
,GXxor
) }, /* 0x5e D^(P|(S&~D)) */
197 { OP(PAT
,DST
,GXnand
) }, /* 0x5f ~(D&P) */
198 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
) }, /* 0x60 P&(D^S) */
199 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXand
),
200 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
201 OP(TMP
,DST
,GXequiv
) }, /* 0x61 ~D^S^(P|(D&S)) */
202 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
203 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x62 D^(S&(P|D)) */
204 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXxor
) }, /* 0x63 S^(D|~P) */
205 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
206 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x64 S^(D&(P|S)) */
207 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXxor
) }, /* 0x65 D^(S|~P) */
208 { OP(SRC
,DST
,GXxor
) }, /* 0x66 S^D */
209 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
210 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x67 S^(D|~(S|P) */
211 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXnor
),
212 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
213 OP(TMP
,DST
,GXequiv
) }, /* 0x68 ~D^S^(P|~(D|S))*/
214 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXequiv
) }, /* 0x69 ~P^(D^S) */
215 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXxor
) }, /* 0x6a D^(P&S) */
216 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
217 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
),
218 OP(PAT
,DST
,GXequiv
) }, /* 0x6b ~P^S^(D&(P|S)) */
219 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
) }, /* 0x6c S^(D&P) */
220 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
221 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
),
222 OP(PAT
,DST
,GXequiv
) }, /* 0x6d ~P^D^(S&(P|D)) */
223 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXorReverse
),
224 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x6e S^(D&(P|~S)) */
225 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXnand
) }, /* 0x6f ~(P&~(S^D)) */
226 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
) }, /* 0x70 P&~(D&S) */
227 { OP(SRC
,TMP
,GXcopy
), OP(DST
,SRC
,GXxor
),
228 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
229 OP(TMP
,DST
,GXequiv
) }, /* 0x71 ~S^((S^D)&(P^D))*/
230 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
231 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x72 S^(D|(P^S)) */
232 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXnand
) },/* 0x73 ~(S&(D|~P)) */
233 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
234 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x74 D^(S|(P^D)) */
235 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXnand
) },/* 0x75 ~(D&(S|~P)) */
236 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXandReverse
),
237 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x76 S^(D|(P&~S)) */
238 { OP(SRC
,DST
,GXnand
) }, /* 0x77 ~(S&D) */
239 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
) }, /* 0x78 P^(D&S) */
240 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXor
),
241 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
242 OP(TMP
,DST
,GXequiv
) }, /* 0x79 ~D^S^(P&(D|S)) */
243 { OP(DST
,SRC
,GXorInverted
), OP(PAT
,SRC
,GXand
),
244 OP(SRC
,DST
,GXxor
) }, /* 0x7a D^(P&(S|~D)) */
245 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXnand
) }, /* 0x7b ~(S&~(D^P)) */
246 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
),
247 OP(SRC
,DST
,GXxor
) }, /* 0x7c S^(P&(D|~S)) */
248 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXnand
) }, /* 0x7d ~(D&~(P^S)) */
249 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
250 OP(SRC
,DST
,GXor
) }, /* 0x7e (S^P)|(S^D) */
251 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXnand
) }, /* 0x7f ~(D&P&S) */
252 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXand
) }, /* 0x80 D&P&S */
253 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
254 OP(SRC
,DST
,GXnor
) }, /* 0x81 ~((S^P)|(S^D)) */
255 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXand
) }, /* 0x82 D&~(P^S) */
256 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
),
257 OP(SRC
,DST
,GXequiv
) }, /* 0x83 ~S^(P&(D|~S)) */
258 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXand
) }, /* 0x84 S&~(D^P) */
259 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXand
),
260 OP(PAT
,DST
,GXequiv
) }, /* 0x85 ~P^(D&(S|~P)) */
261 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXor
),
262 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
263 OP(TMP
,DST
,GXxor
) }, /* 0x86 D^S^(P&(D|S)) */
264 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXequiv
) }, /* 0x87 ~P^(D&S) */
265 { OP(SRC
,DST
,GXand
) }, /* 0x88 S&D */
266 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXandReverse
),
267 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x89 ~S^(D|(P&~S)) */
268 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXand
) }, /* 0x8a D&(S|~P) */
269 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
270 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x8b ~D^(S|(P^D)) */
271 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXand
) }, /* 0x8c S&(D|~P) */
272 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
273 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x8d ~S^(D|(P^S)) */
274 { OP(SRC
,TMP
,GXcopy
), OP(DST
,SRC
,GXxor
),
275 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
276 OP(TMP
,DST
,GXxor
) }, /* 0x8e S^((S^D)&(P^D))*/
277 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXnand
) }, /* 0x8f ~(P&~(D&S)) */
278 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXand
) }, /* 0x90 P&~(D^S) */
279 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXorReverse
),
280 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x91 ~S^(D&(P|~S)) */
281 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
282 OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
),
283 OP(TMP
,DST
,GXxor
) }, /* 0x92 D^P^(S&(D|P)) */
284 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x93 ~S^(P&D) */
285 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
286 OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
),
287 OP(TMP
,DST
,GXxor
) }, /* 0x94 S^P^(D&(P|S)) */
288 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x95 ~D^(P&S) */
289 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXxor
) }, /* 0x96 D^P^S */
290 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
291 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
292 OP(TMP
,DST
,GXxor
) }, /* 0x97 S^P^(D|~(P|S)) */
293 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
294 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x98 ~S^(D|~(P|S)) */
295 { OP(SRC
,DST
,GXequiv
) }, /* 0x99 ~S^D */
296 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x9a D^(P&~S) */
297 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
298 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x9b ~S^(D&(P|S)) */
299 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x9c S^(P&~D) */
300 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
301 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x9d ~D^(S&(P|D)) */
302 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXand
),
303 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
304 OP(TMP
,DST
,GXxor
) }, /* 0x9e D^S^(P|(D&S)) */
305 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXnand
) }, /* 0x9f ~(P&(D^S)) */
306 { OP(PAT
,DST
,GXand
) }, /* 0xa0 D&P */
307 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXor
),
308 OP(PAT
,DST
,GXequiv
) }, /* 0xa1 ~P^(D|(S&~P)) */
309 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXand
) }, /* 0xa2 D&(P|~S) */
310 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXor
),
311 OP(SRC
,DST
,GXequiv
) }, /* 0xa3 ~D^(P|(S^D)) */
312 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXor
),
313 OP(PAT
,DST
,GXequiv
) }, /* 0xa4 ~P^(D|~(S|P)) */
314 { OP(PAT
,DST
,GXequiv
) }, /* 0xa5 ~P^D */
315 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXxor
) },/* 0xa6 D^(S&~P) */
316 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
),
317 OP(PAT
,DST
,GXequiv
) }, /* 0xa7 ~P^(D&(S|P)) */
318 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
) }, /* 0xa8 D&(P|S) */
319 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXequiv
) }, /* 0xa9 ~D^(P|S) */
320 { OP(PAT
,DST
,GXnoop
) }, /* 0xaa D */
321 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXor
) }, /* 0xab D|~(P|S) */
322 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
),
323 OP(SRC
,DST
,GXxor
) }, /* 0xac S^(P&(D^S)) */
324 { OP(DST
,SRC
,GXand
), OP(PAT
,SRC
,GXor
),
325 OP(SRC
,DST
,GXequiv
) }, /* 0xad ~D^(P|(S&D)) */
326 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXor
) }, /* 0xae D|(S&~P) */
327 { OP(PAT
,DST
,GXorInverted
) }, /* 0xaf D|~P */
328 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
) }, /* 0xb0 P&(D|~S) */
329 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
330 OP(PAT
,DST
,GXequiv
) }, /* 0xb1 ~P^(D|(S^P)) */
331 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
332 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
333 OP(TMP
,DST
,GXxor
) }, /* 0xb2 S^((S^P)|(S^D))*/
334 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXnand
) }, /* 0xb3 ~(S&~(D&P)) */
335 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXxor
) }, /* 0xb4 P^(S&~D) */
336 { OP(DST
,SRC
,GXor
), OP(PAT
,SRC
,GXand
),
337 OP(SRC
,DST
,GXequiv
) }, /* 0xb5 ~D^(P&(S|D)) */
338 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
339 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
340 OP(TMP
,DST
,GXxor
) }, /* 0xb6 D^P^(S|(D&P)) */
341 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXnand
) }, /* 0xb7 ~(S&(D^P)) */
342 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
343 OP(PAT
,DST
,GXxor
) }, /* 0xb8 P^(S&(D^P)) */
344 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
345 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0xb9 ~D^(S|(P&D)) */
346 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXor
) }, /* 0xba D|(P&~S) */
347 { OP(SRC
,DST
,GXorInverted
) }, /* 0xbb ~S|D */
348 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
),
349 OP(SRC
,DST
,GXxor
) }, /* 0xbc S^(P&~(D&S)) */
350 { OP(DST
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
351 OP(SRC
,DST
,GXnand
) }, /* 0xbd ~((S^D)&(P^D)) */
352 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
) }, /* 0xbe D|(P^S) */
353 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXor
) }, /* 0xbf D|~(P&S) */
354 { OP(PAT
,SRC
,GXand
) }, /* 0xc0 P&S */
355 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
),
356 OP(SRC
,DST
,GXequiv
) }, /* 0xc1 ~S^(P|(D&~S)) */
357 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
),
358 OP(SRC
,DST
,GXequiv
) }, /* 0xc2 ~S^(P|~(D|S)) */
359 { OP(PAT
,SRC
,GXequiv
) }, /* 0xc3 ~P^S */
360 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXand
) }, /* 0xc4 S&(P|~D) */
361 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
),
362 OP(SRC
,DST
,GXequiv
) }, /* 0xc5 ~S^(P|(D^S)) */
363 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXxor
) },/* 0xc6 S^(D&~P) */
364 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
),
365 OP(PAT
,DST
,GXequiv
) }, /* 0xc7 ~P^(S&(D|P)) */
366 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
) }, /* 0xc8 S&(D|P) */
367 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXequiv
) }, /* 0xc9 ~S^(P|D) */
368 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXand
),
369 OP(SRC
,DST
,GXxor
) }, /* 0xca D^(P&(S^D)) */
370 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
),
371 OP(SRC
,DST
,GXequiv
) }, /* 0xcb ~S^(P|(D&S)) */
372 { OP(SRC
,DST
,GXcopy
) }, /* 0xcc S */
373 { OP(PAT
,DST
,GXnor
), OP(SRC
,DST
,GXor
) }, /* 0xcd S|~(D|P) */
374 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXor
) }, /* 0xce S|(D&~P) */
375 { OP(PAT
,SRC
,GXorInverted
) }, /* 0xcf S|~P */
376 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXand
) }, /* 0xd0 P&(S|~D) */
377 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
),
378 OP(PAT
,DST
,GXequiv
) }, /* 0xd1 ~P^(S|(D^P)) */
379 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXxor
) },/* 0xd2 P^(D&~S) */
380 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
),
381 OP(SRC
,DST
,GXequiv
) }, /* 0xd3 ~S^(P&(D|S)) */
382 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
383 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
384 OP(TMP
,DST
,GXxor
) }, /* 0xd4 S^((S^P)&(D^P))*/
385 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXnand
) }, /* 0xd5 ~(D&~(P&S)) */
386 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
387 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
388 OP(TMP
,DST
,GXxor
) }, /* 0xd6 S^P^(D|(P&S)) */
389 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXnand
) }, /* 0xd7 ~(D&(P^S)) */
390 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
391 OP(PAT
,DST
,GXxor
) }, /* 0xd8 P^(D&(S^P)) */
392 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
393 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0xd9 ~S^(D|(P&S)) */
394 { OP(DST
,SRC
,GXnand
), OP(PAT
,SRC
,GXand
),
395 OP(SRC
,DST
,GXxor
) }, /* 0xda D^(P&~(S&D)) */
396 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
397 OP(SRC
,DST
,GXnand
) }, /* 0xdb ~((S^P)&(S^D)) */
398 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXor
) }, /* 0xdc S|(P&~D) */
399 { OP(SRC
,DST
,GXorReverse
) }, /* 0xdd S|~D */
400 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
) }, /* 0xde S|(D^P) */
401 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXor
) }, /* 0xdf S|~(D&P) */
402 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
) }, /* 0xe0 P&(D|S) */
403 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXequiv
) }, /* 0xe1 ~P^(D|S) */
404 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
405 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe2 D^(S&(P^D)) */
406 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
),
407 OP(PAT
,DST
,GXequiv
) }, /* 0xe3 ~P^(S|(D&P)) */
408 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
409 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe4 S^(D&(P^S)) */
410 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
),
411 OP(PAT
,DST
,GXequiv
) }, /* 0xe5 ~P^(D|(S&P)) */
412 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnand
),
413 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe6 S^(D&~(P&S)) */
414 { OP(PAT
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
415 OP(SRC
,DST
,GXnand
) }, /* 0xe7 ~((S^P)&(D^P)) */
416 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
417 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
418 OP(TMP
,DST
,GXxor
) }, /* 0xe8 S^((S^P)&(S^D))*/
419 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXnand
),
420 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
421 OP(TMP
,DST
,GXequiv
) }, /* 0xe9 ~D^S^(P&~(S&D))*/
422 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
) }, /* 0xea D|(P&S) */
423 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXor
) }, /* 0xeb D|~(P^S) */
424 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
) }, /* 0xec S|(D&P) */
425 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXor
) }, /* 0xed S|~(D^P) */
426 { OP(SRC
,DST
,GXor
) }, /* 0xee S|D */
427 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXor
) }, /* 0xef S|D|~P */
428 { OP(PAT
,DST
,GXcopy
) }, /* 0xf0 P */
429 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
) }, /* 0xf1 P|~(D|S) */
430 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
) }, /* 0xf2 P|(D&~S) */
431 { OP(PAT
,SRC
,GXorReverse
) }, /* 0xf3 P|~S */
432 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXor
) }, /* 0xf4 P|(S&~D) */
433 { OP(PAT
,DST
,GXorReverse
) }, /* 0xf5 P|~D */
434 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
) }, /* 0xf6 P|(D^S) */
435 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXor
) }, /* 0xf7 P|~(S&D) */
436 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
) }, /* 0xf8 P|(D&S) */
437 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXor
) }, /* 0xf9 P|~(D^S) */
438 { OP(PAT
,DST
,GXor
) }, /* 0xfa D|P */
439 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXor
) }, /* 0xfb D|P|~S */
440 { OP(PAT
,SRC
,GXor
) }, /* 0xfc P|S */
441 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXor
) }, /* 0xfd P|S|~D */
442 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXor
) }, /* 0xfe P|D|S */
443 { OP(PAT
,DST
,GXset
) } /* 0xff 1 */
447 #ifdef BITBLT_TEST /* Opcodes test */
449 static int do_bitop( int s
, int d
, int rop
)
454 case GXclear
: res
= 0; break;
455 case GXand
: res
= s
& d
; break;
456 case GXandReverse
: res
= s
& ~d
; break;
457 case GXcopy
: res
= s
; break;
458 case GXandInverted
: res
= ~s
& d
; break;
459 case GXnoop
: res
= d
; break;
460 case GXxor
: res
= s
^ d
; break;
461 case GXor
: res
= s
| d
; break;
462 case GXnor
: res
= ~(s
| d
); break;
463 case GXequiv
: res
= ~s
^ d
; break;
464 case GXinvert
: res
= ~d
; break;
465 case GXorReverse
: res
= s
| ~d
; break;
466 case GXcopyInverted
: res
= ~s
; break;
467 case GXorInverted
: res
= ~s
| d
; break;
468 case GXnand
: res
= ~(s
& d
); break;
469 case GXset
: res
= 1; break;
476 int rop
, i
, res
, src
, dst
, pat
, tmp
, dstUsed
;
479 for (rop
= 0; rop
< 256; rop
++)
482 for (i
= 0; i
< 8; i
++)
487 for (opcode
= BITBLT_Opcodes
[rop
]; *opcode
; opcode
++)
491 case OP_ARGS(DST
,TMP
):
492 tmp
= do_bitop( dst
, tmp
, *opcode
& 0xf );
494 case OP_ARGS(DST
,SRC
):
495 src
= do_bitop( dst
, src
, *opcode
& 0xf );
497 case OP_ARGS(SRC
,TMP
):
498 tmp
= do_bitop( src
, tmp
, *opcode
& 0xf );
500 case OP_ARGS(SRC
,DST
):
501 dst
= do_bitop( src
, dst
, *opcode
& 0xf );
504 case OP_ARGS(PAT
,TMP
):
505 tmp
= do_bitop( pat
, tmp
, *opcode
& 0xf );
507 case OP_ARGS(PAT
,DST
):
508 dst
= do_bitop( pat
, dst
, *opcode
& 0xf );
511 case OP_ARGS(PAT
,SRC
):
512 src
= do_bitop( pat
, src
, *opcode
& 0xf );
514 case OP_ARGS(TMP
,DST
):
515 dst
= do_bitop( tmp
, dst
, *opcode
& 0xf );
518 case OP_ARGS(TMP
,SRC
):
519 src
= do_bitop( tmp
, src
, *opcode
& 0xf );
522 printf( "Invalid opcode %x\n", *opcode
);
525 if (!dstUsed
) dst
= src
;
526 if (dst
) res
|= 1 << i
;
528 if (res
!= rop
) printf( "%02x: ERROR, res=%02x\n", rop
, res
);
534 #endif /* BITBLT_TEST */
537 static void get_colors(X11DRV_PDEVICE
*physDevDst
, X11DRV_PDEVICE
*physDevSrc
,
542 *fg
= physDevDst
->textPixel
;
543 *bg
= physDevDst
->backgroundPixel
;
544 if(physDevSrc
->depth
== 1) {
545 if(GetDIBColorTable(physDevSrc
->dev
.hdc
, 0, 2, rgb
) == 2) {
547 logcolor
= RGB(rgb
[0].rgbRed
, rgb
[0].rgbGreen
, rgb
[0].rgbBlue
);
548 *fg
= X11DRV_PALETTE_ToPhysical( physDevDst
, logcolor
);
549 logcolor
= RGB(rgb
[1].rgbRed
, rgb
[1].rgbGreen
,rgb
[1].rgbBlue
);
550 *bg
= X11DRV_PALETTE_ToPhysical( physDevDst
, logcolor
);
555 /* return a mask for meaningful bits when doing an XGetPixel on an image */
556 static unsigned long image_pixel_mask( X11DRV_PDEVICE
*physDev
)
559 ColorShifts
*shifts
= physDev
->color_shifts
;
561 if (!shifts
) shifts
= &X11DRV_PALETTE_default_shifts
;
562 ret
= (shifts
->physicalRed
.max
<< shifts
->physicalRed
.shift
) |
563 (shifts
->physicalGreen
.max
<< shifts
->physicalGreen
.shift
) |
564 (shifts
->physicalBlue
.max
<< shifts
->physicalBlue
.shift
);
565 if (!ret
) ret
= (1 << physDev
->depth
) - 1;
570 /***********************************************************************
573 * Stretch a row of pixels. Helper function for BITBLT_StretchImage.
575 static void BITBLT_StretchRow( int *rowSrc
, int *rowDst
,
576 INT startDst
, INT widthDst
,
577 INT xinc
, INT xoff
, WORD mode
)
579 register INT xsrc
= xinc
* startDst
+ xoff
;
583 case STRETCH_ANDSCANS
:
584 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
585 *rowDst
++ &= rowSrc
[xsrc
>> 16];
587 case STRETCH_ORSCANS
:
588 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
589 *rowDst
++ |= rowSrc
[xsrc
>> 16];
591 case STRETCH_DELETESCANS
:
592 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
593 *rowDst
++ = rowSrc
[xsrc
>> 16];
599 /***********************************************************************
602 * Shrink a row of pixels. Helper function for BITBLT_StretchImage.
604 static void BITBLT_ShrinkRow( int *rowSrc
, int *rowDst
,
605 INT startSrc
, INT widthSrc
,
606 INT xinc
, INT xoff
, WORD mode
)
608 register INT xdst
= xinc
* startSrc
+ xoff
;
612 case STRETCH_ORSCANS
:
613 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
614 rowDst
[xdst
>> 16] |= *rowSrc
++;
616 case STRETCH_ANDSCANS
:
617 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
618 rowDst
[xdst
>> 16] &= *rowSrc
++;
620 case STRETCH_DELETESCANS
:
621 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
622 rowDst
[xdst
>> 16] = *rowSrc
++;
628 /***********************************************************************
631 * Retrieve a row from an image. Helper function for BITBLT_StretchImage.
633 static void BITBLT_GetRow( XImage
*image
, int *pdata
, INT row
,
634 INT start
, INT width
, INT depthDst
,
635 int fg
, int bg
, unsigned long pixel_mask
, BOOL swap
)
639 assert( (row
>= 0) && (row
< image
->height
) );
640 assert( (start
>= 0) && (width
<= image
->width
) );
642 pdata
+= swap
? start
+width
-1 : start
;
643 if (image
->depth
== depthDst
) /* color -> color */
645 if (X11DRV_PALETTE_XPixelToPalette
&& (depthDst
!= 1))
646 if (swap
) for (i
= 0; i
< width
; i
++)
647 *pdata
-- = X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, i
, row
)];
648 else for (i
= 0; i
< width
; i
++)
649 *pdata
++ = X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, i
, row
)];
651 if (swap
) for (i
= 0; i
< width
; i
++)
652 *pdata
-- = XGetPixel( image
, i
, row
);
653 else for (i
= 0; i
< width
; i
++)
654 *pdata
++ = XGetPixel( image
, i
, row
);
658 if (image
->depth
== 1) /* monochrome -> color */
660 if (X11DRV_PALETTE_XPixelToPalette
)
662 fg
= X11DRV_PALETTE_XPixelToPalette
[fg
];
663 bg
= X11DRV_PALETTE_XPixelToPalette
[bg
];
665 if (swap
) for (i
= 0; i
< width
; i
++)
666 *pdata
-- = XGetPixel( image
, i
, row
) ? bg
: fg
;
667 else for (i
= 0; i
< width
; i
++)
668 *pdata
++ = XGetPixel( image
, i
, row
) ? bg
: fg
;
670 else /* color -> monochrome */
672 if (swap
) for (i
= 0; i
< width
; i
++)
673 *pdata
-- = ((XGetPixel( image
, i
, row
) & pixel_mask
) == bg
) ? 1 : 0;
674 else for (i
= 0; i
< width
; i
++)
675 *pdata
++ = ((XGetPixel( image
, i
, row
) & pixel_mask
) == bg
) ? 1 : 0;
681 /***********************************************************************
682 * BITBLT_StretchImage
684 * Stretch an X image.
685 * FIXME: does not work for full 32-bit coordinates.
687 static void BITBLT_StretchImage( XImage
*srcImage
, XImage
*dstImage
,
688 INT widthSrc
, INT heightSrc
,
689 INT widthDst
, INT heightDst
,
690 RECT
*visRectSrc
, RECT
*visRectDst
,
691 int foreground
, int background
,
692 unsigned long pixel_mask
, WORD mode
)
694 int *rowSrc
, *rowDst
, *pixel
;
696 INT xinc
, xoff
, yinc
, ysrc
, ydst
;
698 BOOL hstretch
, vstretch
, hswap
, vswap
;
700 hswap
= widthSrc
* widthDst
< 0;
701 vswap
= heightSrc
* heightDst
< 0;
702 widthSrc
= abs(widthSrc
);
703 heightSrc
= abs(heightSrc
);
704 widthDst
= abs(widthDst
);
705 heightDst
= abs(heightDst
);
707 if (!(rowSrc
= HeapAlloc( GetProcessHeap(), 0,
708 (widthSrc
+widthDst
)*sizeof(int) ))) return;
709 rowDst
= rowSrc
+ widthSrc
;
711 /* When stretching, all modes are the same, and DELETESCANS is faster */
712 if ((widthSrc
< widthDst
) && (heightSrc
< heightDst
))
713 mode
= STRETCH_DELETESCANS
;
715 if (mode
== STRETCH_HALFTONE
) /* FIXME */
716 mode
= STRETCH_DELETESCANS
;
718 if (mode
!= STRETCH_DELETESCANS
)
719 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
720 widthDst
*sizeof(int) );
722 hstretch
= (widthSrc
< widthDst
);
723 vstretch
= (heightSrc
< heightDst
);
727 xinc
= (widthSrc
<< 16) / widthDst
;
728 xoff
= ((widthSrc
<< 16) - (xinc
* widthDst
)) / 2;
732 xinc
= ((int)widthDst
<< 16) / widthSrc
;
733 xoff
= ((widthDst
<< 16) - (xinc
* widthSrc
)) / 2;
739 yinc
= (heightSrc
<< 16) / heightDst
;
740 ydst
= visRectDst
->top
;
743 ysrc
= yinc
* (heightDst
- ydst
- 1);
749 for ( ; (ydst
< visRectDst
->bottom
); ysrc
+= yinc
, ydst
++)
751 if (((ysrc
>> 16) < visRectSrc
->top
) ||
752 ((ysrc
>> 16) >= visRectSrc
->bottom
)) continue;
754 /* Retrieve a source row */
755 BITBLT_GetRow( srcImage
, rowSrc
, (ysrc
>> 16) - visRectSrc
->top
,
756 hswap
? widthSrc
- visRectSrc
->right
758 visRectSrc
->right
- visRectSrc
->left
,
759 dstImage
->depth
, foreground
, background
, pixel_mask
, hswap
);
761 /* Stretch or shrink it */
763 BITBLT_StretchRow( rowSrc
, rowDst
, visRectDst
->left
,
764 visRectDst
->right
- visRectDst
->left
,
766 else BITBLT_ShrinkRow( rowSrc
, rowDst
,
767 hswap
? widthSrc
- visRectSrc
->right
769 visRectSrc
->right
- visRectSrc
->left
,
772 /* Store the destination row */
773 pixel
= rowDst
+ visRectDst
->right
- 1;
774 y
= ydst
- visRectDst
->top
;
775 for (x
= visRectDst
->right
-visRectDst
->left
-1; x
>= 0; x
--)
776 XPutPixel( dstImage
, x
, y
, *pixel
-- );
777 if (mode
!= STRETCH_DELETESCANS
)
778 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
779 widthDst
*sizeof(int) );
781 /* Make copies of the destination row */
783 pdata
= dstImage
->data
+ dstImage
->bytes_per_line
* y
;
784 while (((ysrc
+ yinc
) >> 16 == ysrc
>> 16) &&
785 (ydst
< visRectDst
->bottom
-1))
787 memcpy( pdata
+ dstImage
->bytes_per_line
, pdata
,
788 dstImage
->bytes_per_line
);
789 pdata
+= dstImage
->bytes_per_line
;
797 yinc
= (heightDst
<< 16) / heightSrc
;
798 ysrc
= visRectSrc
->top
;
799 ydst
= ((heightDst
<< 16) - (yinc
* heightSrc
)) / 2;
802 ydst
+= yinc
* (heightSrc
- ysrc
- 1);
808 for( ; (ysrc
< visRectSrc
->bottom
); ydst
+= yinc
, ysrc
++)
810 if (((ydst
>> 16) < visRectDst
->top
) ||
811 ((ydst
>> 16) >= visRectDst
->bottom
)) continue;
813 /* Retrieve a source row */
814 BITBLT_GetRow( srcImage
, rowSrc
, ysrc
- visRectSrc
->top
,
815 hswap
? widthSrc
- visRectSrc
->right
817 visRectSrc
->right
- visRectSrc
->left
,
818 dstImage
->depth
, foreground
, background
, pixel_mask
, hswap
);
820 /* Stretch or shrink it */
822 BITBLT_StretchRow( rowSrc
, rowDst
, visRectDst
->left
,
823 visRectDst
->right
- visRectDst
->left
,
825 else BITBLT_ShrinkRow( rowSrc
, rowDst
,
826 hswap
? widthSrc
- visRectSrc
->right
828 visRectSrc
->right
- visRectSrc
->left
,
831 /* Merge several source rows into the destination */
832 if (mode
== STRETCH_DELETESCANS
)
834 /* Simply skip the overlapping rows */
835 while (((ydst
+ yinc
) >> 16 == ydst
>> 16) &&
836 (ysrc
< visRectSrc
->bottom
-1))
842 else if (((ydst
+ yinc
) >> 16 == ydst
>> 16) &&
843 (ysrc
< visRectSrc
->bottom
-1))
844 continue; /* Restart loop for next overlapping row */
846 /* Store the destination row */
847 pixel
= rowDst
+ visRectDst
->right
- 1;
848 y
= (ydst
>> 16) - visRectDst
->top
;
849 for (x
= visRectDst
->right
-visRectDst
->left
-1; x
>= 0; x
--)
850 XPutPixel( dstImage
, x
, y
, *pixel
-- );
851 if (mode
!= STRETCH_DELETESCANS
)
852 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
853 widthDst
*sizeof(int) );
857 HeapFree( GetProcessHeap(), 0, rowSrc
);
861 /***********************************************************************
862 * BITBLT_GetSrcAreaStretch
864 * Retrieve an area from the source DC, stretching and mapping all the
865 * pixels to Windows colors.
867 static int BITBLT_GetSrcAreaStretch( X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
868 Pixmap pixmap
, GC gc
,
869 const struct bitblt_coords
*src
, const struct bitblt_coords
*dst
)
871 XImage
*imageSrc
, *imageDst
;
872 RECT rectSrc
= src
->visrect
;
873 RECT rectDst
= dst
->visrect
;
876 rectSrc
.left
-= src
->x
;
877 rectSrc
.right
-= src
->x
;
878 rectSrc
.top
-= src
->y
;
879 rectSrc
.bottom
-= src
->y
;
880 rectDst
.left
-= dst
->x
;
881 rectDst
.right
-= dst
->x
;
882 rectDst
.top
-= dst
->y
;
883 rectDst
.bottom
-= dst
->y
;
886 rectSrc
.left
-= src
->width
;
887 rectSrc
.right
-= src
->width
;
891 rectDst
.left
-= dst
->width
;
892 rectDst
.right
-= dst
->width
;
896 rectSrc
.top
-= src
->height
;
897 rectSrc
.bottom
-= src
->height
;
901 rectDst
.top
-= dst
->height
;
902 rectDst
.bottom
-= dst
->height
;
905 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
907 /* FIXME: avoid BadMatch errors */
908 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
909 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
910 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
911 src
->visrect
.right
- src
->visrect
.left
,
912 src
->visrect
.bottom
- src
->visrect
.top
,
913 AllPlanes
, ZPixmap
);
916 imageDst
= X11DRV_DIB_CreateXImage( rectDst
.right
- rectDst
.left
,
917 rectDst
.bottom
- rectDst
.top
, physDevDst
->depth
);
918 BITBLT_StretchImage( imageSrc
, imageDst
, src
->width
, src
->height
,
919 dst
->width
, dst
->height
, &rectSrc
, &rectDst
,
920 fg
, physDevDst
->depth
!= 1 ? bg
: physDevSrc
->backgroundPixel
,
921 image_pixel_mask( physDevSrc
), GetStretchBltMode(physDevDst
->dev
.hdc
) );
923 XPutImage( gdi_display
, pixmap
, gc
, imageDst
, 0, 0, 0, 0,
924 rectDst
.right
- rectDst
.left
, rectDst
.bottom
- rectDst
.top
);
925 XDestroyImage( imageSrc
);
926 X11DRV_DIB_DestroyXImage( imageDst
);
928 return 0; /* no exposure events generated */
932 /***********************************************************************
935 * Retrieve an area from the source DC, mapping all the
936 * pixels to Windows colors.
938 static int BITBLT_GetSrcArea( X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
939 Pixmap pixmap
, GC gc
, RECT
*visRectSrc
)
941 XImage
*imageSrc
, *imageDst
;
944 INT width
= visRectSrc
->right
- visRectSrc
->left
;
945 INT height
= visRectSrc
->bottom
- visRectSrc
->top
;
947 BOOL memdc
= (GetObjectType(physDevSrc
->dev
.hdc
) == OBJ_MEMDC
);
949 if (physDevSrc
->depth
== physDevDst
->depth
)
952 if (!X11DRV_PALETTE_XPixelToPalette
||
953 (physDevDst
->depth
== 1)) /* monochrome -> monochrome */
955 if (physDevDst
->depth
== 1)
957 /* MSDN says if StretchBlt must convert a bitmap from monochrome
958 to color or vice versa, the foreground and background color of
959 the device context are used. In fact, it also applies to the
960 case when it is converted from mono to mono. */
961 XSetBackground( gdi_display
, gc
, physDevDst
->textPixel
);
962 XSetForeground( gdi_display
, gc
, physDevDst
->backgroundPixel
);
963 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
964 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
965 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
966 width
, height
, 0, 0, 1);
969 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
970 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
971 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
972 width
, height
, 0, 0);
975 else /* color -> color */
978 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
979 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
980 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
981 width
, height
, AllPlanes
, ZPixmap
);
984 /* Make sure we don't get a BadMatch error */
985 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
986 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
987 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
988 width
, height
, 0, 0);
990 imageSrc
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
991 AllPlanes
, ZPixmap
);
993 for (y
= 0; y
< height
; y
++)
994 for (x
= 0; x
< width
; x
++)
995 XPutPixel(imageSrc
, x
, y
,
996 X11DRV_PALETTE_XPixelToPalette
[XGetPixel(imageSrc
, x
, y
)]);
997 XPutImage( gdi_display
, pixmap
, gc
, imageSrc
,
998 0, 0, 0, 0, width
, height
);
999 XDestroyImage( imageSrc
);
1001 wine_tsx11_unlock();
1005 if (physDevSrc
->depth
== 1) /* monochrome -> color */
1007 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
1010 if (X11DRV_PALETTE_XPixelToPalette
)
1012 XSetBackground( gdi_display
, gc
,
1013 X11DRV_PALETTE_XPixelToPalette
[fg
] );
1014 XSetForeground( gdi_display
, gc
,
1015 X11DRV_PALETTE_XPixelToPalette
[bg
]);
1019 XSetBackground( gdi_display
, gc
, fg
);
1020 XSetForeground( gdi_display
, gc
, bg
);
1022 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
1023 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1024 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1025 width
, height
, 0, 0, 1 );
1027 wine_tsx11_unlock();
1029 else /* color -> monochrome */
1031 unsigned long pixel_mask
;
1033 /* FIXME: avoid BadMatch error */
1034 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
1035 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1036 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1037 width
, height
, AllPlanes
, ZPixmap
);
1040 wine_tsx11_unlock();
1043 imageDst
= X11DRV_DIB_CreateXImage( width
, height
, physDevDst
->depth
);
1046 XDestroyImage(imageSrc
);
1047 wine_tsx11_unlock();
1050 pixel_mask
= image_pixel_mask( physDevSrc
);
1051 for (y
= 0; y
< height
; y
++)
1052 for (x
= 0; x
< width
; x
++)
1053 XPutPixel(imageDst
, x
, y
,
1054 !((XGetPixel(imageSrc
,x
,y
) ^ physDevSrc
->backgroundPixel
) & pixel_mask
));
1055 XPutImage( gdi_display
, pixmap
, gc
, imageDst
,
1056 0, 0, 0, 0, width
, height
);
1057 XDestroyImage( imageSrc
);
1058 X11DRV_DIB_DestroyXImage( imageDst
);
1059 wine_tsx11_unlock();
1066 /***********************************************************************
1069 * Retrieve an area from the destination DC, mapping all the
1070 * pixels to Windows colors.
1072 static int BITBLT_GetDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, GC gc
, RECT
*visRectDst
)
1075 INT width
= visRectDst
->right
- visRectDst
->left
;
1076 INT height
= visRectDst
->bottom
- visRectDst
->top
;
1077 BOOL memdc
= (GetObjectType( physDev
->dev
.hdc
) == OBJ_MEMDC
);
1081 if (!X11DRV_PALETTE_XPixelToPalette
|| (physDev
->depth
== 1) ||
1082 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
1084 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
1085 physDev
->dc_rect
.left
+ visRectDst
->left
, physDev
->dc_rect
.top
+ visRectDst
->top
,
1086 width
, height
, 0, 0 );
1095 image
= XGetImage( gdi_display
, physDev
->drawable
,
1096 physDev
->dc_rect
.left
+ visRectDst
->left
,
1097 physDev
->dc_rect
.top
+ visRectDst
->top
,
1098 width
, height
, AllPlanes
, ZPixmap
);
1101 /* Make sure we don't get a BadMatch error */
1102 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
1103 physDev
->dc_rect
.left
+ visRectDst
->left
,
1104 physDev
->dc_rect
.top
+ visRectDst
->top
,
1105 width
, height
, 0, 0);
1107 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1108 AllPlanes
, ZPixmap
);
1112 for (y
= 0; y
< height
; y
++)
1113 for (x
= 0; x
< width
; x
++)
1114 XPutPixel( image
, x
, y
,
1115 X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, x
, y
)]);
1116 XPutImage( gdi_display
, pixmap
, gc
, image
, 0, 0, 0, 0, width
, height
);
1117 XDestroyImage( image
);
1121 wine_tsx11_unlock();
1126 /***********************************************************************
1129 * Put an area back into the destination DC, mapping the pixel
1130 * colors to X pixels.
1132 static int BITBLT_PutDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, RECT
*visRectDst
)
1135 INT width
= visRectDst
->right
- visRectDst
->left
;
1136 INT height
= visRectDst
->bottom
- visRectDst
->top
;
1138 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
1140 if (!X11DRV_PALETTE_PaletteToXPixel
|| (physDev
->depth
== 1) ||
1141 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
1143 XCopyArea( gdi_display
, pixmap
, physDev
->drawable
, physDev
->gc
, 0, 0, width
, height
,
1144 physDev
->dc_rect
.left
+ visRectDst
->left
,
1145 physDev
->dc_rect
.top
+ visRectDst
->top
);
1151 XImage
*image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1152 AllPlanes
, ZPixmap
);
1153 for (y
= 0; y
< height
; y
++)
1154 for (x
= 0; x
< width
; x
++)
1156 XPutPixel( image
, x
, y
,
1157 X11DRV_PALETTE_PaletteToXPixel
[XGetPixel( image
, x
, y
)]);
1159 XPutImage( gdi_display
, physDev
->drawable
, physDev
->gc
, image
, 0, 0,
1160 physDev
->dc_rect
.left
+ visRectDst
->left
,
1161 physDev
->dc_rect
.top
+ visRectDst
->top
, width
, height
);
1162 XDestroyImage( image
);
1168 /***********************************************************************
1169 * BITBLT_GetVisRectangles
1171 * Get the source and destination visible rectangles for StretchBlt().
1172 * Return FALSE if one of the rectangles is empty.
1174 static BOOL
BITBLT_GetVisRectangles( X11DRV_PDEVICE
*physDevDst
, X11DRV_PDEVICE
*physDevSrc
,
1175 struct bitblt_coords
*dst
, struct bitblt_coords
*src
)
1177 RECT rect
, clipRect
;
1179 /* Get the destination visible rectangle */
1183 rect
.right
= dst
->x
+ dst
->width
;
1184 rect
.bottom
= dst
->y
+ dst
->height
;
1185 LPtoDP( physDevDst
->dev
.hdc
, (POINT
*)&rect
, 2 );
1188 dst
->width
= rect
.right
- rect
.left
;
1189 dst
->height
= rect
.bottom
- rect
.top
;
1190 if (dst
->layout
& LAYOUT_RTL
&& dst
->layout
& LAYOUT_BITMAPORIENTATIONPRESERVED
)
1192 SWAP_INT32( &rect
.left
, &rect
.right
);
1194 dst
->width
= rect
.right
- rect
.left
;
1196 if (rect
.left
> rect
.right
) { SWAP_INT32( &rect
.left
, &rect
.right
); rect
.left
++; rect
.right
++; }
1197 if (rect
.top
> rect
.bottom
) { SWAP_INT32( &rect
.top
, &rect
.bottom
); rect
.top
++; rect
.bottom
++; }
1199 GetRgnBox( physDevDst
->region
, &clipRect
);
1200 if (!IntersectRect( &dst
->visrect
, &rect
, &clipRect
)) return FALSE
;
1202 /* Get the source visible rectangle */
1204 if (!physDevSrc
) return TRUE
;
1208 rect
.right
= src
->x
+ src
->width
;
1209 rect
.bottom
= src
->y
+ src
->height
;
1210 LPtoDP( physDevSrc
->dev
.hdc
, (POINT
*)&rect
, 2 );
1213 src
->width
= rect
.right
- rect
.left
;
1214 src
->height
= rect
.bottom
- rect
.top
;
1215 if (src
->layout
& LAYOUT_RTL
&& src
->layout
& LAYOUT_BITMAPORIENTATIONPRESERVED
)
1217 SWAP_INT32( &rect
.left
, &rect
.right
);
1219 src
->width
= rect
.right
- rect
.left
;
1221 if (rect
.left
> rect
.right
) { SWAP_INT32( &rect
.left
, &rect
.right
); rect
.left
++; rect
.right
++; }
1222 if (rect
.top
> rect
.bottom
) { SWAP_INT32( &rect
.top
, &rect
.bottom
); rect
.top
++; rect
.bottom
++; }
1224 /* Apparently the clipping and visible regions are only for output,
1225 so just check against dc extent here to avoid BadMatch errors */
1226 clipRect
= physDevSrc
->drawable_rect
;
1227 OffsetRect( &clipRect
, -(physDevSrc
->drawable_rect
.left
+ physDevSrc
->dc_rect
.left
),
1228 -(physDevSrc
->drawable_rect
.top
+ physDevSrc
->dc_rect
.top
) );
1229 if (!IntersectRect( &src
->visrect
, &rect
, &clipRect
))
1232 /* Intersect the rectangles */
1234 if ((src
->width
== dst
->width
) && (src
->height
== dst
->height
)) /* no stretching */
1236 OffsetRect( &src
->visrect
, dst
->x
- src
->x
, dst
->y
- src
->y
);
1237 if (!IntersectRect( &rect
, &src
->visrect
, &dst
->visrect
)) return FALSE
;
1238 src
->visrect
= dst
->visrect
= rect
;
1239 OffsetRect( &src
->visrect
, src
->x
- dst
->x
, src
->y
- dst
->y
);
1241 else /* stretching */
1243 /* Map source rectangle into destination coordinates */
1244 rect
.left
= dst
->x
+ (src
->visrect
.left
- src
->x
)*dst
->width
/src
->width
;
1245 rect
.top
= dst
->y
+ (src
->visrect
.top
- src
->y
)*dst
->height
/src
->height
;
1246 rect
.right
= dst
->x
+ (src
->visrect
.right
- src
->x
)*dst
->width
/src
->width
;
1247 rect
.bottom
= dst
->y
+ (src
->visrect
.bottom
- src
->y
)*dst
->height
/src
->height
;
1248 if (rect
.left
> rect
.right
) SWAP_INT32( &rect
.left
, &rect
.right
);
1249 if (rect
.top
> rect
.bottom
) SWAP_INT32( &rect
.top
, &rect
.bottom
);
1251 /* Avoid rounding errors */
1256 if (!IntersectRect( &dst
->visrect
, &rect
, &dst
->visrect
)) return FALSE
;
1258 /* Map destination rectangle back to source coordinates */
1259 rect
= dst
->visrect
;
1260 rect
.left
= src
->x
+ (dst
->visrect
.left
- dst
->x
)*src
->width
/dst
->width
;
1261 rect
.top
= src
->y
+ (dst
->visrect
.top
- dst
->y
)*src
->height
/dst
->height
;
1262 rect
.right
= src
->x
+ (dst
->visrect
.right
- dst
->x
)*src
->width
/dst
->width
;
1263 rect
.bottom
= src
->y
+ (dst
->visrect
.bottom
- dst
->y
)*src
->height
/dst
->height
;
1264 if (rect
.left
> rect
.right
) SWAP_INT32( &rect
.left
, &rect
.right
);
1265 if (rect
.top
> rect
.bottom
) SWAP_INT32( &rect
.top
, &rect
.bottom
);
1267 /* Avoid rounding errors */
1272 if (!IntersectRect( &src
->visrect
, &rect
, &src
->visrect
)) return FALSE
;
1278 /***********************************************************************
1279 * client_side_dib_copy
1281 static BOOL
client_side_dib_copy( X11DRV_PDEVICE
*physDevSrc
, INT xSrc
, INT ySrc
,
1282 X11DRV_PDEVICE
*physDevDst
, INT xDst
, INT yDst
,
1283 INT width
, INT height
)
1285 DIBSECTION srcDib
, dstDib
;
1286 BYTE
*srcPtr
, *dstPtr
;
1287 INT srcRowOffset
, dstRowOffset
;
1291 static RECT unusedRect
;
1293 if (GetObjectW(physDevSrc
->bitmap
->hbitmap
, sizeof(srcDib
), &srcDib
) != sizeof(srcDib
))
1295 if (GetObjectW(physDevDst
->bitmap
->hbitmap
, sizeof(dstDib
), &dstDib
) != sizeof(dstDib
))
1298 /* check for oversized values, just like X11DRV_DIB_CopyDIBSection() */
1299 if (xSrc
> srcDib
.dsBm
.bmWidth
|| ySrc
> srcDib
.dsBm
.bmHeight
)
1301 if (xSrc
+ width
> srcDib
.dsBm
.bmWidth
)
1302 width
= srcDib
.dsBm
.bmWidth
- xSrc
;
1303 if (ySrc
+ height
> srcDib
.dsBm
.bmHeight
)
1304 height
= srcDib
.dsBm
.bmHeight
- ySrc
;
1306 if (GetRgnBox(physDevDst
->region
, &unusedRect
) == COMPLEXREGION
)
1308 /* for simple regions, the clipping was already done by BITBLT_GetVisRectangles */
1309 FIXME("potential optimization: client-side complex region clipping\n");
1312 if (dstDib
.dsBm
.bmBitsPixel
<= 8)
1314 static BOOL fixme_once
;
1315 if(!fixme_once
++) FIXME("potential optimization: client-side color-index mode DIB copy\n");
1318 if (!(srcDib
.dsBmih
.biCompression
== BI_BITFIELDS
&&
1319 dstDib
.dsBmih
.biCompression
== BI_BITFIELDS
&&
1320 !memcmp(srcDib
.dsBitfields
, dstDib
.dsBitfields
, 3*sizeof(DWORD
)))
1321 && !(srcDib
.dsBmih
.biCompression
== BI_RGB
&&
1322 dstDib
.dsBmih
.biCompression
== BI_RGB
))
1324 FIXME("potential optimization: client-side compressed DIB copy\n");
1327 if (srcDib
.dsBm
.bmBitsPixel
!= dstDib
.dsBm
.bmBitsPixel
)
1329 FIXME("potential optimization: pixel format conversion\n");
1332 if (srcDib
.dsBmih
.biWidth
< 0 || dstDib
.dsBmih
.biWidth
< 0)
1334 FIXME("negative widths not yet implemented\n");
1338 switch (dstDib
.dsBm
.bmBitsPixel
)
1351 FIXME("don't know how to work with a depth of %d\n", physDevSrc
->depth
);
1355 bytesToCopy
= width
* bytesPerPixel
;
1357 if (physDevSrc
->bitmap
->topdown
)
1359 srcPtr
= &physDevSrc
->bitmap
->base
[ySrc
*srcDib
.dsBm
.bmWidthBytes
+ xSrc
*bytesPerPixel
];
1360 srcRowOffset
= srcDib
.dsBm
.bmWidthBytes
;
1364 srcPtr
= &physDevSrc
->bitmap
->base
[(srcDib
.dsBm
.bmHeight
-ySrc
-1)*srcDib
.dsBm
.bmWidthBytes
1365 + xSrc
*bytesPerPixel
];
1366 srcRowOffset
= -srcDib
.dsBm
.bmWidthBytes
;
1368 if (physDevDst
->bitmap
->topdown
)
1370 dstPtr
= &physDevDst
->bitmap
->base
[yDst
*dstDib
.dsBm
.bmWidthBytes
+ xDst
*bytesPerPixel
];
1371 dstRowOffset
= dstDib
.dsBm
.bmWidthBytes
;
1375 dstPtr
= &physDevDst
->bitmap
->base
[(dstDib
.dsBm
.bmHeight
-yDst
-1)*dstDib
.dsBm
.bmWidthBytes
1376 + xDst
*bytesPerPixel
];
1377 dstRowOffset
= -dstDib
.dsBm
.bmWidthBytes
;
1380 /* Handle overlapping regions on the same DIB */
1381 if (physDevSrc
== physDevDst
&& ySrc
< yDst
)
1383 srcPtr
+= srcRowOffset
* (height
- 1);
1384 srcRowOffset
= -srcRowOffset
;
1385 dstPtr
+= dstRowOffset
* (height
- 1);
1386 dstRowOffset
= -dstRowOffset
;
1389 for (y
= yDst
; y
< yDst
+ height
; ++y
)
1391 memmove(dstPtr
, srcPtr
, bytesToCopy
);
1392 srcPtr
+= srcRowOffset
;
1393 dstPtr
+= dstRowOffset
;
1399 static BOOL
same_format(X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
)
1401 if (physDevSrc
->depth
!= physDevDst
->depth
) return FALSE
;
1402 if (!physDevSrc
->color_shifts
&& !physDevDst
->color_shifts
) return TRUE
;
1403 if (physDevSrc
->color_shifts
&& physDevDst
->color_shifts
)
1404 return !memcmp(physDevSrc
->color_shifts
, physDevDst
->color_shifts
, sizeof(ColorShifts
));
1408 /***********************************************************************
1411 BOOL CDECL
X11DRV_PatBlt( PHYSDEV dev
, INT x
, INT y
, INT width
, INT height
, DWORD rop
)
1413 X11DRV_PDEVICE
*physDev
= get_x11drv_dev( dev
);
1414 BOOL usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
1415 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1416 struct bitblt_coords dst
;
1421 dst
.height
= height
;
1422 dst
.layout
= GetLayout( dev
->hdc
);
1424 if (rop
& NOMIRRORBITMAP
)
1426 dst
.layout
|= LAYOUT_BITMAPORIENTATIONPRESERVED
;
1427 rop
&= ~NOMIRRORBITMAP
;
1430 if (!BITBLT_GetVisRectangles( physDev
, NULL
, &dst
, NULL
)) return TRUE
;
1431 if (usePat
&& !X11DRV_SetupGCForBrush( physDev
)) return TRUE
;
1433 TRACE( "rect=%d,%d %dx%d org=%d,%d vis=%s\n",
1434 dst
.x
, dst
.y
, dst
.width
, dst
.height
,
1435 physDev
->dc_rect
.left
, physDev
->dc_rect
.top
, wine_dbgstr_rect( &dst
.visrect
) );
1437 width
= dst
.visrect
.right
- dst
.visrect
.left
;
1438 height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
1440 X11DRV_LockDIBSection( physDev
, DIB_Status_GdiMod
);
1443 XSetFunction( gdi_display
, physDev
->gc
, OP_ROP(*opcode
) );
1445 switch(rop
) /* a few special cases */
1447 case BLACKNESS
: /* 0x00 */
1448 case WHITENESS
: /* 0xff */
1449 if ((physDev
->depth
!= 1) && X11DRV_PALETTE_PaletteToXPixel
)
1451 XSetFunction( gdi_display
, physDev
->gc
, GXcopy
);
1452 if (rop
== BLACKNESS
)
1453 XSetForeground( gdi_display
, physDev
->gc
, X11DRV_PALETTE_PaletteToXPixel
[0] );
1455 XSetForeground( gdi_display
, physDev
->gc
,
1456 WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ));
1457 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
1460 case DSTINVERT
: /* 0x55 */
1461 if (!(X11DRV_PALETTE_PaletteFlags
& (X11DRV_PALETTE_PRIVATE
| X11DRV_PALETTE_VIRTUAL
)))
1463 /* Xor is much better when we do not have full colormap. */
1464 /* Using white^black ensures that we invert at least black */
1466 unsigned long xor_pix
= (WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ) ^
1467 BlackPixel( gdi_display
, DefaultScreen(gdi_display
) ));
1468 XSetFunction( gdi_display
, physDev
->gc
, GXxor
);
1469 XSetForeground( gdi_display
, physDev
->gc
, xor_pix
);
1470 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
1474 XFillRectangle( gdi_display
, physDev
->drawable
, physDev
->gc
,
1475 physDev
->dc_rect
.left
+ dst
.visrect
.left
,
1476 physDev
->dc_rect
.top
+ dst
.visrect
.top
,
1477 dst
.visrect
.right
- dst
.visrect
.left
,
1478 dst
.visrect
.bottom
- dst
.visrect
.top
);
1479 wine_tsx11_unlock();
1481 X11DRV_UnlockDIBSection( physDev
, TRUE
);
1486 /***********************************************************************
1489 BOOL CDECL
X11DRV_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
1490 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
1492 X11DRV_PDEVICE
*physDevDst
= get_x11drv_dev( dst_dev
);
1493 X11DRV_PDEVICE
*physDevSrc
= get_x11drv_dev( src_dev
); /* FIXME: check that it's really an x11 dev */
1494 BOOL usePat
, useDst
, destUsed
, fStretch
, fNullBrush
;
1496 INT sDst
, sSrc
= DIB_Status_None
;
1498 Pixmap pixmaps
[3] = { 0, 0, 0 }; /* pixmaps for DST, SRC, TMP */
1501 if (IsRectEmpty( &dst
->visrect
)) return TRUE
;
1503 usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
1504 useDst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
1505 fStretch
= (src
->width
!= dst
->width
) || (src
->height
!= dst
->height
);
1507 if (physDevDst
!= physDevSrc
)
1508 sSrc
= X11DRV_LockDIBSection( physDevSrc
, DIB_Status_None
);
1510 width
= dst
->visrect
.right
- dst
->visrect
.left
;
1511 height
= dst
->visrect
.bottom
- dst
->visrect
.top
;
1513 sDst
= X11DRV_LockDIBSection( physDevDst
, DIB_Status_None
);
1514 if (physDevDst
== physDevSrc
) sSrc
= sDst
;
1516 /* try client-side DIB copy */
1517 if (!fStretch
&& rop
== SRCCOPY
&&
1518 sSrc
== DIB_Status_AppMod
&& sDst
== DIB_Status_AppMod
&&
1519 same_format(physDevSrc
, physDevDst
))
1521 if (client_side_dib_copy( physDevSrc
, src
->visrect
.left
, src
->visrect
.top
,
1522 physDevDst
, dst
->visrect
.left
, dst
->visrect
.top
, width
, height
))
1526 X11DRV_CoerceDIBSection( physDevDst
, DIB_Status_GdiMod
);
1528 opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1530 /* a few optimizations for single-op ROPs */
1531 if (!fStretch
&& !opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
))
1533 if (same_format(physDevSrc
, physDevDst
))
1536 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
1537 wine_tsx11_unlock();
1539 if (physDevSrc
!= physDevDst
)
1541 if (sSrc
== DIB_Status_AppMod
)
1543 X11DRV_DIB_CopyDIBSection( physDevSrc
, physDevDst
, src
->visrect
.left
, src
->visrect
.top
,
1544 dst
->visrect
.left
, dst
->visrect
.top
, width
, height
);
1547 X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
);
1550 XCopyArea( gdi_display
, physDevSrc
->drawable
,
1551 physDevDst
->drawable
, physDevDst
->gc
,
1552 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
1553 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
1555 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
1556 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
);
1557 physDevDst
->exposures
++;
1558 wine_tsx11_unlock();
1561 if (physDevSrc
->depth
== 1)
1565 X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
);
1566 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
1568 XSetBackground( gdi_display
, physDevDst
->gc
, fg
);
1569 XSetForeground( gdi_display
, physDevDst
->gc
, bg
);
1570 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
1571 XCopyPlane( gdi_display
, physDevSrc
->drawable
,
1572 physDevDst
->drawable
, physDevDst
->gc
,
1573 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
1574 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
1576 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
1577 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
, 1 );
1578 physDevDst
->exposures
++;
1579 wine_tsx11_unlock();
1585 tmpGC
= XCreateGC( gdi_display
, physDevDst
->drawable
, 0, NULL
);
1586 XSetSubwindowMode( gdi_display
, tmpGC
, IncludeInferiors
);
1587 XSetGraphicsExposures( gdi_display
, tmpGC
, False
);
1588 pixmaps
[DST
] = XCreatePixmap( gdi_display
, root_window
, width
, height
,
1589 physDevDst
->depth
);
1590 pixmaps
[SRC
] = XCreatePixmap( gdi_display
, root_window
, width
, height
,
1591 physDevDst
->depth
);
1592 wine_tsx11_unlock();
1594 if (physDevDst
!= physDevSrc
) X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
);
1596 if(!X11DRV_XRender_GetSrcAreaStretch( physDevSrc
, physDevDst
, pixmaps
[SRC
], tmpGC
, src
, dst
))
1599 BITBLT_GetSrcAreaStretch( physDevSrc
, physDevDst
, pixmaps
[SRC
], tmpGC
, src
, dst
);
1601 BITBLT_GetSrcArea( physDevSrc
, physDevDst
, pixmaps
[SRC
], tmpGC
, &src
->visrect
);
1604 if (useDst
) BITBLT_GetDstArea( physDevDst
, pixmaps
[DST
], tmpGC
, &dst
->visrect
);
1605 if (usePat
) fNullBrush
= !X11DRV_SetupGCForPatBlt( physDevDst
, tmpGC
, TRUE
);
1606 else fNullBrush
= FALSE
;
1610 for ( ; *opcode
; opcode
++)
1612 if (OP_DST(*opcode
) == DST
) destUsed
= TRUE
;
1613 XSetFunction( gdi_display
, tmpGC
, OP_ROP(*opcode
) );
1614 switch(OP_SRCDST(*opcode
))
1616 case OP_ARGS(DST
,TMP
):
1617 case OP_ARGS(SRC
,TMP
):
1619 pixmaps
[TMP
] = XCreatePixmap( gdi_display
, root_window
,
1620 width
, height
, physDevDst
->depth
);
1622 case OP_ARGS(DST
,SRC
):
1623 case OP_ARGS(SRC
,DST
):
1624 case OP_ARGS(TMP
,SRC
):
1625 case OP_ARGS(TMP
,DST
):
1626 XCopyArea( gdi_display
, pixmaps
[OP_SRC(*opcode
)],
1627 pixmaps
[OP_DST(*opcode
)], tmpGC
,
1628 0, 0, width
, height
, 0, 0 );
1631 case OP_ARGS(PAT
,TMP
):
1632 if (!pixmaps
[TMP
] && !fNullBrush
)
1633 pixmaps
[TMP
] = XCreatePixmap( gdi_display
, root_window
,
1634 width
, height
, physDevDst
->depth
);
1636 case OP_ARGS(PAT
,DST
):
1637 case OP_ARGS(PAT
,SRC
):
1639 XFillRectangle( gdi_display
, pixmaps
[OP_DST(*opcode
)],
1640 tmpGC
, 0, 0, width
, height
);
1644 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1645 physDevDst
->exposures
+= BITBLT_PutDstArea( physDevDst
, pixmaps
[destUsed
? DST
: SRC
], &dst
->visrect
);
1646 XFreePixmap( gdi_display
, pixmaps
[DST
] );
1647 if (pixmaps
[SRC
]) XFreePixmap( gdi_display
, pixmaps
[SRC
] );
1648 if (pixmaps
[TMP
]) XFreePixmap( gdi_display
, pixmaps
[TMP
] );
1649 XFreeGC( gdi_display
, tmpGC
);
1650 wine_tsx11_unlock();
1653 if (physDevDst
!= physDevSrc
) X11DRV_UnlockDIBSection( physDevSrc
, FALSE
);
1654 X11DRV_UnlockDIBSection( physDevDst
, TRUE
);
1659 /***********************************************************************
1662 BOOL CDECL
X11DRV_AlphaBlend( PHYSDEV dst_dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
1663 PHYSDEV src_dev
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
1664 BLENDFUNCTION blendfn
)
1666 X11DRV_PDEVICE
*physDevDst
= get_x11drv_dev( dst_dev
);
1667 X11DRV_PDEVICE
*physDevSrc
= get_x11drv_dev( src_dev
); /* FIXME: check that it's really an x11 dev */
1668 struct bitblt_coords src
, dst
;
1672 src
.width
= widthSrc
;
1673 src
.height
= heightSrc
;
1674 src
.layout
= GetLayout( src_dev
->hdc
);
1677 dst
.width
= widthDst
;
1678 dst
.height
= heightDst
;
1679 dst
.layout
= GetLayout( dst_dev
->hdc
);
1681 if (!BITBLT_GetVisRectangles( physDevDst
, physDevSrc
, &dst
, &src
)) return TRUE
;
1683 TRACE( "format %x alpha %u rectdst=%d,%d %dx%d orgdst=%d,%d visdst=%s rectsrc=%d,%d %dx%d orgsrc=%d,%d vissrc=%s\n",
1684 blendfn
.AlphaFormat
, blendfn
.SourceConstantAlpha
, dst
.x
, dst
.y
, dst
.width
, dst
.height
,
1685 physDevDst
->dc_rect
.left
, physDevDst
->dc_rect
.top
, wine_dbgstr_rect( &dst
.visrect
),
1686 src
.x
, src
.y
, src
.width
, src
.height
,
1687 physDevSrc
->dc_rect
.left
, physDevSrc
->dc_rect
.top
, wine_dbgstr_rect( &src
.visrect
) );
1689 if (src
.x
< 0 || src
.y
< 0 || src
.width
< 0 || src
.height
< 0 ||
1690 src
.width
> physDevSrc
->drawable_rect
.right
- physDevSrc
->drawable_rect
.left
- src
.x
||
1691 src
.height
> physDevSrc
->drawable_rect
.bottom
- physDevSrc
->drawable_rect
.top
- src
.y
)
1693 WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src
.x
, src
.y
, src
.width
, src
.height
);
1694 SetLastError( ERROR_INVALID_PARAMETER
);
1698 return XRender_AlphaBlend( physDevDst
, physDevSrc
, &dst
, &src
, blendfn
);