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
,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(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 BITBLT_TEST /* Opcodes test */
485 static int do_bitop( int s
, int d
, int rop
)
490 case GXclear
: res
= 0; break;
491 case GXand
: res
= s
& d
; break;
492 case GXandReverse
: res
= s
& ~d
; break;
493 case GXcopy
: res
= s
; break;
494 case GXandInverted
: res
= ~s
& d
; break;
495 case GXnoop
: res
= d
; break;
496 case GXxor
: res
= s
^ d
; break;
497 case GXor
: res
= s
| d
; break;
498 case GXnor
: res
= ~(s
| d
); break;
499 case GXequiv
: res
= ~s
^ d
; break;
500 case GXinvert
: res
= ~d
; break;
501 case GXorReverse
: res
= s
| ~d
; break;
502 case GXcopyInverted
: res
= ~s
; break;
503 case GXorInverted
: res
= ~s
| d
; break;
504 case GXnand
: res
= ~(s
& d
); break;
505 case GXset
: res
= 1; break;
512 int rop
, i
, res
, src
, dst
, pat
, tmp
, dstUsed
;
515 for (rop
= 0; rop
< 256; rop
++)
518 for (i
= 0; i
< 8; i
++)
523 for (opcode
= BITBLT_Opcodes
[rop
]; *opcode
; opcode
++)
527 case OP_ARGS(DST
,TMP
):
528 tmp
= do_bitop( dst
, tmp
, *opcode
& 0xf );
530 case OP_ARGS(DST
,SRC
):
531 src
= do_bitop( dst
, src
, *opcode
& 0xf );
533 case OP_ARGS(SRC
,TMP
):
534 tmp
= do_bitop( src
, tmp
, *opcode
& 0xf );
536 case OP_ARGS(SRC
,DST
):
537 dst
= do_bitop( src
, dst
, *opcode
& 0xf );
540 case OP_ARGS(PAT
,TMP
):
541 tmp
= do_bitop( pat
, tmp
, *opcode
& 0xf );
543 case OP_ARGS(PAT
,DST
):
544 dst
= do_bitop( pat
, dst
, *opcode
& 0xf );
547 case OP_ARGS(PAT
,SRC
):
548 src
= do_bitop( pat
, src
, *opcode
& 0xf );
550 case OP_ARGS(TMP
,DST
):
551 dst
= do_bitop( tmp
, dst
, *opcode
& 0xf );
554 case OP_ARGS(TMP
,SRC
):
555 src
= do_bitop( tmp
, src
, *opcode
& 0xf );
558 printf( "Invalid opcode %x\n", *opcode
);
561 if (!dstUsed
) dst
= src
;
562 if (dst
) res
|= 1 << i
;
564 if (res
!= rop
) printf( "%02x: ERROR, res=%02x\n", rop
, res
);
570 #endif /* BITBLT_TEST */
573 static void get_colors(X11DRV_PDEVICE
*physDevDst
, X11DRV_PDEVICE
*physDevSrc
,
578 *fg
= physDevDst
->textPixel
;
579 *bg
= physDevDst
->backgroundPixel
;
580 if(physDevSrc
->depth
== 1) {
581 if(GetDIBColorTable(physDevSrc
->dev
.hdc
, 0, 2, rgb
) == 2) {
583 logcolor
= RGB(rgb
[0].rgbRed
, rgb
[0].rgbGreen
, rgb
[0].rgbBlue
);
584 *fg
= X11DRV_PALETTE_ToPhysical( physDevDst
, logcolor
);
585 logcolor
= RGB(rgb
[1].rgbRed
, rgb
[1].rgbGreen
,rgb
[1].rgbBlue
);
586 *bg
= X11DRV_PALETTE_ToPhysical( physDevDst
, logcolor
);
591 /* return a mask for meaningful bits when doing an XGetPixel on an image */
592 static unsigned long image_pixel_mask( X11DRV_PDEVICE
*physDev
)
595 ColorShifts
*shifts
= physDev
->color_shifts
;
597 if (!shifts
) shifts
= &X11DRV_PALETTE_default_shifts
;
598 ret
= (shifts
->physicalRed
.max
<< shifts
->physicalRed
.shift
) |
599 (shifts
->physicalGreen
.max
<< shifts
->physicalGreen
.shift
) |
600 (shifts
->physicalBlue
.max
<< shifts
->physicalBlue
.shift
);
601 if (!ret
) ret
= (1 << physDev
->depth
) - 1;
606 /***********************************************************************
609 * Stretch a row of pixels. Helper function for BITBLT_StretchImage.
611 static void BITBLT_StretchRow( int *rowSrc
, int *rowDst
,
612 INT startDst
, INT widthDst
,
613 INT xinc
, INT xoff
, WORD mode
)
615 register INT xsrc
= xinc
* startDst
+ xoff
;
619 case STRETCH_ANDSCANS
:
620 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
621 *rowDst
++ &= rowSrc
[xsrc
>> 16];
623 case STRETCH_ORSCANS
:
624 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
625 *rowDst
++ |= rowSrc
[xsrc
>> 16];
627 case STRETCH_DELETESCANS
:
628 for(; widthDst
> 0; widthDst
--, xsrc
+= xinc
)
629 *rowDst
++ = rowSrc
[xsrc
>> 16];
635 /***********************************************************************
638 * Shrink a row of pixels. Helper function for BITBLT_StretchImage.
640 static void BITBLT_ShrinkRow( int *rowSrc
, int *rowDst
,
641 INT startSrc
, INT widthSrc
,
642 INT xinc
, INT xoff
, WORD mode
)
644 register INT xdst
= xinc
* startSrc
+ xoff
;
648 case STRETCH_ORSCANS
:
649 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
650 rowDst
[xdst
>> 16] |= *rowSrc
++;
652 case STRETCH_ANDSCANS
:
653 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
654 rowDst
[xdst
>> 16] &= *rowSrc
++;
656 case STRETCH_DELETESCANS
:
657 for(; widthSrc
> 0; widthSrc
--, xdst
+= xinc
)
658 rowDst
[xdst
>> 16] = *rowSrc
++;
664 /***********************************************************************
667 * Retrieve a row from an image. Helper function for BITBLT_StretchImage.
669 static void BITBLT_GetRow( XImage
*image
, int *pdata
, INT row
,
670 INT start
, INT width
, INT depthDst
,
671 int fg
, int bg
, unsigned long pixel_mask
, BOOL swap
)
675 assert( (row
>= 0) && (row
< image
->height
) );
676 assert( (start
>= 0) && (width
<= image
->width
) );
678 pdata
+= swap
? start
+width
-1 : start
;
679 if (image
->depth
== depthDst
) /* color -> color */
681 if (X11DRV_PALETTE_XPixelToPalette
&& (depthDst
!= 1))
682 if (swap
) for (i
= 0; i
< width
; i
++)
683 *pdata
-- = X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, i
, row
)];
684 else for (i
= 0; i
< width
; i
++)
685 *pdata
++ = X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, i
, row
)];
687 if (swap
) for (i
= 0; i
< width
; i
++)
688 *pdata
-- = XGetPixel( image
, i
, row
);
689 else for (i
= 0; i
< width
; i
++)
690 *pdata
++ = XGetPixel( image
, i
, row
);
694 if (image
->depth
== 1) /* monochrome -> color */
696 if (X11DRV_PALETTE_XPixelToPalette
)
698 fg
= X11DRV_PALETTE_XPixelToPalette
[fg
];
699 bg
= X11DRV_PALETTE_XPixelToPalette
[bg
];
701 if (swap
) for (i
= 0; i
< width
; i
++)
702 *pdata
-- = XGetPixel( image
, i
, row
) ? bg
: fg
;
703 else for (i
= 0; i
< width
; i
++)
704 *pdata
++ = XGetPixel( image
, i
, row
) ? bg
: fg
;
706 else /* color -> monochrome */
708 if (swap
) for (i
= 0; i
< width
; i
++)
709 *pdata
-- = ((XGetPixel( image
, i
, row
) & pixel_mask
) == bg
) ? 1 : 0;
710 else for (i
= 0; i
< width
; i
++)
711 *pdata
++ = ((XGetPixel( image
, i
, row
) & pixel_mask
) == bg
) ? 1 : 0;
717 /***********************************************************************
718 * BITBLT_StretchImage
720 * Stretch an X image.
721 * FIXME: does not work for full 32-bit coordinates.
723 static void BITBLT_StretchImage( XImage
*srcImage
, XImage
*dstImage
,
724 INT widthSrc
, INT heightSrc
,
725 INT widthDst
, INT heightDst
,
726 RECT
*visRectSrc
, RECT
*visRectDst
,
727 int foreground
, int background
,
728 unsigned long pixel_mask
, WORD mode
)
730 int *rowSrc
, *rowDst
, *pixel
;
732 INT xinc
, xoff
, yinc
, ysrc
, ydst
;
734 BOOL hstretch
, vstretch
, hswap
, vswap
;
736 hswap
= widthSrc
* widthDst
< 0;
737 vswap
= heightSrc
* heightDst
< 0;
738 widthSrc
= abs(widthSrc
);
739 heightSrc
= abs(heightSrc
);
740 widthDst
= abs(widthDst
);
741 heightDst
= abs(heightDst
);
743 if (!(rowSrc
= HeapAlloc( GetProcessHeap(), 0,
744 (widthSrc
+widthDst
)*sizeof(int) ))) return;
745 rowDst
= rowSrc
+ widthSrc
;
747 /* When stretching, all modes are the same, and DELETESCANS is faster */
748 if ((widthSrc
< widthDst
) && (heightSrc
< heightDst
))
749 mode
= STRETCH_DELETESCANS
;
751 if (mode
== STRETCH_HALFTONE
) /* FIXME */
752 mode
= STRETCH_DELETESCANS
;
754 if (mode
!= STRETCH_DELETESCANS
)
755 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
756 widthDst
*sizeof(int) );
758 hstretch
= (widthSrc
< widthDst
);
759 vstretch
= (heightSrc
< heightDst
);
763 xinc
= (widthSrc
<< 16) / widthDst
;
764 xoff
= ((widthSrc
<< 16) - (xinc
* widthDst
)) / 2;
768 xinc
= ((int)widthDst
<< 16) / widthSrc
;
769 xoff
= ((widthDst
<< 16) - (xinc
* widthSrc
)) / 2;
775 yinc
= (heightSrc
<< 16) / heightDst
;
776 ydst
= visRectDst
->top
;
779 ysrc
= yinc
* (heightDst
- ydst
- 1);
785 for ( ; (ydst
< visRectDst
->bottom
); ysrc
+= yinc
, ydst
++)
787 if (((ysrc
>> 16) < visRectSrc
->top
) ||
788 ((ysrc
>> 16) >= visRectSrc
->bottom
)) continue;
790 /* Retrieve a source row */
791 BITBLT_GetRow( srcImage
, rowSrc
, (ysrc
>> 16) - visRectSrc
->top
,
792 hswap
? widthSrc
- visRectSrc
->right
794 visRectSrc
->right
- visRectSrc
->left
,
795 dstImage
->depth
, foreground
, background
, pixel_mask
, hswap
);
797 /* Stretch or shrink it */
799 BITBLT_StretchRow( rowSrc
, rowDst
, visRectDst
->left
,
800 visRectDst
->right
- visRectDst
->left
,
802 else BITBLT_ShrinkRow( rowSrc
, rowDst
,
803 hswap
? widthSrc
- visRectSrc
->right
805 visRectSrc
->right
- visRectSrc
->left
,
808 /* Store the destination row */
809 pixel
= rowDst
+ visRectDst
->right
- 1;
810 y
= ydst
- visRectDst
->top
;
811 for (x
= visRectDst
->right
-visRectDst
->left
-1; x
>= 0; x
--)
812 XPutPixel( dstImage
, x
, y
, *pixel
-- );
813 if (mode
!= STRETCH_DELETESCANS
)
814 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
815 widthDst
*sizeof(int) );
817 /* Make copies of the destination row */
819 pdata
= dstImage
->data
+ dstImage
->bytes_per_line
* y
;
820 while (((ysrc
+ yinc
) >> 16 == ysrc
>> 16) &&
821 (ydst
< visRectDst
->bottom
-1))
823 memcpy( pdata
+ dstImage
->bytes_per_line
, pdata
,
824 dstImage
->bytes_per_line
);
825 pdata
+= dstImage
->bytes_per_line
;
833 yinc
= (heightDst
<< 16) / heightSrc
;
834 ysrc
= visRectSrc
->top
;
835 ydst
= ((heightDst
<< 16) - (yinc
* heightSrc
)) / 2;
838 ydst
+= yinc
* (heightSrc
- ysrc
- 1);
844 for( ; (ysrc
< visRectSrc
->bottom
); ydst
+= yinc
, ysrc
++)
846 if (((ydst
>> 16) < visRectDst
->top
) ||
847 ((ydst
>> 16) >= visRectDst
->bottom
)) continue;
849 /* Retrieve a source row */
850 BITBLT_GetRow( srcImage
, rowSrc
, ysrc
- visRectSrc
->top
,
851 hswap
? widthSrc
- visRectSrc
->right
853 visRectSrc
->right
- visRectSrc
->left
,
854 dstImage
->depth
, foreground
, background
, pixel_mask
, hswap
);
856 /* Stretch or shrink it */
858 BITBLT_StretchRow( rowSrc
, rowDst
, visRectDst
->left
,
859 visRectDst
->right
- visRectDst
->left
,
861 else BITBLT_ShrinkRow( rowSrc
, rowDst
,
862 hswap
? widthSrc
- visRectSrc
->right
864 visRectSrc
->right
- visRectSrc
->left
,
867 /* Merge several source rows into the destination */
868 if (mode
== STRETCH_DELETESCANS
)
870 /* Simply skip the overlapping rows */
871 while (((ydst
+ yinc
) >> 16 == ydst
>> 16) &&
872 (ysrc
< visRectSrc
->bottom
-1))
878 else if (((ydst
+ yinc
) >> 16 == ydst
>> 16) &&
879 (ysrc
< visRectSrc
->bottom
-1))
880 continue; /* Restart loop for next overlapping row */
882 /* Store the destination row */
883 pixel
= rowDst
+ visRectDst
->right
- 1;
884 y
= (ydst
>> 16) - visRectDst
->top
;
885 for (x
= visRectDst
->right
-visRectDst
->left
-1; x
>= 0; x
--)
886 XPutPixel( dstImage
, x
, y
, *pixel
-- );
887 if (mode
!= STRETCH_DELETESCANS
)
888 memset( rowDst
, (mode
== STRETCH_ANDSCANS
) ? 0xff : 0x00,
889 widthDst
*sizeof(int) );
893 HeapFree( GetProcessHeap(), 0, rowSrc
);
897 /***********************************************************************
898 * BITBLT_GetSrcAreaStretch
900 * Retrieve an area from the source DC, stretching and mapping all the
901 * pixels to Windows colors.
903 static int BITBLT_GetSrcAreaStretch( X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
904 Pixmap pixmap
, GC gc
,
905 const struct bitblt_coords
*src
, const struct bitblt_coords
*dst
)
907 XImage
*imageSrc
, *imageDst
;
908 RECT rectSrc
= src
->visrect
;
909 RECT rectDst
= dst
->visrect
;
912 rectSrc
.left
-= src
->x
;
913 rectSrc
.right
-= src
->x
;
914 rectSrc
.top
-= src
->y
;
915 rectSrc
.bottom
-= src
->y
;
916 rectDst
.left
-= dst
->x
;
917 rectDst
.right
-= dst
->x
;
918 rectDst
.top
-= dst
->y
;
919 rectDst
.bottom
-= dst
->y
;
922 rectSrc
.left
-= src
->width
;
923 rectSrc
.right
-= src
->width
;
927 rectDst
.left
-= dst
->width
;
928 rectDst
.right
-= dst
->width
;
932 rectSrc
.top
-= src
->height
;
933 rectSrc
.bottom
-= src
->height
;
937 rectDst
.top
-= dst
->height
;
938 rectDst
.bottom
-= dst
->height
;
941 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
943 /* FIXME: avoid BadMatch errors */
944 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
945 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
946 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
947 src
->visrect
.right
- src
->visrect
.left
,
948 src
->visrect
.bottom
- src
->visrect
.top
,
949 AllPlanes
, ZPixmap
);
952 imageDst
= X11DRV_DIB_CreateXImage( rectDst
.right
- rectDst
.left
,
953 rectDst
.bottom
- rectDst
.top
, physDevDst
->depth
);
954 BITBLT_StretchImage( imageSrc
, imageDst
, src
->width
, src
->height
,
955 dst
->width
, dst
->height
, &rectSrc
, &rectDst
,
956 fg
, physDevDst
->depth
!= 1 ? bg
: physDevSrc
->backgroundPixel
,
957 image_pixel_mask( physDevSrc
), GetStretchBltMode(physDevDst
->dev
.hdc
) );
959 XPutImage( gdi_display
, pixmap
, gc
, imageDst
, 0, 0, 0, 0,
960 rectDst
.right
- rectDst
.left
, rectDst
.bottom
- rectDst
.top
);
961 XDestroyImage( imageSrc
);
962 X11DRV_DIB_DestroyXImage( imageDst
);
964 return 0; /* no exposure events generated */
968 /***********************************************************************
971 * Retrieve an area from the source DC, mapping all the
972 * pixels to Windows colors.
974 static int BITBLT_GetSrcArea( X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
,
975 Pixmap pixmap
, GC gc
, RECT
*visRectSrc
)
977 XImage
*imageSrc
, *imageDst
;
980 INT width
= visRectSrc
->right
- visRectSrc
->left
;
981 INT height
= visRectSrc
->bottom
- visRectSrc
->top
;
983 BOOL memdc
= (GetObjectType(physDevSrc
->dev
.hdc
) == OBJ_MEMDC
);
985 if (physDevSrc
->depth
== physDevDst
->depth
)
988 if (!X11DRV_PALETTE_XPixelToPalette
||
989 (physDevDst
->depth
== 1)) /* monochrome -> monochrome */
991 if (physDevDst
->depth
== 1)
993 /* MSDN says if StretchBlt must convert a bitmap from monochrome
994 to color or vice versa, the foreground and background color of
995 the device context are used. In fact, it also applies to the
996 case when it is converted from mono to mono. */
997 XSetBackground( gdi_display
, gc
, physDevDst
->textPixel
);
998 XSetForeground( gdi_display
, gc
, physDevDst
->backgroundPixel
);
999 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
1000 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1001 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1002 width
, height
, 0, 0, 1);
1005 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
1006 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1007 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1008 width
, height
, 0, 0);
1011 else /* color -> color */
1014 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
1015 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1016 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1017 width
, height
, AllPlanes
, ZPixmap
);
1020 /* Make sure we don't get a BadMatch error */
1021 XCopyArea( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
1022 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1023 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1024 width
, height
, 0, 0);
1026 imageSrc
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1027 AllPlanes
, ZPixmap
);
1029 for (y
= 0; y
< height
; y
++)
1030 for (x
= 0; x
< width
; x
++)
1031 XPutPixel(imageSrc
, x
, y
,
1032 X11DRV_PALETTE_XPixelToPalette
[XGetPixel(imageSrc
, x
, y
)]);
1033 XPutImage( gdi_display
, pixmap
, gc
, imageSrc
,
1034 0, 0, 0, 0, width
, height
);
1035 XDestroyImage( imageSrc
);
1037 wine_tsx11_unlock();
1041 if (physDevSrc
->depth
== 1) /* monochrome -> color */
1043 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
1046 if (X11DRV_PALETTE_XPixelToPalette
)
1048 XSetBackground( gdi_display
, gc
,
1049 X11DRV_PALETTE_XPixelToPalette
[fg
] );
1050 XSetForeground( gdi_display
, gc
,
1051 X11DRV_PALETTE_XPixelToPalette
[bg
]);
1055 XSetBackground( gdi_display
, gc
, fg
);
1056 XSetForeground( gdi_display
, gc
, bg
);
1058 XCopyPlane( gdi_display
, physDevSrc
->drawable
, pixmap
, gc
,
1059 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1060 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1061 width
, height
, 0, 0, 1 );
1063 wine_tsx11_unlock();
1065 else /* color -> monochrome */
1067 unsigned long pixel_mask
;
1069 /* FIXME: avoid BadMatch error */
1070 imageSrc
= XGetImage( gdi_display
, physDevSrc
->drawable
,
1071 physDevSrc
->dc_rect
.left
+ visRectSrc
->left
,
1072 physDevSrc
->dc_rect
.top
+ visRectSrc
->top
,
1073 width
, height
, AllPlanes
, ZPixmap
);
1076 wine_tsx11_unlock();
1079 imageDst
= X11DRV_DIB_CreateXImage( width
, height
, physDevDst
->depth
);
1082 XDestroyImage(imageSrc
);
1083 wine_tsx11_unlock();
1086 pixel_mask
= image_pixel_mask( physDevSrc
);
1087 for (y
= 0; y
< height
; y
++)
1088 for (x
= 0; x
< width
; x
++)
1089 XPutPixel(imageDst
, x
, y
,
1090 !((XGetPixel(imageSrc
,x
,y
) ^ physDevSrc
->backgroundPixel
) & pixel_mask
));
1091 XPutImage( gdi_display
, pixmap
, gc
, imageDst
,
1092 0, 0, 0, 0, width
, height
);
1093 XDestroyImage( imageSrc
);
1094 X11DRV_DIB_DestroyXImage( imageDst
);
1095 wine_tsx11_unlock();
1102 /***********************************************************************
1105 * Retrieve an area from the destination DC, mapping all the
1106 * pixels to Windows colors.
1108 static int BITBLT_GetDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, GC gc
, RECT
*visRectDst
)
1111 INT width
= visRectDst
->right
- visRectDst
->left
;
1112 INT height
= visRectDst
->bottom
- visRectDst
->top
;
1113 BOOL memdc
= (GetObjectType( physDev
->dev
.hdc
) == OBJ_MEMDC
);
1117 if (!X11DRV_PALETTE_XPixelToPalette
|| (physDev
->depth
== 1) ||
1118 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
1120 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
1121 physDev
->dc_rect
.left
+ visRectDst
->left
, physDev
->dc_rect
.top
+ visRectDst
->top
,
1122 width
, height
, 0, 0 );
1131 image
= XGetImage( gdi_display
, physDev
->drawable
,
1132 physDev
->dc_rect
.left
+ visRectDst
->left
,
1133 physDev
->dc_rect
.top
+ visRectDst
->top
,
1134 width
, height
, AllPlanes
, ZPixmap
);
1137 /* Make sure we don't get a BadMatch error */
1138 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
1139 physDev
->dc_rect
.left
+ visRectDst
->left
,
1140 physDev
->dc_rect
.top
+ visRectDst
->top
,
1141 width
, height
, 0, 0);
1143 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1144 AllPlanes
, ZPixmap
);
1148 for (y
= 0; y
< height
; y
++)
1149 for (x
= 0; x
< width
; x
++)
1150 XPutPixel( image
, x
, y
,
1151 X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, x
, y
)]);
1152 XPutImage( gdi_display
, pixmap
, gc
, image
, 0, 0, 0, 0, width
, height
);
1153 XDestroyImage( image
);
1157 wine_tsx11_unlock();
1162 /***********************************************************************
1165 * Put an area back into the destination DC, mapping the pixel
1166 * colors to X pixels.
1168 static int BITBLT_PutDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, RECT
*visRectDst
)
1171 INT width
= visRectDst
->right
- visRectDst
->left
;
1172 INT height
= visRectDst
->bottom
- visRectDst
->top
;
1174 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
1176 if (!X11DRV_PALETTE_PaletteToXPixel
|| (physDev
->depth
== 1) ||
1177 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
1179 XCopyArea( gdi_display
, pixmap
, physDev
->drawable
, physDev
->gc
, 0, 0, width
, height
,
1180 physDev
->dc_rect
.left
+ visRectDst
->left
,
1181 physDev
->dc_rect
.top
+ visRectDst
->top
);
1187 XImage
*image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
1188 AllPlanes
, ZPixmap
);
1189 for (y
= 0; y
< height
; y
++)
1190 for (x
= 0; x
< width
; x
++)
1192 XPutPixel( image
, x
, y
,
1193 X11DRV_PALETTE_PaletteToXPixel
[XGetPixel( image
, x
, y
)]);
1195 XPutImage( gdi_display
, physDev
->drawable
, physDev
->gc
, image
, 0, 0,
1196 physDev
->dc_rect
.left
+ visRectDst
->left
,
1197 physDev
->dc_rect
.top
+ visRectDst
->top
, width
, height
);
1198 XDestroyImage( image
);
1204 /***********************************************************************
1205 * client_side_dib_copy
1207 static BOOL
client_side_dib_copy( X11DRV_PDEVICE
*physDevSrc
, INT xSrc
, INT ySrc
,
1208 X11DRV_PDEVICE
*physDevDst
, INT xDst
, INT yDst
,
1209 INT width
, INT height
)
1211 DIBSECTION srcDib
, dstDib
;
1212 BYTE
*srcPtr
, *dstPtr
;
1213 INT srcRowOffset
, dstRowOffset
;
1217 static RECT unusedRect
;
1219 if (GetObjectW(physDevSrc
->bitmap
->hbitmap
, sizeof(srcDib
), &srcDib
) != sizeof(srcDib
))
1221 if (GetObjectW(physDevDst
->bitmap
->hbitmap
, sizeof(dstDib
), &dstDib
) != sizeof(dstDib
))
1224 /* check for oversized values, just like X11DRV_DIB_CopyDIBSection() */
1225 if (xSrc
> srcDib
.dsBm
.bmWidth
|| ySrc
> srcDib
.dsBm
.bmHeight
)
1227 if (xSrc
+ width
> srcDib
.dsBm
.bmWidth
)
1228 width
= srcDib
.dsBm
.bmWidth
- xSrc
;
1229 if (ySrc
+ height
> srcDib
.dsBm
.bmHeight
)
1230 height
= srcDib
.dsBm
.bmHeight
- ySrc
;
1232 if (GetRgnBox(physDevDst
->region
, &unusedRect
) == COMPLEXREGION
)
1234 /* for simple regions, the clipping was already done by BITBLT_GetVisRectangles */
1235 FIXME("potential optimization: client-side complex region clipping\n");
1238 if (dstDib
.dsBm
.bmBitsPixel
<= 8)
1240 static BOOL fixme_once
;
1241 if(!fixme_once
++) FIXME("potential optimization: client-side color-index mode DIB copy\n");
1244 if (!(srcDib
.dsBmih
.biCompression
== BI_BITFIELDS
&&
1245 dstDib
.dsBmih
.biCompression
== BI_BITFIELDS
&&
1246 !memcmp(srcDib
.dsBitfields
, dstDib
.dsBitfields
, 3*sizeof(DWORD
)))
1247 && !(srcDib
.dsBmih
.biCompression
== BI_RGB
&&
1248 dstDib
.dsBmih
.biCompression
== BI_RGB
))
1250 FIXME("potential optimization: client-side compressed DIB copy\n");
1253 if (srcDib
.dsBm
.bmBitsPixel
!= dstDib
.dsBm
.bmBitsPixel
)
1255 FIXME("potential optimization: pixel format conversion\n");
1258 if (srcDib
.dsBmih
.biWidth
< 0 || dstDib
.dsBmih
.biWidth
< 0)
1260 FIXME("negative widths not yet implemented\n");
1264 switch (dstDib
.dsBm
.bmBitsPixel
)
1277 FIXME("don't know how to work with a depth of %d\n", physDevSrc
->depth
);
1281 bytesToCopy
= width
* bytesPerPixel
;
1283 if (physDevSrc
->bitmap
->topdown
)
1285 srcPtr
= &physDevSrc
->bitmap
->base
[ySrc
*srcDib
.dsBm
.bmWidthBytes
+ xSrc
*bytesPerPixel
];
1286 srcRowOffset
= srcDib
.dsBm
.bmWidthBytes
;
1290 srcPtr
= &physDevSrc
->bitmap
->base
[(srcDib
.dsBm
.bmHeight
-ySrc
-1)*srcDib
.dsBm
.bmWidthBytes
1291 + xSrc
*bytesPerPixel
];
1292 srcRowOffset
= -srcDib
.dsBm
.bmWidthBytes
;
1294 if (physDevDst
->bitmap
->topdown
)
1296 dstPtr
= &physDevDst
->bitmap
->base
[yDst
*dstDib
.dsBm
.bmWidthBytes
+ xDst
*bytesPerPixel
];
1297 dstRowOffset
= dstDib
.dsBm
.bmWidthBytes
;
1301 dstPtr
= &physDevDst
->bitmap
->base
[(dstDib
.dsBm
.bmHeight
-yDst
-1)*dstDib
.dsBm
.bmWidthBytes
1302 + xDst
*bytesPerPixel
];
1303 dstRowOffset
= -dstDib
.dsBm
.bmWidthBytes
;
1306 /* Handle overlapping regions on the same DIB */
1307 if (physDevSrc
== physDevDst
&& ySrc
< yDst
)
1309 srcPtr
+= srcRowOffset
* (height
- 1);
1310 srcRowOffset
= -srcRowOffset
;
1311 dstPtr
+= dstRowOffset
* (height
- 1);
1312 dstRowOffset
= -dstRowOffset
;
1315 for (y
= yDst
; y
< yDst
+ height
; ++y
)
1317 memmove(dstPtr
, srcPtr
, bytesToCopy
);
1318 srcPtr
+= srcRowOffset
;
1319 dstPtr
+= dstRowOffset
;
1325 static BOOL
same_format(X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
)
1327 if (physDevSrc
->depth
!= physDevDst
->depth
) return FALSE
;
1328 if (!physDevSrc
->color_shifts
&& !physDevDst
->color_shifts
) return TRUE
;
1329 if (physDevSrc
->color_shifts
&& physDevDst
->color_shifts
)
1330 return !memcmp(physDevSrc
->color_shifts
, physDevDst
->color_shifts
, sizeof(ColorShifts
));
1334 /***********************************************************************
1337 BOOL
X11DRV_PatBlt( PHYSDEV dev
, struct bitblt_coords
*dst
, DWORD rop
)
1339 X11DRV_PDEVICE
*physDev
= get_x11drv_dev( dev
);
1340 BOOL usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
1341 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1343 if (IsRectEmpty( &dst
->visrect
)) return TRUE
;
1344 if (usePat
&& !X11DRV_SetupGCForBrush( physDev
)) return TRUE
;
1346 X11DRV_LockDIBSection( physDev
, DIB_Status_GdiMod
);
1349 XSetFunction( gdi_display
, physDev
->gc
, OP_ROP(*opcode
) );
1351 switch(rop
) /* a few special cases */
1353 case BLACKNESS
: /* 0x00 */
1354 case WHITENESS
: /* 0xff */
1355 if ((physDev
->depth
!= 1) && X11DRV_PALETTE_PaletteToXPixel
)
1357 XSetFunction( gdi_display
, physDev
->gc
, GXcopy
);
1358 if (rop
== BLACKNESS
)
1359 XSetForeground( gdi_display
, physDev
->gc
, X11DRV_PALETTE_PaletteToXPixel
[0] );
1361 XSetForeground( gdi_display
, physDev
->gc
,
1362 WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ));
1363 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
1366 case DSTINVERT
: /* 0x55 */
1367 if (!(X11DRV_PALETTE_PaletteFlags
& (X11DRV_PALETTE_PRIVATE
| X11DRV_PALETTE_VIRTUAL
)))
1369 /* Xor is much better when we do not have full colormap. */
1370 /* Using white^black ensures that we invert at least black */
1372 unsigned long xor_pix
= (WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ) ^
1373 BlackPixel( gdi_display
, DefaultScreen(gdi_display
) ));
1374 XSetFunction( gdi_display
, physDev
->gc
, GXxor
);
1375 XSetForeground( gdi_display
, physDev
->gc
, xor_pix
);
1376 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
1380 XFillRectangle( gdi_display
, physDev
->drawable
, physDev
->gc
,
1381 physDev
->dc_rect
.left
+ dst
->visrect
.left
,
1382 physDev
->dc_rect
.top
+ dst
->visrect
.top
,
1383 dst
->visrect
.right
- dst
->visrect
.left
,
1384 dst
->visrect
.bottom
- dst
->visrect
.top
);
1385 wine_tsx11_unlock();
1387 X11DRV_UnlockDIBSection( physDev
, TRUE
);
1392 /***********************************************************************
1395 BOOL
X11DRV_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
1396 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
1398 X11DRV_PDEVICE
*physDevDst
= get_x11drv_dev( dst_dev
);
1399 X11DRV_PDEVICE
*physDevSrc
= get_x11drv_dev( src_dev
); /* FIXME: check that it's really an x11 dev */
1400 BOOL usePat
, useDst
, destUsed
, fStretch
, fNullBrush
;
1402 INT sDst
, sSrc
= DIB_Status_None
;
1404 Pixmap pixmaps
[3] = { 0, 0, 0 }; /* pixmaps for DST, SRC, TMP */
1407 if (IsRectEmpty( &dst
->visrect
)) return TRUE
;
1409 usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
1410 useDst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
1411 fStretch
= (src
->width
!= dst
->width
) || (src
->height
!= dst
->height
);
1413 if (physDevDst
!= physDevSrc
)
1414 sSrc
= X11DRV_LockDIBSection( physDevSrc
, DIB_Status_None
);
1416 width
= dst
->visrect
.right
- dst
->visrect
.left
;
1417 height
= dst
->visrect
.bottom
- dst
->visrect
.top
;
1419 sDst
= X11DRV_LockDIBSection( physDevDst
, DIB_Status_None
);
1420 if (physDevDst
== physDevSrc
) sSrc
= sDst
;
1422 /* try client-side DIB copy */
1423 if (!fStretch
&& rop
== SRCCOPY
&&
1424 sSrc
== DIB_Status_AppMod
&& sDst
== DIB_Status_AppMod
&&
1425 same_format(physDevSrc
, physDevDst
))
1427 if (client_side_dib_copy( physDevSrc
, src
->visrect
.left
, src
->visrect
.top
,
1428 physDevDst
, dst
->visrect
.left
, dst
->visrect
.top
, width
, height
))
1432 X11DRV_CoerceDIBSection( physDevDst
, DIB_Status_GdiMod
);
1434 opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1436 /* a few optimizations for single-op ROPs */
1437 if (!fStretch
&& !opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
))
1439 if (same_format(physDevSrc
, physDevDst
))
1442 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
1443 wine_tsx11_unlock();
1445 if (physDevSrc
!= physDevDst
)
1447 if (sSrc
== DIB_Status_AppMod
)
1449 X11DRV_DIB_CopyDIBSection( physDevSrc
, physDevDst
, src
->visrect
.left
, src
->visrect
.top
,
1450 dst
->visrect
.left
, dst
->visrect
.top
, width
, height
);
1453 X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
);
1456 XCopyArea( gdi_display
, physDevSrc
->drawable
,
1457 physDevDst
->drawable
, physDevDst
->gc
,
1458 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
1459 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
1461 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
1462 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
);
1463 physDevDst
->exposures
++;
1464 wine_tsx11_unlock();
1467 if (physDevSrc
->depth
== 1)
1471 X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
);
1472 get_colors(physDevDst
, physDevSrc
, &fg
, &bg
);
1474 XSetBackground( gdi_display
, physDevDst
->gc
, fg
);
1475 XSetForeground( gdi_display
, physDevDst
->gc
, bg
);
1476 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
1477 XCopyPlane( gdi_display
, physDevSrc
->drawable
,
1478 physDevDst
->drawable
, physDevDst
->gc
,
1479 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
1480 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
1482 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
1483 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
, 1 );
1484 physDevDst
->exposures
++;
1485 wine_tsx11_unlock();
1491 tmpGC
= XCreateGC( gdi_display
, physDevDst
->drawable
, 0, NULL
);
1492 XSetSubwindowMode( gdi_display
, tmpGC
, IncludeInferiors
);
1493 XSetGraphicsExposures( gdi_display
, tmpGC
, False
);
1494 pixmaps
[DST
] = XCreatePixmap( gdi_display
, root_window
, width
, height
,
1495 physDevDst
->depth
);
1496 pixmaps
[SRC
] = XCreatePixmap( gdi_display
, root_window
, width
, height
,
1497 physDevDst
->depth
);
1498 wine_tsx11_unlock();
1500 if (physDevDst
!= physDevSrc
) X11DRV_CoerceDIBSection( physDevSrc
, DIB_Status_GdiMod
);
1502 if(!X11DRV_XRender_GetSrcAreaStretch( physDevSrc
, physDevDst
, pixmaps
[SRC
], tmpGC
, src
, dst
))
1505 BITBLT_GetSrcAreaStretch( physDevSrc
, physDevDst
, pixmaps
[SRC
], tmpGC
, src
, dst
);
1507 BITBLT_GetSrcArea( physDevSrc
, physDevDst
, pixmaps
[SRC
], tmpGC
, &src
->visrect
);
1510 if (useDst
) BITBLT_GetDstArea( physDevDst
, pixmaps
[DST
], tmpGC
, &dst
->visrect
);
1511 if (usePat
) fNullBrush
= !X11DRV_SetupGCForPatBlt( physDevDst
, tmpGC
, TRUE
);
1512 else fNullBrush
= FALSE
;
1516 for ( ; *opcode
; opcode
++)
1518 if (OP_DST(*opcode
) == DST
) destUsed
= TRUE
;
1519 XSetFunction( gdi_display
, tmpGC
, OP_ROP(*opcode
) );
1520 switch(OP_SRCDST(*opcode
))
1522 case OP_ARGS(DST
,TMP
):
1523 case OP_ARGS(SRC
,TMP
):
1525 pixmaps
[TMP
] = XCreatePixmap( gdi_display
, root_window
,
1526 width
, height
, physDevDst
->depth
);
1528 case OP_ARGS(DST
,SRC
):
1529 case OP_ARGS(SRC
,DST
):
1530 case OP_ARGS(TMP
,SRC
):
1531 case OP_ARGS(TMP
,DST
):
1532 XCopyArea( gdi_display
, pixmaps
[OP_SRC(*opcode
)],
1533 pixmaps
[OP_DST(*opcode
)], tmpGC
,
1534 0, 0, width
, height
, 0, 0 );
1537 case OP_ARGS(PAT
,TMP
):
1538 if (!pixmaps
[TMP
] && !fNullBrush
)
1539 pixmaps
[TMP
] = XCreatePixmap( gdi_display
, root_window
,
1540 width
, height
, physDevDst
->depth
);
1542 case OP_ARGS(PAT
,DST
):
1543 case OP_ARGS(PAT
,SRC
):
1545 XFillRectangle( gdi_display
, pixmaps
[OP_DST(*opcode
)],
1546 tmpGC
, 0, 0, width
, height
);
1550 XSetFunction( gdi_display
, physDevDst
->gc
, GXcopy
);
1551 physDevDst
->exposures
+= BITBLT_PutDstArea( physDevDst
, pixmaps
[destUsed
? DST
: SRC
], &dst
->visrect
);
1552 XFreePixmap( gdi_display
, pixmaps
[DST
] );
1553 if (pixmaps
[SRC
]) XFreePixmap( gdi_display
, pixmaps
[SRC
] );
1554 if (pixmaps
[TMP
]) XFreePixmap( gdi_display
, pixmaps
[TMP
] );
1555 XFreeGC( gdi_display
, tmpGC
);
1556 wine_tsx11_unlock();
1559 if (physDevDst
!= physDevSrc
) X11DRV_UnlockDIBSection( physDevSrc
, FALSE
);
1560 X11DRV_UnlockDIBSection( physDevDst
, TRUE
);
1565 /***********************************************************************
1568 BOOL
X11DRV_AlphaBlend( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
1569 PHYSDEV src_dev
, struct bitblt_coords
*src
, BLENDFUNCTION blendfn
)
1571 X11DRV_PDEVICE
*physDevDst
= get_x11drv_dev( dst_dev
);
1572 X11DRV_PDEVICE
*physDevSrc
= get_x11drv_dev( src_dev
); /* FIXME: check that it's really an x11 dev */
1574 if (src
->x
< 0 || src
->y
< 0 || src
->width
< 0 || src
->height
< 0 ||
1575 src
->width
> physDevSrc
->drawable_rect
.right
- physDevSrc
->drawable_rect
.left
- src
->x
||
1576 src
->height
> physDevSrc
->drawable_rect
.bottom
- physDevSrc
->drawable_rect
.top
- src
->y
)
1578 WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src
->x
, src
->y
, src
->width
, src
->height
);
1579 SetLastError( ERROR_INVALID_PARAMETER
);
1582 if (IsRectEmpty( &dst
->visrect
)) return TRUE
;
1584 return XRender_AlphaBlend( physDevDst
, dst
, physDevSrc
, src
, blendfn
);
1588 static void free_heap_bits( struct gdi_image_bits
*bits
)
1590 HeapFree( GetProcessHeap(), 0, bits
->ptr
);
1593 static void free_ximage_bits( struct gdi_image_bits
*bits
)
1597 wine_tsx11_unlock();
1600 /* store the palette or color mask data in the bitmap info structure */
1601 static void set_color_info( const ColorShifts
*color_shifts
, BITMAPINFO
*info
)
1603 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1605 switch (info
->bmiHeader
.biBitCount
)
1610 info
->bmiHeader
.biCompression
= BI_RGB
;
1611 /* FIXME: set color palette */
1615 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1616 colors
[0] = color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
;
1617 colors
[1] = color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
;
1618 colors
[2] = color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
;
1621 info
->bmiHeader
.biCompression
= BI_RGB
;
1626 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1627 static DWORD
copy_image_bits( BITMAPINFO
*info
, const ColorShifts
*color_shifts
, XImage
*image
,
1628 const struct gdi_image_bits
*src_bits
, struct gdi_image_bits
*dst_bits
)
1631 int x
, y
, height
= -info
->bmiHeader
.biHeight
;
1632 unsigned int width_bytes
= image
->bytes_per_line
;
1633 unsigned char *src
, *dst
;
1635 switch (info
->bmiHeader
.biBitCount
)
1638 need_byteswap
= (image
->bitmap_bit_order
!= MSBFirst
);
1641 need_byteswap
= (image
->byte_order
!= MSBFirst
);
1645 need_byteswap
= (image
->byte_order
!= LSBFirst
);
1648 need_byteswap
= ((image
->byte_order
== LSBFirst
&& color_shifts
->logicalBlue
.shift
== 16) ||
1649 (image
->byte_order
== MSBFirst
&& color_shifts
->logicalBlue
.shift
== 0));
1652 need_byteswap
= FALSE
;
1656 if ((need_byteswap
&& !src_bits
->is_copy
) || (width_bytes
& 3))
1658 width_bytes
= (width_bytes
+ 3) & ~3;
1659 info
->bmiHeader
.biSizeImage
= height
* width_bytes
;
1660 if (!(dst_bits
->ptr
= HeapAlloc( GetProcessHeap(), 0, info
->bmiHeader
.biSizeImage
)))
1661 return ERROR_OUTOFMEMORY
;
1662 dst_bits
->offset
= src_bits
->offset
;
1663 dst_bits
->is_copy
= TRUE
;
1664 dst_bits
->free
= free_heap_bits
;
1668 /* swap bits in place */
1669 dst_bits
->ptr
= src_bits
->ptr
;
1670 dst_bits
->offset
= src_bits
->offset
;
1671 dst_bits
->is_copy
= src_bits
->is_copy
;
1672 dst_bits
->free
= NULL
;
1673 if (!need_byteswap
) return ERROR_SUCCESS
; /* nothing to do */
1676 src
= src_bits
->ptr
;
1677 dst
= dst_bits
->ptr
;
1681 switch (info
->bmiHeader
.biBitCount
)
1684 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1685 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1686 dst
[x
] = bit_swap
[src
[x
]];
1689 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1690 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1691 dst
[x
] = (src
[x
] << 4) | (src
[x
] >> 4);
1694 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1695 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1696 ((USHORT
*)dst
)[x
] = RtlUshortByteSwap( ((const USHORT
*)src
)[x
] );
1699 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1700 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1702 unsigned char tmp
= src
[3 * x
];
1703 dst
[3 * x
] = src
[3 * x
+ 2];
1704 dst
[3 * x
+ 1] = src
[3 * x
+ 1];
1705 dst
[3 * x
+ 2] = tmp
;
1709 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1710 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1711 ((ULONG
*)dst
)[x
] = RtlUlongByteSwap( ((const ULONG
*)src
)[x
] );
1717 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1718 memcpy( dst
, src
, image
->bytes_per_line
);
1720 return ERROR_SUCCESS
;
1723 /***********************************************************************
1726 DWORD
X11DRV_PutImage( PHYSDEV dev
, HBITMAP hbitmap
, BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
1727 const RECT
*rect
, DWORD rop
)
1729 X11DRV_PDEVICE
*physdev
;
1730 X_PHYSBITMAP
*bitmap
;
1731 DWORD ret
= ERROR_SUCCESS
;
1734 struct gdi_image_bits dst_bits
;
1735 const XPixmapFormatValues
*format
;
1736 const ColorShifts
*color_shifts
;
1740 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
1742 depth
= bitmap
->pixmap_depth
;
1743 color_shifts
= &bitmap
->pixmap_color_shifts
;
1747 physdev
= get_x11drv_dev( dev
);
1749 depth
= physdev
->depth
;
1750 color_shifts
= physdev
->color_shifts
;
1752 format
= pixmap_formats
[depth
];
1754 if (info
->bmiHeader
.biPlanes
!= 1) goto update_format
;
1755 if (info
->bmiHeader
.biBitCount
!= format
->bits_per_pixel
) goto update_format
;
1756 if (info
->bmiHeader
.biHeight
> 0) goto update_format
; /* bottom-up not supported */
1758 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1760 DWORD
*masks
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1761 if (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
!= masks
[0] ||
1762 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
!= masks
[1] ||
1763 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
!= masks
[2])
1766 else if (info
->bmiHeader
.biCompression
== BI_RGB
)
1768 switch (info
->bmiHeader
.biBitCount
)
1771 if (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
!= 0x7c00 ||
1772 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
!= 0x03e0 ||
1773 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
!= 0x001f)
1778 if (color_shifts
->logicalRed
.max
<< color_shifts
->logicalRed
.shift
!= 0xff0000 ||
1779 color_shifts
->logicalGreen
.max
<< color_shifts
->logicalGreen
.shift
!= 0x00ff00 ||
1780 color_shifts
->logicalBlue
.max
<< color_shifts
->logicalBlue
.shift
!= 0x0000ff)
1785 else goto update_format
;
1787 if (!bits
) return ret
; /* just querying the format */
1790 image
= XCreateImage( gdi_display
, visual
, depth
, ZPixmap
, 0, NULL
,
1791 info
->bmiHeader
.biWidth
, -info
->bmiHeader
.biHeight
, 32, 0 );
1792 wine_tsx11_unlock();
1793 if (!image
) return ERROR_OUTOFMEMORY
;
1795 ret
= copy_image_bits( info
, color_shifts
, image
, bits
, &dst_bits
);
1799 image
->data
= dst_bits
.ptr
;
1803 XPutImage( gdi_display
, bitmap
->pixmap
, get_bitmap_gc(depth
), image
, dst_bits
.offset
, 0,
1804 rect
->left
, rect
->top
, rect
->right
- rect
->left
, rect
->bottom
- rect
->top
);
1805 wine_tsx11_unlock();
1809 /* FIXME: copy rop handling from BitBlt here */
1810 X11DRV_LockDIBSection( physdev
, DIB_Status_GdiMod
);
1812 XPutImage( gdi_display
, physdev
->drawable
, physdev
->gc
, image
, dst_bits
.offset
, 0,
1813 physdev
->dc_rect
.left
+ rect
->left
, physdev
->dc_rect
.top
+ rect
->top
,
1814 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
);
1815 wine_tsx11_unlock();
1816 X11DRV_UnlockDIBSection( physdev
, !ret
);
1822 XDestroyImage( image
);
1823 wine_tsx11_unlock();
1824 if (dst_bits
.free
) dst_bits
.free( &dst_bits
);
1828 info
->bmiHeader
.biPlanes
= 1;
1829 info
->bmiHeader
.biBitCount
= format
->bits_per_pixel
;
1830 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
1831 set_color_info( physdev
->color_shifts
, info
);
1832 return ERROR_BAD_FORMAT
;
1835 /***********************************************************************
1838 DWORD
X11DRV_GetImage( PHYSDEV dev
, HBITMAP hbitmap
, BITMAPINFO
*info
,
1839 struct gdi_image_bits
*bits
, const RECT
*rect
)
1841 X11DRV_PDEVICE
*physdev
;
1842 X_PHYSBITMAP
*bitmap
;
1843 DWORD ret
= ERROR_SUCCESS
;
1845 UINT align
, x
, y
, width
, height
;
1847 struct gdi_image_bits src_bits
;
1848 const XPixmapFormatValues
*format
;
1849 const ColorShifts
*color_shifts
;
1853 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
1855 depth
= bitmap
->pixmap_depth
;
1856 color_shifts
= &bitmap
->pixmap_color_shifts
;
1860 physdev
= get_x11drv_dev( dev
);
1862 depth
= physdev
->depth
;
1863 color_shifts
= physdev
->color_shifts
;
1865 format
= pixmap_formats
[depth
];
1867 /* align start and width to 32-bit boundary */
1868 switch (format
->bits_per_pixel
)
1870 case 1: align
= 32; break;
1871 case 4: align
= 8; break;
1872 case 8: align
= 4; break;
1873 case 16: align
= 2; break;
1874 case 24: align
= 4; break;
1875 case 32: align
= 1; break;
1877 FIXME( "depth %u bpp %u not supported yet\n", depth
, format
->bits_per_pixel
);
1878 return ERROR_BAD_FORMAT
;
1880 src_bits
.offset
= rect
->left
& (align
- 1);
1881 x
= rect
->left
- src_bits
.offset
;
1883 width
= rect
->right
- x
;
1884 height
= rect
->bottom
- rect
->top
;
1885 if (format
->scanline_pad
!= 32) width
= (width
+ (align
- 1)) & ~(align
- 1);
1890 GetObjectW( hbitmap
, sizeof(bm
), &bm
);
1891 width
= min( width
, bm
.bmWidth
- x
);
1892 height
= min( height
, bm
.bmHeight
- y
);
1894 image
= XGetImage( gdi_display
, bitmap
->pixmap
, x
, y
, width
, height
, AllPlanes
, ZPixmap
);
1895 wine_tsx11_unlock();
1897 else if (GetObjectType( dev
->hdc
) == OBJ_MEMDC
)
1899 X11DRV_LockDIBSection( physdev
, DIB_Status_GdiMod
);
1900 width
= min( width
, physdev
->dc_rect
.right
- physdev
->dc_rect
.left
- x
);
1901 height
= min( height
, physdev
->dc_rect
.bottom
- physdev
->dc_rect
.top
- y
);
1903 image
= XGetImage( gdi_display
, physdev
->drawable
,
1904 physdev
->dc_rect
.left
+ x
, physdev
->dc_rect
.top
+ y
,
1905 width
, height
, AllPlanes
, ZPixmap
);
1906 wine_tsx11_unlock();
1907 X11DRV_UnlockDIBSection( physdev
, FALSE
);
1914 /* use a temporary pixmap to avoid BadMatch errors */
1915 pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, depth
);
1916 XCopyArea( gdi_display
, physdev
->drawable
, pixmap
, get_bitmap_gc(depth
),
1917 physdev
->dc_rect
.left
+ x
, physdev
->dc_rect
.top
+ y
, width
, height
, 0, 0 );
1918 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
, AllPlanes
, ZPixmap
);
1919 XFreePixmap( gdi_display
, pixmap
);
1920 wine_tsx11_unlock();
1922 if (!image
) return ERROR_OUTOFMEMORY
;
1924 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1925 info
->bmiHeader
.biWidth
= width
;
1926 info
->bmiHeader
.biHeight
= -height
;
1927 info
->bmiHeader
.biPlanes
= 1;
1928 info
->bmiHeader
.biBitCount
= image
->bits_per_pixel
;
1929 info
->bmiHeader
.biSizeImage
= height
* image
->bytes_per_line
;
1930 info
->bmiHeader
.biXPelsPerMeter
= 0;
1931 info
->bmiHeader
.biYPelsPerMeter
= 0;
1932 info
->bmiHeader
.biClrUsed
= 0;
1933 info
->bmiHeader
.biClrImportant
= 0;
1934 set_color_info( color_shifts
, info
);
1936 src_bits
.ptr
= image
->data
;
1937 src_bits
.is_copy
= TRUE
;
1938 ret
= copy_image_bits( info
, color_shifts
, image
, &src_bits
, bits
);
1940 if (!ret
&& bits
->ptr
== image
->data
)
1942 bits
->free
= free_ximage_bits
;
1946 XDestroyImage( image
);
1947 wine_tsx11_unlock();