usp10: Simplify the offset calculation by always using ETO_PDY.
[wine] / dlls / winex11.drv / bitblt.c
1 /*
2  * GDI bit-blit operations
3  *
4  * Copyright 1993, 1994, 2011 Alexandre Julliard
5  * Copyright 2006 Damjan Jovanovic
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "config.h"
23
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28
29 #include <X11/Xlib.h>
30 #include <X11/Xresource.h>
31 #include <X11/Xutil.h>
32 #ifdef HAVE_X11_EXTENSIONS_SHAPE_H
33 #include <X11/extensions/shape.h>
34 #endif
35 #ifdef HAVE_X11_EXTENSIONS_XSHM_H
36 # include <X11/extensions/XShm.h>
37 # ifdef HAVE_SYS_SHM_H
38 #  include <sys/shm.h>
39 # endif
40 # ifdef HAVE_SYS_IPC_H
41 #  include <sys/ipc.h>
42 # endif
43 #endif
44
45 #include "windef.h"
46 #include "winbase.h"
47 #include "wingdi.h"
48 #include "winuser.h"
49 #include "x11drv.h"
50 #include "winternl.h"
51 #include "wine/debug.h"
52
53 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
54
55
56 #define DST 0   /* Destination drawable */
57 #define SRC 1   /* Source drawable */
58 #define TMP 2   /* Temporary drawable */
59 #define PAT 3   /* Pattern (brush) in destination DC */
60
61 #define OP(src,dst,rop)   (OP_ARGS(src,dst) << 4 | (rop))
62 #define OP_ARGS(src,dst)  (((src) << 2) | (dst))
63
64 #define OP_SRC(opcode)    ((opcode) >> 6)
65 #define OP_DST(opcode)    (((opcode) >> 4) & 3)
66 #define OP_SRCDST(opcode) ((opcode) >> 4)
67 #define OP_ROP(opcode)    ((opcode) & 0x0f)
68
69 #define MAX_OP_LEN  6  /* Longest opcode + 1 for the terminating 0 */
70
71 static const unsigned char BITBLT_Opcodes[256][MAX_OP_LEN] =
72 {
73     { OP(PAT,DST,GXclear) },                         /* 0x00  0              */
74     { OP(PAT,SRC,GXor), OP(SRC,DST,GXnor) },         /* 0x01  ~(D|(P|S))     */
75     { OP(PAT,SRC,GXnor), OP(SRC,DST,GXand) },        /* 0x02  D&~(P|S)       */
76     { OP(PAT,SRC,GXnor) },                           /* 0x03  ~(P|S)         */
77     { OP(PAT,DST,GXnor), OP(SRC,DST,GXand) },        /* 0x04  S&~(D|P)       */
78     { OP(PAT,DST,GXnor) },                           /* 0x05  ~(D|P)         */
79     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnor), },     /* 0x06  ~(P|~(D^S))    */
80     { OP(SRC,DST,GXand), OP(PAT,DST,GXnor) },        /* 0x07  ~(P|(D&S))     */
81     { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXand) },/* 0x08  S&D&~P         */
82     { OP(SRC,DST,GXxor), OP(PAT,DST,GXnor) },        /* 0x09  ~(P|(D^S))     */
83     { OP(PAT,DST,GXandInverted) },                   /* 0x0a  D&~P           */
84     { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXnor) }, /* 0x0b  ~(P|(S&~D))    */
85     { OP(PAT,SRC,GXandInverted) },                   /* 0x0c  S&~P           */
86     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXnor) },/* 0x0d  ~(P|(D&~S))    */
87     { OP(SRC,DST,GXnor), OP(PAT,DST,GXnor) },        /* 0x0e  ~(P|~(D|S))    */
88     { OP(PAT,DST,GXcopyInverted) },                  /* 0x0f  ~P             */
89     { OP(SRC,DST,GXnor), OP(PAT,DST,GXand) },        /* 0x10  P&~(S|D)       */
90     { OP(SRC,DST,GXnor) },                           /* 0x11  ~(D|S)         */
91     { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnor) },      /* 0x12  ~(S|~(D^P))    */
92     { OP(PAT,DST,GXand), OP(SRC,DST,GXnor) },        /* 0x13  ~(S|(D&P))     */
93     { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnor) },      /* 0x14  ~(D|~(P^S))    */
94     { OP(PAT,SRC,GXand), OP(SRC,DST,GXnor) },        /* 0x15  ~(D|(P&S))     */
95     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
96       OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
97       OP(PAT,DST,GXxor) },                           /* 0x16  P^S^(D&~(P&S)  */
98     { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
99       OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
100       OP(TMP,DST,GXequiv) },                         /* 0x17 ~S^((S^P)&(S^D))*/
101     { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
102         OP(SRC,DST,GXand) },                         /* 0x18  (S^P)&(D^P)    */
103     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
104       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x19  ~S^(D&~(P&S))  */
105     { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
106       OP(PAT,DST,GXxor) },                           /* 0x1a  P^(D|(S&P))    */
107     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
108       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x1b  ~S^(D&(P^S))   */
109     { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
110       OP(PAT,DST,GXxor) },                           /* 0x1c  P^(S|(D&P))    */
111     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
112       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x1d  ~D^(S&(D^P))   */
113     { OP(SRC,DST,GXor), OP(PAT,DST,GXxor) },         /* 0x1e  P^(D|S)        */
114     { OP(SRC,DST,GXor), OP(PAT,DST,GXnand) },        /* 0x1f  ~(P&(D|S))     */
115     { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXand) }, /* 0x20  D&(P&~S)       */
116     { OP(PAT,DST,GXxor), OP(SRC,DST,GXnor) },        /* 0x21  ~(S|(D^P))     */
117     { OP(SRC,DST,GXandInverted) },                   /* 0x22  ~S&D           */
118     { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x23  ~(S|(P&~D))    */
119     { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
120       OP(SRC,DST,GXand) },                           /* 0x24   (S^P)&(S^D)   */
121     { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand),
122       OP(PAT,DST,GXequiv) },                         /* 0x25  ~P^(D&~(S&P))  */
123     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
124       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x26  S^(D|(S&P))    */
125     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXequiv),
126       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x27  S^(D|~(P^S))   */
127     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand) },        /* 0x28  D&(P^S)        */
128     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
129       OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
130       OP(PAT,DST,GXequiv) },                         /* 0x29  ~P^S^(D|(P&S)) */
131     { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand) },       /* 0x2a  D&~(P&S)       */
132     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
133       OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
134       OP(TMP,DST,GXequiv) },                         /* 0x2b ~S^((P^S)&(P^D))*/
135     { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
136       OP(SRC,DST,GXxor) },                           /* 0x2c  S^(P&(S|D))    */
137     { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXxor) },  /* 0x2d  P^(S|~D)       */
138     { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
139       OP(PAT,DST,GXxor) },                           /* 0x2e  P^(S|(D^P))    */
140     { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXnand) }, /* 0x2f  ~(P&(S|~D))    */
141     { OP(PAT,SRC,GXandReverse) },                    /* 0x30  P&~S           */
142     { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXnor) },/* 0x31  ~(S|(D&~P))    */
143     { OP(SRC,DST,GXor), OP(PAT,DST,GXor),
144       OP(SRC,DST,GXxor) },                           /* 0x32  S^(D|P|S)      */
145     { OP(SRC,DST,GXcopyInverted) },                  /* 0x33  ~S             */
146     { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
147       OP(SRC,DST,GXxor) },                           /* 0x34  S^(P|(D&S))    */
148     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor),
149       OP(SRC,DST,GXxor) },                           /* 0x35  S^(P|~(D^S))   */
150     { OP(PAT,DST,GXor), OP(SRC,DST,GXxor) },         /* 0x36  S^(D|P)        */
151     { OP(PAT,DST,GXor), OP(SRC,DST,GXnand) },        /* 0x37  ~(S&(D|P))     */
152     { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
153       OP(PAT,DST,GXxor) },                           /* 0x38  P^(S&(D|P))    */
154     { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXxor) },  /* 0x39  S^(P|~D)       */
155     { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
156       OP(SRC,DST,GXxor) },                           /* 0x3a  S^(P|(D^S))    */
157     { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x3b  ~(S&(P|~D))    */
158     { OP(PAT,SRC,GXxor) },                           /* 0x3c  P^S            */
159     { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
160       OP(SRC,DST,GXxor) },                           /* 0x3d  S^(P|~(D|S))   */
161     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
162       OP(SRC,DST,GXxor) },                           /* 0x3e  S^(P|(D&~S))   */
163     { OP(PAT,SRC,GXnand) },                          /* 0x3f  ~(P&S)         */
164     { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXand) }, /* 0x40  P&S&~D         */
165     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnor) },        /* 0x41  ~(D|(P^S))     */
166     { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
167       OP(SRC,DST,GXand) },                           /* 0x42  (S^D)&(P^D)    */
168     { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
169       OP(SRC,DST,GXequiv) },                         /* 0x43  ~S^(P&~(D&S))  */
170     { OP(SRC,DST,GXandReverse) },                    /* 0x44  S&~D           */
171     { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x45  ~(D|(P&~S))    */
172     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
173       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x46  D^(S|(P&D))    */
174     { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
175       OP(PAT,DST,GXequiv) },                         /* 0x47  ~P^(S&(D^P))   */
176     { OP(PAT,DST,GXxor), OP(SRC,DST,GXand) },        /* 0x48  S&(P^D)        */
177     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
178       OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
179       OP(PAT,DST,GXequiv) },                         /* 0x49  ~P^D^(S|(P&D)) */
180     { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
181       OP(SRC,DST,GXxor) },                           /* 0x4a  D^(P&(S|D))    */
182     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXxor) }, /* 0x4b  P^(D|~S)       */
183     { OP(PAT,DST,GXnand), OP(SRC,DST,GXand) },       /* 0x4c  S&~(D&P)       */
184     { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
185       OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
186       OP(TMP,DST,GXequiv) },                         /* 0x4d ~S^((S^P)|(S^D))*/
187     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
188       OP(PAT,DST,GXxor) },                           /* 0x4e  P^(D|(S^P))    */
189     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXnand) },/* 0x4f  ~(P&(D|~S))    */
190     { OP(PAT,DST,GXandReverse) },                    /* 0x50  P&~D           */
191     { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXnor) },/* 0x51  ~(D|(S&~P))    */
192     { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
193       OP(SRC,DST,GXxor) },                           /* 0x52  D^(P|(S&D))    */
194     { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
195       OP(SRC,DST,GXequiv) },                         /* 0x53  ~S^(P&(D^S))   */
196     { OP(PAT,SRC,GXnor), OP(SRC,DST,GXnor) },        /* 0x54  ~(D|~(P|S))    */
197     { OP(PAT,DST,GXinvert) },                        /* 0x55  ~D             */
198     { OP(PAT,SRC,GXor), OP(SRC,DST,GXxor) },         /* 0x56  D^(P|S)        */
199     { OP(PAT,SRC,GXor), OP(SRC,DST,GXnand) },        /* 0x57  ~(D&(P|S))     */
200     { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
201       OP(PAT,DST,GXxor) },                           /* 0x58  P^(D&(P|S))    */
202     { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXxor) },  /* 0x59  D^(P|~S)       */
203     { OP(PAT,DST,GXxor) },                           /* 0x5a  D^P            */
204     { OP(DST,SRC,GXnor), OP(PAT,SRC,GXor),
205       OP(SRC,DST,GXxor) },                           /* 0x5b  D^(P|~(S|D))   */
206     { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
207       OP(SRC,DST,GXxor) },                           /* 0x5c  D^(P|(S^D))    */
208     { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x5d  ~(D&(P|~S))    */
209     { OP(DST,SRC,GXandInverted), OP(PAT,SRC,GXor),
210       OP(SRC,DST,GXxor) },                           /* 0x5e  D^(P|(S&~D))   */
211     { OP(PAT,DST,GXnand) },                          /* 0x5f  ~(D&P)         */
212     { OP(SRC,DST,GXxor), OP(PAT,DST,GXand) },        /* 0x60  P&(D^S)        */
213     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
214       OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
215       OP(TMP,DST,GXequiv) },                         /* 0x61  ~D^S^(P|(D&S)) */
216     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
217       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0x62  D^(S&(P|D))    */
218     { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x63  S^(D|~P)       */
219     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
220       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0x64  S^(D&(P|S))    */
221     { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x65  D^(S|~P)       */
222     { OP(SRC,DST,GXxor) },                           /* 0x66  S^D            */
223     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
224       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x67  S^(D|~(S|P)    */
225     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnor),
226       OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
227       OP(TMP,DST,GXequiv) },                         /* 0x68  ~D^S^(P|~(D|S))*/
228     { OP(SRC,DST,GXxor), OP(PAT,DST,GXequiv) },      /* 0x69  ~P^(D^S)       */
229     { OP(PAT,SRC,GXand), OP(SRC,DST,GXxor) },        /* 0x6a  D^(P&S)        */
230     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
231       OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
232       OP(PAT,DST,GXequiv) },                         /* 0x6b  ~P^S^(D&(P|S)) */
233     { OP(PAT,DST,GXand), OP(SRC,DST,GXxor) },        /* 0x6c  S^(D&P)        */
234     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
235       OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
236       OP(PAT,DST,GXequiv) },                         /* 0x6d  ~P^D^(S&(P|D)) */
237     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
238       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0x6e  S^(D&(P|~S))   */
239     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnand) },     /* 0x6f  ~(P&~(S^D))    */
240     { OP(SRC,DST,GXnand), OP(PAT,DST,GXand) },       /* 0x70  P&~(D&S)       */
241     { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
242       OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
243       OP(TMP,DST,GXequiv) },                         /* 0x71 ~S^((S^D)&(P^D))*/
244     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
245       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x72  S^(D|(P^S))    */
246     { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXnand) },/* 0x73  ~(S&(D|~P))    */
247     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
248       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x74   D^(S|(P^D))   */
249     { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXnand) },/* 0x75  ~(D&(S|~P))    */
250     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
251       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x76  S^(D|(P&~S))   */
252     { OP(SRC,DST,GXnand) },                          /* 0x77  ~(S&D)         */
253     { OP(SRC,DST,GXand), OP(PAT,DST,GXxor) },        /* 0x78  P^(D&S)        */
254     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
255       OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
256       OP(TMP,DST,GXequiv) },                         /* 0x79  ~D^S^(P&(D|S)) */
257     { OP(DST,SRC,GXorInverted), OP(PAT,SRC,GXand),
258       OP(SRC,DST,GXxor) },                           /* 0x7a  D^(P&(S|~D))   */
259     { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnand) },     /* 0x7b  ~(S&~(D^P))    */
260     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
261       OP(SRC,DST,GXxor) },                           /* 0x7c  S^(P&(D|~S))   */
262     { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnand) },     /* 0x7d  ~(D&~(P^S))    */
263     { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
264       OP(SRC,DST,GXor) },                            /* 0x7e  (S^P)|(S^D)    */
265     { OP(PAT,SRC,GXand), OP(SRC,DST,GXnand) },       /* 0x7f  ~(D&P&S)       */
266     { OP(PAT,SRC,GXand), OP(SRC,DST,GXand) },        /* 0x80  D&P&S          */
267     { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
268       OP(SRC,DST,GXnor) },                           /* 0x81  ~((S^P)|(S^D)) */
269     { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXand) },      /* 0x82  D&~(P^S)       */
270     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
271       OP(SRC,DST,GXequiv) },                         /* 0x83  ~S^(P&(D|~S))  */
272     { OP(PAT,DST,GXequiv), OP(SRC,DST,GXand) },      /* 0x84  S&~(D^P)       */
273     { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand),
274       OP(PAT,DST,GXequiv) },                         /* 0x85  ~P^(D&(S|~P))  */
275     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
276       OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
277       OP(TMP,DST,GXxor) },                           /* 0x86  D^S^(P&(D|S))  */
278     { OP(SRC,DST,GXand), OP(PAT,DST,GXequiv) },      /* 0x87  ~P^(D&S)       */
279     { OP(SRC,DST,GXand) },                           /* 0x88  S&D            */
280     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
281       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0x89  ~S^(D|(P&~S))  */
282     { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8a  D&(S|~P)       */
283     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
284       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0x8b  ~D^(S|(P^D))   */
285     { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8c  S&(D|~P)       */
286     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
287       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0x8d  ~S^(D|(P^S))   */
288     { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
289       OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
290       OP(TMP,DST,GXxor) },                           /* 0x8e  S^((S^D)&(P^D))*/
291     { OP(SRC,DST,GXnand), OP(PAT,DST,GXnand) },      /* 0x8f  ~(P&~(D&S))    */
292     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXand) },      /* 0x90  P&~(D^S)       */
293     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
294       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x91  ~S^(D&(P|~S))  */
295     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
296       OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
297       OP(TMP,DST,GXxor) },                           /* 0x92  D^P^(S&(D|P))  */
298     { OP(PAT,DST,GXand), OP(SRC,DST,GXequiv) },      /* 0x93  ~S^(P&D)       */
299     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
300       OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
301       OP(TMP,DST,GXxor) },                           /* 0x94  S^P^(D&(P|S))  */
302     { OP(PAT,SRC,GXand), OP(SRC,DST,GXequiv) },      /* 0x95  ~D^(P&S)       */
303     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXxor) },        /* 0x96  D^P^S          */
304     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
305       OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
306       OP(TMP,DST,GXxor) },                           /* 0x97  S^P^(D|~(P|S)) */
307     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
308       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0x98  ~S^(D|~(P|S))  */
309     { OP(SRC,DST,GXequiv) },                         /* 0x99  ~S^D           */
310     { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9a  D^(P&~S)       */
311     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
312       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x9b  ~S^(D&(P|S))   */
313     { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9c  S^(P&~D)       */
314     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
315       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x9d  ~D^(S&(P|D))   */
316     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
317       OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
318       OP(TMP,DST,GXxor) },                           /* 0x9e  D^S^(P|(D&S))  */
319     { OP(SRC,DST,GXxor), OP(PAT,DST,GXnand) },       /* 0x9f  ~(P&(D^S))     */
320     { OP(PAT,DST,GXand) },                           /* 0xa0  D&P            */
321     { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor),
322       OP(PAT,DST,GXequiv) },                         /* 0xa1  ~P^(D|(S&~P))  */
323     { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXand) },  /* 0xa2  D&(P|~S)       */
324     { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
325       OP(SRC,DST,GXequiv) },                         /* 0xa3  ~D^(P|(S^D))   */
326     { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor),
327       OP(PAT,DST,GXequiv) },                         /* 0xa4  ~P^(D|~(S|P))  */
328     { OP(PAT,DST,GXequiv) },                         /* 0xa5  ~P^D           */
329     { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXxor) },/* 0xa6  D^(S&~P)       */
330     { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
331       OP(PAT,DST,GXequiv) },                         /* 0xa7  ~P^(D&(S|P))   */
332     { OP(PAT,SRC,GXor), OP(SRC,DST,GXand) },         /* 0xa8  D&(P|S)        */
333     { OP(PAT,SRC,GXor), OP(SRC,DST,GXequiv) },       /* 0xa9  ~D^(P|S)       */
334     { OP(PAT,DST,GXnoop) },                          /* 0xaa  D              */
335     { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor) },         /* 0xab  D|~(P|S)       */
336     { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
337       OP(SRC,DST,GXxor) },                           /* 0xac  S^(P&(D^S))    */
338     { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
339       OP(SRC,DST,GXequiv) },                         /* 0xad  ~D^(P|(S&D))   */
340     { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor) }, /* 0xae  D|(S&~P)       */
341     { OP(PAT,DST,GXorInverted) },                    /* 0xaf  D|~P           */
342     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand) }, /* 0xb0  P&(D|~S)       */
343     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
344       OP(PAT,DST,GXequiv) },                         /* 0xb1  ~P^(D|(S^P))   */
345     { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
346       OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
347       OP(TMP,DST,GXxor) },                           /* 0xb2  S^((S^P)|(S^D))*/
348     { OP(PAT,DST,GXnand), OP(SRC,DST,GXnand) },      /* 0xb3  ~(S&~(D&P))    */
349     { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXxor) }, /* 0xb4  P^(S&~D)       */
350     { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
351       OP(SRC,DST,GXequiv) },                         /* 0xb5  ~D^(P&(S|D))   */
352     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
353       OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
354       OP(TMP,DST,GXxor) },                           /* 0xb6  D^P^(S|(D&P))  */
355     { OP(PAT,DST,GXxor), OP(SRC,DST,GXnand) },       /* 0xb7  ~(S&(D^P))     */
356     { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
357       OP(PAT,DST,GXxor) },                           /* 0xb8  P^(S&(D^P))    */
358     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
359       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0xb9  ~D^(S|(P&D))   */
360     { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXor) },  /* 0xba  D|(P&~S)       */
361     { OP(SRC,DST,GXorInverted) },                    /* 0xbb  ~S|D           */
362     { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
363       OP(SRC,DST,GXxor) },                           /* 0xbc  S^(P&~(D&S))   */
364     { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
365       OP(SRC,DST,GXnand) },                          /* 0xbd  ~((S^D)&(P^D)) */
366     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor) },         /* 0xbe  D|(P^S)        */
367     { OP(PAT,SRC,GXnand), OP(SRC,DST,GXor) },        /* 0xbf  D|~(P&S)       */
368     { OP(PAT,SRC,GXand) },                           /* 0xc0  P&S            */
369     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
370       OP(SRC,DST,GXequiv) },                         /* 0xc1  ~S^(P|(D&~S))  */
371     { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
372       OP(SRC,DST,GXequiv) },                         /* 0xc2  ~S^(P|~(D|S))  */
373     { OP(PAT,SRC,GXequiv) },                         /* 0xc3  ~P^S           */
374     { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXand) },  /* 0xc4  S&(P|~D)       */
375     { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
376       OP(SRC,DST,GXequiv) },                         /* 0xc5  ~S^(P|(D^S))   */
377     { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXxor) },/* 0xc6  S^(D&~P)       */
378     { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
379       OP(PAT,DST,GXequiv) },                         /* 0xc7  ~P^(S&(D|P))   */
380     { OP(PAT,DST,GXor), OP(SRC,DST,GXand) },         /* 0xc8  S&(D|P)        */
381     { OP(PAT,DST,GXor), OP(SRC,DST,GXequiv) },       /* 0xc9  ~S^(P|D)       */
382     { OP(DST,SRC,GXxor), OP(PAT,SRC,GXand),
383       OP(SRC,DST,GXxor) },                           /* 0xca  D^(P&(S^D))    */
384     { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
385       OP(SRC,DST,GXequiv) },                         /* 0xcb  ~S^(P|(D&S))   */
386     { OP(SRC,DST,GXcopy) },                          /* 0xcc  S              */
387     { OP(PAT,DST,GXnor), OP(SRC,DST,GXor) },         /* 0xcd  S|~(D|P)       */
388     { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXor) }, /* 0xce  S|(D&~P)       */
389     { OP(PAT,SRC,GXorInverted) },                    /* 0xcf  S|~P           */
390     { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXand) },  /* 0xd0  P&(S|~D)       */
391     { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
392       OP(PAT,DST,GXequiv) },                         /* 0xd1  ~P^(S|(D^P))   */
393     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXxor) },/* 0xd2  P^(D&~S)       */
394     { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
395       OP(SRC,DST,GXequiv) },                         /* 0xd3  ~S^(P&(D|S))   */
396     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
397       OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
398       OP(TMP,DST,GXxor) },                           /* 0xd4  S^((S^P)&(D^P))*/
399     { OP(PAT,SRC,GXnand), OP(SRC,DST,GXnand) },      /* 0xd5  ~(D&~(P&S))    */
400     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
401       OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
402       OP(TMP,DST,GXxor) },                           /* 0xd6  S^P^(D|(P&S))  */
403     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnand) },       /* 0xd7  ~(D&(P^S))     */
404     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
405       OP(PAT,DST,GXxor) },                           /* 0xd8  P^(D&(S^P))    */
406     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
407       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0xd9  ~S^(D|(P&S))   */
408     { OP(DST,SRC,GXnand), OP(PAT,SRC,GXand),
409       OP(SRC,DST,GXxor) },                           /* 0xda  D^(P&~(S&D))   */
410     { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
411       OP(SRC,DST,GXnand) },                          /* 0xdb  ~((S^P)&(S^D)) */
412     { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXor) },  /* 0xdc  S|(P&~D)       */
413     { OP(SRC,DST,GXorReverse) },                     /* 0xdd  S|~D           */
414     { OP(PAT,DST,GXxor), OP(SRC,DST,GXor) },         /* 0xde  S|(D^P)        */
415     { OP(PAT,DST,GXnand), OP(SRC,DST,GXor) },        /* 0xdf  S|~(D&P)       */
416     { OP(SRC,DST,GXor), OP(PAT,DST,GXand) },         /* 0xe0  P&(D|S)        */
417     { OP(SRC,DST,GXor), OP(PAT,DST,GXequiv) },       /* 0xe1  ~P^(D|S)       */
418     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
419       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0xe2  D^(S&(P^D))    */
420     { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
421       OP(PAT,DST,GXequiv) },                         /* 0xe3  ~P^(S|(D&P))   */
422     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
423       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0xe4  S^(D&(P^S))    */
424     { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
425       OP(PAT,DST,GXequiv) },                         /* 0xe5  ~P^(D|(S&P))   */
426     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
427       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0xe6  S^(D&~(P&S))   */
428     { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
429       OP(SRC,DST,GXnand) },                          /* 0xe7  ~((S^P)&(D^P)) */
430     { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
431       OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
432       OP(TMP,DST,GXxor) },                           /* 0xe8  S^((S^P)&(S^D))*/
433     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnand),
434       OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
435       OP(TMP,DST,GXequiv) },                         /* 0xe9  ~D^S^(P&~(S&D))*/
436     { OP(PAT,SRC,GXand), OP(SRC,DST,GXor) },         /* 0xea  D|(P&S)        */
437     { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXor) },       /* 0xeb  D|~(P^S)       */
438     { OP(PAT,DST,GXand), OP(SRC,DST,GXor) },         /* 0xec  S|(D&P)        */
439     { OP(PAT,DST,GXequiv), OP(SRC,DST,GXor) },       /* 0xed  S|~(D^P)       */
440     { OP(SRC,DST,GXor) },                            /* 0xee  S|D            */
441     { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXor) },  /* 0xef  S|D|~P         */
442     { OP(PAT,DST,GXcopy) },                          /* 0xf0  P              */
443     { OP(SRC,DST,GXnor), OP(PAT,DST,GXor) },         /* 0xf1  P|~(D|S)       */
444     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor) }, /* 0xf2  P|(D&~S)       */
445     { OP(PAT,SRC,GXorReverse) },                     /* 0xf3  P|~S           */
446     { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXor) },  /* 0xf4  P|(S&~D)       */
447     { OP(PAT,DST,GXorReverse) },                     /* 0xf5  P|~D           */
448     { OP(SRC,DST,GXxor), OP(PAT,DST,GXor) },         /* 0xf6  P|(D^S)        */
449     { OP(SRC,DST,GXnand), OP(PAT,DST,GXor) },        /* 0xf7  P|~(S&D)       */
450     { OP(SRC,DST,GXand), OP(PAT,DST,GXor) },         /* 0xf8  P|(D&S)        */
451     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor) },       /* 0xf9  P|~(D^S)       */
452     { OP(PAT,DST,GXor) },                            /* 0xfa  D|P            */
453     { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXor) },   /* 0xfb  D|P|~S         */
454     { OP(PAT,SRC,GXor) },                            /* 0xfc  P|S            */
455     { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXor) },   /* 0xfd  P|S|~D         */
456     { OP(SRC,DST,GXor), OP(PAT,DST,GXor) },          /* 0xfe  P|D|S          */
457     { OP(PAT,DST,GXset) }                            /* 0xff  1              */
458 };
459
460 static const unsigned char bit_swap[256] =
461 {
462     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
463     0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
464     0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
465     0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
466     0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
467     0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
468     0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
469     0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
470     0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
471     0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
472     0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
473     0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
474     0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
475     0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
476     0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
477     0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
478     0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
479     0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
480     0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
481     0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
482     0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
483     0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
484     0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
485     0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
486     0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
487     0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
488     0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
489     0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
490     0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
491     0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
492     0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
493     0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
494 };
495
496 #ifdef WORDS_BIGENDIAN
497 static const unsigned int zeropad_masks[32] =
498 {
499     0xffffffff, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
500     0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
501     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
502     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe
503 };
504 #else
505 static const unsigned int zeropad_masks[32] =
506 {
507     0xffffffff, 0x00000080, 0x000000c0, 0x000000e0, 0x000000f0, 0x000000f8, 0x000000fc, 0x000000fe,
508     0x000000ff, 0x000080ff, 0x0000c0ff, 0x0000e0ff, 0x0000f0ff, 0x0000f8ff, 0x0000fcff, 0x0000feff,
509     0x0000ffff, 0x0080ffff, 0x00c0ffff, 0x00e0ffff, 0x00f0ffff, 0x00f8ffff, 0x00fcffff, 0x00feffff,
510     0x00ffffff, 0x80ffffff, 0xc0ffffff, 0xe0ffffff, 0xf0ffffff, 0xf8ffffff, 0xfcffffff, 0xfeffffff
511 };
512 #endif
513
514 #ifdef BITBLT_TEST  /* Opcodes test */
515
516 static int do_bitop( int s, int d, int rop )
517 {
518     int res;
519     switch(rop)
520     {
521     case GXclear:        res = 0; break;
522     case GXand:          res = s & d; break;
523     case GXandReverse:   res = s & ~d; break;
524     case GXcopy:         res = s; break;
525     case GXandInverted:  res = ~s & d; break;
526     case GXnoop:         res = d; break;
527     case GXxor:          res = s ^ d; break;
528     case GXor:           res = s | d; break;
529     case GXnor:          res = ~(s | d); break;
530     case GXequiv:        res = ~s ^ d; break;
531     case GXinvert:       res = ~d; break;
532     case GXorReverse:    res = s | ~d; break;
533     case GXcopyInverted: res = ~s; break;
534     case GXorInverted:   res = ~s | d; break;
535     case GXnand:         res = ~(s & d); break;
536     case GXset:          res = 1; break;
537     }
538     return res & 1;
539 }
540
541 int main()
542 {
543     int rop, i, res, src, dst, pat, tmp, dstUsed;
544     const unsigned char *opcode;
545
546     for (rop = 0; rop < 256; rop++)
547     {
548         res = dstUsed = 0;
549         for (i = 0; i < 8; i++)
550         {
551             pat = (i >> 2) & 1;
552             src = (i >> 1) & 1;
553             dst = i & 1;
554             for (opcode = BITBLT_Opcodes[rop]; *opcode; opcode++)
555             {
556                 switch(*opcode >> 4)
557                 {
558                 case OP_ARGS(DST,TMP):
559                     tmp = do_bitop( dst, tmp, *opcode & 0xf );
560                     break;
561                 case OP_ARGS(DST,SRC):
562                     src = do_bitop( dst, src, *opcode & 0xf );
563                     break;
564                 case OP_ARGS(SRC,TMP):
565                     tmp = do_bitop( src, tmp, *opcode & 0xf );
566                     break;
567                 case OP_ARGS(SRC,DST):
568                     dst = do_bitop( src, dst, *opcode & 0xf );
569                     dstUsed = 1;
570                     break;
571                 case OP_ARGS(PAT,DST):
572                     dst = do_bitop( pat, dst, *opcode & 0xf );
573                     dstUsed = 1;
574                     break;
575                 case OP_ARGS(PAT,SRC):
576                     src = do_bitop( pat, src, *opcode & 0xf );
577                     break;
578                 case OP_ARGS(TMP,DST):
579                     dst = do_bitop( tmp, dst, *opcode & 0xf );
580                     dstUsed = 1;
581                     break;
582                 case OP_ARGS(TMP,SRC):
583                     src = do_bitop( tmp, src, *opcode & 0xf );
584                     break;
585                 default:
586                     printf( "Invalid opcode %x\n", *opcode );
587                 }
588             }
589             if (!dstUsed) dst = src;
590             if (dst) res |= 1 << i;
591         }
592         if (res != rop) printf( "%02x: ERROR, res=%02x\n", rop, res );
593     }
594
595     return 0;
596 }
597
598 #endif  /* BITBLT_TEST */
599
600
601 /* handler for XGetImage BadMatch errors */
602 static int XGetImage_handler( Display *dpy, XErrorEvent *event, void *arg )
603 {
604     return (event->request_code == X_GetImage && event->error_code == BadMatch);
605 }
606
607 /***********************************************************************
608  *           BITBLT_GetDstArea
609  *
610  * Retrieve an area from the destination DC, mapping all the
611  * pixels to Windows colors.
612  */
613 static int BITBLT_GetDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, GC gc, const RECT *visRectDst)
614 {
615     int exposures = 0;
616     INT width  = visRectDst->right - visRectDst->left;
617     INT height = visRectDst->bottom - visRectDst->top;
618
619     if (!X11DRV_PALETTE_XPixelToPalette || (physDev->depth == 1) ||
620         (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
621     {
622         XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
623                    physDev->dc_rect.left + visRectDst->left, physDev->dc_rect.top + visRectDst->top,
624                    width, height, 0, 0 );
625         exposures++;
626     }
627     else
628     {
629         INT x, y;
630         XImage *image;
631
632         /* Make sure we don't get a BadMatch error */
633         XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
634                    physDev->dc_rect.left + visRectDst->left,
635                    physDev->dc_rect.top + visRectDst->top,
636                    width, height, 0, 0);
637         exposures++;
638         image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
639                            AllPlanes, ZPixmap );
640         if (image)
641         {
642             for (y = 0; y < height; y++)
643                 for (x = 0; x < width; x++)
644                     XPutPixel( image, x, y,
645                                X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]);
646             XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height );
647             XDestroyImage( image );
648         }
649     }
650     return exposures;
651 }
652
653
654 /***********************************************************************
655  *           BITBLT_PutDstArea
656  *
657  * Put an area back into the destination DC, mapping the pixel
658  * colors to X pixels.
659  */
660 static int BITBLT_PutDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, const RECT *visRectDst)
661 {
662     int exposures = 0;
663     INT width  = visRectDst->right - visRectDst->left;
664     INT height = visRectDst->bottom - visRectDst->top;
665
666     /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
667
668     if (!X11DRV_PALETTE_PaletteToXPixel || (physDev->depth == 1) ||
669         (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
670     {
671         XCopyArea( gdi_display, pixmap, physDev->drawable, physDev->gc, 0, 0, width, height,
672                    physDev->dc_rect.left + visRectDst->left,
673                    physDev->dc_rect.top + visRectDst->top );
674         exposures++;
675     }
676     else
677     {
678         register INT x, y;
679         XImage *image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
680                                    AllPlanes, ZPixmap );
681         for (y = 0; y < height; y++)
682             for (x = 0; x < width; x++)
683             {
684                 XPutPixel( image, x, y,
685                            X11DRV_PALETTE_PaletteToXPixel[XGetPixel( image, x, y )]);
686             }
687         XPutImage( gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
688                    physDev->dc_rect.left + visRectDst->left,
689                    physDev->dc_rect.top + visRectDst->top, width, height );
690         XDestroyImage( image );
691     }
692     return exposures;
693 }
694
695 static BOOL same_format(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst)
696 {
697     if (physDevSrc->depth != physDevDst->depth) return FALSE;
698     if (!physDevSrc->color_shifts && !physDevDst->color_shifts) return TRUE;
699     if (physDevSrc->color_shifts && physDevDst->color_shifts)
700         return !memcmp(physDevSrc->color_shifts, physDevDst->color_shifts, sizeof(ColorShifts));
701     return FALSE;
702 }
703
704 void execute_rop( X11DRV_PDEVICE *physdev, Pixmap src_pixmap, GC gc, const RECT *visrect, DWORD rop )
705 {
706     Pixmap pixmaps[3];
707     Pixmap result = src_pixmap;
708     BOOL null_brush;
709     const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
710     BOOL use_pat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
711     BOOL use_dst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
712     int width  = visrect->right - visrect->left;
713     int height = visrect->bottom - visrect->top;
714
715     pixmaps[SRC] = src_pixmap;
716     pixmaps[TMP] = 0;
717     pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
718
719     if (use_dst) BITBLT_GetDstArea( physdev, pixmaps[DST], gc, visrect );
720     null_brush = use_pat && !X11DRV_SetupGCForPatBlt( physdev, gc, TRUE );
721
722     for ( ; *opcode; opcode++)
723     {
724         if (OP_DST(*opcode) == DST) result = pixmaps[DST];
725         XSetFunction( gdi_display, gc, OP_ROP(*opcode) );
726         switch(OP_SRCDST(*opcode))
727         {
728         case OP_ARGS(DST,TMP):
729         case OP_ARGS(SRC,TMP):
730             if (!pixmaps[TMP])
731                 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
732             /* fall through */
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 );
739             break;
740         case OP_ARGS(PAT,DST):
741         case OP_ARGS(PAT,SRC):
742             if (!null_brush)
743                 XFillRectangle( gdi_display, pixmaps[OP_DST(*opcode)], gc, 0, 0, width, height );
744             break;
745         }
746     }
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] );
751     add_device_bounds( physdev, visrect );
752 }
753
754 /***********************************************************************
755  *           X11DRV_PatBlt
756  */
757 BOOL X11DRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
758 {
759     X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
760     BOOL usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
761     const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
762
763     if (usePat && !X11DRV_SetupGCForBrush( physDev )) return TRUE;
764
765     XSetFunction( gdi_display, physDev->gc, OP_ROP(*opcode) );
766
767     switch(rop)  /* a few special cases */
768     {
769     case BLACKNESS:  /* 0x00 */
770     case WHITENESS:  /* 0xff */
771         if ((physDev->depth != 1) && X11DRV_PALETTE_PaletteToXPixel)
772         {
773             XSetFunction( gdi_display, physDev->gc, GXcopy );
774             if (rop == BLACKNESS)
775                 XSetForeground( gdi_display, physDev->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
776             else
777                 XSetForeground( gdi_display, physDev->gc,
778                                 WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
779             XSetFillStyle( gdi_display, physDev->gc, FillSolid );
780         }
781         break;
782     case DSTINVERT:  /* 0x55 */
783         if (!(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL)))
784         {
785             /* Xor is much better when we do not have full colormap.   */
786             /* Using white^black ensures that we invert at least black */
787             /* and white. */
788             unsigned long xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
789                                      BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
790             XSetFunction( gdi_display, physDev->gc, GXxor );
791             XSetForeground( gdi_display, physDev->gc, xor_pix);
792             XSetFillStyle( gdi_display, physDev->gc, FillSolid );
793         }
794         break;
795     }
796     XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
797                     physDev->dc_rect.left + dst->visrect.left,
798                     physDev->dc_rect.top + dst->visrect.top,
799                     dst->visrect.right - dst->visrect.left,
800                     dst->visrect.bottom - dst->visrect.top );
801     add_device_bounds( physDev, &dst->visrect );
802     return TRUE;
803 }
804
805
806 /***********************************************************************
807  *           X11DRV_StretchBlt
808  */
809 BOOL X11DRV_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
810                         PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
811 {
812     X11DRV_PDEVICE *physDevDst = get_x11drv_dev( dst_dev );
813     X11DRV_PDEVICE *physDevSrc = get_x11drv_dev( src_dev );
814     INT width, height;
815     const BYTE *opcode;
816     Pixmap src_pixmap;
817     GC gc;
818
819     if (src_dev->funcs != dst_dev->funcs ||
820         src->width != dst->width || src->height != dst->height ||  /* no stretching with core X11 */
821         (physDevDst->depth == 1 && physDevSrc->depth != 1) ||  /* color -> mono done by hand */
822         (X11DRV_PALETTE_XPixelToPalette && physDevSrc->depth != 1))  /* needs palette mapping */
823     {
824         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
825         return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
826     }
827
828     width  = dst->visrect.right - dst->visrect.left;
829     height = dst->visrect.bottom - dst->visrect.top;
830     opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
831
832     add_device_bounds( physDevDst, &dst->visrect );
833
834     /* a few optimizations for single-op ROPs */
835     if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
836     {
837         if (same_format(physDevSrc, physDevDst))
838         {
839             XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
840             XCopyArea( gdi_display, physDevSrc->drawable,
841                        physDevDst->drawable, physDevDst->gc,
842                        physDevSrc->dc_rect.left + src->visrect.left,
843                        physDevSrc->dc_rect.top + src->visrect.top,
844                        width, height,
845                        physDevDst->dc_rect.left + dst->visrect.left,
846                        physDevDst->dc_rect.top + dst->visrect.top );
847             physDevDst->exposures++;
848             return TRUE;
849         }
850         if (physDevSrc->depth == 1)
851         {
852             int text_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetTextColor(physDevDst->dev.hdc) );
853             int bkgnd_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetBkColor(physDevDst->dev.hdc) );
854
855             XSetBackground( gdi_display, physDevDst->gc, text_pixel );
856             XSetForeground( gdi_display, physDevDst->gc, bkgnd_pixel );
857             XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
858             XCopyPlane( gdi_display, physDevSrc->drawable,
859                         physDevDst->drawable, physDevDst->gc,
860                         physDevSrc->dc_rect.left + src->visrect.left,
861                         physDevSrc->dc_rect.top + src->visrect.top,
862                         width, height,
863                         physDevDst->dc_rect.left + dst->visrect.left,
864                         physDevDst->dc_rect.top + dst->visrect.top, 1 );
865             physDevDst->exposures++;
866             return TRUE;
867         }
868     }
869
870     gc = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
871     XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
872     XSetGraphicsExposures( gdi_display, gc, False );
873
874     /* retrieve the source */
875
876     src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, physDevDst->depth );
877     if (physDevSrc->depth == 1)
878     {
879         /* MSDN says if StretchBlt must convert a bitmap from monochrome
880            to color or vice versa, the foreground and background color of
881            the device context are used.  In fact, it also applies to the
882            case when it is converted from mono to mono. */
883         int text_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetTextColor(physDevDst->dev.hdc) );
884         int bkgnd_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetBkColor(physDevDst->dev.hdc) );
885
886         if (X11DRV_PALETTE_XPixelToPalette && physDevDst->depth != 1)
887         {
888             XSetBackground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[text_pixel] );
889             XSetForeground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[bkgnd_pixel]);
890         }
891         else
892         {
893             XSetBackground( gdi_display, gc, text_pixel );
894             XSetForeground( gdi_display, gc, bkgnd_pixel );
895         }
896         XCopyPlane( gdi_display, physDevSrc->drawable, src_pixmap, gc,
897                     physDevSrc->dc_rect.left + src->visrect.left,
898                     physDevSrc->dc_rect.top + src->visrect.top,
899                     width, height, 0, 0, 1 );
900     }
901     else  /* color -> color */
902     {
903         XCopyArea( gdi_display, physDevSrc->drawable, src_pixmap, gc,
904                    physDevSrc->dc_rect.left + src->visrect.left,
905                    physDevSrc->dc_rect.top + src->visrect.top,
906                    width, height, 0, 0 );
907     }
908
909     execute_rop( physDevDst, src_pixmap, gc, &dst->visrect, rop );
910
911     XFreePixmap( gdi_display, src_pixmap );
912     XFreeGC( gdi_display, gc );
913     return TRUE;
914 }
915
916
917 static void free_heap_bits( struct gdi_image_bits *bits )
918 {
919     HeapFree( GetProcessHeap(), 0, bits->ptr );
920 }
921
922 static void free_ximage_bits( struct gdi_image_bits *bits )
923 {
924     XFree( bits->ptr );
925 }
926
927 /* only for use on sanitized BITMAPINFO structures */
928 static inline int get_dib_info_size( const BITMAPINFO *info, UINT coloruse )
929 {
930     if (info->bmiHeader.biCompression == BI_BITFIELDS)
931         return sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD);
932     if (coloruse == DIB_PAL_COLORS)
933         return sizeof(BITMAPINFOHEADER) + info->bmiHeader.biClrUsed * sizeof(WORD);
934     return FIELD_OFFSET( BITMAPINFO, bmiColors[info->bmiHeader.biClrUsed] );
935 }
936
937 static inline int get_dib_stride( int width, int bpp )
938 {
939     return ((width * bpp + 31) >> 3) & ~3;
940 }
941
942 static inline int get_dib_image_size( const BITMAPINFO *info )
943 {
944     return get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount )
945         * abs( info->bmiHeader.biHeight );
946 }
947
948 /* store the palette or color mask data in the bitmap info structure */
949 static void set_color_info( const XVisualInfo *vis, BITMAPINFO *info, BOOL has_alpha )
950 {
951     DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
952
953     info->bmiHeader.biCompression = BI_RGB;
954     info->bmiHeader.biClrUsed = 0;
955
956     switch (info->bmiHeader.biBitCount)
957     {
958     case 4:
959     case 8:
960     {
961         RGBQUAD *rgb = (RGBQUAD *)colors;
962         PALETTEENTRY palette[256];
963         UINT i, count;
964
965         info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
966         count = X11DRV_GetSystemPaletteEntries( NULL, 0, info->bmiHeader.biClrUsed, palette );
967         for (i = 0; i < count; i++)
968         {
969             rgb[i].rgbRed   = palette[i].peRed;
970             rgb[i].rgbGreen = palette[i].peGreen;
971             rgb[i].rgbBlue  = palette[i].peBlue;
972             rgb[i].rgbReserved = 0;
973         }
974         memset( &rgb[count], 0, (info->bmiHeader.biClrUsed - count) * sizeof(*rgb) );
975         break;
976     }
977     case 16:
978         colors[0] = vis->red_mask;
979         colors[1] = vis->green_mask;
980         colors[2] = vis->blue_mask;
981         info->bmiHeader.biCompression = BI_BITFIELDS;
982         break;
983     case 32:
984         colors[0] = vis->red_mask;
985         colors[1] = vis->green_mask;
986         colors[2] = vis->blue_mask;
987         if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff || !has_alpha)
988             info->bmiHeader.biCompression = BI_BITFIELDS;
989         break;
990     }
991 }
992
993 /* check if the specified color info is suitable for PutImage */
994 static BOOL matching_color_info( const XVisualInfo *vis, const BITMAPINFO *info )
995 {
996     DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
997
998     switch (info->bmiHeader.biBitCount)
999     {
1000     case 1:
1001         if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
1002         return !info->bmiHeader.biClrUsed;  /* color map not allowed */
1003     case 4:
1004     case 8:
1005     {
1006         RGBQUAD *rgb = (RGBQUAD *)colors;
1007         PALETTEENTRY palette[256];
1008         UINT i, count;
1009
1010         if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
1011         count = X11DRV_GetSystemPaletteEntries( NULL, 0, 1 << info->bmiHeader.biBitCount, palette );
1012         if (count != info->bmiHeader.biClrUsed) return FALSE;
1013         for (i = 0; i < count; i++)
1014         {
1015             if (rgb[i].rgbRed   != palette[i].peRed ||
1016                 rgb[i].rgbGreen != palette[i].peGreen ||
1017                 rgb[i].rgbBlue  != palette[i].peBlue) return FALSE;
1018         }
1019         return TRUE;
1020     }
1021     case 16:
1022         if (info->bmiHeader.biCompression == BI_BITFIELDS)
1023             return (vis->red_mask == colors[0] &&
1024                     vis->green_mask == colors[1] &&
1025                     vis->blue_mask == colors[2]);
1026         if (info->bmiHeader.biCompression == BI_RGB)
1027             return (vis->red_mask == 0x7c00 && vis->green_mask == 0x03e0 && vis->blue_mask == 0x001f);
1028         break;
1029     case 32:
1030         if (info->bmiHeader.biCompression == BI_BITFIELDS)
1031             return (vis->red_mask == colors[0] &&
1032                     vis->green_mask == colors[1] &&
1033                     vis->blue_mask == colors[2]);
1034         /* fall through */
1035     case 24:
1036         if (info->bmiHeader.biCompression == BI_RGB)
1037             return (vis->red_mask == 0xff0000 && vis->green_mask == 0x00ff00 && vis->blue_mask == 0x0000ff);
1038         break;
1039     }
1040     return FALSE;
1041 }
1042
1043 static inline BOOL is_r8g8b8( const XVisualInfo *vis )
1044 {
1045     return vis->depth == 24 && vis->red_mask == 0xff0000 && vis->blue_mask == 0x0000ff;
1046 }
1047
1048 static inline BOOL image_needs_byteswap( XImage *image, BOOL is_r8g8b8, int bit_count )
1049 {
1050 #ifdef WORDS_BIGENDIAN
1051     static const int client_byte_order = MSBFirst;
1052 #else
1053     static const int client_byte_order = LSBFirst;
1054 #endif
1055
1056     switch (bit_count)
1057     {
1058     case 1:  return image->bitmap_bit_order != MSBFirst;
1059     case 4:  return image->byte_order != MSBFirst;
1060     case 16:
1061     case 32: return image->byte_order != client_byte_order;
1062     case 24: return (image->byte_order == MSBFirst) ^ !is_r8g8b8;
1063     default: return FALSE;
1064     }
1065 }
1066
1067 /* copy image bits with byte swapping and/or pixel mapping */
1068 static void copy_image_byteswap( BITMAPINFO *info, const unsigned char *src, unsigned char *dst,
1069                                  int src_stride, int dst_stride, int height,
1070                                  BOOL byteswap, const int *mapping, unsigned int zeropad_mask )
1071 {
1072     int x, y, padding_pos = abs(dst_stride) / sizeof(unsigned int) - 1;
1073
1074     if (!byteswap && !mapping)  /* simply copy */
1075     {
1076         if (src != dst)
1077         {
1078             for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1079             {
1080                 memcpy( dst, src, src_stride );
1081                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1082             }
1083         }
1084         else if (zeropad_mask != ~0u)  /* only need to clear the padding */
1085         {
1086             for (y = 0; y < height; y++, dst += dst_stride)
1087                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1088         }
1089         return;
1090     }
1091
1092     switch (info->bmiHeader.biBitCount)
1093     {
1094     case 1:
1095         for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1096         {
1097             for (x = 0; x < src_stride; x++) dst[x] = bit_swap[src[x]];
1098             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1099         }
1100         break;
1101     case 4:
1102         for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1103         {
1104             if (mapping)
1105             {
1106                 if (byteswap)
1107                     for (x = 0; x < src_stride; x++)
1108                         dst[x] = (mapping[src[x] & 0x0f] << 4) | mapping[src[x] >> 4];
1109                 else
1110                     for (x = 0; x < src_stride; x++)
1111                         dst[x] = mapping[src[x] & 0x0f] | (mapping[src[x] >> 4] << 4);
1112             }
1113             else
1114                 for (x = 0; x < src_stride; x++)
1115                     dst[x] = (src[x] << 4) | (src[x] >> 4);
1116             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1117         }
1118         break;
1119     case 8:
1120         for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1121         {
1122             for (x = 0; x < src_stride; x++) dst[x] = mapping[src[x]];
1123             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1124         }
1125         break;
1126     case 16:
1127         for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1128         {
1129             for (x = 0; x < info->bmiHeader.biWidth; x++)
1130                 ((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] );
1131             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1132         }
1133         break;
1134     case 24:
1135         for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1136         {
1137             for (x = 0; x < info->bmiHeader.biWidth; x++)
1138             {
1139                 unsigned char tmp = src[3 * x];
1140                 dst[3 * x]     = src[3 * x + 2];
1141                 dst[3 * x + 1] = src[3 * x + 1];
1142                 dst[3 * x + 2] = tmp;
1143             }
1144             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1145         }
1146         break;
1147     case 32:
1148         for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1149             for (x = 0; x < info->bmiHeader.biWidth; x++)
1150                 ((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] );
1151         break;
1152     }
1153 }
1154
1155 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1156 DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
1157                        const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
1158                        struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
1159 {
1160     BOOL need_byteswap = image_needs_byteswap( image, is_r8g8b8, info->bmiHeader.biBitCount );
1161     int height = coords->visrect.bottom - coords->visrect.top;
1162     int width_bytes = image->bytes_per_line;
1163     unsigned char *src, *dst;
1164
1165     src = src_bits->ptr;
1166     if (info->bmiHeader.biHeight > 0)
1167         src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes;
1168     else
1169         src += coords->visrect.top * width_bytes;
1170
1171     if ((need_byteswap && !src_bits->is_copy) ||  /* need to swap bytes */
1172         (zeropad_mask != ~0u && !src_bits->is_copy) ||  /* need to clear padding bytes */
1173         (mapping && !src_bits->is_copy) ||  /* need to remap pixels */
1174         (width_bytes & 3) ||  /* need to fixup line alignment */
1175         (info->bmiHeader.biHeight > 0))  /* need to flip vertically */
1176     {
1177         width_bytes = (width_bytes + 3) & ~3;
1178         info->bmiHeader.biSizeImage = height * width_bytes;
1179         if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
1180             return ERROR_OUTOFMEMORY;
1181         dst_bits->is_copy = TRUE;
1182         dst_bits->free = free_heap_bits;
1183     }
1184     else
1185     {
1186         /* swap bits in place */
1187         dst_bits->ptr = src;
1188         dst_bits->is_copy = src_bits->is_copy;
1189         dst_bits->free = NULL;
1190         if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS;  /* nothing to do */
1191     }
1192
1193     dst = dst_bits->ptr;
1194
1195     if (info->bmiHeader.biHeight > 0)
1196     {
1197         dst += (height - 1) * width_bytes;
1198         width_bytes = -width_bytes;
1199     }
1200
1201     copy_image_byteswap( info, src, dst, image->bytes_per_line, width_bytes, height,
1202                          need_byteswap, mapping, zeropad_mask );
1203     return ERROR_SUCCESS;
1204 }
1205
1206 /***********************************************************************
1207  *           X11DRV_PutImage
1208  */
1209 DWORD X11DRV_PutImage( PHYSDEV dev, HRGN clip, BITMAPINFO *info,
1210                        const struct gdi_image_bits *bits, struct bitblt_coords *src,
1211                        struct bitblt_coords *dst, DWORD rop )
1212 {
1213     X11DRV_PDEVICE *physdev = get_x11drv_dev( dev );
1214     DWORD ret;
1215     XImage *image;
1216     XVisualInfo vis = default_visual;
1217     struct gdi_image_bits dst_bits;
1218     const XPixmapFormatValues *format;
1219     const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1220     const int *mapping = NULL;
1221
1222     vis.depth = physdev->depth;
1223     if (physdev->color_shifts)
1224     {
1225         vis.red_mask   = physdev->color_shifts->logicalRed.max   << physdev->color_shifts->logicalRed.shift;
1226         vis.green_mask = physdev->color_shifts->logicalGreen.max << physdev->color_shifts->logicalGreen.shift;
1227         vis.blue_mask  = physdev->color_shifts->logicalBlue.max  << physdev->color_shifts->logicalBlue.shift;
1228     }
1229     format = pixmap_formats[vis.depth];
1230
1231     if (info->bmiHeader.biPlanes != 1) goto update_format;
1232     if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1233     /* FIXME: could try to handle 1-bpp using XCopyPlane */
1234     if (!matching_color_info( &vis, info )) goto update_format;
1235     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
1236     if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
1237
1238     image = XCreateImage( gdi_display, vis.visual, vis.depth, ZPixmap, 0, NULL,
1239                           info->bmiHeader.biWidth, src->visrect.bottom - src->visrect.top, 32, 0 );
1240     if (!image) return ERROR_OUTOFMEMORY;
1241
1242     if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1243     {
1244         if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1245             mapping = X11DRV_PALETTE_PaletteToXPixel;
1246     }
1247
1248     ret = copy_image_bits( info, is_r8g8b8(&vis), image, bits, &dst_bits, src, mapping, ~0u );
1249
1250     if (!ret)
1251     {
1252         BOOL restore_region = add_extra_clipping_region( physdev, clip );
1253         int width = dst->visrect.right - dst->visrect.left;
1254         int height = dst->visrect.bottom - dst->visrect.top;
1255
1256         image->data = dst_bits.ptr;
1257
1258         /* optimization for single-op ROPs */
1259         if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1260         {
1261             XSetFunction( gdi_display, physdev->gc, OP_ROP(*opcode) );
1262             XPutImage( gdi_display, physdev->drawable, physdev->gc, image, src->visrect.left, 0,
1263                        physdev->dc_rect.left + dst->visrect.left,
1264                        physdev->dc_rect.top + dst->visrect.top, width, height );
1265         }
1266         else
1267         {
1268             GC gc = XCreateGC( gdi_display, physdev->drawable, 0, NULL );
1269             Pixmap src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, vis.depth );
1270
1271             XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
1272             XSetGraphicsExposures( gdi_display, gc, False );
1273             XPutImage( gdi_display, src_pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
1274
1275             execute_rop( physdev, src_pixmap, gc, &dst->visrect, rop );
1276
1277             XFreePixmap( gdi_display, src_pixmap );
1278             XFreeGC( gdi_display, gc );
1279         }
1280
1281         if (restore_region) restore_clipping_region( physdev );
1282         add_device_bounds( physdev, &dst->visrect );
1283         image->data = NULL;
1284     }
1285
1286     XDestroyImage( image );
1287     if (dst_bits.free) dst_bits.free( &dst_bits );
1288     return ret;
1289
1290 update_format:
1291     info->bmiHeader.biPlanes   = 1;
1292     info->bmiHeader.biBitCount = format->bits_per_pixel;
1293     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1294     set_color_info( &vis, info, FALSE );
1295     return ERROR_BAD_FORMAT;
1296 }
1297
1298 /***********************************************************************
1299  *           X11DRV_GetImage
1300  */
1301 DWORD X11DRV_GetImage( PHYSDEV dev, BITMAPINFO *info,
1302                        struct gdi_image_bits *bits, struct bitblt_coords *src )
1303 {
1304     X11DRV_PDEVICE *physdev = get_x11drv_dev( dev );
1305     DWORD ret = ERROR_SUCCESS;
1306     XImage *image;
1307     XVisualInfo vis = default_visual;
1308     UINT align, x, y, width, height;
1309     struct gdi_image_bits src_bits;
1310     const XPixmapFormatValues *format;
1311     const int *mapping = NULL;
1312
1313     vis.depth = physdev->depth;
1314     if (physdev->color_shifts)
1315     {
1316         vis.red_mask   = physdev->color_shifts->logicalRed.max   << physdev->color_shifts->logicalRed.shift;
1317         vis.green_mask = physdev->color_shifts->logicalGreen.max << physdev->color_shifts->logicalGreen.shift;
1318         vis.blue_mask  = physdev->color_shifts->logicalBlue.max  << physdev->color_shifts->logicalBlue.shift;
1319     }
1320     format = pixmap_formats[vis.depth];
1321
1322     /* align start and width to 32-bit boundary */
1323     switch (format->bits_per_pixel)
1324     {
1325     case 1:  align = 32; break;
1326     case 4:  align = 8;  mapping = X11DRV_PALETTE_XPixelToPalette; break;
1327     case 8:  align = 4;  mapping = X11DRV_PALETTE_XPixelToPalette; break;
1328     case 16: align = 2;  break;
1329     case 24: align = 4;  break;
1330     case 32: align = 1;  break;
1331     default:
1332         FIXME( "depth %u bpp %u not supported yet\n", vis.depth, format->bits_per_pixel );
1333         return ERROR_BAD_FORMAT;
1334     }
1335
1336     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
1337     info->bmiHeader.biPlanes        = 1;
1338     info->bmiHeader.biBitCount      = format->bits_per_pixel;
1339     info->bmiHeader.biXPelsPerMeter = 0;
1340     info->bmiHeader.biYPelsPerMeter = 0;
1341     info->bmiHeader.biClrImportant  = 0;
1342     set_color_info( &vis, info, FALSE );
1343
1344     if (!bits) return ERROR_SUCCESS;  /* just querying the color information */
1345
1346     x = src->visrect.left & ~(align - 1);
1347     y = src->visrect.top;
1348     width = src->visrect.right - x;
1349     height = src->visrect.bottom - src->visrect.top;
1350     if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
1351     /* make the source rectangle relative to the returned bits */
1352     src->x -= x;
1353     src->y -= y;
1354     OffsetRect( &src->visrect, -x, -y );
1355
1356     X11DRV_expect_error( gdi_display, XGetImage_handler, NULL );
1357     image = XGetImage( gdi_display, physdev->drawable,
1358                        physdev->dc_rect.left + x, physdev->dc_rect.top + y,
1359                        width, height, AllPlanes, ZPixmap );
1360     if (X11DRV_check_error())
1361     {
1362         /* use a temporary pixmap to avoid the BadMatch error */
1363         Pixmap pixmap = XCreatePixmap( gdi_display, root_window, width, height, vis.depth );
1364         GC gc = XCreateGC( gdi_display, pixmap, 0, NULL );
1365
1366         XSetGraphicsExposures( gdi_display, gc, False );
1367         XCopyArea( gdi_display, physdev->drawable, pixmap, gc,
1368                    physdev->dc_rect.left + x, physdev->dc_rect.top + y, width, height, 0, 0 );
1369         image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1370         XFreePixmap( gdi_display, pixmap );
1371         XFreeGC( gdi_display, gc );
1372     }
1373
1374     if (!image) return ERROR_OUTOFMEMORY;
1375
1376     info->bmiHeader.biWidth     = width;
1377     info->bmiHeader.biHeight    = -height;
1378     info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1379
1380     src_bits.ptr     = image->data;
1381     src_bits.is_copy = TRUE;
1382     ret = copy_image_bits( info, is_r8g8b8(&vis), image, &src_bits, bits, src, mapping,
1383                            zeropad_masks[(width * image->bits_per_pixel) & 31] );
1384
1385     if (!ret && bits->ptr == image->data)
1386     {
1387         bits->free = free_ximage_bits;
1388         image->data = NULL;
1389     }
1390     XDestroyImage( image );
1391     return ret;
1392 }
1393
1394
1395 /***********************************************************************
1396  *           put_pixmap_image
1397  *
1398  * Simplified equivalent of X11DRV_PutImage that writes directly to a pixmap.
1399  */
1400 static DWORD put_pixmap_image( Pixmap pixmap, const XVisualInfo *vis,
1401                                BITMAPINFO *info, const struct gdi_image_bits *bits )
1402 {
1403     DWORD ret;
1404     XImage *image;
1405     GC gc;
1406     struct bitblt_coords coords;
1407     struct gdi_image_bits dst_bits;
1408     const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1409     const int *mapping = NULL;
1410
1411     if (!format) return ERROR_INVALID_PARAMETER;
1412     if (info->bmiHeader.biPlanes != 1) goto update_format;
1413     if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1414     /* FIXME: could try to handle 1-bpp using XCopyPlane */
1415     if (!matching_color_info( vis, info )) goto update_format;
1416     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
1417
1418     coords.x = 0;
1419     coords.y = 0;
1420     coords.width = info->bmiHeader.biWidth;
1421     coords.height = abs( info->bmiHeader.biHeight );
1422     SetRect( &coords.visrect, 0, 0, coords.width, coords.height );
1423
1424     image = XCreateImage( gdi_display, vis->visual, vis->depth, ZPixmap, 0, NULL,
1425                           coords.width, coords.height, 32, 0 );
1426     if (!image) return ERROR_OUTOFMEMORY;
1427
1428     if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1429         mapping = X11DRV_PALETTE_PaletteToXPixel;
1430
1431     if (!(ret = copy_image_bits( info, is_r8g8b8(vis), image, bits, &dst_bits, &coords, mapping, ~0u )))
1432     {
1433         image->data = dst_bits.ptr;
1434         gc = XCreateGC( gdi_display, pixmap, 0, NULL );
1435         XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, coords.width, coords.height );
1436         XFreeGC( gdi_display, gc );
1437         image->data = NULL;
1438     }
1439
1440     XDestroyImage( image );
1441     if (dst_bits.free) dst_bits.free( &dst_bits );
1442     return ret;
1443
1444 update_format:
1445     info->bmiHeader.biPlanes   = 1;
1446     info->bmiHeader.biBitCount = format->bits_per_pixel;
1447     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1448     set_color_info( vis, info, FALSE );
1449     return ERROR_BAD_FORMAT;
1450 }
1451
1452
1453 /***********************************************************************
1454  *           create_pixmap_from_image
1455  */
1456 Pixmap create_pixmap_from_image( HDC hdc, const XVisualInfo *vis, const BITMAPINFO *info,
1457                                  const struct gdi_image_bits *bits, UINT coloruse )
1458 {
1459     static const RGBQUAD default_colortable[2] = { { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff } };
1460     char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1461     char src_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1462     BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
1463     BITMAPINFO *src_info = (BITMAPINFO *)src_buffer;
1464     struct gdi_image_bits dst_bits;
1465     Pixmap pixmap;
1466     DWORD err;
1467     HBITMAP dib;
1468
1469     pixmap = XCreatePixmap( gdi_display, root_window,
1470                             info->bmiHeader.biWidth, abs(info->bmiHeader.biHeight), vis->depth );
1471     if (!pixmap) return 0;
1472
1473     memcpy( src_info, info, get_dib_info_size( info, coloruse ));
1474     memcpy( dst_info, info, get_dib_info_size( info, coloruse ));
1475
1476     if (coloruse == DIB_PAL_COLORS ||
1477         (err = put_pixmap_image( pixmap, vis, dst_info, bits )) == ERROR_BAD_FORMAT)
1478     {
1479         if (dst_info->bmiHeader.biBitCount == 1)  /* set a default color table for 1-bpp */
1480             memcpy( dst_info->bmiColors, default_colortable, sizeof(default_colortable) );
1481         dib = CreateDIBSection( hdc, dst_info, coloruse, &dst_bits.ptr, 0, 0 );
1482         if (dib)
1483         {
1484             if (src_info->bmiHeader.biBitCount == 1 && !src_info->bmiHeader.biClrUsed)
1485                 memcpy( src_info->bmiColors, default_colortable, sizeof(default_colortable) );
1486             SetDIBits( hdc, dib, 0, abs(info->bmiHeader.biHeight), bits->ptr, src_info, coloruse );
1487             dst_bits.free = NULL;
1488             dst_bits.is_copy = TRUE;
1489             err = put_pixmap_image( pixmap, vis, dst_info, &dst_bits );
1490             DeleteObject( dib );
1491         }
1492         else err = ERROR_OUTOFMEMORY;
1493     }
1494
1495     if (!err) return pixmap;
1496
1497     XFreePixmap( gdi_display, pixmap );
1498     return 0;
1499
1500 }
1501
1502
1503 /***********************************************************************
1504  *           get_pixmap_image
1505  *
1506  * Equivalent of X11DRV_GetImage that reads directly from a pixmap.
1507  */
1508 DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo *vis,
1509                         BITMAPINFO *info, struct gdi_image_bits *bits )
1510 {
1511     DWORD ret = ERROR_SUCCESS;
1512     XImage *image;
1513     struct gdi_image_bits src_bits;
1514     struct bitblt_coords coords;
1515     const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1516     const int *mapping = NULL;
1517
1518     if (!format) return ERROR_INVALID_PARAMETER;
1519
1520     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
1521     info->bmiHeader.biWidth         = width;
1522     info->bmiHeader.biHeight        = -height;
1523     info->bmiHeader.biPlanes        = 1;
1524     info->bmiHeader.biBitCount      = format->bits_per_pixel;
1525     info->bmiHeader.biXPelsPerMeter = 0;
1526     info->bmiHeader.biYPelsPerMeter = 0;
1527     info->bmiHeader.biClrImportant  = 0;
1528     set_color_info( vis, info, FALSE );
1529
1530     if (!bits) return ERROR_SUCCESS;  /* just querying the color information */
1531
1532     coords.x = 0;
1533     coords.y = 0;
1534     coords.width = width;
1535     coords.height = height;
1536     SetRect( &coords.visrect, 0, 0, width, height );
1537
1538     image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1539     if (!image) return ERROR_OUTOFMEMORY;
1540
1541     info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1542
1543     src_bits.ptr     = image->data;
1544     src_bits.is_copy = TRUE;
1545     ret = copy_image_bits( info, is_r8g8b8(vis), image, &src_bits, bits, &coords, mapping,
1546                            zeropad_masks[(width * image->bits_per_pixel) & 31] );
1547
1548     if (!ret && bits->ptr == image->data)
1549     {
1550         bits->free = free_ximage_bits;
1551         image->data = NULL;
1552     }
1553     XDestroyImage( image );
1554     return ret;
1555 }
1556
1557
1558 struct x11drv_window_surface
1559 {
1560     struct window_surface header;
1561     Window                window;
1562     GC                    gc;
1563     XImage               *image;
1564     RECT                  bounds;
1565     BOOL                  byteswap;
1566     BOOL                  is_argb;
1567     COLORREF              color_key;
1568     HRGN                  region;
1569     void                 *bits;
1570 #ifdef HAVE_LIBXXSHM
1571     XShmSegmentInfo       shminfo;
1572 #endif
1573     CRITICAL_SECTION      crit;
1574     BITMAPINFO            info;   /* variable size, must be last */
1575 };
1576
1577 static struct x11drv_window_surface *get_x11_surface( struct window_surface *surface )
1578 {
1579     return (struct x11drv_window_surface *)surface;
1580 }
1581
1582 static inline UINT get_color_component( UINT color, UINT mask )
1583 {
1584     int shift;
1585     for (shift = 0; !(mask & 1); shift++) mask >>= 1;
1586     return (color * mask / 255) << shift;
1587 }
1588
1589 static inline void flush_rgn_data( HRGN rgn, RGNDATA *data )
1590 {
1591     HRGN tmp = ExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data );
1592     CombineRgn( rgn, rgn, tmp, RGN_OR );
1593     DeleteObject( tmp );
1594     data->rdh.nCount = 0;
1595 }
1596
1597 static inline void add_row( HRGN rgn, RGNDATA *data, int x, int y, int len )
1598 {
1599     RECT *rect = (RECT *)data->Buffer + data->rdh.nCount;
1600
1601     if (len <= 0) return;
1602     rect->left   = x;
1603     rect->top    = y;
1604     rect->right  = x + len;
1605     rect->bottom = y + 1;
1606     data->rdh.nCount++;
1607     if (data->rdh.nCount * sizeof(RECT) > data->rdh.nRgnSize - sizeof(RECT))
1608         flush_rgn_data( rgn, data );
1609 }
1610
1611 /***********************************************************************
1612  *           update_surface_region
1613  */
1614 static void update_surface_region( struct x11drv_window_surface *surface )
1615 {
1616 #ifdef HAVE_LIBXSHAPE
1617     char buffer[4096];
1618     RGNDATA *data = (RGNDATA *)buffer;
1619     BITMAPINFO *info = &surface->info;
1620     UINT *masks = (UINT *)info->bmiColors;
1621     int x, y, start, width;
1622     HRGN rgn;
1623
1624     if (!shape_layered_windows) return;
1625
1626     if (!surface->is_argb && surface->color_key == CLR_INVALID)
1627     {
1628         XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, None, ShapeSet );
1629         return;
1630     }
1631
1632     data->rdh.dwSize = sizeof(data->rdh);
1633     data->rdh.iType  = RDH_RECTANGLES;
1634     data->rdh.nCount = 0;
1635     data->rdh.nRgnSize = sizeof(buffer) - sizeof(data->rdh);
1636
1637     rgn = CreateRectRgn( 0, 0, 0, 0 );
1638     width = surface->header.rect.right - surface->header.rect.left;
1639
1640     switch (info->bmiHeader.biBitCount)
1641     {
1642     case 16:
1643     {
1644         WORD *bits = surface->bits;
1645         int stride = (width + 1) & ~1;
1646         UINT mask = masks[0] | masks[1] | masks[2];
1647
1648         for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += stride)
1649         {
1650             x = 0;
1651             while (x < width)
1652             {
1653                 while (x < width && (bits[x] & mask) == surface->color_key) x++;
1654                 start = x;
1655                 while (x < width && (bits[x] & mask) != surface->color_key) x++;
1656                 add_row( rgn, data, surface->header.rect.left + start, y, x - start );
1657             }
1658         }
1659         break;
1660     }
1661     case 24:
1662     {
1663         BYTE *bits = surface->bits;
1664         int stride = (width * 3 + 3) & ~3;
1665
1666         for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += stride)
1667         {
1668             x = 0;
1669             while (x < width)
1670             {
1671                 while (x < width &&
1672                        (bits[x * 3] == GetBValue(surface->color_key)) &&
1673                        (bits[x * 3 + 1] == GetGValue(surface->color_key)) &&
1674                        (bits[x * 3 + 2] == GetRValue(surface->color_key)))
1675                     x++;
1676                 start = x;
1677                 while (x < width &&
1678                        ((bits[x * 3] != GetBValue(surface->color_key)) ||
1679                         (bits[x * 3 + 1] != GetGValue(surface->color_key)) ||
1680                         (bits[x * 3 + 2] != GetRValue(surface->color_key))))
1681                     x++;
1682                 add_row( rgn, data, surface->header.rect.left + start, y, x - start );
1683             }
1684         }
1685         break;
1686     }
1687     case 32:
1688     {
1689         DWORD *bits = surface->bits;
1690
1691         if (info->bmiHeader.biCompression == BI_RGB)
1692         {
1693             for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += width)
1694             {
1695                 x = 0;
1696                 while (x < width)
1697                 {
1698                     while (x < width &&
1699                            ((bits[x] & 0xffffff) == surface->color_key ||
1700                             (surface->is_argb && !(bits[x] & 0xff000000)))) x++;
1701                     start = x;
1702                     while (x < width &&
1703                            !((bits[x] & 0xffffff) == surface->color_key ||
1704                              (surface->is_argb && !(bits[x] & 0xff000000)))) x++;
1705                     add_row( rgn, data, surface->header.rect.left + start, y, x - start );
1706                 }
1707             }
1708         }
1709         else
1710         {
1711             UINT mask = masks[0] | masks[1] | masks[2];
1712             for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += width)
1713             {
1714                 x = 0;
1715                 while (x < width)
1716                 {
1717                     while (x < width && (bits[x] & mask) == surface->color_key) x++;
1718                     start = x;
1719                     while (x < width && (bits[x] & mask) != surface->color_key) x++;
1720                     add_row( rgn, data, surface->header.rect.left + start, y, x - start );
1721                 }
1722             }
1723         }
1724         break;
1725     }
1726     default:
1727         assert(0);
1728     }
1729
1730     if (data->rdh.nCount) flush_rgn_data( rgn, data );
1731
1732     if ((data = X11DRV_GetRegionData( rgn, 0 )))
1733     {
1734         XShapeCombineRectangles( gdi_display, surface->window, ShapeBounding, 0, 0,
1735                                  (XRectangle *)data->Buffer, data->rdh.nCount, ShapeSet, YXBanded );
1736         HeapFree( GetProcessHeap(), 0, data );
1737     }
1738
1739     DeleteObject( rgn );
1740 #endif
1741 }
1742
1743 /***********************************************************************
1744  *           set_color_key
1745  */
1746 static void set_color_key( struct x11drv_window_surface *surface, COLORREF key )
1747 {
1748     UINT *masks = (UINT *)surface->info.bmiColors;
1749
1750     if (key == CLR_INVALID)
1751         surface->color_key = CLR_INVALID;
1752     else if (surface->info.bmiHeader.biBitCount <= 8)
1753         surface->color_key = CLR_INVALID;
1754     else if (key & (1 << 24))  /* PALETTEINDEX */
1755         surface->color_key = 0;
1756     else if (key >> 16 == 0x10ff)  /* DIBINDEX */
1757         surface->color_key = 0;
1758     else if (surface->info.bmiHeader.biBitCount == 24)
1759         surface->color_key = key;
1760     else if (surface->info.bmiHeader.biCompression == BI_RGB)
1761         surface->color_key = (GetRValue(key) << 16) | (GetGValue(key) << 8) | GetBValue(key);
1762     else
1763         surface->color_key = get_color_component( GetRValue(key), masks[0] ) |
1764                              get_color_component( GetGValue(key), masks[1] ) |
1765                              get_color_component( GetBValue(key), masks[2] );
1766 }
1767
1768 #ifdef HAVE_LIBXXSHM
1769 static int xshm_error_handler( Display *display, XErrorEvent *event, void *arg )
1770 {
1771     return 1;  /* FIXME: should check event contents */
1772 }
1773
1774 static XImage *create_shm_image( const XVisualInfo *vis, int width, int height, XShmSegmentInfo *shminfo )
1775 {
1776     XImage *image;
1777
1778     shminfo->shmid = -1;
1779     image = XShmCreateImage( gdi_display, vis->visual, vis->depth, ZPixmap, NULL, shminfo, width, height );
1780     if (!image) return NULL;
1781     if (image->bytes_per_line & 3) goto failed;  /* we need 32-bit alignment */
1782
1783     shminfo->shmid = shmget( IPC_PRIVATE, image->bytes_per_line * height, IPC_CREAT | 0700 );
1784     if (shminfo->shmid == -1) goto failed;
1785
1786     shminfo->shmaddr = shmat( shminfo->shmid, 0, 0 );
1787     if (shminfo->shmaddr != (char *)-1)
1788     {
1789         BOOL ok;
1790
1791         shminfo->readOnly = True;
1792         X11DRV_expect_error( gdi_display, xshm_error_handler, NULL );
1793         ok = (XShmAttach( gdi_display, shminfo ) != 0);
1794         XSync( gdi_display, False );
1795         if (!X11DRV_check_error() && ok)
1796         {
1797             image->data = shminfo->shmaddr;
1798             shmctl( shminfo->shmid, IPC_RMID, 0 );
1799             return image;
1800         }
1801         shmdt( shminfo->shmaddr );
1802     }
1803     shmctl( shminfo->shmid, IPC_RMID, 0 );
1804     shminfo->shmid = -1;
1805
1806 failed:
1807     XDestroyImage( image );
1808     return NULL;
1809 }
1810 #endif /* HAVE_LIBXXSHM */
1811
1812 /***********************************************************************
1813  *           x11drv_surface_lock
1814  */
1815 static void x11drv_surface_lock( struct window_surface *window_surface )
1816 {
1817     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1818
1819     EnterCriticalSection( &surface->crit );
1820 }
1821
1822 /***********************************************************************
1823  *           x11drv_surface_unlock
1824  */
1825 static void x11drv_surface_unlock( struct window_surface *window_surface )
1826 {
1827     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1828
1829     LeaveCriticalSection( &surface->crit );
1830 }
1831
1832 /***********************************************************************
1833  *           x11drv_surface_get_bitmap_info
1834  */
1835 static void *x11drv_surface_get_bitmap_info( struct window_surface *window_surface, BITMAPINFO *info )
1836 {
1837     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1838
1839     memcpy( info, &surface->info, get_dib_info_size( &surface->info, DIB_RGB_COLORS ));
1840     return surface->bits;
1841 }
1842
1843 /***********************************************************************
1844  *           x11drv_surface_get_bounds
1845  */
1846 static RECT *x11drv_surface_get_bounds( struct window_surface *window_surface )
1847 {
1848     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1849
1850     return &surface->bounds;
1851 }
1852
1853 /***********************************************************************
1854  *           x11drv_surface_set_region
1855  */
1856 static void x11drv_surface_set_region( struct window_surface *window_surface, HRGN region )
1857 {
1858     RGNDATA *data;
1859     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1860
1861     TRACE( "updating surface %p with %p\n", surface, region );
1862
1863     window_surface->funcs->lock( window_surface );
1864     if (!region)
1865     {
1866         if (surface->region) DeleteObject( surface->region );
1867         surface->region = 0;
1868         XSetClipMask( gdi_display, surface->gc, None );
1869     }
1870     else
1871     {
1872         if (!surface->region) surface->region = CreateRectRgn( 0, 0, 0, 0 );
1873         CombineRgn( surface->region, region, 0, RGN_COPY );
1874         if ((data = X11DRV_GetRegionData( surface->region, 0 )))
1875         {
1876             XSetClipRectangles( gdi_display, surface->gc, 0, 0,
1877                                 (XRectangle *)data->Buffer, data->rdh.nCount, YXBanded );
1878             HeapFree( GetProcessHeap(), 0, data );
1879         }
1880     }
1881     window_surface->funcs->unlock( window_surface );
1882 }
1883
1884 /***********************************************************************
1885  *           x11drv_surface_flush
1886  */
1887 static void x11drv_surface_flush( struct window_surface *window_surface )
1888 {
1889     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1890     unsigned char *src = surface->bits;
1891     unsigned char *dst = (unsigned char *)surface->image->data;
1892     struct bitblt_coords coords;
1893
1894     window_surface->funcs->lock( window_surface );
1895     coords.x = 0;
1896     coords.y = 0;
1897     coords.width  = surface->header.rect.right - surface->header.rect.left;
1898     coords.height = surface->header.rect.bottom - surface->header.rect.top;
1899     SetRect( &coords.visrect, 0, 0, coords.width, coords.height );
1900     if (IntersectRect( &coords.visrect, &coords.visrect, &surface->bounds ))
1901     {
1902         TRACE( "flushing %p %dx%d bounds %s bits %p\n",
1903                surface, coords.width, coords.height,
1904                wine_dbgstr_rect( &surface->bounds ), surface->bits );
1905
1906         if (surface->is_argb || surface->color_key != CLR_INVALID) update_surface_region( surface );
1907
1908         if (src != dst)
1909         {
1910             const int *mapping = NULL;
1911             int width_bytes = surface->image->bytes_per_line;
1912
1913             if (surface->image->bits_per_pixel == 4 || surface->image->bits_per_pixel == 8)
1914                 mapping = X11DRV_PALETTE_PaletteToXPixel;
1915
1916             src += coords.visrect.top * width_bytes;
1917             dst += coords.visrect.top * width_bytes;
1918             copy_image_byteswap( &surface->info, src, dst, width_bytes, width_bytes,
1919                                  coords.visrect.bottom - coords.visrect.top,
1920                                  surface->byteswap, mapping, ~0u );
1921         }
1922
1923 #ifdef HAVE_LIBXXSHM
1924         if (surface->shminfo.shmid != -1)
1925             XShmPutImage( gdi_display, surface->window, surface->gc, surface->image,
1926                           coords.visrect.left, coords.visrect.top,
1927                           surface->header.rect.left + coords.visrect.left,
1928                           surface->header.rect.top + coords.visrect.top,
1929                           coords.visrect.right - coords.visrect.left,
1930                           coords.visrect.bottom - coords.visrect.top, False );
1931         else
1932 #endif
1933         XPutImage( gdi_display, surface->window, surface->gc, surface->image,
1934                    coords.visrect.left, coords.visrect.top,
1935                    surface->header.rect.left + coords.visrect.left,
1936                    surface->header.rect.top + coords.visrect.top,
1937                    coords.visrect.right - coords.visrect.left,
1938                    coords.visrect.bottom - coords.visrect.top );
1939     }
1940     reset_bounds( &surface->bounds );
1941     window_surface->funcs->unlock( window_surface );
1942 }
1943
1944 /***********************************************************************
1945  *           x11drv_surface_destroy
1946  */
1947 static void x11drv_surface_destroy( struct window_surface *window_surface )
1948 {
1949     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1950
1951     TRACE( "freeing %p bits %p\n", surface, surface->bits );
1952     if (surface->gc) XFreeGC( gdi_display, surface->gc );
1953     if (surface->image)
1954     {
1955         if (surface->image->data != surface->bits) HeapFree( GetProcessHeap(), 0, surface->bits );
1956 #ifdef HAVE_LIBXXSHM
1957         if (surface->shminfo.shmid != -1)
1958         {
1959             XShmDetach( gdi_display, &surface->shminfo );
1960             shmdt( surface->shminfo.shmaddr );
1961         }
1962         else
1963 #endif
1964         HeapFree( GetProcessHeap(), 0, surface->image->data );
1965         surface->image->data = NULL;
1966         XDestroyImage( surface->image );
1967     }
1968     surface->crit.DebugInfo->Spare[0] = 0;
1969     DeleteCriticalSection( &surface->crit );
1970     if (surface->region) DeleteObject( surface->region );
1971     HeapFree( GetProcessHeap(), 0, surface );
1972 }
1973
1974 static const struct window_surface_funcs x11drv_surface_funcs =
1975 {
1976     x11drv_surface_lock,
1977     x11drv_surface_unlock,
1978     x11drv_surface_get_bitmap_info,
1979     x11drv_surface_get_bounds,
1980     x11drv_surface_set_region,
1981     x11drv_surface_flush,
1982     x11drv_surface_destroy
1983 };
1984
1985 /***********************************************************************
1986  *           create_surface
1987  */
1988 struct window_surface *create_surface( Window window, const XVisualInfo *vis, const RECT *rect,
1989                                        COLORREF color_key, BOOL use_alpha )
1990 {
1991     const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1992     struct x11drv_window_surface *surface;
1993     int width = rect->right - rect->left, height = rect->bottom - rect->top;
1994     int colors = format->bits_per_pixel <= 8 ? 1 << format->bits_per_pixel : 3;
1995
1996     surface = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1997                          FIELD_OFFSET( struct x11drv_window_surface, info.bmiColors[colors] ));
1998     if (!surface) return NULL;
1999     surface->info.bmiHeader.biSize        = sizeof(surface->info.bmiHeader);
2000     surface->info.bmiHeader.biWidth       = width;
2001     surface->info.bmiHeader.biHeight      = -height; /* top-down */
2002     surface->info.bmiHeader.biPlanes      = 1;
2003     surface->info.bmiHeader.biBitCount    = format->bits_per_pixel;
2004     surface->info.bmiHeader.biSizeImage   = get_dib_image_size( &surface->info );
2005     set_color_info( vis, &surface->info, use_alpha );
2006
2007     InitializeCriticalSection( &surface->crit );
2008     surface->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": surface");
2009
2010     surface->header.funcs = &x11drv_surface_funcs;
2011     surface->header.rect  = *rect;
2012     surface->header.ref   = 1;
2013     surface->window = window;
2014     surface->is_argb = (use_alpha && vis->depth == 32 && surface->info.bmiHeader.biCompression == BI_RGB);
2015     set_color_key( surface, color_key );
2016     reset_bounds( &surface->bounds );
2017
2018 #ifdef HAVE_LIBXXSHM
2019     surface->image = create_shm_image( vis, width, height, &surface->shminfo );
2020     if (!surface->image)
2021 #endif
2022     {
2023         surface->image = XCreateImage( gdi_display, vis->visual, vis->depth, ZPixmap, 0, NULL,
2024                                        width, height, 32, 0 );
2025         if (!surface->image) goto failed;
2026         surface->image->data = HeapAlloc( GetProcessHeap(), 0, surface->info.bmiHeader.biSizeImage );
2027         if (!surface->image->data) goto failed;
2028     }
2029
2030     surface->gc = XCreateGC( gdi_display, window, 0, NULL );
2031     surface->byteswap = image_needs_byteswap( surface->image, is_r8g8b8(vis), format->bits_per_pixel );
2032
2033     if (surface->byteswap || format->bits_per_pixel == 4 || format->bits_per_pixel == 8)
2034     {
2035         /* allocate separate surface bits if byte swapping or palette mapping is required */
2036         if (!(surface->bits  = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
2037                                           surface->info.bmiHeader.biSizeImage )))
2038             goto failed;
2039     }
2040     else surface->bits = surface->image->data;
2041
2042     TRACE( "created %p for %lx %s bits %p-%p image %p\n", surface, window, wine_dbgstr_rect(rect),
2043            surface->bits, (char *)surface->bits + surface->info.bmiHeader.biSizeImage,
2044            surface->image->data );
2045
2046     return &surface->header;
2047
2048 failed:
2049     x11drv_surface_destroy( &surface->header );
2050     return NULL;
2051 }
2052
2053 /***********************************************************************
2054  *           set_surface_color_key
2055  */
2056 void set_surface_color_key( struct window_surface *window_surface, COLORREF color_key )
2057 {
2058     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
2059     COLORREF prev;
2060
2061     window_surface->funcs->lock( window_surface );
2062     prev = surface->color_key;
2063     set_color_key( surface, color_key );
2064     if (surface->color_key != prev) update_surface_region( surface );
2065     window_surface->funcs->unlock( window_surface );
2066 }
2067
2068 /***********************************************************************
2069  *           expose_surface
2070  */
2071 HRGN expose_surface( struct window_surface *window_surface, const RECT *rect )
2072 {
2073     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
2074     HRGN region = 0;
2075
2076     window_surface->funcs->lock( window_surface );
2077     add_bounds_rect( &surface->bounds, rect );
2078     if (surface->region)
2079     {
2080         region = CreateRectRgnIndirect( rect );
2081         if (CombineRgn( region, region, surface->region, RGN_DIFF ) <= NULLREGION)
2082         {
2083             DeleteObject( region );
2084             region = 0;
2085         }
2086     }
2087     window_surface->funcs->unlock( window_surface );
2088     return region;
2089 }