2 * GDI bit-blit operations
4 * Copyright 1993, 1994, 2011 Alexandre Julliard
5 * Copyright 2006 Damjan Jovanovic
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(bitblt
);
40 #define DST 0 /* Destination drawable */
41 #define SRC 1 /* Source drawable */
42 #define TMP 2 /* Temporary drawable */
43 #define PAT 3 /* Pattern (brush) in destination DC */
45 #define OP(src,dst,rop) (OP_ARGS(src,dst) << 4 | (rop))
46 #define OP_ARGS(src,dst) (((src) << 2) | (dst))
48 #define OP_SRC(opcode) ((opcode) >> 6)
49 #define OP_DST(opcode) (((opcode) >> 4) & 3)
50 #define OP_SRCDST(opcode) ((opcode) >> 4)
51 #define OP_ROP(opcode) ((opcode) & 0x0f)
53 #define MAX_OP_LEN 6 /* Longest opcode + 1 for the terminating 0 */
55 #define SWAP_INT32(i1,i2) \
56 do { INT __t = *(i1); *(i1) = *(i2); *(i2) = __t; } while(0)
58 static const unsigned char BITBLT_Opcodes
[256][MAX_OP_LEN
] =
60 { OP(PAT
,DST
,GXclear
) }, /* 0x00 0 */
61 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXnor
) }, /* 0x01 ~(D|(P|S)) */
62 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXand
) }, /* 0x02 D&~(P|S) */
63 { OP(PAT
,SRC
,GXnor
) }, /* 0x03 ~(P|S) */
64 { OP(PAT
,DST
,GXnor
), OP(SRC
,DST
,GXand
) }, /* 0x04 S&~(D|P) */
65 { OP(PAT
,DST
,GXnor
) }, /* 0x05 ~(D|P) */
66 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXnor
), }, /* 0x06 ~(P|~(D^S)) */
67 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXnor
) }, /* 0x07 ~(P|(D&S)) */
68 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXand
) },/* 0x08 S&D&~P */
69 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXnor
) }, /* 0x09 ~(P|(D^S)) */
70 { OP(PAT
,DST
,GXandInverted
) }, /* 0x0a D&~P */
71 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXnor
) }, /* 0x0b ~(P|(S&~D)) */
72 { OP(PAT
,SRC
,GXandInverted
) }, /* 0x0c S&~P */
73 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXnor
) },/* 0x0d ~(P|(D&~S)) */
74 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXnor
) }, /* 0x0e ~(P|~(D|S)) */
75 { OP(PAT
,DST
,GXcopyInverted
) }, /* 0x0f ~P */
76 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXand
) }, /* 0x10 P&~(S|D) */
77 { OP(SRC
,DST
,GXnor
) }, /* 0x11 ~(D|S) */
78 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXnor
) }, /* 0x12 ~(S|~(D^P)) */
79 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXnor
) }, /* 0x13 ~(S|(D&P)) */
80 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXnor
) }, /* 0x14 ~(D|~(P^S)) */
81 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXnor
) }, /* 0x15 ~(D|(P&S)) */
82 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnand
),
83 OP(SRC
,DST
,GXand
), OP(TMP
,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
,SRC
,GXnand
),
91 OP(SRC
,DST
,GXand
), OP(TMP
,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
,SRC
,GXxor
),
95 OP(SRC
,DST
,GXand
), OP(TMP
,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
,SRC
,GXand
),
111 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x26 S^(D|(S&P)) */
112 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXequiv
),
113 OP(SRC
,DST
,GXor
), OP(TMP
,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
,SRC
,GXand
),
116 OP(SRC
,DST
,GXor
), OP(TMP
,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(PAT
,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 */
447 static const unsigned char bit_swap
[256] =
449 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
450 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
451 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
452 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
453 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
454 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
455 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
456 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
457 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
458 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
459 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
460 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
461 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
462 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
463 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
464 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
465 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
466 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
467 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
468 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
469 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
470 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
471 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
472 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
473 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
474 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
475 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
476 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
477 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
478 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
479 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
480 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
483 #ifdef WORDS_BIGENDIAN
484 static const unsigned int zeropad_masks
[32] =
486 0xffffffff, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
487 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
488 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
489 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe
492 static const unsigned int zeropad_masks
[32] =
494 0xffffffff, 0x00000080, 0x000000c0, 0x000000e0, 0x000000f0, 0x000000f8, 0x000000fc, 0x000000fe,
495 0x000000ff, 0x000080ff, 0x0000c0ff, 0x0000e0ff, 0x0000f0ff, 0x0000f8ff, 0x0000fcff, 0x0000feff,
496 0x0000ffff, 0x0080ffff, 0x00c0ffff, 0x00e0ffff, 0x00f0ffff, 0x00f8ffff, 0x00fcffff, 0x00feffff,
497 0x00ffffff, 0x80ffffff, 0xc0ffffff, 0xe0ffffff, 0xf0ffffff, 0xf8ffffff, 0xfcffffff, 0xfeffffff
501 #ifdef BITBLT_TEST /* Opcodes test */
503 static int do_bitop( int s
, int d
, int rop
)
508 case GXclear
: res
= 0; break;
509 case GXand
: res
= s
& d
; break;
510 case GXandReverse
: res
= s
& ~d
; break;
511 case GXcopy
: res
= s
; break;
512 case GXandInverted
: res
= ~s
& d
; break;
513 case GXnoop
: res
= d
; break;
514 case GXxor
: res
= s
^ d
; break;
515 case GXor
: res
= s
| d
; break;
516 case GXnor
: res
= ~(s
| d
); break;
517 case GXequiv
: res
= ~s
^ d
; break;
518 case GXinvert
: res
= ~d
; break;
519 case GXorReverse
: res
= s
| ~d
; break;
520 case GXcopyInverted
: res
= ~s
; break;
521 case GXorInverted
: res
= ~s
| d
; break;
522 case GXnand
: res
= ~(s
& d
); break;
523 case GXset
: res
= 1; break;
530 int rop
, i
, res
, src
, dst
, pat
, tmp
, dstUsed
;
531 const unsigned char *opcode
;
533 for (rop
= 0; rop
< 256; rop
++)
536 for (i
= 0; i
< 8; i
++)
541 for (opcode
= BITBLT_Opcodes
[rop
]; *opcode
; opcode
++)
545 case OP_ARGS(DST
,TMP
):
546 tmp
= do_bitop( dst
, tmp
, *opcode
& 0xf );
548 case OP_ARGS(DST
,SRC
):
549 src
= do_bitop( dst
, src
, *opcode
& 0xf );
551 case OP_ARGS(SRC
,TMP
):
552 tmp
= do_bitop( src
, tmp
, *opcode
& 0xf );
554 case OP_ARGS(SRC
,DST
):
555 dst
= do_bitop( src
, dst
, *opcode
& 0xf );
558 case OP_ARGS(PAT
,DST
):
559 dst
= do_bitop( pat
, dst
, *opcode
& 0xf );
562 case OP_ARGS(PAT
,SRC
):
563 src
= do_bitop( pat
, src
, *opcode
& 0xf );
565 case OP_ARGS(TMP
,DST
):
566 dst
= do_bitop( tmp
, dst
, *opcode
& 0xf );
569 case OP_ARGS(TMP
,SRC
):
570 src
= do_bitop( tmp
, src
, *opcode
& 0xf );
573 printf( "Invalid opcode %x\n", *opcode
);
576 if (!dstUsed
) dst
= src
;
577 if (dst
) res
|= 1 << i
;
579 if (res
!= rop
) printf( "%02x: ERROR, res=%02x\n", rop
, res
);
585 #endif /* BITBLT_TEST */
588 static void get_colors(X11DRV_PDEVICE
*physDevDst
, X11DRV_PDEVICE
*physDevSrc
,
593 *fg
= physDevDst
->textPixel
;
594 *bg
= physDevDst
->backgroundPixel
;
595 if(physDevSrc
->depth
== 1) {
596 if(GetDIBColorTable(physDevSrc
->dev
.hdc
, 0, 2, rgb
) == 2) {
598 logcolor
= RGB(rgb
[0].rgbRed
, rgb
[0].rgbGreen
, rgb
[0].rgbBlue
);
599 *fg
= X11DRV_PALETTE_ToPhysical( physDevDst
, logcolor
);
600 logcolor
= RGB(rgb
[1].rgbRed
, rgb
[1].rgbGreen
,rgb
[1].rgbBlue
);
601 *bg
= X11DRV_PALETTE_ToPhysical( physDevDst
, logcolor
);
606 /* return a mask for meaningful bits when doing an XGetPixel on an image */
607 static unsigned long image_pixel_mask( X11DRV_PDEVICE
*physDev
)
610 ColorShifts
*shifts
= physDev
->color_shifts
;
612 if (!shifts
) shifts
= &X11DRV_PALETTE_default_shifts
;
613 ret
= (shifts
->physicalRed
.max
<< shifts
->physicalRed
.shift
) |
614 (shifts
->physicalGreen
.max
<< shifts
->physicalGreen
.shift
) |
615 (shifts
->physicalBlue
.max
<< shifts
->physicalBlue
.shift
);
616 if (!ret
) ret
= (1 << physDev
->depth
) - 1;
621 /***********************************************************************
624 * Stretch a row of pixels. Helper function for BITBLT_StretchImage.
626 static void BITBLT_StretchRow( int *rowSrc
, int *rowDst
,
627 INT startDst
, INT widthDst
,
628 INT xinc
, INT xoff
, WORD mode
)
630 register INT xsrc
= xinc
* startDst
+ xoff
;
634 case STRETCH_ANDSCANS
:
635 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
636 *rowDst
++ &= rowSrc
[xsrc
>> 16];
638 case STRETCH_ORSCANS
:
639 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
640 *rowDst
++ |= rowSrc
[xsrc
>> 16];
642 case STRETCH_DELETESCANS
:
643 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
644 *rowDst
++ = rowSrc
[xsrc
>> 16];
650 /***********************************************************************
653 * Shrink a row of pixels. Helper function for BITBLT_StretchImage.
655 static void BITBLT_ShrinkRow( int *rowSrc
, int *rowDst
,
656 INT startSrc
, INT widthSrc
,
657 INT xinc
, INT xoff
, WORD mode
)
659 register INT xdst
= xinc
* startSrc
+ xoff
;
663 case STRETCH_ORSCANS
:
664 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
665 rowDst
[xdst
>> 16] |= *rowSrc
++;
667 case STRETCH_ANDSCANS
:
668 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
669 rowDst
[xdst
>> 16] &= *rowSrc
++;
671 case STRETCH_DELETESCANS
:
672 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
673 rowDst
[xdst
>> 16] = *rowSrc
++;
679 /***********************************************************************
682 * Retrieve a row from an image. Helper function for BITBLT_StretchImage.
684 static void BITBLT_GetRow( XImage
*image
, int *pdata
, INT row
,
685 INT start
, INT width
, INT depthDst
,
686 int fg
, int bg
, unsigned long pixel_mask
, BOOL swap
)
690 assert( (row
>= 0) && (row
< image
->height
) );
691 assert( (start
>= 0) && (width
<= image
->width
) );
693 pdata
+= swap
? start
+width
-1 : start
;
694 if (image
->depth
== depthDst
) /* color -> color */
696 if (X11DRV_PALETTE_XPixelToPalette
&& (depthDst
!= 1))
697 if (swap
) for (i
= 0; i
< width
; i
++)
698 *pdata
-- = X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, i
, row
)];
699 else for (i
= 0; i
< width
; i
++)
700 *pdata
++ = X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, i
, row
)];
702 if (swap
) for (i
= 0; i
< width
; i
++)
703 *pdata
-- = XGetPixel( image
, i
, row
);
704 else for (i
= 0; i
< width
; i
++)
705 *pdata
++ = XGetPixel( image
, i
, row
);
709 if (image
->depth
== 1) /* monochrome -> color */
711 if (X11DRV_PALETTE_XPixelToPalette
)
713 fg
= X11DRV_PALETTE_XPixelToPalette
[fg
];
714 bg
= X11DRV_PALETTE_XPixelToPalette
[bg
];
716 if (swap
) for (i
= 0; i
< width
; i
++)
717 *pdata
-- = XGetPixel( image
, i
, row
) ? bg
: fg
;
718 else for (i
= 0; i
< width
; i
++)
719 *pdata
++ = XGetPixel( image
, i
, row
) ? bg
: fg
;
721 else /* color -> monochrome */
723 if (swap
) for (i
= 0; i
< width
; i
++)
724 *pdata
-- = ((XGetPixel( image
, i
, row
) & pixel_mask
) == bg
) ? 1 : 0;
725 else for (i
= 0; i
< width
; i
++)
726 *pdata
++ = ((XGetPixel( image
, i
, row
) & pixel_mask
) == bg
) ? 1 : 0;
732 /***********************************************************************
733 * BITBLT_StretchImage
735 * Stretch an X image.
736 * FIXME: does not work for full 32-bit coordinates.
738 static void BITBLT_StretchImage( XImage
*srcImage
, XImage
*dstImage
,
739 INT widthSrc
, INT heightSrc
,
740 INT widthDst
, INT heightDst
,
741 RECT
*visRectSrc
, RECT
*visRectDst
,
742 int foreground
, int background
,
743 unsigned long pixel_mask
, WORD mode
)
745 int *rowSrc
, *rowDst
, *pixel
;
747 INT xinc
, xoff
, yinc
, ysrc
, ydst
;
749 BOOL hstretch
, vstretch
, hswap
, vswap
;
751 hswap
= widthSrc
* widthDst
< 0;
752 vswap
= heightSrc
* heightDst
< 0;
753 widthSrc
= abs(widthSrc
);
754 heightSrc
= abs(heightSrc
);
755 widthDst
= abs(widthDst
);
756 heightDst
= abs(heightDst
);
758 if (!(rowSrc
= HeapAlloc( GetProcessHeap(), 0,
759 (widthSrc
+widthDst
)*sizeof(int) ))) return;
760 rowDst
= rowSrc
+ widthSrc
;
762 /* When stretching, all modes are the same, and DELETESCANS is faster */
763 if ((widthSrc
< widthDst
) && (heightSrc
< heightDst
))
764 mode
= STRETCH_DELETESCANS
;
766 if (mode
== STRETCH_HALFTONE
) /* FIXME */
767 mode
= STRETCH_DELETESCANS
;
769 if (mode
!= STRETCH_DELETESCANS
)
770 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
771 widthDst
*sizeof(int) );
773 hstretch
= (widthSrc
< widthDst
);
774 vstretch
= (heightSrc
< heightDst
);
778 xinc
= (widthSrc
<< 16) / widthDst
;
779 xoff
= ((widthSrc
<< 16) - (xinc
* widthDst
)) / 2;
783 xinc
= ((int)widthDst
<< 16) / widthSrc
;
784 xoff
= ((widthDst
<< 16) - (xinc
* widthSrc
)) / 2;
790 yinc
= (heightSrc
<< 16) / heightDst
;
791 ydst
= visRectDst
->top
;
794 ysrc
= yinc
* (heightDst
- ydst
- 1);
800 for ( ; (ydst
< visRectDst
->bottom
); ysrc
+= yinc
, ydst
++)
802 if (((ysrc
>> 16) < visRectSrc
->top
) ||
803 ((ysrc
>> 16) >= visRectSrc
->bottom
)) continue;
805 /* Retrieve a source row */
806 BITBLT_GetRow( srcImage
, rowSrc
, (ysrc
>> 16) - visRectSrc
->top
,
807 visRectSrc
->left
, visRectSrc
->right
- visRectSrc
->left
,
808 dstImage
->depth
, foreground
, background
, pixel_mask
, hswap
);
810 /* Stretch or shrink it */
812 BITBLT_StretchRow( rowSrc
, rowDst
, visRectDst
->left
,
813 visRectDst
->right
- visRectDst
->left
,
815 else BITBLT_ShrinkRow( rowSrc
, rowDst
, visRectSrc
->left
,
816 visRectSrc
->right
- visRectSrc
->left
,
819 /* Store the destination row */
820 pixel
= rowDst
+ visRectDst
->right
- 1;
821 y
= ydst
- visRectDst
->top
;
822 for (x
= visRectDst
->right
-visRectDst
->left
-1; x
>= 0; x
--)
823 XPutPixel( dstImage
, x
, y
, *pixel
-- );
824 if (mode
!= STRETCH_DELETESCANS
)
825 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
826 widthDst
*sizeof(int) );
828 /* Make copies of the destination row */
830 pdata
= dstImage
->data
+ dstImage
->bytes_per_line
* y
;
831 while (((ysrc
+ yinc
) >> 16 == ysrc
>> 16) &&
832 (ydst
< visRectDst
->bottom
-1))
834 memcpy( pdata
+ dstImage
->bytes_per_line
, pdata
,
835 dstImage
->bytes_per_line
);
836 pdata
+= dstImage
->bytes_per_line
;
844 yinc
= (heightDst
<< 16) / heightSrc
;
845 ysrc
= visRectSrc
->top
;
846 ydst
= ((heightDst
<< 16) - (yinc
* heightSrc
)) / 2;
849 ydst
+= yinc
* (heightSrc
- ysrc
- 1);
855 for( ; (ysrc
< visRectSrc
->bottom
); ydst
+= yinc
, ysrc
++)
857 if (((ydst
>> 16) < visRectDst
->top
) ||
858 ((ydst
>> 16) >= visRectDst
->bottom
)) continue;
860 /* Retrieve a source row */
861 BITBLT_GetRow( srcImage
, rowSrc
, ysrc
- visRectSrc
->top
,
862 visRectSrc
->left
, visRectSrc
->right
- visRectSrc
->left
,
863 dstImage
->depth
, foreground
, background
, pixel_mask
, hswap
);
865 /* Stretch or shrink it */
867 BITBLT_StretchRow( rowSrc
, rowDst
, visRectDst
->left
,
868 visRectDst
->right
- visRectDst
->left
,
870 else BITBLT_ShrinkRow( rowSrc
, rowDst
, visRectSrc
->left
,
871 visRectSrc
->right
- visRectSrc
->left
,
874 /* Merge several source rows into the destination */
875 if (mode
== STRETCH_DELETESCANS
)
877 /* Simply skip the overlapping rows */
878 while (((ydst
+ yinc
) >> 16 == ydst
>> 16) &&
879 (ysrc
< visRectSrc
->bottom
-1))
885 else if (((ydst
+ yinc
) >> 16 == ydst
>> 16) &&
886 (ysrc
< visRectSrc
->bottom
-1))
887 continue; /* Restart loop for next overlapping row */
889 /* Store the destination row */
890 pixel
= rowDst
+ visRectDst
->right
- 1;
891 y
= (ydst
>> 16) - visRectDst
->top
;
892 for (x
= visRectDst
->right
-visRectDst
->left
-1; x
>= 0; x
--)
893 XPutPixel( dstImage
, x
, y
, *pixel
-- );
894 if (mode
!= STRETCH_DELETESCANS
)
895 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
896 widthDst
*sizeof(int) );
900 HeapFree( GetProcessHeap(), 0, rowSrc
);
904 /***********************************************************************
905 * BITBLT_GetSrcAreaStretch
907 * Retrieve an area from the source DC, stretching and mapping all the
908 * pixels to Windows colors.
910 static int BITBLT_GetSrcAreaStretch( X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
911 Pixmap pixmap
, GC gc
,
912 const struct bitblt_coords
*src
, const struct bitblt_coords
*dst
)
914 XImage
*imageSrc
, *imageDst
;
915 RECT rectSrc
= src
->visrect
;
916 RECT rectDst
= dst
->visrect
;
919 rectSrc
.left
-= src
->x
;
920 rectSrc
.right
-= src
->x
;
921 rectSrc
.top
-= src
->y
;
922 rectSrc
.bottom
-= src
->y
;
923 rectDst
.left
-= dst
->x
;
924 rectDst
.right
-= dst
->x
;
925 rectDst
.top
-= dst
->y
;
926 rectDst
.bottom
-= dst
->y
;
929 rectSrc
.left
-= src
->width
;
930 rectSrc
.right
-= src
->width
;
934 rectDst
.left
-= dst
->width
;
935 rectDst
.right
-= dst
->width
;
939 rectSrc
.top
-= src
->height
;
940 rectSrc
.bottom
-= src
->height
;
944 rectDst
.top
-= dst
->height
;
945 rectDst
.bottom
-= dst
->height
;
948 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
950 /* FIXME: avoid BadMatch errors */
951 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
952 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
953 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
954 src
->visrect
.right
- src
->visrect
.left
,
955 src
->visrect
.bottom
- src
->visrect
.top
,
956 AllPlanes
, ZPixmap
);
959 imageDst
= X11DRV_DIB_CreateXImage( rectDst
.right
- rectDst
.left
,
960 rectDst
.bottom
- rectDst
.top
, physDevDst
->depth
);
961 BITBLT_StretchImage( imageSrc
, imageDst
, src
->width
, src
->height
,
962 dst
->width
, dst
->height
, &rectSrc
, &rectDst
,
963 fg
, physDevDst
->depth
!= 1 ? bg
: physDevSrc
->backgroundPixel
,
964 image_pixel_mask( physDevSrc
), GetStretchBltMode(physDevDst
->dev
.hdc
) );
966 XPutImage( gdi_display
, pixmap
, gc
, imageDst
, 0, 0, 0, 0,
967 rectDst
.right
- rectDst
.left
, rectDst
.bottom
- rectDst
.top
);
968 XDestroyImage( imageSrc
);
969 X11DRV_DIB_DestroyXImage( imageDst
);
971 return 0; /* no exposure events generated */
975 /***********************************************************************
978 * Retrieve an area from the source DC, mapping all the
979 * pixels to Windows colors.
981 static int BITBLT_GetSrcArea( X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
982 Pixmap pixmap
, GC gc
, RECT
*visRectSrc
)
984 XImage
*imageSrc
, *imageDst
;
987 INT width
= visRectSrc
->right
- visRectSrc
->left
;
988 INT height
= visRectSrc
->bottom
- visRectSrc
->top
;
990 BOOL memdc
= (GetObjectType(physDevSrc
->dev
.hdc
) == OBJ_MEMDC
);
992 if (physDevSrc
->depth
== physDevDst
->depth
)
995 if (!X11DRV_PALETTE_XPixelToPalette
||
996 (physDevDst
->depth
== 1)) /* monochrome -> monochrome */
998 if (physDevDst
->depth
== 1)
1000 /* MSDN says if StretchBlt must convert a bitmap from monochrome
1001 to color or vice versa, the foreground and background color of
1002 the device context are used. In fact, it also applies to the
1003 case when it is converted from mono to mono. */
1004 XSetBackground( gdi_display
, gc
, physDevDst
->textPixel
);
1005 XSetForeground( gdi_display
, gc
, physDevDst
->backgroundPixel
);
1006 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
1007 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1008 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1009 width
, height
, 0, 0, 1);
1012 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
1013 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1014 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1015 width
, height
, 0, 0);
1018 else /* color -> color */
1021 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
1022 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1023 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1024 width
, height
, AllPlanes
, ZPixmap
);
1027 /* Make sure we don't get a BadMatch error */
1028 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
1029 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1030 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1031 width
, height
, 0, 0);
1033 imageSrc
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1034 AllPlanes
, ZPixmap
);
1036 for (y
= 0; y
< height
; y
++)
1037 for (x
= 0; x
< width
; x
++)
1038 XPutPixel(imageSrc
, x
, y
,
1039 X11DRV_PALETTE_XPixelToPalette
[XGetPixel(imageSrc
, x
, y
)]);
1040 XPutImage( gdi_display
, pixmap
, gc
, imageSrc
,
1041 0, 0, 0, 0, width
, height
);
1042 XDestroyImage( imageSrc
);
1044 wine_tsx11_unlock();
1048 if (physDevSrc
->depth
== 1) /* monochrome -> color */
1050 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
1053 if (X11DRV_PALETTE_XPixelToPalette
)
1055 XSetBackground( gdi_display
, gc
,
1056 X11DRV_PALETTE_XPixelToPalette
[fg
] );
1057 XSetForeground( gdi_display
, gc
,
1058 X11DRV_PALETTE_XPixelToPalette
[bg
]);
1062 XSetBackground( gdi_display
, gc
, fg
);
1063 XSetForeground( gdi_display
, gc
, bg
);
1065 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
1066 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1067 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1068 width
, height
, 0, 0, 1 );
1070 wine_tsx11_unlock();
1072 else /* color -> monochrome */
1074 unsigned long pixel_mask
;
1076 /* FIXME: avoid BadMatch error */
1077 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
1078 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1079 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1080 width
, height
, AllPlanes
, ZPixmap
);
1083 wine_tsx11_unlock();
1086 imageDst
= X11DRV_DIB_CreateXImage( width
, height
, physDevDst
->depth
);
1089 XDestroyImage(imageSrc
);
1090 wine_tsx11_unlock();
1093 pixel_mask
= image_pixel_mask( physDevSrc
);
1094 for (y
= 0; y
< height
; y
++)
1095 for (x
= 0; x
< width
; x
++)
1096 XPutPixel(imageDst
, x
, y
,
1097 !((XGetPixel(imageSrc
,x
,y
) ^ physDevSrc
->backgroundPixel
) & pixel_mask
));
1098 XPutImage( gdi_display
, pixmap
, gc
, imageDst
,
1099 0, 0, 0, 0, width
, height
);
1100 XDestroyImage( imageSrc
);
1101 X11DRV_DIB_DestroyXImage( imageDst
);
1102 wine_tsx11_unlock();
1109 /***********************************************************************
1112 * Retrieve an area from the destination DC, mapping all the
1113 * pixels to Windows colors.
1115 static int BITBLT_GetDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, GC gc
, const RECT
*visRectDst
)
1118 INT width
= visRectDst
->right
- visRectDst
->left
;
1119 INT height
= visRectDst
->bottom
- visRectDst
->top
;
1120 BOOL memdc
= (GetObjectType( physDev
->dev
.hdc
) == OBJ_MEMDC
);
1124 if (!X11DRV_PALETTE_XPixelToPalette
|| (physDev
->depth
== 1) ||
1125 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
1127 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
1128 physDev
->dc_rect
.left
+ visRectDst
->left
, physDev
->dc_rect
.top
+ visRectDst
->top
,
1129 width
, height
, 0, 0 );
1138 image
= XGetImage( gdi_display
, physDev
->drawable
,
1139 physDev
->dc_rect
.left
+ visRectDst
->left
,
1140 physDev
->dc_rect
.top
+ visRectDst
->top
,
1141 width
, height
, AllPlanes
, ZPixmap
);
1144 /* Make sure we don't get a BadMatch error */
1145 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
1146 physDev
->dc_rect
.left
+ visRectDst
->left
,
1147 physDev
->dc_rect
.top
+ visRectDst
->top
,
1148 width
, height
, 0, 0);
1150 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1151 AllPlanes
, ZPixmap
);
1155 for (y
= 0; y
< height
; y
++)
1156 for (x
= 0; x
< width
; x
++)
1157 XPutPixel( image
, x
, y
,
1158 X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, x
, y
)]);
1159 XPutImage( gdi_display
, pixmap
, gc
, image
, 0, 0, 0, 0, width
, height
);
1160 XDestroyImage( image
);
1164 wine_tsx11_unlock();
1169 /***********************************************************************
1172 * Put an area back into the destination DC, mapping the pixel
1173 * colors to X pixels.
1175 static int BITBLT_PutDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, const RECT
*visRectDst
)
1178 INT width
= visRectDst
->right
- visRectDst
->left
;
1179 INT height
= visRectDst
->bottom
- visRectDst
->top
;
1181 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
1183 if (!X11DRV_PALETTE_PaletteToXPixel
|| (physDev
->depth
== 1) ||
1184 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
1186 XCopyArea( gdi_display
, pixmap
, physDev
->drawable
, physDev
->gc
, 0, 0, width
, height
,
1187 physDev
->dc_rect
.left
+ visRectDst
->left
,
1188 physDev
->dc_rect
.top
+ visRectDst
->top
);
1194 XImage
*image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1195 AllPlanes
, ZPixmap
);
1196 for (y
= 0; y
< height
; y
++)
1197 for (x
= 0; x
< width
; x
++)
1199 XPutPixel( image
, x
, y
,
1200 X11DRV_PALETTE_PaletteToXPixel
[XGetPixel( image
, x
, y
)]);
1202 XPutImage( gdi_display
, physDev
->drawable
, physDev
->gc
, image
, 0, 0,
1203 physDev
->dc_rect
.left
+ visRectDst
->left
,
1204 physDev
->dc_rect
.top
+ visRectDst
->top
, width
, height
);
1205 XDestroyImage( image
);
1211 /***********************************************************************
1212 * client_side_dib_copy
1214 static BOOL
client_side_dib_copy( X11DRV_PDEVICE
*physDevSrc
, INT xSrc
, INT ySrc
,
1215 X11DRV_PDEVICE
*physDevDst
, INT xDst
, INT yDst
,
1216 INT width
, INT height
)
1218 DIBSECTION srcDib
, dstDib
;
1219 BYTE
*srcPtr
, *dstPtr
;
1220 INT srcRowOffset
, dstRowOffset
;
1224 static RECT unusedRect
;
1226 if (GetObjectW(physDevSrc
->bitmap
->hbitmap
, sizeof(srcDib
), &srcDib
) != sizeof(srcDib
))
1228 if (GetObjectW(physDevDst
->bitmap
->hbitmap
, sizeof(dstDib
), &dstDib
) != sizeof(dstDib
))
1231 /* check for oversized values, just like X11DRV_DIB_CopyDIBSection() */
1232 if (xSrc
> srcDib
.dsBm
.bmWidth
|| ySrc
> srcDib
.dsBm
.bmHeight
)
1234 if (xSrc
+ width
> srcDib
.dsBm
.bmWidth
)
1235 width
= srcDib
.dsBm
.bmWidth
- xSrc
;
1236 if (ySrc
+ height
> srcDib
.dsBm
.bmHeight
)
1237 height
= srcDib
.dsBm
.bmHeight
- ySrc
;
1239 if (GetRgnBox(physDevDst
->region
, &unusedRect
) == COMPLEXREGION
)
1241 /* for simple regions, the clipping was already done by BITBLT_GetVisRectangles */
1242 FIXME("potential optimization: client-side complex region clipping\n");
1245 if (dstDib
.dsBm
.bmBitsPixel
<= 8)
1247 static BOOL fixme_once
;
1248 if(!fixme_once
++) FIXME("potential optimization: client-side color-index mode DIB copy\n");
1251 if (!(srcDib
.dsBmih
.biCompression
== BI_BITFIELDS
&&
1252 dstDib
.dsBmih
.biCompression
== BI_BITFIELDS
&&
1253 !memcmp(srcDib
.dsBitfields
, dstDib
.dsBitfields
, 3*sizeof(DWORD
)))
1254 && !(srcDib
.dsBmih
.biCompression
== BI_RGB
&&
1255 dstDib
.dsBmih
.biCompression
== BI_RGB
))
1257 FIXME("potential optimization: client-side compressed DIB copy\n");
1260 if (srcDib
.dsBm
.bmBitsPixel
!= dstDib
.dsBm
.bmBitsPixel
)
1262 FIXME("potential optimization: pixel format conversion\n");
1265 if (srcDib
.dsBmih
.biWidth
< 0 || dstDib
.dsBmih
.biWidth
< 0)
1267 FIXME("negative widths not yet implemented\n");
1271 switch (dstDib
.dsBm
.bmBitsPixel
)
1284 FIXME("don't know how to work with a depth of %d\n", physDevSrc
->depth
);
1288 bytesToCopy
= width
* bytesPerPixel
;
1290 if (physDevSrc
->bitmap
->topdown
)
1292 srcPtr
= &physDevSrc
->bitmap
->base
[ySrc
*srcDib
.dsBm
.bmWidthBytes
+ xSrc
*bytesPerPixel
];
1293 srcRowOffset
= srcDib
.dsBm
.bmWidthBytes
;
1297 srcPtr
= &physDevSrc
->bitmap
->base
[(srcDib
.dsBm
.bmHeight
-ySrc
-1)*srcDib
.dsBm
.bmWidthBytes
1298 + xSrc
*bytesPerPixel
];
1299 srcRowOffset
= -srcDib
.dsBm
.bmWidthBytes
;
1301 if (physDevDst
->bitmap
->topdown
)
1303 dstPtr
= &physDevDst
->bitmap
->base
[yDst
*dstDib
.dsBm
.bmWidthBytes
+ xDst
*bytesPerPixel
];
1304 dstRowOffset
= dstDib
.dsBm
.bmWidthBytes
;
1308 dstPtr
= &physDevDst
->bitmap
->base
[(dstDib
.dsBm
.bmHeight
-yDst
-1)*dstDib
.dsBm
.bmWidthBytes
1309 + xDst
*bytesPerPixel
];
1310 dstRowOffset
= -dstDib
.dsBm
.bmWidthBytes
;
1313 /* Handle overlapping regions on the same DIB */
1314 if (physDevSrc
== physDevDst
&& ySrc
< yDst
)
1316 srcPtr
+= srcRowOffset
* (height
- 1);
1317 srcRowOffset
= -srcRowOffset
;
1318 dstPtr
+= dstRowOffset
* (height
- 1);
1319 dstRowOffset
= -dstRowOffset
;
1322 for (y
= yDst
; y
< yDst
+ height
; ++y
)
1324 memmove(dstPtr
, srcPtr
, bytesToCopy
);
1325 srcPtr
+= srcRowOffset
;
1326 dstPtr
+= dstRowOffset
;
1332 static BOOL
same_format(X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
)
1334 if (physDevSrc
->depth
!= physDevDst
->depth
) return FALSE
;
1335 if (!physDevSrc
->color_shifts
&& !physDevDst
->color_shifts
) return TRUE
;
1336 if (physDevSrc
->color_shifts
&& physDevDst
->color_shifts
)
1337 return !memcmp(physDevSrc
->color_shifts
, physDevDst
->color_shifts
, sizeof(ColorShifts
));
1341 static void execute_rop( X11DRV_PDEVICE
*physdev
, Pixmap src_pixmap
, GC gc
,
1342 const RECT
*visrect
, DWORD rop
)
1345 Pixmap result
= src_pixmap
;
1347 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1348 BOOL use_pat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
1349 BOOL use_dst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
1350 int width
= visrect
->right
- visrect
->left
;
1351 int height
= visrect
->bottom
- visrect
->top
;
1353 pixmaps
[SRC
] = src_pixmap
;
1356 pixmaps
[DST
] = XCreatePixmap( gdi_display
, root_window
, width
, height
, physdev
->depth
);
1357 wine_tsx11_unlock();
1359 if (use_dst
) BITBLT_GetDstArea( physdev
, pixmaps
[DST
], gc
, visrect
);
1360 null_brush
= use_pat
&& !X11DRV_SetupGCForPatBlt( physdev
, gc
, TRUE
);
1363 for ( ; *opcode
; opcode
++)
1365 if (OP_DST(*opcode
) == DST
) result
= pixmaps
[DST
];
1366 XSetFunction( gdi_display
, gc
, OP_ROP(*opcode
) );
1367 switch(OP_SRCDST(*opcode
))
1369 case OP_ARGS(DST
,TMP
):
1370 case OP_ARGS(SRC
,TMP
):
1372 pixmaps
[TMP
] = XCreatePixmap( gdi_display
, root_window
, width
, height
, physdev
->depth
);
1374 case OP_ARGS(DST
,SRC
):
1375 case OP_ARGS(SRC
,DST
):
1376 case OP_ARGS(TMP
,SRC
):
1377 case OP_ARGS(TMP
,DST
):
1378 XCopyArea( gdi_display
, pixmaps
[OP_SRC(*opcode
)], pixmaps
[OP_DST(*opcode
)], gc
,
1379 0, 0, width
, height
, 0, 0 );
1381 case OP_ARGS(PAT
,DST
):
1382 case OP_ARGS(PAT
,SRC
):
1384 XFillRectangle( gdi_display
, pixmaps
[OP_DST(*opcode
)], gc
, 0, 0, width
, height
);
1388 XSetFunction( gdi_display
, physdev
->gc
, GXcopy
);
1389 physdev
->exposures
+= BITBLT_PutDstArea( physdev
, result
, visrect
);
1390 XFreePixmap( gdi_display
, pixmaps
[DST
] );
1391 if (pixmaps
[TMP
]) XFreePixmap( gdi_display
, pixmaps
[TMP
] );
1392 wine_tsx11_unlock();
1395 /***********************************************************************
1398 BOOL
X11DRV_PatBlt( PHYSDEV dev
, struct bitblt_coords
*dst
, DWORD rop
)
1400 X11DRV_PDEVICE
*physDev
= get_x11drv_dev( dev
);
1401 BOOL usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
1402 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1404 if (usePat
&& !X11DRV_SetupGCForBrush( physDev
)) return TRUE
;
1406 X11DRV_LockDIBSection( physDev
, DIB_Status_GdiMod
);
1409 XSetFunction( gdi_display
, physDev
->gc
, OP_ROP(*opcode
) );
1411 switch(rop
) /* a few special cases */
1413 case BLACKNESS
: /* 0x00 */
1414 case WHITENESS
: /* 0xff */
1415 if ((physDev
->depth
!= 1) && X11DRV_PALETTE_PaletteToXPixel
)
1417 XSetFunction( gdi_display
, physDev
->gc
, GXcopy
);
1418 if (rop
== BLACKNESS
)
1419 XSetForeground( gdi_display
, physDev
->gc
, X11DRV_PALETTE_PaletteToXPixel
[0] );
1421 XSetForeground( gdi_display
, physDev
->gc
,
1422 WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ));
1423 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
1426 case DSTINVERT
: /* 0x55 */
1427 if (!(X11DRV_PALETTE_PaletteFlags
& (X11DRV_PALETTE_PRIVATE
| X11DRV_PALETTE_VIRTUAL
)))
1429 /* Xor is much better when we do not have full colormap. */
1430 /* Using white^black ensures that we invert at least black */
1432 unsigned long xor_pix
= (WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ) ^
1433 BlackPixel( gdi_display
, DefaultScreen(gdi_display
) ));
1434 XSetFunction( gdi_display
, physDev
->gc
, GXxor
);
1435 XSetForeground( gdi_display
, physDev
->gc
, xor_pix
);
1436 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
1440 XFillRectangle( gdi_display
, physDev
->drawable
, physDev
->gc
,
1441 physDev
->dc_rect
.left
+ dst
->visrect
.left
,
1442 physDev
->dc_rect
.top
+ dst
->visrect
.top
,
1443 dst
->visrect
.right
- dst
->visrect
.left
,
1444 dst
->visrect
.bottom
- dst
->visrect
.top
);
1445 wine_tsx11_unlock();
1447 X11DRV_UnlockDIBSection( physDev
, TRUE
);
1452 /***********************************************************************
1455 BOOL
X11DRV_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
1456 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
1458 X11DRV_PDEVICE
*physDevDst
= get_x11drv_dev( dst_dev
);
1459 X11DRV_PDEVICE
*physDevSrc
= get_x11drv_dev( src_dev
); /* FIXME: check that it's really an x11 dev */
1462 INT sDst
, sSrc
= DIB_Status_None
;
1467 fStretch
= (src
->width
!= dst
->width
) || (src
->height
!= dst
->height
);
1469 if (physDevDst
!= physDevSrc
)
1470 sSrc
= X11DRV_LockDIBSection( physDevSrc
, DIB_Status_None
);
1472 width
= dst
->visrect
.right
- dst
->visrect
.left
;
1473 height
= dst
->visrect
.bottom
- dst
->visrect
.top
;
1475 sDst
= X11DRV_LockDIBSection( physDevDst
, DIB_Status_None
);
1476 if (physDevDst
== physDevSrc
) sSrc
= sDst
;
1478 /* try client-side DIB copy */
1479 if (!fStretch
&& rop
== SRCCOPY
&&
1480 sSrc
== DIB_Status_AppMod
&& sDst
== DIB_Status_AppMod
&&
1481 same_format(physDevSrc
, physDevDst
))
1483 if (client_side_dib_copy( physDevSrc
, src
->visrect
.left
, src
->visrect
.top
,
1484 physDevDst
, dst
->visrect
.left
, dst
->visrect
.top
, width
, height
))
1488 X11DRV_CoerceDIBSection( physDevDst
, DIB_Status_GdiMod
);
1490 opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1492 /* a few optimizations for single-op ROPs */
1493 if (!fStretch
&& !opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
))
1495 if (same_format(physDevSrc
, physDevDst
))
1498 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
1499 wine_tsx11_unlock();
1501 if (physDevSrc
!= physDevDst
)
1503 if (sSrc
== DIB_Status_AppMod
)
1505 X11DRV_DIB_CopyDIBSection( physDevSrc
, physDevDst
, src
->visrect
.left
, src
->visrect
.top
,
1506 dst
->visrect
.left
, dst
->visrect
.top
, width
, height
);
1509 X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
);
1512 XCopyArea( gdi_display
, physDevSrc
->drawable
,
1513 physDevDst
->drawable
, physDevDst
->gc
,
1514 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
1515 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
1517 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
1518 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
);
1519 physDevDst
->exposures
++;
1520 wine_tsx11_unlock();
1523 if (physDevSrc
->depth
== 1)
1527 X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
);
1528 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
1530 XSetBackground( gdi_display
, physDevDst
->gc
, fg
);
1531 XSetForeground( gdi_display
, physDevDst
->gc
, bg
);
1532 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
1533 XCopyPlane( gdi_display
, physDevSrc
->drawable
,
1534 physDevDst
->drawable
, physDevDst
->gc
,
1535 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
1536 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
1538 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
1539 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
, 1 );
1540 physDevDst
->exposures
++;
1541 wine_tsx11_unlock();
1547 tmpGC
= XCreateGC( gdi_display
, physDevDst
->drawable
, 0, NULL
);
1548 XSetSubwindowMode( gdi_display
, tmpGC
, IncludeInferiors
);
1549 XSetGraphicsExposures( gdi_display
, tmpGC
, False
);
1550 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, physDevDst
->depth
);
1551 wine_tsx11_unlock();
1553 if (physDevDst
!= physDevSrc
) X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
);
1555 if(!X11DRV_XRender_GetSrcAreaStretch( physDevSrc
, physDevDst
, src_pixmap
, tmpGC
, src
, dst
))
1558 BITBLT_GetSrcAreaStretch( physDevSrc
, physDevDst
, src_pixmap
, tmpGC
, src
, dst
);
1560 BITBLT_GetSrcArea( physDevSrc
, physDevDst
, src_pixmap
, tmpGC
, &src
->visrect
);
1563 execute_rop( physDevDst
, src_pixmap
, tmpGC
, &dst
->visrect
, rop
);
1566 XFreePixmap( gdi_display
, src_pixmap
);
1567 XFreeGC( gdi_display
, tmpGC
);
1568 wine_tsx11_unlock();
1571 if (physDevDst
!= physDevSrc
) X11DRV_UnlockDIBSection( physDevSrc
, FALSE
);
1572 X11DRV_UnlockDIBSection( physDevDst
, TRUE
);
1577 /***********************************************************************
1580 BOOL
X11DRV_AlphaBlend( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
1581 PHYSDEV src_dev
, struct bitblt_coords
*src
, BLENDFUNCTION blendfn
)
1583 X11DRV_PDEVICE
*physDevDst
= get_x11drv_dev( dst_dev
);
1584 X11DRV_PDEVICE
*physDevSrc
= get_x11drv_dev( src_dev
); /* FIXME: check that it's really an x11 dev */
1586 if (src
->x
< 0 || src
->y
< 0 || src
->width
< 0 || src
->height
< 0 ||
1587 src
->width
> physDevSrc
->drawable_rect
.right
- physDevSrc
->drawable_rect
.left
- src
->x
||
1588 src
->height
> physDevSrc
->drawable_rect
.bottom
- physDevSrc
->drawable_rect
.top
- src
->y
)
1590 WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src
->x
, src
->y
, src
->width
, src
->height
);
1591 SetLastError( ERROR_INVALID_PARAMETER
);
1595 return XRender_AlphaBlend( physDevDst
, dst
, physDevSrc
, src
, blendfn
);
1599 static void free_heap_bits( struct gdi_image_bits
*bits
)
1601 HeapFree( GetProcessHeap(), 0, bits
->ptr
);
1604 static void free_ximage_bits( struct gdi_image_bits
*bits
)
1608 wine_tsx11_unlock();
1611 /* store the palette or color mask data in the bitmap info structure */
1612 static void set_color_info( PHYSDEV dev
, const ColorShifts
*color_shifts
, BITMAPINFO
*info
)
1614 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1616 info
->bmiHeader
.biCompression
= BI_RGB
;
1617 info
->bmiHeader
.biClrUsed
= 0;
1619 switch (info
->bmiHeader
.biBitCount
)
1624 RGBQUAD
*rgb
= (RGBQUAD
*)colors
;
1625 PALETTEENTRY palette
[256];
1628 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
1629 count
= X11DRV_GetSystemPaletteEntries( dev
, 0, info
->bmiHeader
.biClrUsed
, palette
);
1630 for (i
= 0; i
< count
; i
++)
1632 rgb
[i
].rgbRed
= palette
[i
].peRed
;
1633 rgb
[i
].rgbGreen
= palette
[i
].peGreen
;
1634 rgb
[i
].rgbBlue
= palette
[i
].peBlue
;
1635 rgb
[i
].rgbReserved
= 0;
1637 memset( &rgb
[count
], 0, (info
->bmiHeader
.biClrUsed
- count
) * sizeof(*rgb
) );
1641 colors
[0] = color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
;
1642 colors
[1] = color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
;
1643 colors
[2] = color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
;
1644 if (colors
[0] != 0x7c00 || colors
[1] != 0x03e0 || colors
[2] != 0x001f)
1645 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1648 colors
[0] = color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
;
1649 colors
[1] = color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
;
1650 colors
[2] = color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
;
1651 if (colors
[0] != 0xff0000 || colors
[1] != 0x00ff00 || colors
[2] != 0x0000ff)
1652 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1657 /* check if the specified color info is suitable for PutImage */
1658 static BOOL
matching_color_info( PHYSDEV dev
, const ColorShifts
*color_shifts
, const BITMAPINFO
*info
)
1660 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1662 switch (info
->bmiHeader
.biBitCount
)
1665 if (info
->bmiHeader
.biCompression
!= BI_RGB
) return FALSE
;
1666 return !info
->bmiHeader
.biClrUsed
; /* color map not allowed */
1670 RGBQUAD
*rgb
= (RGBQUAD
*)colors
;
1671 PALETTEENTRY palette
[256];
1674 if (info
->bmiHeader
.biCompression
!= BI_RGB
) return FALSE
;
1675 count
= X11DRV_GetSystemPaletteEntries( dev
, 0, 1 << info
->bmiHeader
.biBitCount
, palette
);
1676 if (count
!= info
->bmiHeader
.biClrUsed
) return FALSE
;
1677 for (i
= 0; i
< count
; i
++)
1679 if (rgb
[i
].rgbRed
!= palette
[i
].peRed
||
1680 rgb
[i
].rgbGreen
!= palette
[i
].peGreen
||
1681 rgb
[i
].rgbBlue
!= palette
[i
].peBlue
) return FALSE
;
1686 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1687 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== colors
[0] &&
1688 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== colors
[1] &&
1689 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== colors
[2]);
1690 if (info
->bmiHeader
.biCompression
== BI_RGB
)
1691 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== 0x7c00 &&
1692 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== 0x03e0 &&
1693 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== 0x001f);
1696 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1697 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== colors
[0] &&
1698 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== colors
[1] &&
1699 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== colors
[2]);
1702 if (info
->bmiHeader
.biCompression
== BI_RGB
)
1703 return (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
== 0xff0000 &&
1704 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
== 0x00ff00 &&
1705 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
== 0x0000ff);
1711 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1712 static DWORD
copy_image_bits( BITMAPINFO
*info
, const ColorShifts
*color_shifts
, XImage
*image
,
1713 const struct gdi_image_bits
*src_bits
, struct gdi_image_bits
*dst_bits
,
1714 struct bitblt_coords
*coords
, const int *mapping
, unsigned int zeropad_mask
)
1716 #ifdef WORDS_BIGENDIAN
1717 static const int client_byte_order
= MSBFirst
;
1719 static const int client_byte_order
= LSBFirst
;
1722 int x
, y
, height
= coords
->visrect
.bottom
- coords
->visrect
.top
;
1723 int width_bytes
= image
->bytes_per_line
;
1725 unsigned char *src
, *dst
;
1727 switch (info
->bmiHeader
.biBitCount
)
1730 need_byteswap
= (image
->bitmap_bit_order
!= MSBFirst
);
1733 need_byteswap
= (image
->byte_order
!= MSBFirst
);
1737 need_byteswap
= (image
->byte_order
!= client_byte_order
);
1740 need_byteswap
= ((image
->byte_order
== LSBFirst
&& color_shifts
->logicalBlue
.shift
== 16) ||
1741 (image
->byte_order
== MSBFirst
&& color_shifts
->logicalBlue
.shift
== 0));
1744 need_byteswap
= FALSE
;
1748 src
= src_bits
->ptr
;
1749 if (info
->bmiHeader
.biHeight
> 0)
1750 src
+= (info
->bmiHeader
.biHeight
- coords
->visrect
.bottom
) * width_bytes
;
1752 src
+= coords
->visrect
.top
* width_bytes
;
1754 if ((need_byteswap
&& !src_bits
->is_copy
) || /* need to swap bytes */
1755 (zeropad_mask
!= ~0u && !src_bits
->is_copy
) || /* need to clear padding bytes */
1756 (mapping
&& !src_bits
->is_copy
) || /* need to remap pixels */
1757 (width_bytes
& 3) || /* need to fixup line alignment */
1758 (info
->bmiHeader
.biHeight
> 0)) /* need to flip vertically */
1760 width_bytes
= (width_bytes
+ 3) & ~3;
1761 info
->bmiHeader
.biSizeImage
= height
* width_bytes
;
1762 if (!(dst_bits
->ptr
= HeapAlloc( GetProcessHeap(), 0, info
->bmiHeader
.biSizeImage
)))
1763 return ERROR_OUTOFMEMORY
;
1764 dst_bits
->is_copy
= TRUE
;
1765 dst_bits
->free
= free_heap_bits
;
1769 /* swap bits in place */
1770 dst_bits
->ptr
= src
;
1771 dst_bits
->is_copy
= src_bits
->is_copy
;
1772 dst_bits
->free
= NULL
;
1773 if (!need_byteswap
&& zeropad_mask
== ~0u && !mapping
) return ERROR_SUCCESS
; /* nothing to do */
1776 dst
= dst_bits
->ptr
;
1777 padding_pos
= width_bytes
/sizeof(unsigned int) - 1;
1779 if (info
->bmiHeader
.biHeight
> 0)
1781 dst
+= (height
- 1) * width_bytes
;
1782 width_bytes
= -width_bytes
;
1785 if (need_byteswap
|| mapping
)
1787 switch (info
->bmiHeader
.biBitCount
)
1790 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1792 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1793 dst
[x
] = bit_swap
[src
[x
]];
1794 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1798 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1801 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1802 dst
[x
] = (mapping
[src
[x
] & 0x0f] << 4) | mapping
[src
[x
] >> 4];
1804 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1805 dst
[x
] = (src
[x
] << 4) | (src
[x
] >> 4);
1806 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1810 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1812 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1813 dst
[x
] = mapping
[src
[x
]];
1814 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1818 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1820 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1821 ((USHORT
*)dst
)[x
] = RtlUshortByteSwap( ((const USHORT
*)src
)[x
] );
1822 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1826 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1828 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1830 unsigned char tmp
= src
[3 * x
];
1831 dst
[3 * x
] = src
[3 * x
+ 2];
1832 dst
[3 * x
+ 1] = src
[3 * x
+ 1];
1833 dst
[3 * x
+ 2] = tmp
;
1835 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1839 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1840 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1841 ((ULONG
*)dst
)[x
] = RtlUlongByteSwap( ((const ULONG
*)src
)[x
] );
1845 else if (src
!= dst
)
1847 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1849 memcpy( dst
, src
, image
->bytes_per_line
);
1850 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1853 else /* only need to clear the padding */
1855 for (y
= 0; y
< height
; y
++, dst
+= width_bytes
)
1856 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1858 return ERROR_SUCCESS
;
1861 /***********************************************************************
1864 DWORD
X11DRV_PutImage( PHYSDEV dev
, HBITMAP hbitmap
, HRGN clip
, BITMAPINFO
*info
,
1865 const struct gdi_image_bits
*bits
, struct bitblt_coords
*src
,
1866 struct bitblt_coords
*dst
, DWORD rop
)
1868 X11DRV_PDEVICE
*physdev
;
1869 X_PHYSBITMAP
*bitmap
;
1873 struct gdi_image_bits dst_bits
;
1874 const XPixmapFormatValues
*format
;
1875 const ColorShifts
*color_shifts
;
1876 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1877 const int *mapping
= NULL
;
1881 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
1883 depth
= bitmap
->pixmap_depth
;
1884 color_shifts
= &bitmap
->pixmap_color_shifts
;
1888 physdev
= get_x11drv_dev( dev
);
1890 depth
= physdev
->depth
;
1891 color_shifts
= physdev
->color_shifts
;
1893 format
= pixmap_formats
[depth
];
1895 if (info
->bmiHeader
.biPlanes
!= 1) goto update_format
;
1896 if (info
->bmiHeader
.biBitCount
!= format
->bits_per_pixel
) goto update_format
;
1897 /* FIXME: could try to handle 1-bpp using XCopyPlane */
1898 if (!matching_color_info( dev
, color_shifts
, info
)) goto update_format
;
1899 if (!bits
) return ERROR_SUCCESS
; /* just querying the format */
1900 if ((src
->width
!= dst
->width
) || (src
->height
!= dst
->height
)) return ERROR_TRANSFORM_NOT_SUPPORTED
;
1903 image
= XCreateImage( gdi_display
, visual
, depth
, ZPixmap
, 0, NULL
,
1904 info
->bmiHeader
.biWidth
, src
->visrect
.bottom
- src
->visrect
.top
, 32, 0 );
1905 wine_tsx11_unlock();
1906 if (!image
) return ERROR_OUTOFMEMORY
;
1908 if (image
->bits_per_pixel
== 4 || image
->bits_per_pixel
== 8)
1910 if (bitmap
|| (!opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
)))
1911 mapping
= X11DRV_PALETTE_PaletteToXPixel
;
1914 ret
= copy_image_bits( info
, color_shifts
, image
, bits
, &dst_bits
, src
, mapping
, ~0u );
1918 int width
= dst
->visrect
.right
- dst
->visrect
.left
;
1919 int height
= dst
->visrect
.bottom
- dst
->visrect
.top
;
1921 image
->data
= dst_bits
.ptr
;
1922 /* hack: make sure the bits are readable if we are reading from a DIB section */
1923 /* to be removed once we get rid of DIB access protections */
1924 if (!dst_bits
.is_copy
) IsBadReadPtr( dst_bits
.ptr
, height
* image
->bytes_per_line
);
1928 RGNDATA
*clip_data
= NULL
;
1931 if (clip
) clip_data
= X11DRV_GetRegionData( clip
, 0 );
1932 X11DRV_DIB_Lock( bitmap
, DIB_Status_GdiMod
);
1935 gc
= XCreateGC( gdi_display
, bitmap
->pixmap
, 0, NULL
);
1936 XSetGraphicsExposures( gdi_display
, gc
, False
);
1937 if (clip_data
) XSetClipRectangles( gdi_display
, gc
, 0, 0, (XRectangle
*)clip_data
->Buffer
,
1938 clip_data
->rdh
.nCount
, YXBanded
);
1939 XPutImage( gdi_display
, bitmap
->pixmap
, gc
, image
, src
->visrect
.left
, 0,
1940 dst
->visrect
.left
, dst
->visrect
.top
, width
, height
);
1941 XFreeGC( gdi_display
, gc
);
1942 wine_tsx11_unlock();
1944 X11DRV_DIB_Unlock( bitmap
, TRUE
);
1945 HeapFree( GetProcessHeap(), 0, clip_data
);
1949 HRGN saved_region
= 0;
1951 if (clip
) saved_region
= add_extra_clipping_region( physdev
, clip
);
1952 X11DRV_LockDIBSection( physdev
, DIB_Status_GdiMod
);
1954 /* optimization for single-op ROPs */
1955 if (!opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
))
1958 XSetFunction( gdi_display
, physdev
->gc
, OP_ROP(*opcode
) );
1959 XPutImage( gdi_display
, physdev
->drawable
, physdev
->gc
, image
, src
->visrect
.left
, 0,
1960 physdev
->dc_rect
.left
+ dst
->visrect
.left
,
1961 physdev
->dc_rect
.top
+ dst
->visrect
.top
, width
, height
);
1962 wine_tsx11_unlock();
1970 gc
= XCreateGC( gdi_display
, physdev
->drawable
, 0, NULL
);
1971 XSetSubwindowMode( gdi_display
, gc
, IncludeInferiors
);
1972 XSetGraphicsExposures( gdi_display
, gc
, False
);
1973 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, depth
);
1974 XPutImage( gdi_display
, src_pixmap
, gc
, image
, src
->visrect
.left
, 0, 0, 0, width
, height
);
1975 wine_tsx11_unlock();
1977 execute_rop( physdev
, src_pixmap
, gc
, &dst
->visrect
, rop
);
1980 XFreePixmap( gdi_display
, src_pixmap
);
1981 XFreeGC( gdi_display
, gc
);
1982 wine_tsx11_unlock();
1985 X11DRV_UnlockDIBSection( physdev
, !ret
);
1986 if (saved_region
) restore_clipping_region( physdev
, saved_region
);
1992 XDestroyImage( image
);
1993 wine_tsx11_unlock();
1994 if (dst_bits
.free
) dst_bits
.free( &dst_bits
);
1998 info
->bmiHeader
.biPlanes
= 1;
1999 info
->bmiHeader
.biBitCount
= format
->bits_per_pixel
;
2000 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
2001 set_color_info( dev
, color_shifts
, info
);
2002 return ERROR_BAD_FORMAT
;
2005 /***********************************************************************
2008 DWORD
X11DRV_GetImage( PHYSDEV dev
, HBITMAP hbitmap
, BITMAPINFO
*info
,
2009 struct gdi_image_bits
*bits
, struct bitblt_coords
*src
)
2011 X11DRV_PDEVICE
*physdev
;
2012 X_PHYSBITMAP
*bitmap
;
2013 DWORD ret
= ERROR_SUCCESS
;
2015 UINT align
, x
, y
, width
, height
;
2017 struct gdi_image_bits src_bits
;
2018 const XPixmapFormatValues
*format
;
2019 const ColorShifts
*color_shifts
;
2020 const int *mapping
= NULL
;
2024 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
2026 depth
= bitmap
->pixmap_depth
;
2027 color_shifts
= &bitmap
->pixmap_color_shifts
;
2031 physdev
= get_x11drv_dev( dev
);
2033 depth
= physdev
->depth
;
2034 color_shifts
= physdev
->color_shifts
;
2036 format
= pixmap_formats
[depth
];
2038 /* align start and width to 32-bit boundary */
2039 switch (format
->bits_per_pixel
)
2041 case 1: align
= 32; break;
2042 case 4: align
= 8; mapping
= X11DRV_PALETTE_XPixelToPalette
; break;
2043 case 8: align
= 4; mapping
= X11DRV_PALETTE_XPixelToPalette
; break;
2044 case 16: align
= 2; break;
2045 case 24: align
= 4; break;
2046 case 32: align
= 1; break;
2048 FIXME( "depth %u bpp %u not supported yet\n", depth
, format
->bits_per_pixel
);
2049 return ERROR_BAD_FORMAT
;
2052 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
2053 info
->bmiHeader
.biPlanes
= 1;
2054 info
->bmiHeader
.biBitCount
= format
->bits_per_pixel
;
2055 info
->bmiHeader
.biXPelsPerMeter
= 0;
2056 info
->bmiHeader
.biYPelsPerMeter
= 0;
2057 info
->bmiHeader
.biClrImportant
= 0;
2058 set_color_info( dev
, color_shifts
, info
);
2060 if (!bits
) return ERROR_SUCCESS
; /* just querying the color information */
2062 x
= src
->visrect
.left
& ~(align
- 1);
2063 y
= src
->visrect
.top
;
2064 width
= src
->visrect
.right
- x
;
2065 height
= src
->visrect
.bottom
- src
->visrect
.top
;
2066 if (format
->scanline_pad
!= 32) width
= (width
+ (align
- 1)) & ~(align
- 1);
2067 /* make the source rectangle relative to the returned bits */
2070 OffsetRect( &src
->visrect
, -x
, -y
);
2075 GetObjectW( hbitmap
, sizeof(bm
), &bm
);
2076 width
= min( width
, bm
.bmWidth
- x
);
2077 height
= min( height
, bm
.bmHeight
- y
);
2078 X11DRV_DIB_Lock( bitmap
, DIB_Status_GdiMod
);
2080 image
= XGetImage( gdi_display
, bitmap
->pixmap
, x
, y
, width
, height
, AllPlanes
, ZPixmap
);
2081 wine_tsx11_unlock();
2082 X11DRV_DIB_Unlock( bitmap
, TRUE
);
2084 else if (GetObjectType( dev
->hdc
) == OBJ_MEMDC
)
2086 X11DRV_LockDIBSection( physdev
, DIB_Status_GdiMod
);
2087 width
= min( width
, physdev
->dc_rect
.right
- physdev
->dc_rect
.left
- x
);
2088 height
= min( height
, physdev
->dc_rect
.bottom
- physdev
->dc_rect
.top
- y
);
2090 image
= XGetImage( gdi_display
, physdev
->drawable
,
2091 physdev
->dc_rect
.left
+ x
, physdev
->dc_rect
.top
+ y
,
2092 width
, height
, AllPlanes
, ZPixmap
);
2093 wine_tsx11_unlock();
2094 X11DRV_UnlockDIBSection( physdev
, FALSE
);
2101 /* use a temporary pixmap to avoid BadMatch errors */
2102 pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, depth
);
2103 XCopyArea( gdi_display
, physdev
->drawable
, pixmap
, get_bitmap_gc(depth
),
2104 physdev
->dc_rect
.left
+ x
, physdev
->dc_rect
.top
+ y
, width
, height
, 0, 0 );
2105 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
, AllPlanes
, ZPixmap
);
2106 XFreePixmap( gdi_display
, pixmap
);
2107 wine_tsx11_unlock();
2109 if (!image
) return ERROR_OUTOFMEMORY
;
2111 info
->bmiHeader
.biWidth
= width
;
2112 info
->bmiHeader
.biHeight
= -height
;
2113 info
->bmiHeader
.biSizeImage
= height
* image
->bytes_per_line
;
2115 src_bits
.ptr
= image
->data
;
2116 src_bits
.is_copy
= TRUE
;
2117 ret
= copy_image_bits( info
, color_shifts
, image
, &src_bits
, bits
, src
, mapping
,
2118 zeropad_masks
[(width
* image
->bits_per_pixel
) & 31] );
2120 if (!ret
&& bits
->ptr
== image
->data
)
2122 bits
->free
= free_ximage_bits
;
2126 XDestroyImage( image
);
2127 wine_tsx11_unlock();