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
30 #include <X11/Xresource.h>
31 #include <X11/Xutil.h>
33 #include <X11/extensions/shape.h>
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
47 #define DST 0 /* Destination drawable */
48 #define SRC 1 /* Source drawable */
49 #define TMP 2 /* Temporary drawable */
50 #define PAT 3 /* Pattern (brush) in destination DC */
52 #define OP(src,dst,rop) (OP_ARGS(src,dst) << 4 | (rop))
53 #define OP_ARGS(src,dst) (((src) << 2) | (dst))
55 #define OP_SRC(opcode) ((opcode) >> 6)
56 #define OP_DST(opcode) (((opcode) >> 4) & 3)
57 #define OP_SRCDST(opcode) ((opcode) >> 4)
58 #define OP_ROP(opcode) ((opcode) & 0x0f)
60 #define MAX_OP_LEN 6 /* Longest opcode + 1 for the terminating 0 */
62 static const unsigned char BITBLT_Opcodes[256][MAX_OP_LEN] =
64 { OP(PAT,DST,GXclear) }, /* 0x00 0 */
65 { OP(PAT,SRC,GXor), OP(SRC,DST,GXnor) }, /* 0x01 ~(D|(P|S)) */
66 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXand) }, /* 0x02 D&~(P|S) */
67 { OP(PAT,SRC,GXnor) }, /* 0x03 ~(P|S) */
68 { OP(PAT,DST,GXnor), OP(SRC,DST,GXand) }, /* 0x04 S&~(D|P) */
69 { OP(PAT,DST,GXnor) }, /* 0x05 ~(D|P) */
70 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnor), }, /* 0x06 ~(P|~(D^S)) */
71 { OP(SRC,DST,GXand), OP(PAT,DST,GXnor) }, /* 0x07 ~(P|(D&S)) */
72 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXand) },/* 0x08 S&D&~P */
73 { OP(SRC,DST,GXxor), OP(PAT,DST,GXnor) }, /* 0x09 ~(P|(D^S)) */
74 { OP(PAT,DST,GXandInverted) }, /* 0x0a D&~P */
75 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXnor) }, /* 0x0b ~(P|(S&~D)) */
76 { OP(PAT,SRC,GXandInverted) }, /* 0x0c S&~P */
77 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXnor) },/* 0x0d ~(P|(D&~S)) */
78 { OP(SRC,DST,GXnor), OP(PAT,DST,GXnor) }, /* 0x0e ~(P|~(D|S)) */
79 { OP(PAT,DST,GXcopyInverted) }, /* 0x0f ~P */
80 { OP(SRC,DST,GXnor), OP(PAT,DST,GXand) }, /* 0x10 P&~(S|D) */
81 { OP(SRC,DST,GXnor) }, /* 0x11 ~(D|S) */
82 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnor) }, /* 0x12 ~(S|~(D^P)) */
83 { OP(PAT,DST,GXand), OP(SRC,DST,GXnor) }, /* 0x13 ~(S|(D&P)) */
84 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnor) }, /* 0x14 ~(D|~(P^S)) */
85 { OP(PAT,SRC,GXand), OP(SRC,DST,GXnor) }, /* 0x15 ~(D|(P&S)) */
86 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
87 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
88 OP(PAT,DST,GXxor) }, /* 0x16 P^S^(D&~(P&S) */
89 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
90 OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
91 OP(TMP,DST,GXequiv) }, /* 0x17 ~S^((S^P)&(S^D))*/
92 { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
93 OP(SRC,DST,GXand) }, /* 0x18 (S^P)&(D^P) */
94 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
95 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x19 ~S^(D&~(P&S)) */
96 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
97 OP(PAT,DST,GXxor) }, /* 0x1a P^(D|(S&P)) */
98 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
99 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x1b ~S^(D&(P^S)) */
100 { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
101 OP(PAT,DST,GXxor) }, /* 0x1c P^(S|(D&P)) */
102 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
103 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x1d ~D^(S&(D^P)) */
104 { OP(SRC,DST,GXor), OP(PAT,DST,GXxor) }, /* 0x1e P^(D|S) */
105 { OP(SRC,DST,GXor), OP(PAT,DST,GXnand) }, /* 0x1f ~(P&(D|S)) */
106 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXand) }, /* 0x20 D&(P&~S) */
107 { OP(PAT,DST,GXxor), OP(SRC,DST,GXnor) }, /* 0x21 ~(S|(D^P)) */
108 { OP(SRC,DST,GXandInverted) }, /* 0x22 ~S&D */
109 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x23 ~(S|(P&~D)) */
110 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
111 OP(SRC,DST,GXand) }, /* 0x24 (S^P)&(S^D) */
112 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand),
113 OP(PAT,DST,GXequiv) }, /* 0x25 ~P^(D&~(S&P)) */
114 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
115 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x26 S^(D|(S&P)) */
116 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXequiv),
117 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x27 S^(D|~(P^S)) */
118 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand) }, /* 0x28 D&(P^S) */
119 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
120 OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
121 OP(PAT,DST,GXequiv) }, /* 0x29 ~P^S^(D|(P&S)) */
122 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand) }, /* 0x2a D&~(P&S) */
123 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
124 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
125 OP(TMP,DST,GXequiv) }, /* 0x2b ~S^((P^S)&(P^D))*/
126 { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
127 OP(SRC,DST,GXxor) }, /* 0x2c S^(P&(S|D)) */
128 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXxor) }, /* 0x2d P^(S|~D) */
129 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
130 OP(PAT,DST,GXxor) }, /* 0x2e P^(S|(D^P)) */
131 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXnand) }, /* 0x2f ~(P&(S|~D)) */
132 { OP(PAT,SRC,GXandReverse) }, /* 0x30 P&~S */
133 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXnor) },/* 0x31 ~(S|(D&~P)) */
134 { OP(SRC,DST,GXor), OP(PAT,DST,GXor),
135 OP(SRC,DST,GXxor) }, /* 0x32 S^(D|P|S) */
136 { OP(SRC,DST,GXcopyInverted) }, /* 0x33 ~S */
137 { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
138 OP(SRC,DST,GXxor) }, /* 0x34 S^(P|(D&S)) */
139 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor),
140 OP(SRC,DST,GXxor) }, /* 0x35 S^(P|~(D^S)) */
141 { OP(PAT,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x36 S^(D|P) */
142 { OP(PAT,DST,GXor), OP(SRC,DST,GXnand) }, /* 0x37 ~(S&(D|P)) */
143 { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
144 OP(PAT,DST,GXxor) }, /* 0x38 P^(S&(D|P)) */
145 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXxor) }, /* 0x39 S^(P|~D) */
146 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
147 OP(SRC,DST,GXxor) }, /* 0x3a S^(P|(D^S)) */
148 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x3b ~(S&(P|~D)) */
149 { OP(PAT,SRC,GXxor) }, /* 0x3c P^S */
150 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
151 OP(SRC,DST,GXxor) }, /* 0x3d S^(P|~(D|S)) */
152 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
153 OP(SRC,DST,GXxor) }, /* 0x3e S^(P|(D&~S)) */
154 { OP(PAT,SRC,GXnand) }, /* 0x3f ~(P&S) */
155 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXand) }, /* 0x40 P&S&~D */
156 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnor) }, /* 0x41 ~(D|(P^S)) */
157 { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
158 OP(SRC,DST,GXand) }, /* 0x42 (S^D)&(P^D) */
159 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
160 OP(SRC,DST,GXequiv) }, /* 0x43 ~S^(P&~(D&S)) */
161 { OP(SRC,DST,GXandReverse) }, /* 0x44 S&~D */
162 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x45 ~(D|(P&~S)) */
163 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
164 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x46 D^(S|(P&D)) */
165 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
166 OP(PAT,DST,GXequiv) }, /* 0x47 ~P^(S&(D^P)) */
167 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand) }, /* 0x48 S&(P^D) */
168 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
169 OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
170 OP(PAT,DST,GXequiv) }, /* 0x49 ~P^D^(S|(P&D)) */
171 { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
172 OP(SRC,DST,GXxor) }, /* 0x4a D^(P&(S|D)) */
173 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXxor) }, /* 0x4b P^(D|~S) */
174 { OP(PAT,DST,GXnand), OP(SRC,DST,GXand) }, /* 0x4c S&~(D&P) */
175 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
176 OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
177 OP(TMP,DST,GXequiv) }, /* 0x4d ~S^((S^P)|(S^D))*/
178 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
179 OP(PAT,DST,GXxor) }, /* 0x4e P^(D|(S^P)) */
180 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXnand) },/* 0x4f ~(P&(D|~S)) */
181 { OP(PAT,DST,GXandReverse) }, /* 0x50 P&~D */
182 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXnor) },/* 0x51 ~(D|(S&~P)) */
183 { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
184 OP(SRC,DST,GXxor) }, /* 0x52 D^(P|(S&D)) */
185 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
186 OP(SRC,DST,GXequiv) }, /* 0x53 ~S^(P&(D^S)) */
187 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXnor) }, /* 0x54 ~(D|~(P|S)) */
188 { OP(PAT,DST,GXinvert) }, /* 0x55 ~D */
189 { OP(PAT,SRC,GXor), OP(SRC,DST,GXxor) }, /* 0x56 D^(P|S) */
190 { OP(PAT,SRC,GXor), OP(SRC,DST,GXnand) }, /* 0x57 ~(D&(P|S)) */
191 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
192 OP(PAT,DST,GXxor) }, /* 0x58 P^(D&(P|S)) */
193 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXxor) }, /* 0x59 D^(P|~S) */
194 { OP(PAT,DST,GXxor) }, /* 0x5a D^P */
195 { OP(DST,SRC,GXnor), OP(PAT,SRC,GXor),
196 OP(SRC,DST,GXxor) }, /* 0x5b D^(P|~(S|D)) */
197 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
198 OP(SRC,DST,GXxor) }, /* 0x5c D^(P|(S^D)) */
199 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x5d ~(D&(P|~S)) */
200 { OP(DST,SRC,GXandInverted), OP(PAT,SRC,GXor),
201 OP(SRC,DST,GXxor) }, /* 0x5e D^(P|(S&~D)) */
202 { OP(PAT,DST,GXnand) }, /* 0x5f ~(D&P) */
203 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand) }, /* 0x60 P&(D^S) */
204 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
205 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
206 OP(TMP,DST,GXequiv) }, /* 0x61 ~D^S^(P|(D&S)) */
207 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
208 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x62 D^(S&(P|D)) */
209 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x63 S^(D|~P) */
210 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
211 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x64 S^(D&(P|S)) */
212 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x65 D^(S|~P) */
213 { OP(SRC,DST,GXxor) }, /* 0x66 S^D */
214 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
215 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x67 S^(D|~(S|P) */
216 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnor),
217 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
218 OP(TMP,DST,GXequiv) }, /* 0x68 ~D^S^(P|~(D|S))*/
219 { OP(SRC,DST,GXxor), OP(PAT,DST,GXequiv) }, /* 0x69 ~P^(D^S) */
220 { OP(PAT,SRC,GXand), OP(SRC,DST,GXxor) }, /* 0x6a D^(P&S) */
221 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
222 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
223 OP(PAT,DST,GXequiv) }, /* 0x6b ~P^S^(D&(P|S)) */
224 { OP(PAT,DST,GXand), OP(SRC,DST,GXxor) }, /* 0x6c S^(D&P) */
225 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
226 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
227 OP(PAT,DST,GXequiv) }, /* 0x6d ~P^D^(S&(P|D)) */
228 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
229 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x6e S^(D&(P|~S)) */
230 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnand) }, /* 0x6f ~(P&~(S^D)) */
231 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand) }, /* 0x70 P&~(D&S) */
232 { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
233 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
234 OP(TMP,DST,GXequiv) }, /* 0x71 ~S^((S^D)&(P^D))*/
235 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
236 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x72 S^(D|(P^S)) */
237 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXnand) },/* 0x73 ~(S&(D|~P)) */
238 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
239 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x74 D^(S|(P^D)) */
240 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXnand) },/* 0x75 ~(D&(S|~P)) */
241 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
242 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x76 S^(D|(P&~S)) */
243 { OP(SRC,DST,GXnand) }, /* 0x77 ~(S&D) */
244 { OP(SRC,DST,GXand), OP(PAT,DST,GXxor) }, /* 0x78 P^(D&S) */
245 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
246 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
247 OP(TMP,DST,GXequiv) }, /* 0x79 ~D^S^(P&(D|S)) */
248 { OP(DST,SRC,GXorInverted), OP(PAT,SRC,GXand),
249 OP(SRC,DST,GXxor) }, /* 0x7a D^(P&(S|~D)) */
250 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnand) }, /* 0x7b ~(S&~(D^P)) */
251 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
252 OP(SRC,DST,GXxor) }, /* 0x7c S^(P&(D|~S)) */
253 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnand) }, /* 0x7d ~(D&~(P^S)) */
254 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
255 OP(SRC,DST,GXor) }, /* 0x7e (S^P)|(S^D) */
256 { OP(PAT,SRC,GXand), OP(SRC,DST,GXnand) }, /* 0x7f ~(D&P&S) */
257 { OP(PAT,SRC,GXand), OP(SRC,DST,GXand) }, /* 0x80 D&P&S */
258 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
259 OP(SRC,DST,GXnor) }, /* 0x81 ~((S^P)|(S^D)) */
260 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXand) }, /* 0x82 D&~(P^S) */
261 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
262 OP(SRC,DST,GXequiv) }, /* 0x83 ~S^(P&(D|~S)) */
263 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXand) }, /* 0x84 S&~(D^P) */
264 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand),
265 OP(PAT,DST,GXequiv) }, /* 0x85 ~P^(D&(S|~P)) */
266 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
267 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
268 OP(TMP,DST,GXxor) }, /* 0x86 D^S^(P&(D|S)) */
269 { OP(SRC,DST,GXand), OP(PAT,DST,GXequiv) }, /* 0x87 ~P^(D&S) */
270 { OP(SRC,DST,GXand) }, /* 0x88 S&D */
271 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
272 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x89 ~S^(D|(P&~S)) */
273 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8a D&(S|~P) */
274 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
275 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x8b ~D^(S|(P^D)) */
276 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8c S&(D|~P) */
277 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
278 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x8d ~S^(D|(P^S)) */
279 { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
280 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
281 OP(TMP,DST,GXxor) }, /* 0x8e S^((S^D)&(P^D))*/
282 { OP(SRC,DST,GXnand), OP(PAT,DST,GXnand) }, /* 0x8f ~(P&~(D&S)) */
283 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXand) }, /* 0x90 P&~(D^S) */
284 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
285 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x91 ~S^(D&(P|~S)) */
286 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
287 OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
288 OP(TMP,DST,GXxor) }, /* 0x92 D^P^(S&(D|P)) */
289 { OP(PAT,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x93 ~S^(P&D) */
290 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
291 OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
292 OP(TMP,DST,GXxor) }, /* 0x94 S^P^(D&(P|S)) */
293 { OP(PAT,SRC,GXand), OP(SRC,DST,GXequiv) }, /* 0x95 ~D^(P&S) */
294 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXxor) }, /* 0x96 D^P^S */
295 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
296 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
297 OP(TMP,DST,GXxor) }, /* 0x97 S^P^(D|~(P|S)) */
298 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
299 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x98 ~S^(D|~(P|S)) */
300 { OP(SRC,DST,GXequiv) }, /* 0x99 ~S^D */
301 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9a D^(P&~S) */
302 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
303 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x9b ~S^(D&(P|S)) */
304 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9c S^(P&~D) */
305 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
306 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x9d ~D^(S&(P|D)) */
307 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
308 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
309 OP(TMP,DST,GXxor) }, /* 0x9e D^S^(P|(D&S)) */
310 { OP(SRC,DST,GXxor), OP(PAT,DST,GXnand) }, /* 0x9f ~(P&(D^S)) */
311 { OP(PAT,DST,GXand) }, /* 0xa0 D&P */
312 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor),
313 OP(PAT,DST,GXequiv) }, /* 0xa1 ~P^(D|(S&~P)) */
314 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXand) }, /* 0xa2 D&(P|~S) */
315 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
316 OP(SRC,DST,GXequiv) }, /* 0xa3 ~D^(P|(S^D)) */
317 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor),
318 OP(PAT,DST,GXequiv) }, /* 0xa4 ~P^(D|~(S|P)) */
319 { OP(PAT,DST,GXequiv) }, /* 0xa5 ~P^D */
320 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXxor) },/* 0xa6 D^(S&~P) */
321 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
322 OP(PAT,DST,GXequiv) }, /* 0xa7 ~P^(D&(S|P)) */
323 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand) }, /* 0xa8 D&(P|S) */
324 { OP(PAT,SRC,GXor), OP(SRC,DST,GXequiv) }, /* 0xa9 ~D^(P|S) */
325 { OP(PAT,DST,GXnoop) }, /* 0xaa D */
326 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor) }, /* 0xab D|~(P|S) */
327 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
328 OP(SRC,DST,GXxor) }, /* 0xac S^(P&(D^S)) */
329 { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
330 OP(SRC,DST,GXequiv) }, /* 0xad ~D^(P|(S&D)) */
331 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor) }, /* 0xae D|(S&~P) */
332 { OP(PAT,DST,GXorInverted) }, /* 0xaf D|~P */
333 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand) }, /* 0xb0 P&(D|~S) */
334 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
335 OP(PAT,DST,GXequiv) }, /* 0xb1 ~P^(D|(S^P)) */
336 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
337 OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
338 OP(TMP,DST,GXxor) }, /* 0xb2 S^((S^P)|(S^D))*/
339 { OP(PAT,DST,GXnand), OP(SRC,DST,GXnand) }, /* 0xb3 ~(S&~(D&P)) */
340 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXxor) }, /* 0xb4 P^(S&~D) */
341 { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
342 OP(SRC,DST,GXequiv) }, /* 0xb5 ~D^(P&(S|D)) */
343 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
344 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
345 OP(TMP,DST,GXxor) }, /* 0xb6 D^P^(S|(D&P)) */
346 { OP(PAT,DST,GXxor), OP(SRC,DST,GXnand) }, /* 0xb7 ~(S&(D^P)) */
347 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
348 OP(PAT,DST,GXxor) }, /* 0xb8 P^(S&(D^P)) */
349 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
350 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0xb9 ~D^(S|(P&D)) */
351 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXor) }, /* 0xba D|(P&~S) */
352 { OP(SRC,DST,GXorInverted) }, /* 0xbb ~S|D */
353 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
354 OP(SRC,DST,GXxor) }, /* 0xbc S^(P&~(D&S)) */
355 { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
356 OP(SRC,DST,GXnand) }, /* 0xbd ~((S^D)&(P^D)) */
357 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor) }, /* 0xbe D|(P^S) */
358 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXor) }, /* 0xbf D|~(P&S) */
359 { OP(PAT,SRC,GXand) }, /* 0xc0 P&S */
360 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
361 OP(SRC,DST,GXequiv) }, /* 0xc1 ~S^(P|(D&~S)) */
362 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
363 OP(SRC,DST,GXequiv) }, /* 0xc2 ~S^(P|~(D|S)) */
364 { OP(PAT,SRC,GXequiv) }, /* 0xc3 ~P^S */
365 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXand) }, /* 0xc4 S&(P|~D) */
366 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
367 OP(SRC,DST,GXequiv) }, /* 0xc5 ~S^(P|(D^S)) */
368 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXxor) },/* 0xc6 S^(D&~P) */
369 { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
370 OP(PAT,DST,GXequiv) }, /* 0xc7 ~P^(S&(D|P)) */
371 { OP(PAT,DST,GXor), OP(SRC,DST,GXand) }, /* 0xc8 S&(D|P) */
372 { OP(PAT,DST,GXor), OP(SRC,DST,GXequiv) }, /* 0xc9 ~S^(P|D) */
373 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXand),
374 OP(SRC,DST,GXxor) }, /* 0xca D^(P&(S^D)) */
375 { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
376 OP(SRC,DST,GXequiv) }, /* 0xcb ~S^(P|(D&S)) */
377 { OP(SRC,DST,GXcopy) }, /* 0xcc S */
378 { OP(PAT,DST,GXnor), OP(SRC,DST,GXor) }, /* 0xcd S|~(D|P) */
379 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXor) }, /* 0xce S|(D&~P) */
380 { OP(PAT,SRC,GXorInverted) }, /* 0xcf S|~P */
381 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXand) }, /* 0xd0 P&(S|~D) */
382 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
383 OP(PAT,DST,GXequiv) }, /* 0xd1 ~P^(S|(D^P)) */
384 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXxor) },/* 0xd2 P^(D&~S) */
385 { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
386 OP(SRC,DST,GXequiv) }, /* 0xd3 ~S^(P&(D|S)) */
387 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
388 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
389 OP(TMP,DST,GXxor) }, /* 0xd4 S^((S^P)&(D^P))*/
390 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXnand) }, /* 0xd5 ~(D&~(P&S)) */
391 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
392 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
393 OP(TMP,DST,GXxor) }, /* 0xd6 S^P^(D|(P&S)) */
394 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnand) }, /* 0xd7 ~(D&(P^S)) */
395 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
396 OP(PAT,DST,GXxor) }, /* 0xd8 P^(D&(S^P)) */
397 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
398 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0xd9 ~S^(D|(P&S)) */
399 { OP(DST,SRC,GXnand), OP(PAT,SRC,GXand),
400 OP(SRC,DST,GXxor) }, /* 0xda D^(P&~(S&D)) */
401 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
402 OP(SRC,DST,GXnand) }, /* 0xdb ~((S^P)&(S^D)) */
403 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXor) }, /* 0xdc S|(P&~D) */
404 { OP(SRC,DST,GXorReverse) }, /* 0xdd S|~D */
405 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor) }, /* 0xde S|(D^P) */
406 { OP(PAT,DST,GXnand), OP(SRC,DST,GXor) }, /* 0xdf S|~(D&P) */
407 { OP(SRC,DST,GXor), OP(PAT,DST,GXand) }, /* 0xe0 P&(D|S) */
408 { OP(SRC,DST,GXor), OP(PAT,DST,GXequiv) }, /* 0xe1 ~P^(D|S) */
409 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
410 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe2 D^(S&(P^D)) */
411 { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
412 OP(PAT,DST,GXequiv) }, /* 0xe3 ~P^(S|(D&P)) */
413 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
414 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe4 S^(D&(P^S)) */
415 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
416 OP(PAT,DST,GXequiv) }, /* 0xe5 ~P^(D|(S&P)) */
417 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
418 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe6 S^(D&~(P&S)) */
419 { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
420 OP(SRC,DST,GXnand) }, /* 0xe7 ~((S^P)&(D^P)) */
421 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
422 OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
423 OP(TMP,DST,GXxor) }, /* 0xe8 S^((S^P)&(S^D))*/
424 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnand),
425 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
426 OP(TMP,DST,GXequiv) }, /* 0xe9 ~D^S^(P&~(S&D))*/
427 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor) }, /* 0xea D|(P&S) */
428 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXor) }, /* 0xeb D|~(P^S) */
429 { OP(PAT,DST,GXand), OP(SRC,DST,GXor) }, /* 0xec S|(D&P) */
430 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXor) }, /* 0xed S|~(D^P) */
431 { OP(SRC,DST,GXor) }, /* 0xee S|D */
432 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXor) }, /* 0xef S|D|~P */
433 { OP(PAT,DST,GXcopy) }, /* 0xf0 P */
434 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor) }, /* 0xf1 P|~(D|S) */
435 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor) }, /* 0xf2 P|(D&~S) */
436 { OP(PAT,SRC,GXorReverse) }, /* 0xf3 P|~S */
437 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXor) }, /* 0xf4 P|(S&~D) */
438 { OP(PAT,DST,GXorReverse) }, /* 0xf5 P|~D */
439 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor) }, /* 0xf6 P|(D^S) */
440 { OP(SRC,DST,GXnand), OP(PAT,DST,GXor) }, /* 0xf7 P|~(S&D) */
441 { OP(SRC,DST,GXand), OP(PAT,DST,GXor) }, /* 0xf8 P|(D&S) */
442 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor) }, /* 0xf9 P|~(D^S) */
443 { OP(PAT,DST,GXor) }, /* 0xfa D|P */
444 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXor) }, /* 0xfb D|P|~S */
445 { OP(PAT,SRC,GXor) }, /* 0xfc P|S */
446 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXor) }, /* 0xfd P|S|~D */
447 { OP(SRC,DST,GXor), OP(PAT,DST,GXor) }, /* 0xfe P|D|S */
448 { OP(PAT,DST,GXset) } /* 0xff 1 */
451 static const unsigned char bit_swap[256] =
453 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
454 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
455 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
456 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
457 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
458 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
459 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
460 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
461 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
462 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
463 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
464 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
465 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
466 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
467 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
468 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
469 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
470 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
471 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
472 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
473 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
474 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
475 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
476 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
477 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
478 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
479 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
480 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
481 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
482 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
483 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
484 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
487 #ifdef WORDS_BIGENDIAN
488 static const unsigned int zeropad_masks[32] =
490 0xffffffff, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
491 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
492 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
493 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe
496 static const unsigned int zeropad_masks[32] =
498 0xffffffff, 0x00000080, 0x000000c0, 0x000000e0, 0x000000f0, 0x000000f8, 0x000000fc, 0x000000fe,
499 0x000000ff, 0x000080ff, 0x0000c0ff, 0x0000e0ff, 0x0000f0ff, 0x0000f8ff, 0x0000fcff, 0x0000feff,
500 0x0000ffff, 0x0080ffff, 0x00c0ffff, 0x00e0ffff, 0x00f0ffff, 0x00f8ffff, 0x00fcffff, 0x00feffff,
501 0x00ffffff, 0x80ffffff, 0xc0ffffff, 0xe0ffffff, 0xf0ffffff, 0xf8ffffff, 0xfcffffff, 0xfeffffff
505 #ifdef BITBLT_TEST /* Opcodes test */
507 static int do_bitop( int s, int d, int rop )
512 case GXclear: res = 0; break;
513 case GXand: res = s & d; break;
514 case GXandReverse: res = s & ~d; break;
515 case GXcopy: res = s; break;
516 case GXandInverted: res = ~s & d; break;
517 case GXnoop: res = d; break;
518 case GXxor: res = s ^ d; break;
519 case GXor: res = s | d; break;
520 case GXnor: res = ~(s | d); break;
521 case GXequiv: res = ~s ^ d; break;
522 case GXinvert: res = ~d; break;
523 case GXorReverse: res = s | ~d; break;
524 case GXcopyInverted: res = ~s; break;
525 case GXorInverted: res = ~s | d; break;
526 case GXnand: res = ~(s & d); break;
527 case GXset: res = 1; break;
534 int rop, i, res, src, dst, pat, tmp, dstUsed;
535 const unsigned char *opcode;
537 for (rop = 0; rop < 256; rop++)
540 for (i = 0; i < 8; i++)
545 for (opcode = BITBLT_Opcodes[rop]; *opcode; opcode++)
549 case OP_ARGS(DST,TMP):
550 tmp = do_bitop( dst, tmp, *opcode & 0xf );
552 case OP_ARGS(DST,SRC):
553 src = do_bitop( dst, src, *opcode & 0xf );
555 case OP_ARGS(SRC,TMP):
556 tmp = do_bitop( src, tmp, *opcode & 0xf );
558 case OP_ARGS(SRC,DST):
559 dst = do_bitop( src, dst, *opcode & 0xf );
562 case OP_ARGS(PAT,DST):
563 dst = do_bitop( pat, dst, *opcode & 0xf );
566 case OP_ARGS(PAT,SRC):
567 src = do_bitop( pat, src, *opcode & 0xf );
569 case OP_ARGS(TMP,DST):
570 dst = do_bitop( tmp, dst, *opcode & 0xf );
573 case OP_ARGS(TMP,SRC):
574 src = do_bitop( tmp, src, *opcode & 0xf );
577 printf( "Invalid opcode %x\n", *opcode );
580 if (!dstUsed) dst = src;
581 if (dst) res |= 1 << i;
583 if (res != rop) printf( "%02x: ERROR, res=%02x\n", rop, res );
589 #endif /* BITBLT_TEST */
592 /* handler for XGetImage BadMatch errors */
593 static int XGetImage_handler( Display *dpy, XErrorEvent *event, void *arg )
595 return (event->request_code == X_GetImage && event->error_code == BadMatch);
598 /***********************************************************************
601 * Retrieve an area from the destination DC, mapping all the
602 * pixels to Windows colors.
604 static int BITBLT_GetDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, GC gc, const RECT *visRectDst)
607 INT width = visRectDst->right - visRectDst->left;
608 INT height = visRectDst->bottom - visRectDst->top;
610 if (!X11DRV_PALETTE_XPixelToPalette || (physDev->depth == 1) ||
611 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
613 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
614 physDev->dc_rect.left + visRectDst->left, physDev->dc_rect.top + visRectDst->top,
615 width, height, 0, 0 );
623 /* Make sure we don't get a BadMatch error */
624 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
625 physDev->dc_rect.left + visRectDst->left,
626 physDev->dc_rect.top + visRectDst->top,
627 width, height, 0, 0);
629 image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
630 AllPlanes, ZPixmap );
633 for (y = 0; y < height; y++)
634 for (x = 0; x < width; x++)
635 XPutPixel( image, x, y,
636 X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]);
637 XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height );
638 XDestroyImage( image );
645 /***********************************************************************
648 * Put an area back into the destination DC, mapping the pixel
649 * colors to X pixels.
651 static int BITBLT_PutDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, const RECT *visRectDst)
654 INT width = visRectDst->right - visRectDst->left;
655 INT height = visRectDst->bottom - visRectDst->top;
657 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
659 if (!X11DRV_PALETTE_PaletteToXPixel || (physDev->depth == 1) ||
660 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
662 XCopyArea( gdi_display, pixmap, physDev->drawable, physDev->gc, 0, 0, width, height,
663 physDev->dc_rect.left + visRectDst->left,
664 physDev->dc_rect.top + visRectDst->top );
670 XImage *image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
671 AllPlanes, ZPixmap );
672 for (y = 0; y < height; y++)
673 for (x = 0; x < width; x++)
675 XPutPixel( image, x, y,
676 X11DRV_PALETTE_PaletteToXPixel[XGetPixel( image, x, y )]);
678 XPutImage( gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
679 physDev->dc_rect.left + visRectDst->left,
680 physDev->dc_rect.top + visRectDst->top, width, height );
681 XDestroyImage( image );
686 static BOOL same_format(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst)
688 if (physDevSrc->depth != physDevDst->depth) return FALSE;
689 if (!physDevSrc->color_shifts && !physDevDst->color_shifts) return TRUE;
690 if (physDevSrc->color_shifts && physDevDst->color_shifts)
691 return !memcmp(physDevSrc->color_shifts, physDevDst->color_shifts, sizeof(ColorShifts));
695 void execute_rop( X11DRV_PDEVICE *physdev, Pixmap src_pixmap, GC gc, const RECT *visrect, DWORD rop )
698 Pixmap result = src_pixmap;
700 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
701 BOOL use_pat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
702 BOOL use_dst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
703 int width = visrect->right - visrect->left;
704 int height = visrect->bottom - visrect->top;
706 pixmaps[SRC] = src_pixmap;
708 pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
710 if (use_dst) BITBLT_GetDstArea( physdev, pixmaps[DST], gc, visrect );
711 null_brush = use_pat && !X11DRV_SetupGCForPatBlt( physdev, gc, TRUE );
713 for ( ; *opcode; opcode++)
715 if (OP_DST(*opcode) == DST) result = pixmaps[DST];
716 XSetFunction( gdi_display, gc, OP_ROP(*opcode) );
717 switch(OP_SRCDST(*opcode))
719 case OP_ARGS(DST,TMP):
720 case OP_ARGS(SRC,TMP):
722 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
724 case OP_ARGS(DST,SRC):
725 case OP_ARGS(SRC,DST):
726 case OP_ARGS(TMP,SRC):
727 case OP_ARGS(TMP,DST):
728 XCopyArea( gdi_display, pixmaps[OP_SRC(*opcode)], pixmaps[OP_DST(*opcode)], gc,
729 0, 0, width, height, 0, 0 );
731 case OP_ARGS(PAT,DST):
732 case OP_ARGS(PAT,SRC):
734 XFillRectangle( gdi_display, pixmaps[OP_DST(*opcode)], gc, 0, 0, width, height );
738 XSetFunction( gdi_display, physdev->gc, GXcopy );
739 physdev->exposures += BITBLT_PutDstArea( physdev, result, visrect );
740 XFreePixmap( gdi_display, pixmaps[DST] );
741 if (pixmaps[TMP]) XFreePixmap( gdi_display, pixmaps[TMP] );
742 add_device_bounds( physdev, visrect );
745 /***********************************************************************
748 BOOL X11DRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
750 X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
751 BOOL usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
752 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
754 if (usePat && !X11DRV_SetupGCForBrush( physDev )) return TRUE;
756 XSetFunction( gdi_display, physDev->gc, OP_ROP(*opcode) );
758 switch(rop) /* a few special cases */
760 case BLACKNESS: /* 0x00 */
761 case WHITENESS: /* 0xff */
762 if ((physDev->depth != 1) && X11DRV_PALETTE_PaletteToXPixel)
764 XSetFunction( gdi_display, physDev->gc, GXcopy );
765 if (rop == BLACKNESS)
766 XSetForeground( gdi_display, physDev->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
768 XSetForeground( gdi_display, physDev->gc,
769 WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
770 XSetFillStyle( gdi_display, physDev->gc, FillSolid );
773 case DSTINVERT: /* 0x55 */
774 if (!(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL)))
776 /* Xor is much better when we do not have full colormap. */
777 /* Using white^black ensures that we invert at least black */
779 unsigned long xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
780 BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
781 XSetFunction( gdi_display, physDev->gc, GXxor );
782 XSetForeground( gdi_display, physDev->gc, xor_pix);
783 XSetFillStyle( gdi_display, physDev->gc, FillSolid );
787 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
788 physDev->dc_rect.left + dst->visrect.left,
789 physDev->dc_rect.top + dst->visrect.top,
790 dst->visrect.right - dst->visrect.left,
791 dst->visrect.bottom - dst->visrect.top );
792 add_device_bounds( physDev, &dst->visrect );
797 /***********************************************************************
800 BOOL X11DRV_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
801 PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
803 X11DRV_PDEVICE *physDevDst = get_x11drv_dev( dst_dev );
804 X11DRV_PDEVICE *physDevSrc = get_x11drv_dev( src_dev );
810 if (src_dev->funcs != dst_dev->funcs ||
811 src->width != dst->width || src->height != dst->height || /* no stretching with core X11 */
812 (physDevDst->depth == 1 && physDevSrc->depth != 1) || /* color -> mono done by hand */
813 (X11DRV_PALETTE_XPixelToPalette && physDevSrc->depth != 1)) /* needs palette mapping */
815 dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
816 return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
819 width = dst->visrect.right - dst->visrect.left;
820 height = dst->visrect.bottom - dst->visrect.top;
821 opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
823 add_device_bounds( physDevDst, &dst->visrect );
825 /* a few optimizations for single-op ROPs */
826 if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
828 if (same_format(physDevSrc, physDevDst))
830 XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
831 XCopyArea( gdi_display, physDevSrc->drawable,
832 physDevDst->drawable, physDevDst->gc,
833 physDevSrc->dc_rect.left + src->visrect.left,
834 physDevSrc->dc_rect.top + src->visrect.top,
836 physDevDst->dc_rect.left + dst->visrect.left,
837 physDevDst->dc_rect.top + dst->visrect.top );
838 physDevDst->exposures++;
841 if (physDevSrc->depth == 1)
843 int text_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetTextColor(physDevDst->dev.hdc) );
844 int bkgnd_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetBkColor(physDevDst->dev.hdc) );
846 XSetBackground( gdi_display, physDevDst->gc, text_pixel );
847 XSetForeground( gdi_display, physDevDst->gc, bkgnd_pixel );
848 XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
849 XCopyPlane( gdi_display, physDevSrc->drawable,
850 physDevDst->drawable, physDevDst->gc,
851 physDevSrc->dc_rect.left + src->visrect.left,
852 physDevSrc->dc_rect.top + src->visrect.top,
854 physDevDst->dc_rect.left + dst->visrect.left,
855 physDevDst->dc_rect.top + dst->visrect.top, 1 );
856 physDevDst->exposures++;
861 gc = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
862 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
863 XSetGraphicsExposures( gdi_display, gc, False );
865 /* retrieve the source */
867 src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, physDevDst->depth );
868 if (physDevSrc->depth == 1)
870 /* MSDN says if StretchBlt must convert a bitmap from monochrome
871 to color or vice versa, the foreground and background color of
872 the device context are used. In fact, it also applies to the
873 case when it is converted from mono to mono. */
874 int text_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetTextColor(physDevDst->dev.hdc) );
875 int bkgnd_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetBkColor(physDevDst->dev.hdc) );
877 if (X11DRV_PALETTE_XPixelToPalette && physDevDst->depth != 1)
879 XSetBackground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[text_pixel] );
880 XSetForeground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[bkgnd_pixel]);
884 XSetBackground( gdi_display, gc, text_pixel );
885 XSetForeground( gdi_display, gc, bkgnd_pixel );
887 XCopyPlane( gdi_display, physDevSrc->drawable, src_pixmap, gc,
888 physDevSrc->dc_rect.left + src->visrect.left,
889 physDevSrc->dc_rect.top + src->visrect.top,
890 width, height, 0, 0, 1 );
892 else /* color -> color */
894 XCopyArea( gdi_display, physDevSrc->drawable, src_pixmap, gc,
895 physDevSrc->dc_rect.left + src->visrect.left,
896 physDevSrc->dc_rect.top + src->visrect.top,
897 width, height, 0, 0 );
900 execute_rop( physDevDst, src_pixmap, gc, &dst->visrect, rop );
902 XFreePixmap( gdi_display, src_pixmap );
903 XFreeGC( gdi_display, gc );
908 static void free_heap_bits( struct gdi_image_bits *bits )
910 HeapFree( GetProcessHeap(), 0, bits->ptr );
913 static void free_ximage_bits( struct gdi_image_bits *bits )
918 /* only for use on sanitized BITMAPINFO structures */
919 static inline int get_dib_info_size( const BITMAPINFO *info, UINT coloruse )
921 if (info->bmiHeader.biCompression == BI_BITFIELDS)
922 return sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD);
923 if (coloruse == DIB_PAL_COLORS)
924 return sizeof(BITMAPINFOHEADER) + info->bmiHeader.biClrUsed * sizeof(WORD);
925 return FIELD_OFFSET( BITMAPINFO, bmiColors[info->bmiHeader.biClrUsed] );
928 static inline int get_dib_stride( int width, int bpp )
930 return ((width * bpp + 31) >> 3) & ~3;
933 static inline int get_dib_image_size( const BITMAPINFO *info )
935 return get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount )
936 * abs( info->bmiHeader.biHeight );
939 /* store the palette or color mask data in the bitmap info structure */
940 static void set_color_info( const XVisualInfo *vis, BITMAPINFO *info )
942 DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
944 info->bmiHeader.biCompression = BI_RGB;
945 info->bmiHeader.biClrUsed = 0;
947 switch (info->bmiHeader.biBitCount)
952 RGBQUAD *rgb = (RGBQUAD *)colors;
953 PALETTEENTRY palette[256];
956 info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
957 count = X11DRV_GetSystemPaletteEntries( NULL, 0, info->bmiHeader.biClrUsed, palette );
958 for (i = 0; i < count; i++)
960 rgb[i].rgbRed = palette[i].peRed;
961 rgb[i].rgbGreen = palette[i].peGreen;
962 rgb[i].rgbBlue = palette[i].peBlue;
963 rgb[i].rgbReserved = 0;
965 memset( &rgb[count], 0, (info->bmiHeader.biClrUsed - count) * sizeof(*rgb) );
969 colors[0] = vis->red_mask;
970 colors[1] = vis->green_mask;
971 colors[2] = vis->blue_mask;
972 info->bmiHeader.biCompression = BI_BITFIELDS;
975 colors[0] = vis->red_mask;
976 colors[1] = vis->green_mask;
977 colors[2] = vis->blue_mask;
978 if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff)
979 info->bmiHeader.biCompression = BI_BITFIELDS;
984 /* check if the specified color info is suitable for PutImage */
985 static BOOL matching_color_info( const XVisualInfo *vis, const BITMAPINFO *info )
987 DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
989 switch (info->bmiHeader.biBitCount)
992 if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
993 return !info->bmiHeader.biClrUsed; /* color map not allowed */
997 RGBQUAD *rgb = (RGBQUAD *)colors;
998 PALETTEENTRY palette[256];
1001 if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
1002 count = X11DRV_GetSystemPaletteEntries( NULL, 0, 1 << info->bmiHeader.biBitCount, palette );
1003 if (count != info->bmiHeader.biClrUsed) return FALSE;
1004 for (i = 0; i < count; i++)
1006 if (rgb[i].rgbRed != palette[i].peRed ||
1007 rgb[i].rgbGreen != palette[i].peGreen ||
1008 rgb[i].rgbBlue != palette[i].peBlue) return FALSE;
1013 if (info->bmiHeader.biCompression == BI_BITFIELDS)
1014 return (vis->red_mask == colors[0] &&
1015 vis->green_mask == colors[1] &&
1016 vis->blue_mask == colors[2]);
1017 if (info->bmiHeader.biCompression == BI_RGB)
1018 return (vis->red_mask == 0x7c00 && vis->green_mask == 0x03e0 && vis->blue_mask == 0x001f);
1021 if (info->bmiHeader.biCompression == BI_BITFIELDS)
1022 return (vis->red_mask == colors[0] &&
1023 vis->green_mask == colors[1] &&
1024 vis->blue_mask == colors[2]);
1027 if (info->bmiHeader.biCompression == BI_RGB)
1028 return (vis->red_mask == 0xff0000 && vis->green_mask == 0x00ff00 && vis->blue_mask == 0x0000ff);
1034 static inline BOOL is_r8g8b8( const XVisualInfo *vis )
1036 return vis->depth == 24 && vis->red_mask == 0xff0000 && vis->blue_mask == 0x0000ff;
1039 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1040 DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
1041 const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
1042 struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
1044 #ifdef WORDS_BIGENDIAN
1045 static const int client_byte_order = MSBFirst;
1047 static const int client_byte_order = LSBFirst;
1050 int x, y, height = coords->visrect.bottom - coords->visrect.top;
1051 int width_bytes = image->bytes_per_line;
1053 unsigned char *src, *dst;
1055 switch (info->bmiHeader.biBitCount)
1058 need_byteswap = (image->bitmap_bit_order != MSBFirst);
1061 need_byteswap = (image->byte_order != MSBFirst);
1065 need_byteswap = (image->byte_order != client_byte_order);
1068 need_byteswap = (image->byte_order == MSBFirst) ^ !is_r8g8b8;
1071 need_byteswap = FALSE;
1075 src = src_bits->ptr;
1076 if (info->bmiHeader.biHeight > 0)
1077 src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes;
1079 src += coords->visrect.top * width_bytes;
1081 if ((need_byteswap && !src_bits->is_copy) || /* need to swap bytes */
1082 (zeropad_mask != ~0u && !src_bits->is_copy) || /* need to clear padding bytes */
1083 (mapping && !src_bits->is_copy) || /* need to remap pixels */
1084 (width_bytes & 3) || /* need to fixup line alignment */
1085 (info->bmiHeader.biHeight > 0)) /* need to flip vertically */
1087 width_bytes = (width_bytes + 3) & ~3;
1088 info->bmiHeader.biSizeImage = height * width_bytes;
1089 if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
1090 return ERROR_OUTOFMEMORY;
1091 dst_bits->is_copy = TRUE;
1092 dst_bits->free = free_heap_bits;
1096 /* swap bits in place */
1097 dst_bits->ptr = src;
1098 dst_bits->is_copy = src_bits->is_copy;
1099 dst_bits->free = NULL;
1100 if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS; /* nothing to do */
1103 dst = dst_bits->ptr;
1104 padding_pos = width_bytes/sizeof(unsigned int) - 1;
1106 if (info->bmiHeader.biHeight > 0)
1108 dst += (height - 1) * width_bytes;
1109 width_bytes = -width_bytes;
1112 if (need_byteswap || mapping)
1114 switch (info->bmiHeader.biBitCount)
1117 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1119 for (x = 0; x < image->bytes_per_line; x++)
1120 dst[x] = bit_swap[src[x]];
1121 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1125 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1128 for (x = 0; x < image->bytes_per_line; x++)
1129 dst[x] = (mapping[src[x] & 0x0f] << 4) | mapping[src[x] >> 4];
1131 for (x = 0; x < image->bytes_per_line; x++)
1132 dst[x] = (src[x] << 4) | (src[x] >> 4);
1133 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1137 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]];
1141 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1145 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1147 for (x = 0; x < info->bmiHeader.biWidth; x++)
1148 ((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] );
1149 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1153 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1155 for (x = 0; x < info->bmiHeader.biWidth; x++)
1157 unsigned char tmp = src[3 * x];
1158 dst[3 * x] = src[3 * x + 2];
1159 dst[3 * x + 1] = src[3 * x + 1];
1160 dst[3 * x + 2] = tmp;
1162 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1166 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1167 for (x = 0; x < info->bmiHeader.biWidth; x++)
1168 ((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] );
1172 else if (src != dst)
1174 for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1176 memcpy( dst, src, image->bytes_per_line );
1177 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1180 else /* only need to clear the padding */
1182 for (y = 0; y < height; y++, dst += width_bytes)
1183 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1185 return ERROR_SUCCESS;
1188 /***********************************************************************
1191 DWORD X11DRV_PutImage( PHYSDEV dev, HRGN clip, BITMAPINFO *info,
1192 const struct gdi_image_bits *bits, struct bitblt_coords *src,
1193 struct bitblt_coords *dst, DWORD rop )
1195 X11DRV_PDEVICE *physdev = get_x11drv_dev( dev );
1199 struct gdi_image_bits dst_bits;
1200 const XPixmapFormatValues *format;
1201 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1202 const int *mapping = NULL;
1204 vis.depth = physdev->depth;
1205 if (physdev->color_shifts)
1207 vis.red_mask = physdev->color_shifts->logicalRed.max << physdev->color_shifts->logicalRed.shift;
1208 vis.green_mask = physdev->color_shifts->logicalGreen.max << physdev->color_shifts->logicalGreen.shift;
1209 vis.blue_mask = physdev->color_shifts->logicalBlue.max << physdev->color_shifts->logicalBlue.shift;
1211 format = pixmap_formats[vis.depth];
1213 if (info->bmiHeader.biPlanes != 1) goto update_format;
1214 if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1215 /* FIXME: could try to handle 1-bpp using XCopyPlane */
1216 if (!matching_color_info( &vis, info )) goto update_format;
1217 if (!bits) return ERROR_SUCCESS; /* just querying the format */
1218 if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
1220 image = XCreateImage( gdi_display, visual, vis.depth, ZPixmap, 0, NULL,
1221 info->bmiHeader.biWidth, src->visrect.bottom - src->visrect.top, 32, 0 );
1222 if (!image) return ERROR_OUTOFMEMORY;
1224 if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1226 if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1227 mapping = X11DRV_PALETTE_PaletteToXPixel;
1230 ret = copy_image_bits( info, is_r8g8b8(&vis), image, bits, &dst_bits, src, mapping, ~0u );
1234 BOOL restore_region = add_extra_clipping_region( physdev, clip );
1235 int width = dst->visrect.right - dst->visrect.left;
1236 int height = dst->visrect.bottom - dst->visrect.top;
1238 image->data = dst_bits.ptr;
1240 /* optimization for single-op ROPs */
1241 if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1243 XSetFunction( gdi_display, physdev->gc, OP_ROP(*opcode) );
1244 XPutImage( gdi_display, physdev->drawable, physdev->gc, image, src->visrect.left, 0,
1245 physdev->dc_rect.left + dst->visrect.left,
1246 physdev->dc_rect.top + dst->visrect.top, width, height );
1250 GC gc = XCreateGC( gdi_display, physdev->drawable, 0, NULL );
1251 Pixmap src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, vis.depth );
1253 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
1254 XSetGraphicsExposures( gdi_display, gc, False );
1255 XPutImage( gdi_display, src_pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
1257 execute_rop( physdev, src_pixmap, gc, &dst->visrect, rop );
1259 XFreePixmap( gdi_display, src_pixmap );
1260 XFreeGC( gdi_display, gc );
1263 if (restore_region) restore_clipping_region( physdev );
1264 add_device_bounds( physdev, &dst->visrect );
1268 XDestroyImage( image );
1269 if (dst_bits.free) dst_bits.free( &dst_bits );
1273 info->bmiHeader.biPlanes = 1;
1274 info->bmiHeader.biBitCount = format->bits_per_pixel;
1275 if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1276 set_color_info( &vis, info );
1277 return ERROR_BAD_FORMAT;
1280 /***********************************************************************
1283 DWORD X11DRV_GetImage( PHYSDEV dev, BITMAPINFO *info,
1284 struct gdi_image_bits *bits, struct bitblt_coords *src )
1286 X11DRV_PDEVICE *physdev = get_x11drv_dev( dev );
1287 DWORD ret = ERROR_SUCCESS;
1290 UINT align, x, y, width, height;
1291 struct gdi_image_bits src_bits;
1292 const XPixmapFormatValues *format;
1293 const int *mapping = NULL;
1295 vis.depth = physdev->depth;
1296 if (physdev->color_shifts)
1298 vis.red_mask = physdev->color_shifts->logicalRed.max << physdev->color_shifts->logicalRed.shift;
1299 vis.green_mask = physdev->color_shifts->logicalGreen.max << physdev->color_shifts->logicalGreen.shift;
1300 vis.blue_mask = physdev->color_shifts->logicalBlue.max << physdev->color_shifts->logicalBlue.shift;
1302 format = pixmap_formats[vis.depth];
1304 /* align start and width to 32-bit boundary */
1305 switch (format->bits_per_pixel)
1307 case 1: align = 32; break;
1308 case 4: align = 8; mapping = X11DRV_PALETTE_XPixelToPalette; break;
1309 case 8: align = 4; mapping = X11DRV_PALETTE_XPixelToPalette; break;
1310 case 16: align = 2; break;
1311 case 24: align = 4; break;
1312 case 32: align = 1; break;
1314 FIXME( "depth %u bpp %u not supported yet\n", vis.depth, format->bits_per_pixel );
1315 return ERROR_BAD_FORMAT;
1318 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1319 info->bmiHeader.biPlanes = 1;
1320 info->bmiHeader.biBitCount = format->bits_per_pixel;
1321 info->bmiHeader.biXPelsPerMeter = 0;
1322 info->bmiHeader.biYPelsPerMeter = 0;
1323 info->bmiHeader.biClrImportant = 0;
1324 set_color_info( &vis, info );
1326 if (!bits) return ERROR_SUCCESS; /* just querying the color information */
1328 x = src->visrect.left & ~(align - 1);
1329 y = src->visrect.top;
1330 width = src->visrect.right - x;
1331 height = src->visrect.bottom - src->visrect.top;
1332 if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
1333 /* make the source rectangle relative to the returned bits */
1336 OffsetRect( &src->visrect, -x, -y );
1338 X11DRV_expect_error( gdi_display, XGetImage_handler, NULL );
1339 image = XGetImage( gdi_display, physdev->drawable,
1340 physdev->dc_rect.left + x, physdev->dc_rect.top + y,
1341 width, height, AllPlanes, ZPixmap );
1342 if (X11DRV_check_error())
1344 /* use a temporary pixmap to avoid the BadMatch error */
1345 Pixmap pixmap = XCreatePixmap( gdi_display, root_window, width, height, vis.depth );
1346 GC gc = XCreateGC( gdi_display, pixmap, 0, NULL );
1348 XSetGraphicsExposures( gdi_display, gc, False );
1349 XCopyArea( gdi_display, physdev->drawable, pixmap, gc,
1350 physdev->dc_rect.left + x, physdev->dc_rect.top + y, width, height, 0, 0 );
1351 image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1352 XFreePixmap( gdi_display, pixmap );
1353 XFreeGC( gdi_display, gc );
1356 if (!image) return ERROR_OUTOFMEMORY;
1358 info->bmiHeader.biWidth = width;
1359 info->bmiHeader.biHeight = -height;
1360 info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1362 src_bits.ptr = image->data;
1363 src_bits.is_copy = TRUE;
1364 ret = copy_image_bits( info, is_r8g8b8(&vis), image, &src_bits, bits, src, mapping,
1365 zeropad_masks[(width * image->bits_per_pixel) & 31] );
1367 if (!ret && bits->ptr == image->data)
1369 bits->free = free_ximage_bits;
1372 XDestroyImage( image );
1377 /***********************************************************************
1380 * Simplified equivalent of X11DRV_PutImage that writes directly to a pixmap.
1382 static DWORD put_pixmap_image( Pixmap pixmap, const XVisualInfo *vis,
1383 BITMAPINFO *info, const struct gdi_image_bits *bits )
1388 struct bitblt_coords coords;
1389 struct gdi_image_bits dst_bits;
1390 const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1391 const int *mapping = NULL;
1393 if (!format) return ERROR_INVALID_PARAMETER;
1394 if (info->bmiHeader.biPlanes != 1) goto update_format;
1395 if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1396 /* FIXME: could try to handle 1-bpp using XCopyPlane */
1397 if (!matching_color_info( vis, info )) goto update_format;
1398 if (!bits) return ERROR_SUCCESS; /* just querying the format */
1402 coords.width = info->bmiHeader.biWidth;
1403 coords.height = abs( info->bmiHeader.biHeight );
1404 SetRect( &coords.visrect, 0, 0, coords.width, coords.height );
1406 image = XCreateImage( gdi_display, visual, vis->depth, ZPixmap, 0, NULL,
1407 coords.width, coords.height, 32, 0 );
1408 if (!image) return ERROR_OUTOFMEMORY;
1410 if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1411 mapping = X11DRV_PALETTE_PaletteToXPixel;
1413 if (!(ret = copy_image_bits( info, is_r8g8b8(vis), image, bits, &dst_bits, &coords, mapping, ~0u )))
1415 image->data = dst_bits.ptr;
1416 gc = XCreateGC( gdi_display, pixmap, 0, NULL );
1417 XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, coords.width, coords.height );
1418 XFreeGC( gdi_display, gc );
1422 XDestroyImage( image );
1423 if (dst_bits.free) dst_bits.free( &dst_bits );
1427 info->bmiHeader.biPlanes = 1;
1428 info->bmiHeader.biBitCount = format->bits_per_pixel;
1429 if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1430 set_color_info( vis, info );
1431 return ERROR_BAD_FORMAT;
1435 /***********************************************************************
1436 * create_pixmap_from_image
1438 Pixmap create_pixmap_from_image( HDC hdc, const XVisualInfo *vis, const BITMAPINFO *info,
1439 const struct gdi_image_bits *bits, UINT coloruse )
1441 static const RGBQUAD default_colortable[2] = { { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff } };
1442 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1443 char src_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1444 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
1445 BITMAPINFO *src_info = (BITMAPINFO *)src_buffer;
1446 struct gdi_image_bits dst_bits;
1451 pixmap = XCreatePixmap( gdi_display, root_window,
1452 info->bmiHeader.biWidth, abs(info->bmiHeader.biHeight), vis->depth );
1453 if (!pixmap) return 0;
1455 memcpy( src_info, info, get_dib_info_size( info, coloruse ));
1456 memcpy( dst_info, info, get_dib_info_size( info, coloruse ));
1458 if (coloruse == DIB_PAL_COLORS ||
1459 (err = put_pixmap_image( pixmap, vis, dst_info, bits )) == ERROR_BAD_FORMAT)
1461 if (dst_info->bmiHeader.biBitCount == 1) /* set a default color table for 1-bpp */
1462 memcpy( dst_info->bmiColors, default_colortable, sizeof(default_colortable) );
1463 dib = CreateDIBSection( hdc, dst_info, coloruse, &dst_bits.ptr, 0, 0 );
1466 if (src_info->bmiHeader.biBitCount == 1 && !src_info->bmiHeader.biClrUsed)
1467 memcpy( src_info->bmiColors, default_colortable, sizeof(default_colortable) );
1468 SetDIBits( hdc, dib, 0, abs(info->bmiHeader.biHeight), bits->ptr, src_info, coloruse );
1469 dst_bits.free = NULL;
1470 dst_bits.is_copy = TRUE;
1471 err = put_pixmap_image( pixmap, vis, dst_info, &dst_bits );
1472 DeleteObject( dib );
1474 else err = ERROR_OUTOFMEMORY;
1477 if (!err) return pixmap;
1479 XFreePixmap( gdi_display, pixmap );
1485 /***********************************************************************
1488 * Equivalent of X11DRV_GetImage that reads directly from a pixmap.
1490 DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo *vis,
1491 BITMAPINFO *info, struct gdi_image_bits *bits )
1493 DWORD ret = ERROR_SUCCESS;
1495 struct gdi_image_bits src_bits;
1496 struct bitblt_coords coords;
1497 const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1498 const int *mapping = NULL;
1500 if (!format) return ERROR_INVALID_PARAMETER;
1502 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1503 info->bmiHeader.biWidth = width;
1504 info->bmiHeader.biHeight = -height;
1505 info->bmiHeader.biPlanes = 1;
1506 info->bmiHeader.biBitCount = format->bits_per_pixel;
1507 info->bmiHeader.biXPelsPerMeter = 0;
1508 info->bmiHeader.biYPelsPerMeter = 0;
1509 info->bmiHeader.biClrImportant = 0;
1510 set_color_info( vis, info );
1512 if (!bits) return ERROR_SUCCESS; /* just querying the color information */
1516 coords.width = width;
1517 coords.height = height;
1518 SetRect( &coords.visrect, 0, 0, width, height );
1520 image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1521 if (!image) return ERROR_OUTOFMEMORY;
1523 info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1525 src_bits.ptr = image->data;
1526 src_bits.is_copy = TRUE;
1527 ret = copy_image_bits( info, is_r8g8b8(vis), image, &src_bits, bits, &coords, mapping,
1528 zeropad_masks[(width * image->bits_per_pixel) & 31] );
1530 if (!ret && bits->ptr == image->data)
1532 bits->free = free_ximage_bits;
1535 XDestroyImage( image );
1540 struct x11drv_window_surface
1542 struct window_surface header;
1549 struct gdi_image_bits bits;
1550 CRITICAL_SECTION crit;
1551 BITMAPINFO info; /* variable size, must be last */
1554 static struct x11drv_window_surface *get_x11_surface( struct window_surface *surface )
1556 return (struct x11drv_window_surface *)surface;
1559 static inline UINT get_color_component( UINT color, UINT mask )
1562 for (shift = 0; !(mask & 1); shift++) mask >>= 1;
1563 return (color * mask / 255) << shift;
1566 static inline void flush_rgn_data( HRGN rgn, RGNDATA *data )
1568 HRGN tmp = ExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data );
1569 CombineRgn( rgn, rgn, tmp, RGN_OR );
1570 DeleteObject( tmp );
1571 data->rdh.nCount = 0;
1574 static inline void add_row( HRGN rgn, RGNDATA *data, int x, int y, int len )
1576 RECT *rect = (RECT *)data->Buffer + data->rdh.nCount;
1578 if (len <= 0) return;
1581 rect->right = x + len;
1582 rect->bottom = y + 1;
1584 if (data->rdh.nCount * sizeof(RECT) > data->rdh.nRgnSize - sizeof(RECT))
1585 flush_rgn_data( rgn, data );
1588 /***********************************************************************
1589 * update_surface_region
1591 static void update_surface_region( struct x11drv_window_surface *surface )
1593 #ifdef HAVE_LIBXSHAPE
1595 RGNDATA *data = (RGNDATA *)buffer;
1596 BITMAPINFO *info = &surface->info;
1597 UINT *masks = (UINT *)info->bmiColors;
1598 int x, y, start, width;
1601 if (surface->color_key == CLR_INVALID)
1603 XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, None, ShapeSet );
1607 data->rdh.dwSize = sizeof(data->rdh);
1608 data->rdh.iType = RDH_RECTANGLES;
1609 data->rdh.nCount = 0;
1610 data->rdh.nRgnSize = sizeof(buffer) - sizeof(data->rdh);
1612 rgn = CreateRectRgn( 0, 0, 0, 0 );
1613 width = surface->header.rect.right - surface->header.rect.left;
1615 switch (info->bmiHeader.biBitCount)
1619 WORD *bits = surface->bits.ptr;
1620 int stride = (width + 1) & ~1;
1621 UINT mask = masks[0] | masks[1] | masks[2];
1623 for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += stride)
1628 while (x < width && (bits[x] & mask) == surface->color_key) x++;
1630 while (x < width && (bits[x] & mask) != surface->color_key) x++;
1631 add_row( rgn, data, surface->header.rect.left + start, y, x - start );
1638 BYTE *bits = surface->bits.ptr;
1639 int stride = (width * 3 + 3) & ~3;
1641 for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += stride)
1647 (bits[x * 3] == GetBValue(surface->color_key)) &&
1648 (bits[x * 3 + 1] == GetGValue(surface->color_key)) &&
1649 (bits[x * 3 + 2] == GetRValue(surface->color_key)))
1653 ((bits[x * 3] != GetBValue(surface->color_key)) ||
1654 (bits[x * 3 + 1] != GetGValue(surface->color_key)) ||
1655 (bits[x * 3 + 2] != GetRValue(surface->color_key))))
1657 add_row( rgn, data, surface->header.rect.left + start, y, x - start );
1664 DWORD *bits = surface->bits.ptr;
1665 UINT mask = info->bmiHeader.biCompression == BI_RGB ? 0xffffff : (masks[0] | masks[1] | masks[2]);
1667 for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += width)
1672 while (x < width && (bits[x] & mask) == surface->color_key) x++;
1674 while (x < width && (bits[x] & mask) != surface->color_key) x++;
1675 add_row( rgn, data, surface->header.rect.left + start, y, x - start );
1684 if (data->rdh.nCount) flush_rgn_data( rgn, data );
1686 if ((data = X11DRV_GetRegionData( rgn, 0 )))
1688 XShapeCombineRectangles( gdi_display, surface->window, ShapeBounding, 0, 0,
1689 (XRectangle *)data->Buffer, data->rdh.nCount, ShapeSet, YXBanded );
1690 HeapFree( GetProcessHeap(), 0, data );
1693 DeleteObject( rgn );
1697 /***********************************************************************
1700 static void set_color_key( struct x11drv_window_surface *surface, COLORREF key )
1702 UINT *masks = (UINT *)surface->info.bmiColors;
1704 if (key == CLR_INVALID)
1705 surface->color_key = CLR_INVALID;
1706 else if (surface->info.bmiHeader.biBitCount <= 8)
1707 surface->color_key = CLR_INVALID;
1708 else if (key & (1 << 24)) /* PALETTEINDEX */
1709 surface->color_key = 0;
1710 else if (key >> 16 == 0x10ff) /* DIBINDEX */
1711 surface->color_key = 0;
1712 else if (surface->info.bmiHeader.biBitCount == 24)
1713 surface->color_key = key;
1714 else if (surface->info.bmiHeader.biCompression == BI_RGB)
1715 surface->color_key = (GetRValue(key) << 16) | (GetGValue(key) << 8) | GetBValue(key);
1717 surface->color_key = get_color_component( GetRValue(key), masks[0] ) |
1718 get_color_component( GetGValue(key), masks[1] ) |
1719 get_color_component( GetBValue(key), masks[2] );
1722 /***********************************************************************
1723 * x11drv_surface_lock
1725 static void x11drv_surface_lock( struct window_surface *window_surface )
1727 struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1729 EnterCriticalSection( &surface->crit );
1732 /***********************************************************************
1733 * x11drv_surface_unlock
1735 static void x11drv_surface_unlock( struct window_surface *window_surface )
1737 struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1739 LeaveCriticalSection( &surface->crit );
1742 /***********************************************************************
1743 * x11drv_surface_get_bitmap_info
1745 static void *x11drv_surface_get_bitmap_info( struct window_surface *window_surface, BITMAPINFO *info )
1747 struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1749 memcpy( info, &surface->info, get_dib_info_size( &surface->info, DIB_RGB_COLORS ));
1750 return surface->bits.ptr;
1753 /***********************************************************************
1754 * x11drv_surface_get_bounds
1756 static RECT *x11drv_surface_get_bounds( struct window_surface *window_surface )
1758 struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1760 return &surface->bounds;
1763 /***********************************************************************
1764 * x11drv_surface_flush
1766 static void x11drv_surface_flush( struct window_surface *window_surface )
1768 struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1769 struct bitblt_coords coords;
1770 struct gdi_image_bits dst_bits;
1771 const int *mapping = NULL;
1773 window_surface->funcs->lock( window_surface );
1776 coords.width = surface->header.rect.right - surface->header.rect.left;
1777 coords.height = surface->header.rect.bottom - surface->header.rect.top;
1778 SetRect( &coords.visrect, 0, 0, coords.width, coords.height );
1779 if (IntersectRect( &coords.visrect, &coords.visrect, &surface->bounds ))
1781 TRACE( "flushing %p %dx%d bounds %s bits %p\n",
1782 surface, coords.width, coords.height,
1783 wine_dbgstr_rect( &surface->bounds ), surface->bits.ptr );
1785 if (surface->color_key != CLR_INVALID) update_surface_region( surface );
1787 if (surface->image->bits_per_pixel == 4 || surface->image->bits_per_pixel == 8)
1788 mapping = X11DRV_PALETTE_PaletteToXPixel;
1790 if (!copy_image_bits( &surface->info, surface->is_r8g8b8, surface->image,
1791 &surface->bits, &dst_bits, &coords, mapping, ~0u ))
1793 surface->image->data = dst_bits.ptr;
1794 XPutImage( gdi_display, surface->window, surface->gc, surface->image,
1795 coords.visrect.left, 0,
1796 surface->header.rect.left + coords.visrect.left,
1797 surface->header.rect.top + coords.visrect.top,
1798 coords.visrect.right - coords.visrect.left,
1799 coords.visrect.bottom - coords.visrect.top );
1800 surface->image->data = NULL;
1803 if (dst_bits.free) dst_bits.free( &dst_bits );
1805 reset_bounds( &surface->bounds );
1806 window_surface->funcs->unlock( window_surface );
1809 /***********************************************************************
1810 * x11drv_surface_destroy
1812 static void x11drv_surface_destroy( struct window_surface *window_surface )
1814 struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1816 TRACE( "freeing %p bits %p\n", surface, surface->bits.ptr );
1817 if (surface->gc) XFreeGC( gdi_display, surface->gc );
1818 if (surface->image) XDestroyImage( surface->image );
1819 if (surface->bits.free) surface->bits.free( &surface->bits );
1820 surface->crit.DebugInfo->Spare[0] = 0;
1821 DeleteCriticalSection( &surface->crit );
1822 HeapFree( GetProcessHeap(), 0, surface );
1825 static const struct window_surface_funcs x11drv_surface_funcs =
1827 x11drv_surface_lock,
1828 x11drv_surface_unlock,
1829 x11drv_surface_get_bitmap_info,
1830 x11drv_surface_get_bounds,
1831 x11drv_surface_flush,
1832 x11drv_surface_destroy
1835 /***********************************************************************
1838 struct window_surface *create_surface( Window window, const XVisualInfo *vis, const RECT *rect,
1839 COLORREF color_key )
1841 const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1842 struct x11drv_window_surface *surface;
1843 int width = rect->right - rect->left, height = rect->bottom - rect->top;
1844 int colors = format->bits_per_pixel <= 8 ? 1 << format->bits_per_pixel : 3;
1846 surface = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1847 FIELD_OFFSET( struct x11drv_window_surface, info.bmiColors[colors] ));
1848 if (!surface) return NULL;
1849 surface->info.bmiHeader.biSize = sizeof(surface->info.bmiHeader);
1850 surface->info.bmiHeader.biWidth = width;
1851 surface->info.bmiHeader.biHeight = -height; /* top-down */
1852 surface->info.bmiHeader.biPlanes = 1;
1853 surface->info.bmiHeader.biBitCount = format->bits_per_pixel;
1854 surface->info.bmiHeader.biSizeImage = get_dib_image_size( &surface->info );
1855 set_color_info( vis, &surface->info );
1857 InitializeCriticalSection( &surface->crit );
1858 surface->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": surface");
1860 surface->header.funcs = &x11drv_surface_funcs;
1861 surface->header.rect = *rect;
1862 surface->header.ref = 1;
1863 surface->window = window;
1864 surface->is_r8g8b8 = is_r8g8b8( vis );
1865 set_color_key( surface, color_key );
1866 reset_bounds( &surface->bounds );
1867 if (!(surface->bits.ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1868 surface->info.bmiHeader.biSizeImage )))
1871 surface->bits.free = free_heap_bits;
1873 surface->image = XCreateImage( gdi_display, visual, vis->depth, ZPixmap, 0, NULL,
1874 width, height, 32, 0 );
1875 if (!surface->image) goto failed;
1876 surface->gc = XCreateGC( gdi_display, window, 0, NULL );
1878 TRACE( "created %p for %lx %s bits %p-%p\n", surface, window, wine_dbgstr_rect(rect),
1879 surface->bits.ptr, (char *)surface->bits.ptr + surface->info.bmiHeader.biSizeImage );
1881 return &surface->header;
1884 x11drv_surface_destroy( &surface->header );
1888 /***********************************************************************
1889 * set_surface_color_key
1891 void set_surface_color_key( struct window_surface *window_surface, COLORREF color_key )
1893 struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1896 window_surface->funcs->lock( window_surface );
1897 prev = surface->color_key;
1898 set_color_key( surface, color_key );
1899 if (surface->color_key != prev) update_surface_region( surface );
1900 window_surface->funcs->unlock( window_surface );