2 * GDI bit-blit operations
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <X11/Intrinsic.h>
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
->org
.x
+ visRectSrc
->left
,
880 physDevSrc
->org
.y
+ visRectSrc
->top
,
881 visRectSrc
->right
- visRectSrc
->left
,
882 visRectSrc
->bottom
- visRectSrc
->top
,
883 AllPlanes
, ZPixmap
);
884 imageDst
= X11DRV_DIB_CreateXImage( rectDst
.right
- rectDst
.left
,
885 rectDst
.bottom
- rectDst
.top
, physDevDst
->depth
);
886 BITBLT_StretchImage( imageSrc
, imageDst
, widthSrc
, heightSrc
,
887 widthDst
, heightDst
, &rectSrc
, &rectDst
,
888 fg
, physDevDst
->depth
!= 1 ?
889 bg
: physDevSrc
->backgroundPixel
,
890 GetStretchBltMode(physDevDst
->hdc
) );
891 XPutImage( gdi_display
, pixmap
, gc
, imageDst
, 0, 0, 0, 0,
892 rectDst
.right
- rectDst
.left
, rectDst
.bottom
- rectDst
.top
);
893 XDestroyImage( imageSrc
);
894 XDestroyImage( imageDst
);
895 return 0; /* no exposure events generated */
899 /***********************************************************************
902 * Retrieve an area from the source DC, mapping all the
903 * pixels to Windows colors.
905 static int BITBLT_GetSrcArea( X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
906 Pixmap pixmap
, GC gc
, INT xSrc
, INT ySrc
, RECT
*visRectSrc
)
908 XImage
*imageSrc
, *imageDst
;
911 INT width
= visRectSrc
->right
- visRectSrc
->left
;
912 INT height
= visRectSrc
->bottom
- visRectSrc
->top
;
915 if (physDevSrc
->depth
== physDevDst
->depth
)
917 if (!X11DRV_PALETTE_XPixelToPalette
||
918 (physDevDst
->depth
== 1)) /* monochrome -> monochrome */
920 if (physDevDst
->depth
== 1)
922 /* MSDN says if StretchBlt must convert a bitmap from monochrome
923 to color or vice versa, the forground and background color of
924 the device context are used. In fact, it also applies to the
925 case when it is converted from mono to mono. */
926 XSetBackground( gdi_display
, gc
, physDevDst
->textPixel
);
927 XSetForeground( gdi_display
, gc
, physDevDst
->backgroundPixel
);
928 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
929 physDevSrc
->org
.x
+ visRectSrc
->left
,
930 physDevSrc
->org
.y
+ visRectSrc
->top
,
931 width
, height
, 0, 0, 1);
934 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
935 physDevSrc
->org
.x
+ visRectSrc
->left
,
936 physDevSrc
->org
.y
+ visRectSrc
->top
,
937 width
, height
, 0, 0);
940 else /* color -> color */
942 if (GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
943 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
944 physDevSrc
->org
.x
+ visRectSrc
->left
,
945 physDevSrc
->org
.y
+ visRectSrc
->top
,
946 width
, height
, AllPlanes
, ZPixmap
);
949 /* Make sure we don't get a BadMatch error */
950 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
951 physDevSrc
->org
.x
+ visRectSrc
->left
,
952 physDevSrc
->org
.y
+ visRectSrc
->top
,
953 width
, height
, 0, 0);
955 imageSrc
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
956 AllPlanes
, ZPixmap
);
958 for (y
= 0; y
< height
; y
++)
959 for (x
= 0; x
< width
; x
++)
960 XPutPixel(imageSrc
, x
, y
,
961 X11DRV_PALETTE_XPixelToPalette
[XGetPixel(imageSrc
, x
, y
)]);
962 XPutImage( gdi_display
, pixmap
, gc
, imageSrc
,
963 0, 0, 0, 0, width
, height
);
964 XDestroyImage( imageSrc
);
969 if (physDevSrc
->depth
== 1) /* monochrome -> color */
971 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
973 if (X11DRV_PALETTE_XPixelToPalette
)
975 XSetBackground( gdi_display
, gc
,
976 X11DRV_PALETTE_XPixelToPalette
[fg
] );
977 XSetForeground( gdi_display
, gc
,
978 X11DRV_PALETTE_XPixelToPalette
[bg
]);
982 XSetBackground( gdi_display
, gc
, fg
);
983 XSetForeground( gdi_display
, gc
, bg
);
985 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
986 physDevSrc
->org
.x
+ visRectSrc
->left
,
987 physDevSrc
->org
.y
+ visRectSrc
->top
,
988 width
, height
, 0, 0, 1 );
991 else /* color -> monochrome */
993 /* FIXME: avoid BadMatch error */
994 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
995 physDevSrc
->org
.x
+ visRectSrc
->left
,
996 physDevSrc
->org
.y
+ visRectSrc
->top
,
997 width
, height
, AllPlanes
, ZPixmap
);
1002 imageDst
= X11DRV_DIB_CreateXImage( width
, height
, physDevDst
->depth
);
1005 XDestroyImage(imageSrc
);
1008 for (y
= 0; y
< height
; y
++)
1009 for (x
= 0; x
< width
; x
++)
1010 XPutPixel(imageDst
, x
, y
, (XGetPixel(imageSrc
,x
,y
) ==
1011 physDevSrc
->backgroundPixel
) );
1012 XPutImage( gdi_display
, pixmap
, gc
, imageDst
,
1013 0, 0, 0, 0, width
, height
);
1014 XDestroyImage( imageSrc
);
1015 XDestroyImage( imageDst
);
1022 /***********************************************************************
1025 * Retrieve an area from the destination DC, mapping all the
1026 * pixels to Windows colors.
1028 static int BITBLT_GetDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, GC gc
, RECT
*visRectDst
)
1031 INT width
= visRectDst
->right
- visRectDst
->left
;
1032 INT height
= visRectDst
->bottom
- visRectDst
->top
;
1034 if (!X11DRV_PALETTE_XPixelToPalette
|| (physDev
->depth
== 1) ||
1035 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
1037 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
1038 physDev
->org
.x
+ visRectDst
->left
, physDev
->org
.y
+ visRectDst
->top
,
1039 width
, height
, 0, 0 );
1047 if (GetObjectType( physDev
->hdc
) == OBJ_MEMDC
)
1048 image
= XGetImage( gdi_display
, physDev
->drawable
,
1049 physDev
->org
.x
+ visRectDst
->left
,
1050 physDev
->org
.y
+ visRectDst
->top
,
1051 width
, height
, AllPlanes
, ZPixmap
);
1054 /* Make sure we don't get a BadMatch error */
1055 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
1056 physDev
->org
.x
+ visRectDst
->left
,
1057 physDev
->org
.y
+ visRectDst
->top
,
1058 width
, height
, 0, 0);
1060 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1061 AllPlanes
, ZPixmap
);
1063 for (y
= 0; y
< height
; y
++)
1064 for (x
= 0; x
< width
; x
++)
1065 XPutPixel( image
, x
, y
,
1066 X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, x
, y
)]);
1067 XPutImage( gdi_display
, pixmap
, gc
, image
, 0, 0, 0, 0, width
, height
);
1068 XDestroyImage( image
);
1074 /***********************************************************************
1077 * Put an area back into the destination DC, mapping the pixel
1078 * colors to X pixels.
1080 static int BITBLT_PutDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, RECT
*visRectDst
)
1083 INT width
= visRectDst
->right
- visRectDst
->left
;
1084 INT height
= visRectDst
->bottom
- visRectDst
->top
;
1086 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
1088 if (!X11DRV_PALETTE_PaletteToXPixel
|| (physDev
->depth
== 1) ||
1089 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
1091 XCopyArea( gdi_display
, pixmap
, physDev
->drawable
, physDev
->gc
, 0, 0, width
, height
,
1092 physDev
->org
.x
+ visRectDst
->left
,
1093 physDev
->org
.y
+ visRectDst
->top
);
1099 XImage
*image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1100 AllPlanes
, ZPixmap
);
1101 for (y
= 0; y
< height
; y
++)
1102 for (x
= 0; x
< width
; x
++)
1104 XPutPixel( image
, x
, y
,
1105 X11DRV_PALETTE_PaletteToXPixel
[XGetPixel( image
, x
, y
)]);
1107 XPutImage( gdi_display
, physDev
->drawable
, physDev
->gc
, image
, 0, 0,
1108 physDev
->org
.x
+ visRectDst
->left
,
1109 physDev
->org
.y
+ visRectDst
->top
, width
, height
);
1110 XDestroyImage( image
);
1116 /***********************************************************************
1117 * BITBLT_GetVisRectangles
1119 * Get the source and destination visible rectangles for StretchBlt().
1120 * Return FALSE if one of the rectangles is empty.
1122 static BOOL
BITBLT_GetVisRectangles( X11DRV_PDEVICE
*physDevDst
, INT xDst
, INT yDst
,
1123 INT widthDst
, INT heightDst
,
1124 X11DRV_PDEVICE
*physDevSrc
, INT xSrc
, INT ySrc
,
1125 INT widthSrc
, INT heightSrc
,
1126 RECT
*visRectSrc
, RECT
*visRectDst
)
1128 RECT rect
, clipRect
;
1130 /* Get the destination visible rectangle */
1134 rect
.right
= xDst
+ widthDst
;
1135 rect
.bottom
= yDst
+ heightDst
;
1136 if (widthDst
< 0) SWAP_INT32( &rect
.left
, &rect
.right
);
1137 if (heightDst
< 0) SWAP_INT32( &rect
.top
, &rect
.bottom
);
1138 GetRgnBox( physDevDst
->region
, &clipRect
);
1139 if (!IntersectRect( visRectDst
, &rect
, &clipRect
)) return FALSE
;
1141 /* Get the source visible rectangle */
1143 if (!physDevSrc
) return TRUE
;
1146 rect
.right
= xSrc
+ widthSrc
;
1147 rect
.bottom
= ySrc
+ heightSrc
;
1148 if (widthSrc
< 0) SWAP_INT32( &rect
.left
, &rect
.right
);
1149 if (heightSrc
< 0) SWAP_INT32( &rect
.top
, &rect
.bottom
);
1150 /* Apparently the clipping and visible regions are only for output,
1151 so just check against dc extent here to avoid BadMatch errors */
1152 if (physDevSrc
->bitmap
)
1155 GetObjectW( physDevSrc
->bitmap
->hbitmap
, sizeof(bm
), &bm
);
1156 SetRect( &clipRect
, 0, 0, bm
.bmWidth
, bm
.bmHeight
);
1158 else SetRect( &clipRect
, 0, 0, screen_width
, screen_height
);
1159 if (!IntersectRect( visRectSrc
, &rect
, &clipRect
))
1162 /* Intersect the rectangles */
1164 if ((widthSrc
== widthDst
) && (heightSrc
== heightDst
)) /* no stretching */
1166 visRectSrc
->left
+= xDst
- xSrc
;
1167 visRectSrc
->right
+= xDst
- xSrc
;
1168 visRectSrc
->top
+= yDst
- ySrc
;
1169 visRectSrc
->bottom
+= yDst
- ySrc
;
1170 if (!IntersectRect( &rect
, visRectSrc
, visRectDst
)) return FALSE
;
1171 *visRectSrc
= *visRectDst
= rect
;
1172 visRectSrc
->left
+= xSrc
- xDst
;
1173 visRectSrc
->right
+= xSrc
- xDst
;
1174 visRectSrc
->top
+= ySrc
- yDst
;
1175 visRectSrc
->bottom
+= ySrc
- yDst
;
1177 else /* stretching */
1179 /* Map source rectangle into destination coordinates */
1180 rect
.left
= xDst
+ (visRectSrc
->left
- xSrc
)*widthDst
/widthSrc
;
1181 rect
.top
= yDst
+ (visRectSrc
->top
- ySrc
)*heightDst
/heightSrc
;
1182 rect
.right
= xDst
+ ((visRectSrc
->right
- xSrc
)*widthDst
)/widthSrc
;
1183 rect
.bottom
= yDst
+ ((visRectSrc
->bottom
- ySrc
)*heightDst
)/heightSrc
;
1184 if (rect
.left
> rect
.right
) SWAP_INT32( &rect
.left
, &rect
.right
);
1185 if (rect
.top
> rect
.bottom
) SWAP_INT32( &rect
.top
, &rect
.bottom
);
1187 /* Avoid rounding errors */
1192 if (!IntersectRect( visRectDst
, &rect
, visRectDst
)) return FALSE
;
1194 /* Map destination rectangle back to source coordinates */
1196 rect
.left
= xSrc
+ (visRectDst
->left
- xDst
)*widthSrc
/widthDst
;
1197 rect
.top
= ySrc
+ (visRectDst
->top
- yDst
)*heightSrc
/heightDst
;
1198 rect
.right
= xSrc
+ ((visRectDst
->right
- xDst
)*widthSrc
)/widthDst
;
1199 rect
.bottom
= ySrc
+ ((visRectDst
->bottom
- yDst
)*heightSrc
)/heightDst
;
1200 if (rect
.left
> rect
.right
) SWAP_INT32( &rect
.left
, &rect
.right
);
1201 if (rect
.top
> rect
.bottom
) SWAP_INT32( &rect
.top
, &rect
.bottom
);
1203 /* Avoid rounding errors */
1208 if (!IntersectRect( visRectSrc
, &rect
, visRectSrc
)) return FALSE
;
1214 /***********************************************************************
1215 * BITBLT_InternalStretchBlt
1217 * Implementation of PatBlt(), BitBlt() and StretchBlt().
1219 static BOOL
BITBLT_InternalStretchBlt( X11DRV_PDEVICE
*physDevDst
, INT xDst
, INT yDst
,
1220 INT widthDst
, INT heightDst
,
1221 X11DRV_PDEVICE
*physDevSrc
, INT xSrc
, INT ySrc
,
1222 INT widthSrc
, INT heightSrc
,
1225 BOOL usePat
, useSrc
, useDst
, destUsed
, fStretch
, fNullBrush
;
1226 RECT visRectDst
, visRectSrc
;
1229 Pixmap pixmaps
[3] = { 0, 0, 0 }; /* pixmaps for DST, SRC, TMP */
1233 /* compensate for off-by-one shifting for negative widths and heights */
1243 usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
1244 useSrc
= (((rop
>> 2) & 0x330000) != (rop
& 0x330000));
1245 useDst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
1246 if (!physDevSrc
&& useSrc
) return FALSE
;
1248 /* Map the coordinates to device coords */
1252 pts
[1].x
= xDst
+ widthDst
;
1253 pts
[1].y
= yDst
+ heightDst
;
1254 LPtoDP(physDevDst
->hdc
, pts
, 2);
1257 widthDst
= pts
[1].x
- pts
[0].x
;
1258 heightDst
= pts
[1].y
- pts
[0].y
;
1260 TRACE(" rectdst=%d,%d-%d,%d orgdst=%ld,%ld\n",
1261 xDst
, yDst
, widthDst
, heightDst
,
1262 physDevDst
->org
.x
, physDevDst
->org
.y
);
1268 pts
[1].x
= xSrc
+ widthSrc
;
1269 pts
[1].y
= ySrc
+ heightSrc
;
1270 LPtoDP(physDevSrc
->hdc
, pts
, 2);
1273 widthSrc
= pts
[1].x
- pts
[0].x
;
1274 heightSrc
= pts
[1].y
- pts
[0].y
;
1276 fStretch
= (widthSrc
!= widthDst
) || (heightSrc
!= heightDst
);
1277 TRACE(" rectsrc=%d,%d-%d,%d orgsrc=%ld,%ld\n",
1278 xSrc
, ySrc
, widthSrc
, heightSrc
,
1279 physDevSrc
->org
.x
, physDevSrc
->org
.y
);
1280 if (!BITBLT_GetVisRectangles( physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
1281 physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
,
1282 &visRectSrc
, &visRectDst
))
1284 TRACE(" vissrc=%ld,%ld-%ld,%ld visdst=%ld,%ld-%ld,%ld\n",
1285 visRectSrc
.left
, visRectSrc
.top
,
1286 visRectSrc
.right
, visRectSrc
.bottom
,
1287 visRectDst
.left
, visRectDst
.top
,
1288 visRectDst
.right
, visRectDst
.bottom
);
1293 if (!BITBLT_GetVisRectangles( physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
1294 NULL
, 0, 0, 0, 0, NULL
, &visRectDst
))
1296 TRACE(" vissrc=none visdst=%ld,%ld-%ld,%ld\n",
1297 visRectDst
.left
, visRectDst
.top
,
1298 visRectDst
.right
, visRectDst
.bottom
);
1301 width
= visRectDst
.right
- visRectDst
.left
;
1302 height
= visRectDst
.bottom
- visRectDst
.top
;
1304 if (!fStretch
) switch(rop
) /* A few optimisations */
1306 case BLACKNESS
: /* 0x00 */
1308 if ((physDevDst
->depth
== 1) || !X11DRV_PALETTE_PaletteToXPixel
)
1309 XSetFunction( gdi_display
, physDevDst
->gc
, GXclear
);
1312 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1313 XSetForeground( gdi_display
, physDevDst
->gc
, X11DRV_PALETTE_PaletteToXPixel
[0] );
1314 XSetFillStyle( gdi_display
, physDevDst
->gc
, FillSolid
);
1316 XFillRectangle( gdi_display
, physDevDst
->drawable
, physDevDst
->gc
,
1317 physDevDst
->org
.x
+ visRectDst
.left
,
1318 physDevDst
->org
.y
+ visRectDst
.top
,
1320 wine_tsx11_unlock();
1323 case DSTINVERT
: /* 0x55 */
1325 XSetFunction( gdi_display
, physDevDst
->gc
, GXinvert
);
1327 if( X11DRV_PALETTE_PaletteFlags
& (X11DRV_PALETTE_PRIVATE
| X11DRV_PALETTE_VIRTUAL
) )
1328 XSetFunction( gdi_display
, physDevDst
->gc
, GXinvert
);
1331 /* Xor is much better when we do not have full colormap. */
1332 /* Using white^black ensures that we invert at least black */
1334 Pixel xor_pix
= (WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ) ^
1335 BlackPixel( gdi_display
, DefaultScreen(gdi_display
) ));
1336 XSetFunction( gdi_display
, physDevDst
->gc
, GXxor
);
1337 XSetForeground( gdi_display
, physDevDst
->gc
, xor_pix
);
1338 XSetFillStyle( gdi_display
, physDevDst
->gc
, FillSolid
);
1340 XFillRectangle( gdi_display
, physDevDst
->drawable
, physDevDst
->gc
,
1341 physDevDst
->org
.x
+ visRectDst
.left
,
1342 physDevDst
->org
.y
+ visRectDst
.top
,
1344 wine_tsx11_unlock();
1347 case PATINVERT
: /* 0x5a */
1348 if (X11DRV_SetupGCForBrush( physDevDst
))
1351 XSetFunction( gdi_display
, physDevDst
->gc
, GXxor
);
1352 XFillRectangle( gdi_display
, physDevDst
->drawable
, physDevDst
->gc
,
1353 physDevDst
->org
.x
+ visRectDst
.left
,
1354 physDevDst
->org
.y
+ visRectDst
.top
,
1356 wine_tsx11_unlock();
1361 if (X11DRV_SetupGCForBrush( physDevDst
))
1364 XSetFunction( gdi_display
, physDevDst
->gc
, GXequiv
);
1365 XFillRectangle( gdi_display
, physDevDst
->drawable
, physDevDst
->gc
,
1366 physDevDst
->org
.x
+ visRectDst
.left
,
1367 physDevDst
->org
.y
+ visRectDst
.top
,
1369 wine_tsx11_unlock();
1373 case SRCCOPY
: /* 0xcc */
1374 if (physDevSrc
->depth
== physDevDst
->depth
)
1377 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1378 XCopyArea( gdi_display
, physDevSrc
->drawable
,
1379 physDevDst
->drawable
, physDevDst
->gc
,
1380 physDevSrc
->org
.x
+ visRectSrc
.left
,
1381 physDevSrc
->org
.y
+ visRectSrc
.top
,
1383 physDevDst
->org
.x
+ visRectDst
.left
,
1384 physDevDst
->org
.y
+ visRectDst
.top
);
1385 physDevDst
->exposures
++;
1386 wine_tsx11_unlock();
1390 if (physDevSrc
->depth
== 1)
1393 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
1396 XSetBackground( gdi_display
, physDevDst
->gc
, fg
);
1397 XSetForeground( gdi_display
, physDevDst
->gc
, bg
);
1398 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1399 XCopyPlane( gdi_display
, physDevSrc
->drawable
,
1400 physDevDst
->drawable
, physDevDst
->gc
,
1401 physDevSrc
->org
.x
+ visRectSrc
.left
,
1402 physDevSrc
->org
.y
+ visRectSrc
.top
,
1404 physDevDst
->org
.x
+ visRectDst
.left
,
1405 physDevDst
->org
.y
+ visRectDst
.top
, 1 );
1406 physDevDst
->exposures
++;
1407 wine_tsx11_unlock();
1412 case PATCOPY
: /* 0xf0 */
1413 if (!X11DRV_SetupGCForBrush( physDevDst
)) return TRUE
;
1415 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1416 XFillRectangle( gdi_display
, physDevDst
->drawable
, physDevDst
->gc
,
1417 physDevDst
->org
.x
+ visRectDst
.left
,
1418 physDevDst
->org
.y
+ visRectDst
.top
,
1420 wine_tsx11_unlock();
1423 case WHITENESS
: /* 0xff */
1425 if ((physDevDst
->depth
== 1) || !X11DRV_PALETTE_PaletteToXPixel
)
1426 XSetFunction( gdi_display
, physDevDst
->gc
, GXset
);
1429 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1430 XSetForeground( gdi_display
, physDevDst
->gc
,
1431 WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ));
1432 XSetFillStyle( gdi_display
, physDevDst
->gc
, FillSolid
);
1434 XFillRectangle( gdi_display
, physDevDst
->drawable
, physDevDst
->gc
,
1435 physDevDst
->org
.x
+ visRectDst
.left
,
1436 physDevDst
->org
.y
+ visRectDst
.top
,
1438 wine_tsx11_unlock();
1444 tmpGC
= XCreateGC( gdi_display
, physDevDst
->drawable
, 0, NULL
);
1445 XSetSubwindowMode( gdi_display
, tmpGC
, IncludeInferiors
);
1446 XSetGraphicsExposures( gdi_display
, tmpGC
, False
);
1447 pixmaps
[DST
] = XCreatePixmap( gdi_display
, root_window
, width
, height
,
1448 physDevDst
->depth
);
1451 pixmaps
[SRC
] = XCreatePixmap( gdi_display
, root_window
, width
, height
,
1452 physDevDst
->depth
);
1454 BITBLT_GetSrcAreaStretch( physDevSrc
, physDevDst
, pixmaps
[SRC
], tmpGC
,
1455 xSrc
, ySrc
, widthSrc
, heightSrc
,
1456 xDst
, yDst
, widthDst
, heightDst
,
1457 &visRectSrc
, &visRectDst
);
1459 BITBLT_GetSrcArea( physDevSrc
, physDevDst
, pixmaps
[SRC
], tmpGC
,
1460 xSrc
, ySrc
, &visRectSrc
);
1463 if (useDst
) BITBLT_GetDstArea( physDevDst
, pixmaps
[DST
], tmpGC
, &visRectDst
);
1464 if (usePat
) fNullBrush
= !X11DRV_SetupGCForPatBlt( physDevDst
, tmpGC
, TRUE
);
1465 else fNullBrush
= FALSE
;
1468 for (opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff]; *opcode
; opcode
++)
1470 if (OP_DST(*opcode
) == DST
) destUsed
= TRUE
;
1471 XSetFunction( gdi_display
, tmpGC
, OP_ROP(*opcode
) );
1472 switch(OP_SRCDST(*opcode
))
1474 case OP_ARGS(DST
,TMP
):
1475 case OP_ARGS(SRC
,TMP
):
1477 pixmaps
[TMP
] = XCreatePixmap( gdi_display
, root_window
,
1478 width
, height
, physDevDst
->depth
);
1480 case OP_ARGS(DST
,SRC
):
1481 case OP_ARGS(SRC
,DST
):
1482 case OP_ARGS(TMP
,SRC
):
1483 case OP_ARGS(TMP
,DST
):
1485 XCopyArea( gdi_display
, pixmaps
[OP_SRC(*opcode
)],
1486 pixmaps
[OP_DST(*opcode
)], tmpGC
,
1487 0, 0, width
, height
, 0, 0 );
1490 case OP_ARGS(PAT
,TMP
):
1491 if (!pixmaps
[TMP
] && !fNullBrush
)
1492 pixmaps
[TMP
] = XCreatePixmap( gdi_display
, root_window
,
1493 width
, height
, physDevDst
->depth
);
1495 case OP_ARGS(PAT
,DST
):
1496 case OP_ARGS(PAT
,SRC
):
1498 XFillRectangle( gdi_display
, pixmaps
[OP_DST(*opcode
)],
1499 tmpGC
, 0, 0, width
, height
);
1503 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1504 physDevDst
->exposures
+= BITBLT_PutDstArea( physDevDst
, pixmaps
[destUsed
? DST
: SRC
],
1506 XFreePixmap( gdi_display
, pixmaps
[DST
] );
1507 if (pixmaps
[SRC
]) XFreePixmap( gdi_display
, pixmaps
[SRC
] );
1508 if (pixmaps
[TMP
]) XFreePixmap( gdi_display
, pixmaps
[TMP
] );
1509 XFreeGC( gdi_display
, tmpGC
);
1510 wine_tsx11_unlock();
1515 /***********************************************************************
1518 BOOL
X11DRV_PatBlt( X11DRV_PDEVICE
*physDev
, INT left
, INT top
, INT width
, INT height
, DWORD rop
)
1522 X11DRV_LockDIBSection( physDev
, DIB_Status_GdiMod
, FALSE
);
1523 result
= BITBLT_InternalStretchBlt( physDev
, left
, top
, width
, height
, NULL
, 0, 0, 0, 0, rop
);
1524 X11DRV_UnlockDIBSection( physDev
, TRUE
);
1529 /***********************************************************************
1532 BOOL
X11DRV_BitBlt( X11DRV_PDEVICE
*physDevDst
, INT xDst
, INT yDst
,
1533 INT width
, INT height
, X11DRV_PDEVICE
*physDevSrc
,
1534 INT xSrc
, INT ySrc
, DWORD rop
)
1536 BOOL result
= FALSE
;
1538 RECT visRectDst
, visRectSrc
;
1540 if (((rop
>> 16) & 0x55) == ((rop
>> 17) & 0x55)) {
1541 /* FIXME: seems the ROP doesn't include destination;
1542 * now if the destination area include the entire dcDst,
1543 * we can pass TRUE instead of FALSE to CoerceDIBSection(dcDst...),
1544 * which may avoid a copy in some situations */
1547 sDst
= X11DRV_LockDIBSection( physDevDst
, DIB_Status_None
, FALSE
);
1548 if (physDevDst
!= physDevSrc
)
1549 sSrc
= X11DRV_LockDIBSection( physDevSrc
, DIB_Status_None
, FALSE
);
1553 if ((sSrc
== DIB_Status_AppMod
) && (rop
== SRCCOPY
) &&
1554 (physDevSrc
->depth
== physDevDst
->depth
))
1557 /* do everything ourselves; map coordinates */
1561 pts
[1].x
= xSrc
+ width
;
1562 pts
[1].y
= ySrc
+ height
;
1564 LPtoDP(physDevSrc
->hdc
, pts
, 2);
1565 width
= pts
[1].x
- pts
[0].x
;
1566 height
= pts
[1].y
- pts
[0].y
;
1572 LPtoDP(physDevDst
->hdc
, pts
, 1);
1577 /* Perform basic clipping */
1578 if (!BITBLT_GetVisRectangles( physDevDst
, xDst
, yDst
, width
, height
,
1579 physDevSrc
, xSrc
, ySrc
, width
, height
,
1580 &visRectSrc
, &visRectDst
))
1583 xSrc
= visRectSrc
.left
;
1584 ySrc
= visRectSrc
.top
;
1585 xDst
= visRectDst
.left
;
1586 yDst
= visRectDst
.top
;
1587 width
= visRectDst
.right
- visRectDst
.left
;
1588 height
= visRectDst
.bottom
- visRectDst
.top
;
1590 if (sDst
== DIB_Status_AppMod
) {
1591 FIXME("potential optimization - client-side DIB copy\n");
1593 X11DRV_CoerceDIBSection( physDevDst
, DIB_Status_GdiMod
, FALSE
);
1595 X11DRV_DIB_CopyDIBSection( physDevSrc
, physDevDst
, xSrc
, ySrc
, xDst
, yDst
, width
, height
);
1600 X11DRV_CoerceDIBSection( physDevDst
, DIB_Status_GdiMod
, FALSE
);
1601 if (physDevDst
!= physDevSrc
)
1602 X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
, FALSE
);
1604 result
= BITBLT_InternalStretchBlt( physDevDst
, xDst
, yDst
, width
, height
,
1605 physDevSrc
, xSrc
, ySrc
, width
, height
, rop
);
1608 if (physDevDst
!= physDevSrc
)
1609 X11DRV_UnlockDIBSection( physDevSrc
, FALSE
);
1610 X11DRV_UnlockDIBSection( physDevDst
, TRUE
);
1616 /***********************************************************************
1619 BOOL
X11DRV_StretchBlt( X11DRV_PDEVICE
*physDevDst
, INT xDst
, INT yDst
,
1620 INT widthDst
, INT heightDst
,
1621 X11DRV_PDEVICE
*physDevSrc
, INT xSrc
, INT ySrc
,
1622 INT widthSrc
, INT heightSrc
, DWORD rop
)
1626 X11DRV_LockDIBSection( physDevDst
, DIB_Status_GdiMod
, FALSE
);
1627 if (physDevDst
!= physDevSrc
)
1628 X11DRV_LockDIBSection( physDevSrc
, DIB_Status_GdiMod
, FALSE
);
1630 result
= BITBLT_InternalStretchBlt( physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
1631 physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
1633 if (physDevDst
!= physDevSrc
)
1634 X11DRV_UnlockDIBSection( physDevSrc
, FALSE
);
1635 X11DRV_UnlockDIBSection( physDevDst
, TRUE
);