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 static const unsigned char BITBLT_Opcodes
[256][MAX_OP_LEN
] =
57 { OP(PAT
,DST
,GXclear
) }, /* 0x00 0 */
58 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXnor
) }, /* 0x01 ~(D|(P|S)) */
59 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXand
) }, /* 0x02 D&~(P|S) */
60 { OP(PAT
,SRC
,GXnor
) }, /* 0x03 ~(P|S) */
61 { OP(PAT
,DST
,GXnor
), OP(SRC
,DST
,GXand
) }, /* 0x04 S&~(D|P) */
62 { OP(PAT
,DST
,GXnor
) }, /* 0x05 ~(D|P) */
63 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXnor
), }, /* 0x06 ~(P|~(D^S)) */
64 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXnor
) }, /* 0x07 ~(P|(D&S)) */
65 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXand
) },/* 0x08 S&D&~P */
66 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXnor
) }, /* 0x09 ~(P|(D^S)) */
67 { OP(PAT
,DST
,GXandInverted
) }, /* 0x0a D&~P */
68 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXnor
) }, /* 0x0b ~(P|(S&~D)) */
69 { OP(PAT
,SRC
,GXandInverted
) }, /* 0x0c S&~P */
70 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXnor
) },/* 0x0d ~(P|(D&~S)) */
71 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXnor
) }, /* 0x0e ~(P|~(D|S)) */
72 { OP(PAT
,DST
,GXcopyInverted
) }, /* 0x0f ~P */
73 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXand
) }, /* 0x10 P&~(S|D) */
74 { OP(SRC
,DST
,GXnor
) }, /* 0x11 ~(D|S) */
75 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXnor
) }, /* 0x12 ~(S|~(D^P)) */
76 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXnor
) }, /* 0x13 ~(S|(D&P)) */
77 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXnor
) }, /* 0x14 ~(D|~(P^S)) */
78 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXnor
) }, /* 0x15 ~(D|(P&S)) */
79 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnand
),
80 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
),
81 OP(PAT
,DST
,GXxor
) }, /* 0x16 P^S^(D&~(P&S) */
82 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
83 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
84 OP(TMP
,DST
,GXequiv
) }, /* 0x17 ~S^((S^P)&(S^D))*/
85 { OP(PAT
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
86 OP(SRC
,DST
,GXand
) }, /* 0x18 (S^P)&(D^P) */
87 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnand
),
88 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x19 ~S^(D&~(P&S)) */
89 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
),
90 OP(PAT
,DST
,GXxor
) }, /* 0x1a P^(D|(S&P)) */
91 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
92 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x1b ~S^(D&(P^S)) */
93 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
),
94 OP(PAT
,DST
,GXxor
) }, /* 0x1c P^(S|(D&P)) */
95 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
96 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x1d ~D^(S&(D^P)) */
97 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
) }, /* 0x1e P^(D|S) */
98 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXnand
) }, /* 0x1f ~(P&(D|S)) */
99 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXand
) }, /* 0x20 D&(P&~S) */
100 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXnor
) }, /* 0x21 ~(S|(D^P)) */
101 { OP(SRC
,DST
,GXandInverted
) }, /* 0x22 ~S&D */
102 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXnor
) }, /* 0x23 ~(S|(P&~D)) */
103 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
104 OP(SRC
,DST
,GXand
) }, /* 0x24 (S^P)&(S^D) */
105 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXand
),
106 OP(PAT
,DST
,GXequiv
) }, /* 0x25 ~P^(D&~(S&P)) */
107 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
108 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x26 S^(D|(S&P)) */
109 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXequiv
),
110 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x27 S^(D|~(P^S)) */
111 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
) }, /* 0x28 D&(P^S) */
112 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
113 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
),
114 OP(PAT
,DST
,GXequiv
) }, /* 0x29 ~P^S^(D|(P&S)) */
115 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXand
) }, /* 0x2a D&~(P&S) */
116 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
117 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
118 OP(TMP
,DST
,GXequiv
) }, /* 0x2b ~S^((P^S)&(P^D))*/
119 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
),
120 OP(SRC
,DST
,GXxor
) }, /* 0x2c S^(P&(S|D)) */
121 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXxor
) }, /* 0x2d P^(S|~D) */
122 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
),
123 OP(PAT
,DST
,GXxor
) }, /* 0x2e P^(S|(D^P)) */
124 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXnand
) }, /* 0x2f ~(P&(S|~D)) */
125 { OP(PAT
,SRC
,GXandReverse
) }, /* 0x30 P&~S */
126 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXnor
) },/* 0x31 ~(S|(D&~P)) */
127 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXor
),
128 OP(SRC
,DST
,GXxor
) }, /* 0x32 S^(D|P|S) */
129 { OP(SRC
,DST
,GXcopyInverted
) }, /* 0x33 ~S */
130 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
),
131 OP(SRC
,DST
,GXxor
) }, /* 0x34 S^(P|(D&S)) */
132 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXor
),
133 OP(SRC
,DST
,GXxor
) }, /* 0x35 S^(P|~(D^S)) */
134 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x36 S^(D|P) */
135 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXnand
) }, /* 0x37 ~(S&(D|P)) */
136 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
),
137 OP(PAT
,DST
,GXxor
) }, /* 0x38 P^(S&(D|P)) */
138 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x39 S^(P|~D) */
139 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
),
140 OP(SRC
,DST
,GXxor
) }, /* 0x3a S^(P|(D^S)) */
141 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXnand
) }, /* 0x3b ~(S&(P|~D)) */
142 { OP(PAT
,SRC
,GXxor
) }, /* 0x3c P^S */
143 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
),
144 OP(SRC
,DST
,GXxor
) }, /* 0x3d S^(P|~(D|S)) */
145 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
),
146 OP(SRC
,DST
,GXxor
) }, /* 0x3e S^(P|(D&~S)) */
147 { OP(PAT
,SRC
,GXnand
) }, /* 0x3f ~(P&S) */
148 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXand
) }, /* 0x40 P&S&~D */
149 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXnor
) }, /* 0x41 ~(D|(P^S)) */
150 { OP(DST
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
151 OP(SRC
,DST
,GXand
) }, /* 0x42 (S^D)&(P^D) */
152 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
),
153 OP(SRC
,DST
,GXequiv
) }, /* 0x43 ~S^(P&~(D&S)) */
154 { OP(SRC
,DST
,GXandReverse
) }, /* 0x44 S&~D */
155 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXnor
) }, /* 0x45 ~(D|(P&~S)) */
156 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
157 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x46 D^(S|(P&D)) */
158 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
159 OP(PAT
,DST
,GXequiv
) }, /* 0x47 ~P^(S&(D^P)) */
160 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
) }, /* 0x48 S&(P^D) */
161 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
162 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
),
163 OP(PAT
,DST
,GXequiv
) }, /* 0x49 ~P^D^(S|(P&D)) */
164 { OP(DST
,SRC
,GXor
), OP(PAT
,SRC
,GXand
),
165 OP(SRC
,DST
,GXxor
) }, /* 0x4a D^(P&(S|D)) */
166 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXxor
) }, /* 0x4b P^(D|~S) */
167 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXand
) }, /* 0x4c S&~(D&P) */
168 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
169 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
170 OP(TMP
,DST
,GXequiv
) }, /* 0x4d ~S^((S^P)|(S^D))*/
171 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
172 OP(PAT
,DST
,GXxor
) }, /* 0x4e P^(D|(S^P)) */
173 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXnand
) },/* 0x4f ~(P&(D|~S)) */
174 { OP(PAT
,DST
,GXandReverse
) }, /* 0x50 P&~D */
175 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXnor
) },/* 0x51 ~(D|(S&~P)) */
176 { OP(DST
,SRC
,GXand
), OP(PAT
,SRC
,GXor
),
177 OP(SRC
,DST
,GXxor
) }, /* 0x52 D^(P|(S&D)) */
178 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
),
179 OP(SRC
,DST
,GXequiv
) }, /* 0x53 ~S^(P&(D^S)) */
180 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXnor
) }, /* 0x54 ~(D|~(P|S)) */
181 { OP(PAT
,DST
,GXinvert
) }, /* 0x55 ~D */
182 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXxor
) }, /* 0x56 D^(P|S) */
183 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXnand
) }, /* 0x57 ~(D&(P|S)) */
184 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
),
185 OP(PAT
,DST
,GXxor
) }, /* 0x58 P^(D&(P|S)) */
186 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x59 D^(P|~S) */
187 { OP(PAT
,DST
,GXxor
) }, /* 0x5a D^P */
188 { OP(DST
,SRC
,GXnor
), OP(PAT
,SRC
,GXor
),
189 OP(SRC
,DST
,GXxor
) }, /* 0x5b D^(P|~(S|D)) */
190 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXor
),
191 OP(SRC
,DST
,GXxor
) }, /* 0x5c D^(P|(S^D)) */
192 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXnand
) }, /* 0x5d ~(D&(P|~S)) */
193 { OP(DST
,SRC
,GXandInverted
), OP(PAT
,SRC
,GXor
),
194 OP(SRC
,DST
,GXxor
) }, /* 0x5e D^(P|(S&~D)) */
195 { OP(PAT
,DST
,GXnand
) }, /* 0x5f ~(D&P) */
196 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
) }, /* 0x60 P&(D^S) */
197 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXand
),
198 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
199 OP(TMP
,DST
,GXequiv
) }, /* 0x61 ~D^S^(P|(D&S)) */
200 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
201 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x62 D^(S&(P|D)) */
202 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXxor
) }, /* 0x63 S^(D|~P) */
203 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
204 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x64 S^(D&(P|S)) */
205 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXxor
) }, /* 0x65 D^(S|~P) */
206 { OP(SRC
,DST
,GXxor
) }, /* 0x66 S^D */
207 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
208 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x67 S^(D|~(S|P) */
209 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXnor
),
210 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
211 OP(TMP
,DST
,GXequiv
) }, /* 0x68 ~D^S^(P|~(D|S))*/
212 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXequiv
) }, /* 0x69 ~P^(D^S) */
213 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXxor
) }, /* 0x6a D^(P&S) */
214 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
215 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
),
216 OP(PAT
,DST
,GXequiv
) }, /* 0x6b ~P^S^(D&(P|S)) */
217 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
) }, /* 0x6c S^(D&P) */
218 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
219 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
),
220 OP(PAT
,DST
,GXequiv
) }, /* 0x6d ~P^D^(S&(P|D)) */
221 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXorReverse
),
222 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0x6e S^(D&(P|~S)) */
223 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXnand
) }, /* 0x6f ~(P&~(S^D)) */
224 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
) }, /* 0x70 P&~(D&S) */
225 { OP(SRC
,TMP
,GXcopy
), OP(DST
,SRC
,GXxor
),
226 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
227 OP(TMP
,DST
,GXequiv
) }, /* 0x71 ~S^((S^D)&(P^D))*/
228 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
229 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x72 S^(D|(P^S)) */
230 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXnand
) },/* 0x73 ~(S&(D|~P)) */
231 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
232 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x74 D^(S|(P^D)) */
233 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXnand
) },/* 0x75 ~(D&(S|~P)) */
234 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXandReverse
),
235 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXxor
) }, /* 0x76 S^(D|(P&~S)) */
236 { OP(SRC
,DST
,GXnand
) }, /* 0x77 ~(S&D) */
237 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
) }, /* 0x78 P^(D&S) */
238 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXor
),
239 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
240 OP(TMP
,DST
,GXequiv
) }, /* 0x79 ~D^S^(P&(D|S)) */
241 { OP(DST
,SRC
,GXorInverted
), OP(PAT
,SRC
,GXand
),
242 OP(SRC
,DST
,GXxor
) }, /* 0x7a D^(P&(S|~D)) */
243 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXnand
) }, /* 0x7b ~(S&~(D^P)) */
244 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
),
245 OP(SRC
,DST
,GXxor
) }, /* 0x7c S^(P&(D|~S)) */
246 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXnand
) }, /* 0x7d ~(D&~(P^S)) */
247 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
248 OP(SRC
,DST
,GXor
) }, /* 0x7e (S^P)|(S^D) */
249 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXnand
) }, /* 0x7f ~(D&P&S) */
250 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXand
) }, /* 0x80 D&P&S */
251 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
252 OP(SRC
,DST
,GXnor
) }, /* 0x81 ~((S^P)|(S^D)) */
253 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXand
) }, /* 0x82 D&~(P^S) */
254 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
),
255 OP(SRC
,DST
,GXequiv
) }, /* 0x83 ~S^(P&(D|~S)) */
256 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXand
) }, /* 0x84 S&~(D^P) */
257 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXand
),
258 OP(PAT
,DST
,GXequiv
) }, /* 0x85 ~P^(D&(S|~P)) */
259 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXor
),
260 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
261 OP(TMP
,DST
,GXxor
) }, /* 0x86 D^S^(P&(D|S)) */
262 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXequiv
) }, /* 0x87 ~P^(D&S) */
263 { OP(SRC
,DST
,GXand
) }, /* 0x88 S&D */
264 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXandReverse
),
265 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x89 ~S^(D|(P&~S)) */
266 { OP(PAT
,SRC
,GXorInverted
), OP(SRC
,DST
,GXand
) }, /* 0x8a D&(S|~P) */
267 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
268 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x8b ~D^(S|(P^D)) */
269 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXand
) }, /* 0x8c S&(D|~P) */
270 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
271 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x8d ~S^(D|(P^S)) */
272 { OP(SRC
,TMP
,GXcopy
), OP(DST
,SRC
,GXxor
),
273 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
274 OP(TMP
,DST
,GXxor
) }, /* 0x8e S^((S^D)&(P^D))*/
275 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXnand
) }, /* 0x8f ~(P&~(D&S)) */
276 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXand
) }, /* 0x90 P&~(D^S) */
277 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXorReverse
),
278 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x91 ~S^(D&(P|~S)) */
279 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
280 OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
),
281 OP(TMP
,DST
,GXxor
) }, /* 0x92 D^P^(S&(D|P)) */
282 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x93 ~S^(P&D) */
283 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
284 OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXxor
),
285 OP(TMP
,DST
,GXxor
) }, /* 0x94 S^P^(D&(P|S)) */
286 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXequiv
) }, /* 0x95 ~D^(P&S) */
287 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXxor
) }, /* 0x96 D^P^S */
288 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
289 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
290 OP(TMP
,DST
,GXxor
) }, /* 0x97 S^P^(D|~(P|S)) */
291 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnor
),
292 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0x98 ~S^(D|~(P|S)) */
293 { OP(SRC
,DST
,GXequiv
) }, /* 0x99 ~S^D */
294 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x9a D^(P&~S) */
295 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXor
),
296 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x9b ~S^(D&(P|S)) */
297 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXxor
) }, /* 0x9c S^(P&~D) */
298 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXor
),
299 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXequiv
) }, /* 0x9d ~D^(S&(P|D)) */
300 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXand
),
301 OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXxor
),
302 OP(TMP
,DST
,GXxor
) }, /* 0x9e D^S^(P|(D&S)) */
303 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXnand
) }, /* 0x9f ~(P&(D^S)) */
304 { OP(PAT
,DST
,GXand
) }, /* 0xa0 D&P */
305 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXor
),
306 OP(PAT
,DST
,GXequiv
) }, /* 0xa1 ~P^(D|(S&~P)) */
307 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXand
) }, /* 0xa2 D&(P|~S) */
308 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXor
),
309 OP(SRC
,DST
,GXequiv
) }, /* 0xa3 ~D^(P|(S^D)) */
310 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXor
),
311 OP(PAT
,DST
,GXequiv
) }, /* 0xa4 ~P^(D|~(S|P)) */
312 { OP(PAT
,DST
,GXequiv
) }, /* 0xa5 ~P^D */
313 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXxor
) },/* 0xa6 D^(S&~P) */
314 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
),
315 OP(PAT
,DST
,GXequiv
) }, /* 0xa7 ~P^(D&(S|P)) */
316 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXand
) }, /* 0xa8 D&(P|S) */
317 { OP(PAT
,SRC
,GXor
), OP(SRC
,DST
,GXequiv
) }, /* 0xa9 ~D^(P|S) */
318 { OP(PAT
,DST
,GXnoop
) }, /* 0xaa D */
319 { OP(PAT
,SRC
,GXnor
), OP(SRC
,DST
,GXor
) }, /* 0xab D|~(P|S) */
320 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXand
),
321 OP(SRC
,DST
,GXxor
) }, /* 0xac S^(P&(D^S)) */
322 { OP(DST
,SRC
,GXand
), OP(PAT
,SRC
,GXor
),
323 OP(SRC
,DST
,GXequiv
) }, /* 0xad ~D^(P|(S&D)) */
324 { OP(PAT
,SRC
,GXandInverted
), OP(SRC
,DST
,GXor
) }, /* 0xae D|(S&~P) */
325 { OP(PAT
,DST
,GXorInverted
) }, /* 0xaf D|~P */
326 { OP(SRC
,DST
,GXorInverted
), OP(PAT
,DST
,GXand
) }, /* 0xb0 P&(D|~S) */
327 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
328 OP(PAT
,DST
,GXequiv
) }, /* 0xb1 ~P^(D|(S^P)) */
329 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
330 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
),
331 OP(TMP
,DST
,GXxor
) }, /* 0xb2 S^((S^P)|(S^D))*/
332 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXnand
) }, /* 0xb3 ~(S&~(D&P)) */
333 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXxor
) }, /* 0xb4 P^(S&~D) */
334 { OP(DST
,SRC
,GXor
), OP(PAT
,SRC
,GXand
),
335 OP(SRC
,DST
,GXequiv
) }, /* 0xb5 ~D^(P&(S|D)) */
336 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
337 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
338 OP(TMP
,DST
,GXxor
) }, /* 0xb6 D^P^(S|(D&P)) */
339 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXnand
) }, /* 0xb7 ~(S&(D^P)) */
340 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
341 OP(PAT
,DST
,GXxor
) }, /* 0xb8 P^(S&(D^P)) */
342 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXand
),
343 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0xb9 ~D^(S|(P&D)) */
344 { OP(PAT
,SRC
,GXandReverse
), OP(SRC
,DST
,GXor
) }, /* 0xba D|(P&~S) */
345 { OP(SRC
,DST
,GXorInverted
) }, /* 0xbb ~S|D */
346 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXand
),
347 OP(SRC
,DST
,GXxor
) }, /* 0xbc S^(P&~(D&S)) */
348 { OP(DST
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
349 OP(SRC
,DST
,GXnand
) }, /* 0xbd ~((S^D)&(P^D)) */
350 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXor
) }, /* 0xbe D|(P^S) */
351 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXor
) }, /* 0xbf D|~(P&S) */
352 { OP(PAT
,SRC
,GXand
) }, /* 0xc0 P&S */
353 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
),
354 OP(SRC
,DST
,GXequiv
) }, /* 0xc1 ~S^(P|(D&~S)) */
355 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
),
356 OP(SRC
,DST
,GXequiv
) }, /* 0xc2 ~S^(P|~(D|S)) */
357 { OP(PAT
,SRC
,GXequiv
) }, /* 0xc3 ~P^S */
358 { OP(PAT
,DST
,GXorReverse
), OP(SRC
,DST
,GXand
) }, /* 0xc4 S&(P|~D) */
359 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
),
360 OP(SRC
,DST
,GXequiv
) }, /* 0xc5 ~S^(P|(D^S)) */
361 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXxor
) },/* 0xc6 S^(D&~P) */
362 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
),
363 OP(PAT
,DST
,GXequiv
) }, /* 0xc7 ~P^(S&(D|P)) */
364 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXand
) }, /* 0xc8 S&(D|P) */
365 { OP(PAT
,DST
,GXor
), OP(SRC
,DST
,GXequiv
) }, /* 0xc9 ~S^(P|D) */
366 { OP(DST
,SRC
,GXxor
), OP(PAT
,SRC
,GXand
),
367 OP(SRC
,DST
,GXxor
) }, /* 0xca D^(P&(S^D)) */
368 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
),
369 OP(SRC
,DST
,GXequiv
) }, /* 0xcb ~S^(P|(D&S)) */
370 { OP(SRC
,DST
,GXcopy
) }, /* 0xcc S */
371 { OP(PAT
,DST
,GXnor
), OP(SRC
,DST
,GXor
) }, /* 0xcd S|~(D|P) */
372 { OP(PAT
,DST
,GXandInverted
), OP(SRC
,DST
,GXor
) }, /* 0xce S|(D&~P) */
373 { OP(PAT
,SRC
,GXorInverted
) }, /* 0xcf S|~P */
374 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXand
) }, /* 0xd0 P&(S|~D) */
375 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
),
376 OP(PAT
,DST
,GXequiv
) }, /* 0xd1 ~P^(S|(D^P)) */
377 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXxor
) },/* 0xd2 P^(D&~S) */
378 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
),
379 OP(SRC
,DST
,GXequiv
) }, /* 0xd3 ~S^(P&(D|S)) */
380 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
381 OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXand
),
382 OP(TMP
,DST
,GXxor
) }, /* 0xd4 S^((S^P)&(D^P))*/
383 { OP(PAT
,SRC
,GXnand
), OP(SRC
,DST
,GXnand
) }, /* 0xd5 ~(D&~(P&S)) */
384 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
385 OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXxor
),
386 OP(TMP
,DST
,GXxor
) }, /* 0xd6 S^P^(D|(P&S)) */
387 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXnand
) }, /* 0xd7 ~(D&(P^S)) */
388 { OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
389 OP(PAT
,DST
,GXxor
) }, /* 0xd8 P^(D&(S^P)) */
390 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXand
),
391 OP(SRC
,DST
,GXor
), OP(TMP
,DST
,GXequiv
) }, /* 0xd9 ~S^(D|(P&S)) */
392 { OP(DST
,SRC
,GXnand
), OP(PAT
,SRC
,GXand
),
393 OP(SRC
,DST
,GXxor
) }, /* 0xda D^(P&~(S&D)) */
394 { OP(SRC
,DST
,GXxor
), OP(PAT
,SRC
,GXxor
),
395 OP(SRC
,DST
,GXnand
) }, /* 0xdb ~((S^P)&(S^D)) */
396 { OP(PAT
,DST
,GXandReverse
), OP(SRC
,DST
,GXor
) }, /* 0xdc S|(P&~D) */
397 { OP(SRC
,DST
,GXorReverse
) }, /* 0xdd S|~D */
398 { OP(PAT
,DST
,GXxor
), OP(SRC
,DST
,GXor
) }, /* 0xde S|(D^P) */
399 { OP(PAT
,DST
,GXnand
), OP(SRC
,DST
,GXor
) }, /* 0xdf S|~(D&P) */
400 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXand
) }, /* 0xe0 P&(D|S) */
401 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXequiv
) }, /* 0xe1 ~P^(D|S) */
402 { OP(DST
,TMP
,GXcopy
), OP(PAT
,DST
,GXxor
),
403 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe2 D^(S&(P^D)) */
404 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
),
405 OP(PAT
,DST
,GXequiv
) }, /* 0xe3 ~P^(S|(D&P)) */
406 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXxor
),
407 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe4 S^(D&(P^S)) */
408 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
),
409 OP(PAT
,DST
,GXequiv
) }, /* 0xe5 ~P^(D|(S&P)) */
410 { OP(SRC
,TMP
,GXcopy
), OP(PAT
,SRC
,GXnand
),
411 OP(SRC
,DST
,GXand
), OP(TMP
,DST
,GXxor
) }, /* 0xe6 S^(D&~(P&S)) */
412 { OP(PAT
,SRC
,GXxor
), OP(PAT
,DST
,GXxor
),
413 OP(SRC
,DST
,GXnand
) }, /* 0xe7 ~((S^P)&(D^P)) */
414 { OP(SRC
,TMP
,GXcopy
), OP(SRC
,DST
,GXxor
),
415 OP(PAT
,SRC
,GXxor
), OP(SRC
,DST
,GXand
),
416 OP(TMP
,DST
,GXxor
) }, /* 0xe8 S^((S^P)&(S^D))*/
417 { OP(DST
,TMP
,GXcopy
), OP(SRC
,DST
,GXnand
),
418 OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXxor
),
419 OP(TMP
,DST
,GXequiv
) }, /* 0xe9 ~D^S^(P&~(S&D))*/
420 { OP(PAT
,SRC
,GXand
), OP(SRC
,DST
,GXor
) }, /* 0xea D|(P&S) */
421 { OP(PAT
,SRC
,GXequiv
), OP(SRC
,DST
,GXor
) }, /* 0xeb D|~(P^S) */
422 { OP(PAT
,DST
,GXand
), OP(SRC
,DST
,GXor
) }, /* 0xec S|(D&P) */
423 { OP(PAT
,DST
,GXequiv
), OP(SRC
,DST
,GXor
) }, /* 0xed S|~(D^P) */
424 { OP(SRC
,DST
,GXor
) }, /* 0xee S|D */
425 { OP(PAT
,DST
,GXorInverted
), OP(SRC
,DST
,GXor
) }, /* 0xef S|D|~P */
426 { OP(PAT
,DST
,GXcopy
) }, /* 0xf0 P */
427 { OP(SRC
,DST
,GXnor
), OP(PAT
,DST
,GXor
) }, /* 0xf1 P|~(D|S) */
428 { OP(SRC
,DST
,GXandInverted
), OP(PAT
,DST
,GXor
) }, /* 0xf2 P|(D&~S) */
429 { OP(PAT
,SRC
,GXorReverse
) }, /* 0xf3 P|~S */
430 { OP(SRC
,DST
,GXandReverse
), OP(PAT
,DST
,GXor
) }, /* 0xf4 P|(S&~D) */
431 { OP(PAT
,DST
,GXorReverse
) }, /* 0xf5 P|~D */
432 { OP(SRC
,DST
,GXxor
), OP(PAT
,DST
,GXor
) }, /* 0xf6 P|(D^S) */
433 { OP(SRC
,DST
,GXnand
), OP(PAT
,DST
,GXor
) }, /* 0xf7 P|~(S&D) */
434 { OP(SRC
,DST
,GXand
), OP(PAT
,DST
,GXor
) }, /* 0xf8 P|(D&S) */
435 { OP(SRC
,DST
,GXequiv
), OP(PAT
,DST
,GXor
) }, /* 0xf9 P|~(D^S) */
436 { OP(PAT
,DST
,GXor
) }, /* 0xfa D|P */
437 { OP(PAT
,SRC
,GXorReverse
), OP(SRC
,DST
,GXor
) }, /* 0xfb D|P|~S */
438 { OP(PAT
,SRC
,GXor
) }, /* 0xfc P|S */
439 { OP(SRC
,DST
,GXorReverse
), OP(PAT
,DST
,GXor
) }, /* 0xfd P|S|~D */
440 { OP(SRC
,DST
,GXor
), OP(PAT
,DST
,GXor
) }, /* 0xfe P|D|S */
441 { OP(PAT
,DST
,GXset
) } /* 0xff 1 */
444 static const unsigned char bit_swap
[256] =
446 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
447 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
448 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
449 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
450 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
451 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
452 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
453 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
454 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
455 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
456 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
457 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
458 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
459 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
460 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
461 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
462 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
463 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
464 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
465 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
466 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
467 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
468 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
469 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
470 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
471 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
472 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
473 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
474 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
475 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
476 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
477 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
480 #ifdef WORDS_BIGENDIAN
481 static const unsigned int zeropad_masks
[32] =
483 0xffffffff, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
484 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
485 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
486 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe
489 static const unsigned int zeropad_masks
[32] =
491 0xffffffff, 0x00000080, 0x000000c0, 0x000000e0, 0x000000f0, 0x000000f8, 0x000000fc, 0x000000fe,
492 0x000000ff, 0x000080ff, 0x0000c0ff, 0x0000e0ff, 0x0000f0ff, 0x0000f8ff, 0x0000fcff, 0x0000feff,
493 0x0000ffff, 0x0080ffff, 0x00c0ffff, 0x00e0ffff, 0x00f0ffff, 0x00f8ffff, 0x00fcffff, 0x00feffff,
494 0x00ffffff, 0x80ffffff, 0xc0ffffff, 0xe0ffffff, 0xf0ffffff, 0xf8ffffff, 0xfcffffff, 0xfeffffff
498 #ifdef BITBLT_TEST /* Opcodes test */
500 static int do_bitop( int s
, int d
, int rop
)
505 case GXclear
: res
= 0; break;
506 case GXand
: res
= s
& d
; break;
507 case GXandReverse
: res
= s
& ~d
; break;
508 case GXcopy
: res
= s
; break;
509 case GXandInverted
: res
= ~s
& d
; break;
510 case GXnoop
: res
= d
; break;
511 case GXxor
: res
= s
^ d
; break;
512 case GXor
: res
= s
| d
; break;
513 case GXnor
: res
= ~(s
| d
); break;
514 case GXequiv
: res
= ~s
^ d
; break;
515 case GXinvert
: res
= ~d
; break;
516 case GXorReverse
: res
= s
| ~d
; break;
517 case GXcopyInverted
: res
= ~s
; break;
518 case GXorInverted
: res
= ~s
| d
; break;
519 case GXnand
: res
= ~(s
& d
); break;
520 case GXset
: res
= 1; break;
527 int rop
, i
, res
, src
, dst
, pat
, tmp
, dstUsed
;
528 const unsigned char *opcode
;
530 for (rop
= 0; rop
< 256; rop
++)
533 for (i
= 0; i
< 8; i
++)
538 for (opcode
= BITBLT_Opcodes
[rop
]; *opcode
; opcode
++)
542 case OP_ARGS(DST
,TMP
):
543 tmp
= do_bitop( dst
, tmp
, *opcode
& 0xf );
545 case OP_ARGS(DST
,SRC
):
546 src
= do_bitop( dst
, src
, *opcode
& 0xf );
548 case OP_ARGS(SRC
,TMP
):
549 tmp
= do_bitop( src
, tmp
, *opcode
& 0xf );
551 case OP_ARGS(SRC
,DST
):
552 dst
= do_bitop( src
, dst
, *opcode
& 0xf );
555 case OP_ARGS(PAT
,DST
):
556 dst
= do_bitop( pat
, dst
, *opcode
& 0xf );
559 case OP_ARGS(PAT
,SRC
):
560 src
= do_bitop( pat
, src
, *opcode
& 0xf );
562 case OP_ARGS(TMP
,DST
):
563 dst
= do_bitop( tmp
, dst
, *opcode
& 0xf );
566 case OP_ARGS(TMP
,SRC
):
567 src
= do_bitop( tmp
, src
, *opcode
& 0xf );
570 printf( "Invalid opcode %x\n", *opcode
);
573 if (!dstUsed
) dst
= src
;
574 if (dst
) res
|= 1 << i
;
576 if (res
!= rop
) printf( "%02x: ERROR, res=%02x\n", rop
, res
);
582 #endif /* BITBLT_TEST */
585 /* handler for XGetImage BadMatch errors */
586 static int XGetImage_handler( Display
*dpy
, XErrorEvent
*event
, void *arg
)
588 return (event
->request_code
== X_GetImage
&& event
->error_code
== BadMatch
);
591 /***********************************************************************
594 * Retrieve an area from the destination DC, mapping all the
595 * pixels to Windows colors.
597 static int BITBLT_GetDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, GC gc
, const RECT
*visRectDst
)
600 INT width
= visRectDst
->right
- visRectDst
->left
;
601 INT height
= visRectDst
->bottom
- visRectDst
->top
;
602 BOOL memdc
= (GetObjectType( physDev
->dev
.hdc
) == OBJ_MEMDC
);
606 if (!X11DRV_PALETTE_XPixelToPalette
|| (physDev
->depth
== 1) ||
607 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
609 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
610 physDev
->dc_rect
.left
+ visRectDst
->left
, physDev
->dc_rect
.top
+ visRectDst
->top
,
611 width
, height
, 0, 0 );
620 image
= XGetImage( gdi_display
, physDev
->drawable
,
621 physDev
->dc_rect
.left
+ visRectDst
->left
,
622 physDev
->dc_rect
.top
+ visRectDst
->top
,
623 width
, height
, AllPlanes
, ZPixmap
);
626 /* Make sure we don't get a BadMatch error */
627 XCopyArea( gdi_display
, physDev
->drawable
, pixmap
, gc
,
628 physDev
->dc_rect
.left
+ visRectDst
->left
,
629 physDev
->dc_rect
.top
+ visRectDst
->top
,
630 width
, height
, 0, 0);
632 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
633 AllPlanes
, ZPixmap
);
637 for (y
= 0; y
< height
; y
++)
638 for (x
= 0; x
< width
; x
++)
639 XPutPixel( image
, x
, y
,
640 X11DRV_PALETTE_XPixelToPalette
[XGetPixel( image
, x
, y
)]);
641 XPutImage( gdi_display
, pixmap
, gc
, image
, 0, 0, 0, 0, width
, height
);
642 XDestroyImage( image
);
651 /***********************************************************************
654 * Put an area back into the destination DC, mapping the pixel
655 * colors to X pixels.
657 static int BITBLT_PutDstArea(X11DRV_PDEVICE
*physDev
, Pixmap pixmap
, const RECT
*visRectDst
)
660 INT width
= visRectDst
->right
- visRectDst
->left
;
661 INT height
= visRectDst
->bottom
- visRectDst
->top
;
663 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
665 if (!X11DRV_PALETTE_PaletteToXPixel
|| (physDev
->depth
== 1) ||
666 (X11DRV_PALETTE_PaletteFlags
& X11DRV_PALETTE_VIRTUAL
) )
668 XCopyArea( gdi_display
, pixmap
, physDev
->drawable
, physDev
->gc
, 0, 0, width
, height
,
669 physDev
->dc_rect
.left
+ visRectDst
->left
,
670 physDev
->dc_rect
.top
+ visRectDst
->top
);
676 XImage
*image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
,
677 AllPlanes
, ZPixmap
);
678 for (y
= 0; y
< height
; y
++)
679 for (x
= 0; x
< width
; x
++)
681 XPutPixel( image
, x
, y
,
682 X11DRV_PALETTE_PaletteToXPixel
[XGetPixel( image
, x
, y
)]);
684 XPutImage( gdi_display
, physDev
->drawable
, physDev
->gc
, image
, 0, 0,
685 physDev
->dc_rect
.left
+ visRectDst
->left
,
686 physDev
->dc_rect
.top
+ visRectDst
->top
, width
, height
);
687 XDestroyImage( image
);
692 static BOOL
same_format(X11DRV_PDEVICE
*physDevSrc
, X11DRV_PDEVICE
*physDevDst
)
694 if (physDevSrc
->depth
!= physDevDst
->depth
) return FALSE
;
695 if (!physDevSrc
->color_shifts
&& !physDevDst
->color_shifts
) return TRUE
;
696 if (physDevSrc
->color_shifts
&& physDevDst
->color_shifts
)
697 return !memcmp(physDevSrc
->color_shifts
, physDevDst
->color_shifts
, sizeof(ColorShifts
));
701 void execute_rop( X11DRV_PDEVICE
*physdev
, Pixmap src_pixmap
, GC gc
, const RECT
*visrect
, DWORD rop
)
704 Pixmap result
= src_pixmap
;
706 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
707 BOOL use_pat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
708 BOOL use_dst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
709 int width
= visrect
->right
- visrect
->left
;
710 int height
= visrect
->bottom
- visrect
->top
;
712 pixmaps
[SRC
] = src_pixmap
;
715 pixmaps
[DST
] = XCreatePixmap( gdi_display
, root_window
, width
, height
, physdev
->depth
);
718 if (use_dst
) BITBLT_GetDstArea( physdev
, pixmaps
[DST
], gc
, visrect
);
719 null_brush
= use_pat
&& !X11DRV_SetupGCForPatBlt( physdev
, gc
, TRUE
);
722 for ( ; *opcode
; opcode
++)
724 if (OP_DST(*opcode
) == DST
) result
= pixmaps
[DST
];
725 XSetFunction( gdi_display
, gc
, OP_ROP(*opcode
) );
726 switch(OP_SRCDST(*opcode
))
728 case OP_ARGS(DST
,TMP
):
729 case OP_ARGS(SRC
,TMP
):
731 pixmaps
[TMP
] = XCreatePixmap( gdi_display
, root_window
, width
, height
, physdev
->depth
);
733 case OP_ARGS(DST
,SRC
):
734 case OP_ARGS(SRC
,DST
):
735 case OP_ARGS(TMP
,SRC
):
736 case OP_ARGS(TMP
,DST
):
737 XCopyArea( gdi_display
, pixmaps
[OP_SRC(*opcode
)], pixmaps
[OP_DST(*opcode
)], gc
,
738 0, 0, width
, height
, 0, 0 );
740 case OP_ARGS(PAT
,DST
):
741 case OP_ARGS(PAT
,SRC
):
743 XFillRectangle( gdi_display
, pixmaps
[OP_DST(*opcode
)], gc
, 0, 0, width
, height
);
747 XSetFunction( gdi_display
, physdev
->gc
, GXcopy
);
748 physdev
->exposures
+= BITBLT_PutDstArea( physdev
, result
, visrect
);
749 XFreePixmap( gdi_display
, pixmaps
[DST
] );
750 if (pixmaps
[TMP
]) XFreePixmap( gdi_display
, pixmaps
[TMP
] );
752 add_device_bounds( physdev
, visrect
);
755 /***********************************************************************
758 BOOL
X11DRV_PatBlt( PHYSDEV dev
, struct bitblt_coords
*dst
, DWORD rop
)
760 X11DRV_PDEVICE
*physDev
= get_x11drv_dev( dev
);
761 BOOL usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
762 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
764 if (usePat
&& !X11DRV_SetupGCForBrush( physDev
)) return TRUE
;
767 XSetFunction( gdi_display
, physDev
->gc
, OP_ROP(*opcode
) );
769 switch(rop
) /* a few special cases */
771 case BLACKNESS
: /* 0x00 */
772 case WHITENESS
: /* 0xff */
773 if ((physDev
->depth
!= 1) && X11DRV_PALETTE_PaletteToXPixel
)
775 XSetFunction( gdi_display
, physDev
->gc
, GXcopy
);
776 if (rop
== BLACKNESS
)
777 XSetForeground( gdi_display
, physDev
->gc
, X11DRV_PALETTE_PaletteToXPixel
[0] );
779 XSetForeground( gdi_display
, physDev
->gc
,
780 WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ));
781 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
784 case DSTINVERT
: /* 0x55 */
785 if (!(X11DRV_PALETTE_PaletteFlags
& (X11DRV_PALETTE_PRIVATE
| X11DRV_PALETTE_VIRTUAL
)))
787 /* Xor is much better when we do not have full colormap. */
788 /* Using white^black ensures that we invert at least black */
790 unsigned long xor_pix
= (WhitePixel( gdi_display
, DefaultScreen(gdi_display
) ) ^
791 BlackPixel( gdi_display
, DefaultScreen(gdi_display
) ));
792 XSetFunction( gdi_display
, physDev
->gc
, GXxor
);
793 XSetForeground( gdi_display
, physDev
->gc
, xor_pix
);
794 XSetFillStyle( gdi_display
, physDev
->gc
, FillSolid
);
798 XFillRectangle( gdi_display
, physDev
->drawable
, physDev
->gc
,
799 physDev
->dc_rect
.left
+ dst
->visrect
.left
,
800 physDev
->dc_rect
.top
+ dst
->visrect
.top
,
801 dst
->visrect
.right
- dst
->visrect
.left
,
802 dst
->visrect
.bottom
- dst
->visrect
.top
);
804 add_device_bounds( physDev
, &dst
->visrect
);
809 /***********************************************************************
812 BOOL
X11DRV_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
813 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
815 X11DRV_PDEVICE
*physDevDst
= get_x11drv_dev( dst_dev
);
816 X11DRV_PDEVICE
*physDevSrc
= get_x11drv_dev( src_dev
);
822 if (src_dev
->funcs
!= dst_dev
->funcs
||
823 src
->width
!= dst
->width
|| src
->height
!= dst
->height
|| /* no stretching with core X11 */
824 (physDevDst
->depth
== 1 && physDevSrc
->depth
!= 1) || /* color -> mono done by hand */
825 (X11DRV_PALETTE_XPixelToPalette
&& physDevSrc
->depth
!= 1)) /* needs palette mapping */
827 dst_dev
= GET_NEXT_PHYSDEV( dst_dev
, pStretchBlt
);
828 return dst_dev
->funcs
->pStretchBlt( dst_dev
, dst
, src_dev
, src
, rop
);
831 width
= dst
->visrect
.right
- dst
->visrect
.left
;
832 height
= dst
->visrect
.bottom
- dst
->visrect
.top
;
833 opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
835 add_device_bounds( physDevDst
, &dst
->visrect
);
837 /* a few optimizations for single-op ROPs */
838 if (!opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
))
840 if (same_format(physDevSrc
, physDevDst
))
843 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
844 XCopyArea( gdi_display
, physDevSrc
->drawable
,
845 physDevDst
->drawable
, physDevDst
->gc
,
846 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
847 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
849 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
850 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
);
851 physDevDst
->exposures
++;
855 if (physDevSrc
->depth
== 1)
857 int text_pixel
= X11DRV_PALETTE_ToPhysical( physDevDst
, GetTextColor(physDevDst
->dev
.hdc
) );
858 int bkgnd_pixel
= X11DRV_PALETTE_ToPhysical( physDevDst
, GetBkColor(physDevDst
->dev
.hdc
) );
861 XSetBackground( gdi_display
, physDevDst
->gc
, text_pixel
);
862 XSetForeground( gdi_display
, physDevDst
->gc
, bkgnd_pixel
);
863 XSetFunction( gdi_display
, physDevDst
->gc
, OP_ROP(*opcode
) );
864 XCopyPlane( gdi_display
, physDevSrc
->drawable
,
865 physDevDst
->drawable
, physDevDst
->gc
,
866 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
867 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
869 physDevDst
->dc_rect
.left
+ dst
->visrect
.left
,
870 physDevDst
->dc_rect
.top
+ dst
->visrect
.top
, 1 );
871 physDevDst
->exposures
++;
878 gc
= XCreateGC( gdi_display
, physDevDst
->drawable
, 0, NULL
);
879 XSetSubwindowMode( gdi_display
, gc
, IncludeInferiors
);
880 XSetGraphicsExposures( gdi_display
, gc
, False
);
882 /* retrieve the source */
884 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, physDevDst
->depth
);
885 if (physDevSrc
->depth
== 1)
887 /* MSDN says if StretchBlt must convert a bitmap from monochrome
888 to color or vice versa, the foreground and background color of
889 the device context are used. In fact, it also applies to the
890 case when it is converted from mono to mono. */
891 int text_pixel
= X11DRV_PALETTE_ToPhysical( physDevDst
, GetTextColor(physDevDst
->dev
.hdc
) );
892 int bkgnd_pixel
= X11DRV_PALETTE_ToPhysical( physDevDst
, GetBkColor(physDevDst
->dev
.hdc
) );
894 if (X11DRV_PALETTE_XPixelToPalette
&& physDevDst
->depth
!= 1)
896 XSetBackground( gdi_display
, gc
, X11DRV_PALETTE_XPixelToPalette
[text_pixel
] );
897 XSetForeground( gdi_display
, gc
, X11DRV_PALETTE_XPixelToPalette
[bkgnd_pixel
]);
901 XSetBackground( gdi_display
, gc
, text_pixel
);
902 XSetForeground( gdi_display
, gc
, bkgnd_pixel
);
904 XCopyPlane( gdi_display
, physDevSrc
->drawable
, src_pixmap
, gc
,
905 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
906 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
907 width
, height
, 0, 0, 1 );
909 else /* color -> color */
911 XCopyArea( gdi_display
, physDevSrc
->drawable
, src_pixmap
, gc
,
912 physDevSrc
->dc_rect
.left
+ src
->visrect
.left
,
913 physDevSrc
->dc_rect
.top
+ src
->visrect
.top
,
914 width
, height
, 0, 0 );
918 execute_rop( physDevDst
, src_pixmap
, gc
, &dst
->visrect
, rop
);
921 XFreePixmap( gdi_display
, src_pixmap
);
922 XFreeGC( gdi_display
, gc
);
928 static void free_heap_bits( struct gdi_image_bits
*bits
)
930 HeapFree( GetProcessHeap(), 0, bits
->ptr
);
933 static void free_ximage_bits( struct gdi_image_bits
*bits
)
940 /* only for use on sanitized BITMAPINFO structures */
941 static inline int get_dib_info_size( const BITMAPINFO
*info
, UINT coloruse
)
943 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
944 return sizeof(BITMAPINFOHEADER
) + 3 * sizeof(DWORD
);
945 if (coloruse
== DIB_PAL_COLORS
)
946 return sizeof(BITMAPINFOHEADER
) + info
->bmiHeader
.biClrUsed
* sizeof(WORD
);
947 return FIELD_OFFSET( BITMAPINFO
, bmiColors
[info
->bmiHeader
.biClrUsed
] );
950 /* store the palette or color mask data in the bitmap info structure */
951 static void set_color_info( const XVisualInfo
*vis
, BITMAPINFO
*info
)
953 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
955 info
->bmiHeader
.biCompression
= BI_RGB
;
956 info
->bmiHeader
.biClrUsed
= 0;
958 switch (info
->bmiHeader
.biBitCount
)
963 RGBQUAD
*rgb
= (RGBQUAD
*)colors
;
964 PALETTEENTRY palette
[256];
967 info
->bmiHeader
.biClrUsed
= 1 << info
->bmiHeader
.biBitCount
;
968 count
= X11DRV_GetSystemPaletteEntries( NULL
, 0, info
->bmiHeader
.biClrUsed
, palette
);
969 for (i
= 0; i
< count
; i
++)
971 rgb
[i
].rgbRed
= palette
[i
].peRed
;
972 rgb
[i
].rgbGreen
= palette
[i
].peGreen
;
973 rgb
[i
].rgbBlue
= palette
[i
].peBlue
;
974 rgb
[i
].rgbReserved
= 0;
976 memset( &rgb
[count
], 0, (info
->bmiHeader
.biClrUsed
- count
) * sizeof(*rgb
) );
980 colors
[0] = vis
->red_mask
;
981 colors
[1] = vis
->green_mask
;
982 colors
[2] = vis
->blue_mask
;
983 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
986 colors
[0] = vis
->red_mask
;
987 colors
[1] = vis
->green_mask
;
988 colors
[2] = vis
->blue_mask
;
989 if (colors
[0] != 0xff0000 || colors
[1] != 0x00ff00 || colors
[2] != 0x0000ff)
990 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
995 /* check if the specified color info is suitable for PutImage */
996 static BOOL
matching_color_info( const XVisualInfo
*vis
, const BITMAPINFO
*info
)
998 DWORD
*colors
= (DWORD
*)((char *)info
+ info
->bmiHeader
.biSize
);
1000 switch (info
->bmiHeader
.biBitCount
)
1003 if (info
->bmiHeader
.biCompression
!= BI_RGB
) return FALSE
;
1004 return !info
->bmiHeader
.biClrUsed
; /* color map not allowed */
1008 RGBQUAD
*rgb
= (RGBQUAD
*)colors
;
1009 PALETTEENTRY palette
[256];
1012 if (info
->bmiHeader
.biCompression
!= BI_RGB
) return FALSE
;
1013 count
= X11DRV_GetSystemPaletteEntries( NULL
, 0, 1 << info
->bmiHeader
.biBitCount
, palette
);
1014 if (count
!= info
->bmiHeader
.biClrUsed
) return FALSE
;
1015 for (i
= 0; i
< count
; i
++)
1017 if (rgb
[i
].rgbRed
!= palette
[i
].peRed
||
1018 rgb
[i
].rgbGreen
!= palette
[i
].peGreen
||
1019 rgb
[i
].rgbBlue
!= palette
[i
].peBlue
) return FALSE
;
1024 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1025 return (vis
->red_mask
== colors
[0] &&
1026 vis
->green_mask
== colors
[1] &&
1027 vis
->blue_mask
== colors
[2]);
1028 if (info
->bmiHeader
.biCompression
== BI_RGB
)
1029 return (vis
->red_mask
== 0x7c00 && vis
->green_mask
== 0x03e0 && vis
->blue_mask
== 0x001f);
1032 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
1033 return (vis
->red_mask
== colors
[0] &&
1034 vis
->green_mask
== colors
[1] &&
1035 vis
->blue_mask
== colors
[2]);
1038 if (info
->bmiHeader
.biCompression
== BI_RGB
)
1039 return (vis
->red_mask
== 0xff0000 && vis
->green_mask
== 0x00ff00 && vis
->blue_mask
== 0x0000ff);
1045 static inline BOOL
is_r8g8b8( const XVisualInfo
*vis
)
1047 return vis
->depth
== 24 && vis
->red_mask
== 0xff0000 && vis
->blue_mask
== 0x0000ff;
1050 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1051 DWORD
copy_image_bits( BITMAPINFO
*info
, BOOL is_r8g8b8
, XImage
*image
,
1052 const struct gdi_image_bits
*src_bits
, struct gdi_image_bits
*dst_bits
,
1053 struct bitblt_coords
*coords
, const int *mapping
, unsigned int zeropad_mask
)
1055 #ifdef WORDS_BIGENDIAN
1056 static const int client_byte_order
= MSBFirst
;
1058 static const int client_byte_order
= LSBFirst
;
1061 int x
, y
, height
= coords
->visrect
.bottom
- coords
->visrect
.top
;
1062 int width_bytes
= image
->bytes_per_line
;
1064 unsigned char *src
, *dst
;
1066 switch (info
->bmiHeader
.biBitCount
)
1069 need_byteswap
= (image
->bitmap_bit_order
!= MSBFirst
);
1072 need_byteswap
= (image
->byte_order
!= MSBFirst
);
1076 need_byteswap
= (image
->byte_order
!= client_byte_order
);
1079 need_byteswap
= (image
->byte_order
== MSBFirst
) ^ !is_r8g8b8
;
1082 need_byteswap
= FALSE
;
1086 src
= src_bits
->ptr
;
1087 if (info
->bmiHeader
.biHeight
> 0)
1088 src
+= (info
->bmiHeader
.biHeight
- coords
->visrect
.bottom
) * width_bytes
;
1090 src
+= coords
->visrect
.top
* width_bytes
;
1092 if ((need_byteswap
&& !src_bits
->is_copy
) || /* need to swap bytes */
1093 (zeropad_mask
!= ~0u && !src_bits
->is_copy
) || /* need to clear padding bytes */
1094 (mapping
&& !src_bits
->is_copy
) || /* need to remap pixels */
1095 (width_bytes
& 3) || /* need to fixup line alignment */
1096 (info
->bmiHeader
.biHeight
> 0)) /* need to flip vertically */
1098 width_bytes
= (width_bytes
+ 3) & ~3;
1099 info
->bmiHeader
.biSizeImage
= height
* width_bytes
;
1100 if (!(dst_bits
->ptr
= HeapAlloc( GetProcessHeap(), 0, info
->bmiHeader
.biSizeImage
)))
1101 return ERROR_OUTOFMEMORY
;
1102 dst_bits
->is_copy
= TRUE
;
1103 dst_bits
->free
= free_heap_bits
;
1107 /* swap bits in place */
1108 dst_bits
->ptr
= src
;
1109 dst_bits
->is_copy
= src_bits
->is_copy
;
1110 dst_bits
->free
= NULL
;
1111 if (!need_byteswap
&& zeropad_mask
== ~0u && !mapping
) return ERROR_SUCCESS
; /* nothing to do */
1114 dst
= dst_bits
->ptr
;
1115 padding_pos
= width_bytes
/sizeof(unsigned int) - 1;
1117 if (info
->bmiHeader
.biHeight
> 0)
1119 dst
+= (height
- 1) * width_bytes
;
1120 width_bytes
= -width_bytes
;
1123 if (need_byteswap
|| mapping
)
1125 switch (info
->bmiHeader
.biBitCount
)
1128 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1130 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1131 dst
[x
] = bit_swap
[src
[x
]];
1132 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1136 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1139 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1140 dst
[x
] = (mapping
[src
[x
] & 0x0f] << 4) | mapping
[src
[x
] >> 4];
1142 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1143 dst
[x
] = (src
[x
] << 4) | (src
[x
] >> 4);
1144 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1148 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1150 for (x
= 0; x
< image
->bytes_per_line
; x
++)
1151 dst
[x
] = mapping
[src
[x
]];
1152 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1156 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1158 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1159 ((USHORT
*)dst
)[x
] = RtlUshortByteSwap( ((const USHORT
*)src
)[x
] );
1160 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1164 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1166 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1168 unsigned char tmp
= src
[3 * x
];
1169 dst
[3 * x
] = src
[3 * x
+ 2];
1170 dst
[3 * x
+ 1] = src
[3 * x
+ 1];
1171 dst
[3 * x
+ 2] = tmp
;
1173 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1177 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1178 for (x
= 0; x
< info
->bmiHeader
.biWidth
; x
++)
1179 ((ULONG
*)dst
)[x
] = RtlUlongByteSwap( ((const ULONG
*)src
)[x
] );
1183 else if (src
!= dst
)
1185 for (y
= 0; y
< height
; y
++, src
+= image
->bytes_per_line
, dst
+= width_bytes
)
1187 memcpy( dst
, src
, image
->bytes_per_line
);
1188 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1191 else /* only need to clear the padding */
1193 for (y
= 0; y
< height
; y
++, dst
+= width_bytes
)
1194 ((unsigned int *)dst
)[padding_pos
] &= zeropad_mask
;
1196 return ERROR_SUCCESS
;
1199 /***********************************************************************
1202 DWORD
X11DRV_PutImage( PHYSDEV dev
, HBITMAP hbitmap
, HRGN clip
, BITMAPINFO
*info
,
1203 const struct gdi_image_bits
*bits
, struct bitblt_coords
*src
,
1204 struct bitblt_coords
*dst
, DWORD rop
)
1206 X11DRV_PDEVICE
*physdev
;
1207 X_PHYSBITMAP
*bitmap
;
1211 struct gdi_image_bits dst_bits
;
1212 const XPixmapFormatValues
*format
;
1213 const BYTE
*opcode
= BITBLT_Opcodes
[(rop
>> 16) & 0xff];
1214 const int *mapping
= NULL
;
1218 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
1220 vis
.depth
= bitmap
->depth
;
1221 vis
.red_mask
= bitmap
->color_shifts
.logicalRed
.max
<< bitmap
->color_shifts
.logicalRed
.shift
;
1222 vis
.green_mask
= bitmap
->color_shifts
.logicalGreen
.max
<< bitmap
->color_shifts
.logicalGreen
.shift
;
1223 vis
.blue_mask
= bitmap
->color_shifts
.logicalBlue
.max
<< bitmap
->color_shifts
.logicalBlue
.shift
;
1227 physdev
= get_x11drv_dev( dev
);
1229 vis
.depth
= physdev
->depth
;
1230 if (physdev
->color_shifts
)
1232 vis
.red_mask
= physdev
->color_shifts
->logicalRed
.max
<< physdev
->color_shifts
->logicalRed
.shift
;
1233 vis
.green_mask
= physdev
->color_shifts
->logicalGreen
.max
<< physdev
->color_shifts
->logicalGreen
.shift
;
1234 vis
.blue_mask
= physdev
->color_shifts
->logicalBlue
.max
<< physdev
->color_shifts
->logicalBlue
.shift
;
1237 format
= pixmap_formats
[vis
.depth
];
1239 if (info
->bmiHeader
.biPlanes
!= 1) goto update_format
;
1240 if (info
->bmiHeader
.biBitCount
!= format
->bits_per_pixel
) goto update_format
;
1241 /* FIXME: could try to handle 1-bpp using XCopyPlane */
1242 if (!matching_color_info( &vis
, info
)) goto update_format
;
1243 if (!bits
) return ERROR_SUCCESS
; /* just querying the format */
1244 if ((src
->width
!= dst
->width
) || (src
->height
!= dst
->height
)) return ERROR_TRANSFORM_NOT_SUPPORTED
;
1247 image
= XCreateImage( gdi_display
, visual
, vis
.depth
, ZPixmap
, 0, NULL
,
1248 info
->bmiHeader
.biWidth
, src
->visrect
.bottom
- src
->visrect
.top
, 32, 0 );
1249 wine_tsx11_unlock();
1250 if (!image
) return ERROR_OUTOFMEMORY
;
1252 if (image
->bits_per_pixel
== 4 || image
->bits_per_pixel
== 8)
1254 if (bitmap
|| (!opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
)))
1255 mapping
= X11DRV_PALETTE_PaletteToXPixel
;
1258 ret
= copy_image_bits( info
, is_r8g8b8(&vis
), image
, bits
, &dst_bits
, src
, mapping
, ~0u );
1262 int width
= dst
->visrect
.right
- dst
->visrect
.left
;
1263 int height
= dst
->visrect
.bottom
- dst
->visrect
.top
;
1265 image
->data
= dst_bits
.ptr
;
1269 RGNDATA
*clip_data
= NULL
;
1272 if (clip
) clip_data
= X11DRV_GetRegionData( clip
, 0 );
1275 gc
= XCreateGC( gdi_display
, bitmap
->pixmap
, 0, NULL
);
1276 XSetGraphicsExposures( gdi_display
, gc
, False
);
1277 if (clip_data
) XSetClipRectangles( gdi_display
, gc
, 0, 0, (XRectangle
*)clip_data
->Buffer
,
1278 clip_data
->rdh
.nCount
, YXBanded
);
1279 XPutImage( gdi_display
, bitmap
->pixmap
, gc
, image
, src
->visrect
.left
, 0,
1280 dst
->visrect
.left
, dst
->visrect
.top
, width
, height
);
1281 XFreeGC( gdi_display
, gc
);
1282 wine_tsx11_unlock();
1283 HeapFree( GetProcessHeap(), 0, clip_data
);
1287 BOOL restore_region
= add_extra_clipping_region( physdev
, clip
);
1289 /* optimization for single-op ROPs */
1290 if (!opcode
[1] && OP_SRCDST(opcode
[0]) == OP_ARGS(SRC
,DST
))
1293 XSetFunction( gdi_display
, physdev
->gc
, OP_ROP(*opcode
) );
1294 XPutImage( gdi_display
, physdev
->drawable
, physdev
->gc
, image
, src
->visrect
.left
, 0,
1295 physdev
->dc_rect
.left
+ dst
->visrect
.left
,
1296 physdev
->dc_rect
.top
+ dst
->visrect
.top
, width
, height
);
1297 wine_tsx11_unlock();
1305 gc
= XCreateGC( gdi_display
, physdev
->drawable
, 0, NULL
);
1306 XSetSubwindowMode( gdi_display
, gc
, IncludeInferiors
);
1307 XSetGraphicsExposures( gdi_display
, gc
, False
);
1308 src_pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, vis
.depth
);
1309 XPutImage( gdi_display
, src_pixmap
, gc
, image
, src
->visrect
.left
, 0, 0, 0, width
, height
);
1310 wine_tsx11_unlock();
1312 execute_rop( physdev
, src_pixmap
, gc
, &dst
->visrect
, rop
);
1315 XFreePixmap( gdi_display
, src_pixmap
);
1316 XFreeGC( gdi_display
, gc
);
1317 wine_tsx11_unlock();
1320 if (restore_region
) restore_clipping_region( physdev
);
1321 add_device_bounds( physdev
, &dst
->visrect
);
1327 XDestroyImage( image
);
1328 wine_tsx11_unlock();
1329 if (dst_bits
.free
) dst_bits
.free( &dst_bits
);
1333 info
->bmiHeader
.biPlanes
= 1;
1334 info
->bmiHeader
.biBitCount
= format
->bits_per_pixel
;
1335 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
1336 set_color_info( &vis
, info
);
1337 return ERROR_BAD_FORMAT
;
1340 /***********************************************************************
1343 DWORD
X11DRV_GetImage( PHYSDEV dev
, HBITMAP hbitmap
, BITMAPINFO
*info
,
1344 struct gdi_image_bits
*bits
, struct bitblt_coords
*src
)
1346 X11DRV_PDEVICE
*physdev
;
1347 X_PHYSBITMAP
*bitmap
;
1348 DWORD ret
= ERROR_SUCCESS
;
1351 UINT align
, x
, y
, width
, height
;
1352 struct gdi_image_bits src_bits
;
1353 const XPixmapFormatValues
*format
;
1354 const int *mapping
= NULL
;
1358 if (!(bitmap
= X11DRV_get_phys_bitmap( hbitmap
))) return ERROR_INVALID_HANDLE
;
1360 vis
.depth
= bitmap
->depth
;
1361 vis
.red_mask
= bitmap
->color_shifts
.logicalRed
.max
<< bitmap
->color_shifts
.logicalRed
.shift
;
1362 vis
.green_mask
= bitmap
->color_shifts
.logicalGreen
.max
<< bitmap
->color_shifts
.logicalGreen
.shift
;
1363 vis
.blue_mask
= bitmap
->color_shifts
.logicalBlue
.max
<< bitmap
->color_shifts
.logicalBlue
.shift
;
1367 physdev
= get_x11drv_dev( dev
);
1369 vis
.depth
= physdev
->depth
;
1370 if (physdev
->color_shifts
)
1372 vis
.red_mask
= physdev
->color_shifts
->logicalRed
.max
<< physdev
->color_shifts
->logicalRed
.shift
;
1373 vis
.green_mask
= physdev
->color_shifts
->logicalGreen
.max
<< physdev
->color_shifts
->logicalGreen
.shift
;
1374 vis
.blue_mask
= physdev
->color_shifts
->logicalBlue
.max
<< physdev
->color_shifts
->logicalBlue
.shift
;
1377 format
= pixmap_formats
[vis
.depth
];
1379 /* align start and width to 32-bit boundary */
1380 switch (format
->bits_per_pixel
)
1382 case 1: align
= 32; break;
1383 case 4: align
= 8; mapping
= X11DRV_PALETTE_XPixelToPalette
; break;
1384 case 8: align
= 4; mapping
= X11DRV_PALETTE_XPixelToPalette
; break;
1385 case 16: align
= 2; break;
1386 case 24: align
= 4; break;
1387 case 32: align
= 1; break;
1389 FIXME( "depth %u bpp %u not supported yet\n", vis
.depth
, format
->bits_per_pixel
);
1390 return ERROR_BAD_FORMAT
;
1393 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1394 info
->bmiHeader
.biPlanes
= 1;
1395 info
->bmiHeader
.biBitCount
= format
->bits_per_pixel
;
1396 info
->bmiHeader
.biXPelsPerMeter
= 0;
1397 info
->bmiHeader
.biYPelsPerMeter
= 0;
1398 info
->bmiHeader
.biClrImportant
= 0;
1399 set_color_info( &vis
, info
);
1401 if (!bits
) return ERROR_SUCCESS
; /* just querying the color information */
1403 x
= src
->visrect
.left
& ~(align
- 1);
1404 y
= src
->visrect
.top
;
1405 width
= src
->visrect
.right
- x
;
1406 height
= src
->visrect
.bottom
- src
->visrect
.top
;
1407 if (format
->scanline_pad
!= 32) width
= (width
+ (align
- 1)) & ~(align
- 1);
1408 /* make the source rectangle relative to the returned bits */
1411 OffsetRect( &src
->visrect
, -x
, -y
);
1416 GetObjectW( hbitmap
, sizeof(bm
), &bm
);
1417 width
= min( width
, bm
.bmWidth
- x
);
1418 height
= min( height
, bm
.bmHeight
- y
);
1420 image
= XGetImage( gdi_display
, bitmap
->pixmap
, x
, y
, width
, height
, AllPlanes
, ZPixmap
);
1421 wine_tsx11_unlock();
1423 else if (GetObjectType( dev
->hdc
) == OBJ_MEMDC
)
1425 width
= min( width
, physdev
->dc_rect
.right
- physdev
->dc_rect
.left
- x
);
1426 height
= min( height
, physdev
->dc_rect
.bottom
- physdev
->dc_rect
.top
- y
);
1428 image
= XGetImage( gdi_display
, physdev
->drawable
,
1429 physdev
->dc_rect
.left
+ x
, physdev
->dc_rect
.top
+ y
,
1430 width
, height
, AllPlanes
, ZPixmap
);
1431 wine_tsx11_unlock();
1435 X11DRV_expect_error( gdi_display
, XGetImage_handler
, NULL
);
1436 image
= XGetImage( gdi_display
, physdev
->drawable
,
1437 physdev
->dc_rect
.left
+ x
, physdev
->dc_rect
.top
+ y
,
1438 width
, height
, AllPlanes
, ZPixmap
);
1439 if (X11DRV_check_error())
1441 /* use a temporary pixmap to avoid the BadMatch error */
1445 pixmap
= XCreatePixmap( gdi_display
, root_window
, width
, height
, vis
.depth
);
1446 XCopyArea( gdi_display
, physdev
->drawable
, pixmap
, get_bitmap_gc(vis
.depth
),
1447 physdev
->dc_rect
.left
+ x
, physdev
->dc_rect
.top
+ y
, width
, height
, 0, 0 );
1448 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
, AllPlanes
, ZPixmap
);
1449 XFreePixmap( gdi_display
, pixmap
);
1450 wine_tsx11_unlock();
1453 if (!image
) return ERROR_OUTOFMEMORY
;
1455 info
->bmiHeader
.biWidth
= width
;
1456 info
->bmiHeader
.biHeight
= -height
;
1457 info
->bmiHeader
.biSizeImage
= height
* image
->bytes_per_line
;
1459 src_bits
.ptr
= image
->data
;
1460 src_bits
.is_copy
= TRUE
;
1461 ret
= copy_image_bits( info
, is_r8g8b8(&vis
), image
, &src_bits
, bits
, src
, mapping
,
1462 zeropad_masks
[(width
* image
->bits_per_pixel
) & 31] );
1464 if (!ret
&& bits
->ptr
== image
->data
)
1466 bits
->free
= free_ximage_bits
;
1470 XDestroyImage( image
);
1471 wine_tsx11_unlock();
1476 /***********************************************************************
1479 * Simplified equivalent of X11DRV_PutImage that writes directly to a pixmap.
1481 static DWORD
put_pixmap_image( Pixmap pixmap
, const XVisualInfo
*vis
,
1482 BITMAPINFO
*info
, const struct gdi_image_bits
*bits
)
1486 struct bitblt_coords coords
;
1487 struct gdi_image_bits dst_bits
;
1488 const XPixmapFormatValues
*format
= pixmap_formats
[vis
->depth
];
1489 const int *mapping
= NULL
;
1491 if (!format
) return ERROR_INVALID_PARAMETER
;
1492 if (info
->bmiHeader
.biPlanes
!= 1) goto update_format
;
1493 if (info
->bmiHeader
.biBitCount
!= format
->bits_per_pixel
) goto update_format
;
1494 /* FIXME: could try to handle 1-bpp using XCopyPlane */
1495 if (!matching_color_info( vis
, info
)) goto update_format
;
1496 if (!bits
) return ERROR_SUCCESS
; /* just querying the format */
1500 coords
.width
= info
->bmiHeader
.biWidth
;
1501 coords
.height
= abs( info
->bmiHeader
.biHeight
);
1502 SetRect( &coords
.visrect
, 0, 0, coords
.width
, coords
.height
);
1505 image
= XCreateImage( gdi_display
, visual
, vis
->depth
, ZPixmap
, 0, NULL
,
1506 coords
.width
, coords
.height
, 32, 0 );
1507 wine_tsx11_unlock();
1508 if (!image
) return ERROR_OUTOFMEMORY
;
1510 if (image
->bits_per_pixel
== 4 || image
->bits_per_pixel
== 8)
1511 mapping
= X11DRV_PALETTE_PaletteToXPixel
;
1513 if (!(ret
= copy_image_bits( info
, is_r8g8b8(vis
), image
, bits
, &dst_bits
, &coords
, mapping
, ~0u )))
1515 image
->data
= dst_bits
.ptr
;
1517 XPutImage( gdi_display
, pixmap
, get_bitmap_gc( vis
->depth
),
1518 image
, 0, 0, 0, 0, coords
.width
, coords
.height
);
1519 wine_tsx11_unlock();
1524 XDestroyImage( image
);
1525 wine_tsx11_unlock();
1526 if (dst_bits
.free
) dst_bits
.free( &dst_bits
);
1530 info
->bmiHeader
.biPlanes
= 1;
1531 info
->bmiHeader
.biBitCount
= format
->bits_per_pixel
;
1532 if (info
->bmiHeader
.biHeight
> 0) info
->bmiHeader
.biHeight
= -info
->bmiHeader
.biHeight
;
1533 set_color_info( vis
, info
);
1534 return ERROR_BAD_FORMAT
;
1538 /***********************************************************************
1539 * create_pixmap_from_image
1541 Pixmap
create_pixmap_from_image( HDC hdc
, const XVisualInfo
*vis
, const BITMAPINFO
*info
,
1542 const struct gdi_image_bits
*bits
, UINT coloruse
)
1544 static const RGBQUAD default_colortable
[2] = { { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff } };
1545 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1546 char src_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1547 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
1548 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_buffer
;
1549 struct gdi_image_bits dst_bits
;
1555 pixmap
= XCreatePixmap( gdi_display
, root_window
,
1556 info
->bmiHeader
.biWidth
, abs(info
->bmiHeader
.biHeight
), vis
->depth
);
1557 wine_tsx11_unlock();
1558 if (!pixmap
) return 0;
1560 memcpy( src_info
, info
, get_dib_info_size( info
, coloruse
));
1561 memcpy( dst_info
, info
, get_dib_info_size( info
, coloruse
));
1563 if (coloruse
== DIB_PAL_COLORS
||
1564 (err
= put_pixmap_image( pixmap
, vis
, dst_info
, bits
)) == ERROR_BAD_FORMAT
)
1566 if (dst_info
->bmiHeader
.biBitCount
== 1) /* set a default color table for 1-bpp */
1567 memcpy( dst_info
->bmiColors
, default_colortable
, sizeof(default_colortable
) );
1568 dib
= CreateDIBSection( hdc
, dst_info
, coloruse
, &dst_bits
.ptr
, 0, 0 );
1571 if (src_info
->bmiHeader
.biBitCount
== 1 && !src_info
->bmiHeader
.biClrUsed
)
1572 memcpy( src_info
->bmiColors
, default_colortable
, sizeof(default_colortable
) );
1573 SetDIBits( hdc
, dib
, 0, abs(info
->bmiHeader
.biHeight
), bits
->ptr
, src_info
, coloruse
);
1574 dst_bits
.free
= NULL
;
1575 dst_bits
.is_copy
= TRUE
;
1576 err
= put_pixmap_image( pixmap
, vis
, dst_info
, &dst_bits
);
1577 DeleteObject( dib
);
1579 else err
= ERROR_OUTOFMEMORY
;
1582 if (!err
) return pixmap
;
1585 XFreePixmap( gdi_display
, pixmap
);
1586 wine_tsx11_unlock();
1592 /***********************************************************************
1595 * Equivalent of X11DRV_GetImage that reads directly from a pixmap.
1597 DWORD
get_pixmap_image( Pixmap pixmap
, int width
, int height
, const XVisualInfo
*vis
,
1598 BITMAPINFO
*info
, struct gdi_image_bits
*bits
)
1600 DWORD ret
= ERROR_SUCCESS
;
1602 struct gdi_image_bits src_bits
;
1603 struct bitblt_coords coords
;
1604 const XPixmapFormatValues
*format
= pixmap_formats
[vis
->depth
];
1605 const int *mapping
= NULL
;
1607 if (!format
) return ERROR_INVALID_PARAMETER
;
1609 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1610 info
->bmiHeader
.biWidth
= width
;
1611 info
->bmiHeader
.biHeight
= -height
;
1612 info
->bmiHeader
.biPlanes
= 1;
1613 info
->bmiHeader
.biBitCount
= format
->bits_per_pixel
;
1614 info
->bmiHeader
.biXPelsPerMeter
= 0;
1615 info
->bmiHeader
.biYPelsPerMeter
= 0;
1616 info
->bmiHeader
.biClrImportant
= 0;
1617 set_color_info( vis
, info
);
1619 if (!bits
) return ERROR_SUCCESS
; /* just querying the color information */
1623 coords
.width
= width
;
1624 coords
.height
= height
;
1625 SetRect( &coords
.visrect
, 0, 0, width
, height
);
1628 image
= XGetImage( gdi_display
, pixmap
, 0, 0, width
, height
, AllPlanes
, ZPixmap
);
1629 wine_tsx11_unlock();
1630 if (!image
) return ERROR_OUTOFMEMORY
;
1632 info
->bmiHeader
.biSizeImage
= height
* image
->bytes_per_line
;
1634 src_bits
.ptr
= image
->data
;
1635 src_bits
.is_copy
= TRUE
;
1636 ret
= copy_image_bits( info
, is_r8g8b8(vis
), image
, &src_bits
, bits
, &coords
, mapping
,
1637 zeropad_masks
[(width
* image
->bits_per_pixel
) & 31] );
1639 if (!ret
&& bits
->ptr
== image
->data
)
1641 bits
->free
= free_ximage_bits
;
1645 XDestroyImage( image
);
1646 wine_tsx11_unlock();