wmiutils: Implement IWbemPath::SetClassName.
[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     const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1046     return format->bits_per_pixel == 24 && vis->red_mask == 0xff0000 && vis->blue_mask == 0x0000ff;
1047 }
1048
1049 static inline BOOL image_needs_byteswap( XImage *image, BOOL is_r8g8b8, int bit_count )
1050 {
1051 #ifdef WORDS_BIGENDIAN
1052     static const int client_byte_order = MSBFirst;
1053 #else
1054     static const int client_byte_order = LSBFirst;
1055 #endif
1056
1057     switch (bit_count)
1058     {
1059     case 1:  return image->bitmap_bit_order != MSBFirst;
1060     case 4:  return image->byte_order != MSBFirst;
1061     case 16:
1062     case 32: return image->byte_order != client_byte_order;
1063     case 24: return (image->byte_order == MSBFirst) ^ !is_r8g8b8;
1064     default: return FALSE;
1065     }
1066 }
1067
1068 /* copy image bits with byte swapping and/or pixel mapping */
1069 static void copy_image_byteswap( BITMAPINFO *info, const unsigned char *src, unsigned char *dst,
1070                                  int src_stride, int dst_stride, int height,
1071                                  BOOL byteswap, const int *mapping, unsigned int zeropad_mask )
1072 {
1073     int x, y, padding_pos = abs(dst_stride) / sizeof(unsigned int) - 1;
1074
1075     if (!byteswap && !mapping)  /* simply copy */
1076     {
1077         if (src != dst)
1078         {
1079             for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1080             {
1081                 memcpy( dst, src, src_stride );
1082                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1083             }
1084         }
1085         else if (zeropad_mask != ~0u)  /* only need to clear the padding */
1086         {
1087             for (y = 0; y < height; y++, dst += dst_stride)
1088                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1089         }
1090         return;
1091     }
1092
1093     switch (info->bmiHeader.biBitCount)
1094     {
1095     case 1:
1096         for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1097         {
1098             for (x = 0; x < src_stride; x++) dst[x] = bit_swap[src[x]];
1099             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1100         }
1101         break;
1102     case 4:
1103         for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1104         {
1105             if (mapping)
1106             {
1107                 if (byteswap)
1108                     for (x = 0; x < src_stride; x++)
1109                         dst[x] = (mapping[src[x] & 0x0f] << 4) | mapping[src[x] >> 4];
1110                 else
1111                     for (x = 0; x < src_stride; x++)
1112                         dst[x] = mapping[src[x] & 0x0f] | (mapping[src[x] >> 4] << 4);
1113             }
1114             else
1115                 for (x = 0; x < src_stride; x++)
1116                     dst[x] = (src[x] << 4) | (src[x] >> 4);
1117             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1118         }
1119         break;
1120     case 8:
1121         for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1122         {
1123             for (x = 0; x < src_stride; x++) dst[x] = mapping[src[x]];
1124             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1125         }
1126         break;
1127     case 16:
1128         for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1129         {
1130             for (x = 0; x < info->bmiHeader.biWidth; x++)
1131                 ((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] );
1132             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1133         }
1134         break;
1135     case 24:
1136         for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1137         {
1138             for (x = 0; x < info->bmiHeader.biWidth; x++)
1139             {
1140                 unsigned char tmp = src[3 * x];
1141                 dst[3 * x]     = src[3 * x + 2];
1142                 dst[3 * x + 1] = src[3 * x + 1];
1143                 dst[3 * x + 2] = tmp;
1144             }
1145             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1146         }
1147         break;
1148     case 32:
1149         for (y = 0; y < height; y++, src += src_stride, dst += dst_stride)
1150             for (x = 0; x < info->bmiHeader.biWidth; x++)
1151                 ((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] );
1152         break;
1153     }
1154 }
1155
1156 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1157 DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
1158                        const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
1159                        struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
1160 {
1161     BOOL need_byteswap = image_needs_byteswap( image, is_r8g8b8, info->bmiHeader.biBitCount );
1162     int height = coords->visrect.bottom - coords->visrect.top;
1163     int width_bytes = image->bytes_per_line;
1164     unsigned char *src, *dst;
1165
1166     src = src_bits->ptr;
1167     if (info->bmiHeader.biHeight > 0)
1168         src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes;
1169     else
1170         src += coords->visrect.top * width_bytes;
1171
1172     if ((need_byteswap && !src_bits->is_copy) ||  /* need to swap bytes */
1173         (zeropad_mask != ~0u && !src_bits->is_copy) ||  /* need to clear padding bytes */
1174         (mapping && !src_bits->is_copy) ||  /* need to remap pixels */
1175         (width_bytes & 3) ||  /* need to fixup line alignment */
1176         (info->bmiHeader.biHeight > 0))  /* need to flip vertically */
1177     {
1178         width_bytes = (width_bytes + 3) & ~3;
1179         info->bmiHeader.biSizeImage = height * width_bytes;
1180         if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
1181             return ERROR_OUTOFMEMORY;
1182         dst_bits->is_copy = TRUE;
1183         dst_bits->free = free_heap_bits;
1184     }
1185     else
1186     {
1187         /* swap bits in place */
1188         dst_bits->ptr = src;
1189         dst_bits->is_copy = src_bits->is_copy;
1190         dst_bits->free = NULL;
1191         if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS;  /* nothing to do */
1192     }
1193
1194     dst = dst_bits->ptr;
1195
1196     if (info->bmiHeader.biHeight > 0)
1197     {
1198         dst += (height - 1) * width_bytes;
1199         width_bytes = -width_bytes;
1200     }
1201
1202     copy_image_byteswap( info, src, dst, image->bytes_per_line, width_bytes, height,
1203                          need_byteswap, mapping, zeropad_mask );
1204     return ERROR_SUCCESS;
1205 }
1206
1207 /***********************************************************************
1208  *           X11DRV_PutImage
1209  */
1210 DWORD X11DRV_PutImage( PHYSDEV dev, HRGN clip, BITMAPINFO *info,
1211                        const struct gdi_image_bits *bits, struct bitblt_coords *src,
1212                        struct bitblt_coords *dst, DWORD rop )
1213 {
1214     X11DRV_PDEVICE *physdev = get_x11drv_dev( dev );
1215     DWORD ret;
1216     XImage *image;
1217     XVisualInfo vis = default_visual;
1218     struct gdi_image_bits dst_bits;
1219     const XPixmapFormatValues *format;
1220     const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1221     const int *mapping = NULL;
1222
1223     vis.depth = physdev->depth;
1224     if (physdev->color_shifts)
1225     {
1226         vis.red_mask   = physdev->color_shifts->logicalRed.max   << physdev->color_shifts->logicalRed.shift;
1227         vis.green_mask = physdev->color_shifts->logicalGreen.max << physdev->color_shifts->logicalGreen.shift;
1228         vis.blue_mask  = physdev->color_shifts->logicalBlue.max  << physdev->color_shifts->logicalBlue.shift;
1229     }
1230     format = pixmap_formats[vis.depth];
1231
1232     if (info->bmiHeader.biPlanes != 1) goto update_format;
1233     if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1234     /* FIXME: could try to handle 1-bpp using XCopyPlane */
1235     if (!matching_color_info( &vis, info )) goto update_format;
1236     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
1237     if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
1238
1239     image = XCreateImage( gdi_display, vis.visual, vis.depth, ZPixmap, 0, NULL,
1240                           info->bmiHeader.biWidth, src->visrect.bottom - src->visrect.top, 32, 0 );
1241     if (!image) return ERROR_OUTOFMEMORY;
1242
1243     if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1244     {
1245         if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1246             mapping = X11DRV_PALETTE_PaletteToXPixel;
1247     }
1248
1249     ret = copy_image_bits( info, is_r8g8b8(&vis), image, bits, &dst_bits, src, mapping, ~0u );
1250
1251     if (!ret)
1252     {
1253         BOOL restore_region = add_extra_clipping_region( physdev, clip );
1254         int width = dst->visrect.right - dst->visrect.left;
1255         int height = dst->visrect.bottom - dst->visrect.top;
1256
1257         image->data = dst_bits.ptr;
1258
1259         /* optimization for single-op ROPs */
1260         if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1261         {
1262             XSetFunction( gdi_display, physdev->gc, OP_ROP(*opcode) );
1263             XPutImage( gdi_display, physdev->drawable, physdev->gc, image, src->visrect.left, 0,
1264                        physdev->dc_rect.left + dst->visrect.left,
1265                        physdev->dc_rect.top + dst->visrect.top, width, height );
1266         }
1267         else
1268         {
1269             GC gc = XCreateGC( gdi_display, physdev->drawable, 0, NULL );
1270             Pixmap src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, vis.depth );
1271
1272             XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
1273             XSetGraphicsExposures( gdi_display, gc, False );
1274             XPutImage( gdi_display, src_pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
1275
1276             execute_rop( physdev, src_pixmap, gc, &dst->visrect, rop );
1277
1278             XFreePixmap( gdi_display, src_pixmap );
1279             XFreeGC( gdi_display, gc );
1280         }
1281
1282         if (restore_region) restore_clipping_region( physdev );
1283         add_device_bounds( physdev, &dst->visrect );
1284         image->data = NULL;
1285     }
1286
1287     XDestroyImage( image );
1288     if (dst_bits.free) dst_bits.free( &dst_bits );
1289     return ret;
1290
1291 update_format:
1292     info->bmiHeader.biPlanes   = 1;
1293     info->bmiHeader.biBitCount = format->bits_per_pixel;
1294     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1295     set_color_info( &vis, info, FALSE );
1296     return ERROR_BAD_FORMAT;
1297 }
1298
1299 /***********************************************************************
1300  *           X11DRV_GetImage
1301  */
1302 DWORD X11DRV_GetImage( PHYSDEV dev, BITMAPINFO *info,
1303                        struct gdi_image_bits *bits, struct bitblt_coords *src )
1304 {
1305     X11DRV_PDEVICE *physdev = get_x11drv_dev( dev );
1306     DWORD ret = ERROR_SUCCESS;
1307     XImage *image;
1308     XVisualInfo vis = default_visual;
1309     UINT align, x, y, width, height;
1310     struct gdi_image_bits src_bits;
1311     const XPixmapFormatValues *format;
1312     const int *mapping = NULL;
1313
1314     vis.depth = physdev->depth;
1315     if (physdev->color_shifts)
1316     {
1317         vis.red_mask   = physdev->color_shifts->logicalRed.max   << physdev->color_shifts->logicalRed.shift;
1318         vis.green_mask = physdev->color_shifts->logicalGreen.max << physdev->color_shifts->logicalGreen.shift;
1319         vis.blue_mask  = physdev->color_shifts->logicalBlue.max  << physdev->color_shifts->logicalBlue.shift;
1320     }
1321     format = pixmap_formats[vis.depth];
1322
1323     /* align start and width to 32-bit boundary */
1324     switch (format->bits_per_pixel)
1325     {
1326     case 1:  align = 32; break;
1327     case 4:  align = 8;  mapping = X11DRV_PALETTE_XPixelToPalette; break;
1328     case 8:  align = 4;  mapping = X11DRV_PALETTE_XPixelToPalette; break;
1329     case 16: align = 2;  break;
1330     case 24: align = 4;  break;
1331     case 32: align = 1;  break;
1332     default:
1333         FIXME( "depth %u bpp %u not supported yet\n", vis.depth, format->bits_per_pixel );
1334         return ERROR_BAD_FORMAT;
1335     }
1336
1337     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
1338     info->bmiHeader.biPlanes        = 1;
1339     info->bmiHeader.biBitCount      = format->bits_per_pixel;
1340     info->bmiHeader.biXPelsPerMeter = 0;
1341     info->bmiHeader.biYPelsPerMeter = 0;
1342     info->bmiHeader.biClrImportant  = 0;
1343     set_color_info( &vis, info, FALSE );
1344
1345     if (!bits) return ERROR_SUCCESS;  /* just querying the color information */
1346
1347     x = src->visrect.left & ~(align - 1);
1348     y = src->visrect.top;
1349     width = src->visrect.right - x;
1350     height = src->visrect.bottom - src->visrect.top;
1351     if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
1352     /* make the source rectangle relative to the returned bits */
1353     src->x -= x;
1354     src->y -= y;
1355     OffsetRect( &src->visrect, -x, -y );
1356
1357     X11DRV_expect_error( gdi_display, XGetImage_handler, NULL );
1358     image = XGetImage( gdi_display, physdev->drawable,
1359                        physdev->dc_rect.left + x, physdev->dc_rect.top + y,
1360                        width, height, AllPlanes, ZPixmap );
1361     if (X11DRV_check_error())
1362     {
1363         /* use a temporary pixmap to avoid the BadMatch error */
1364         Pixmap pixmap = XCreatePixmap( gdi_display, root_window, width, height, vis.depth );
1365         GC gc = XCreateGC( gdi_display, pixmap, 0, NULL );
1366
1367         XSetGraphicsExposures( gdi_display, gc, False );
1368         XCopyArea( gdi_display, physdev->drawable, pixmap, gc,
1369                    physdev->dc_rect.left + x, physdev->dc_rect.top + y, width, height, 0, 0 );
1370         image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1371         XFreePixmap( gdi_display, pixmap );
1372         XFreeGC( gdi_display, gc );
1373     }
1374
1375     if (!image) return ERROR_OUTOFMEMORY;
1376
1377     info->bmiHeader.biWidth     = width;
1378     info->bmiHeader.biHeight    = -height;
1379     info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1380
1381     src_bits.ptr     = image->data;
1382     src_bits.is_copy = TRUE;
1383     ret = copy_image_bits( info, is_r8g8b8(&vis), image, &src_bits, bits, src, mapping,
1384                            zeropad_masks[(width * image->bits_per_pixel) & 31] );
1385
1386     if (!ret && bits->ptr == image->data)
1387     {
1388         bits->free = free_ximage_bits;
1389         image->data = NULL;
1390     }
1391     XDestroyImage( image );
1392     return ret;
1393 }
1394
1395
1396 /***********************************************************************
1397  *           put_pixmap_image
1398  *
1399  * Simplified equivalent of X11DRV_PutImage that writes directly to a pixmap.
1400  */
1401 static DWORD put_pixmap_image( Pixmap pixmap, const XVisualInfo *vis,
1402                                BITMAPINFO *info, const struct gdi_image_bits *bits )
1403 {
1404     DWORD ret;
1405     XImage *image;
1406     GC gc;
1407     struct bitblt_coords coords;
1408     struct gdi_image_bits dst_bits;
1409     const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1410     const int *mapping = NULL;
1411
1412     if (!format) return ERROR_INVALID_PARAMETER;
1413     if (info->bmiHeader.biPlanes != 1) goto update_format;
1414     if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1415     /* FIXME: could try to handle 1-bpp using XCopyPlane */
1416     if (!matching_color_info( vis, info )) goto update_format;
1417     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
1418
1419     coords.x = 0;
1420     coords.y = 0;
1421     coords.width = info->bmiHeader.biWidth;
1422     coords.height = abs( info->bmiHeader.biHeight );
1423     SetRect( &coords.visrect, 0, 0, coords.width, coords.height );
1424
1425     image = XCreateImage( gdi_display, vis->visual, vis->depth, ZPixmap, 0, NULL,
1426                           coords.width, coords.height, 32, 0 );
1427     if (!image) return ERROR_OUTOFMEMORY;
1428
1429     if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1430         mapping = X11DRV_PALETTE_PaletteToXPixel;
1431
1432     if (!(ret = copy_image_bits( info, is_r8g8b8(vis), image, bits, &dst_bits, &coords, mapping, ~0u )))
1433     {
1434         image->data = dst_bits.ptr;
1435         gc = XCreateGC( gdi_display, pixmap, 0, NULL );
1436         XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, coords.width, coords.height );
1437         XFreeGC( gdi_display, gc );
1438         image->data = NULL;
1439     }
1440
1441     XDestroyImage( image );
1442     if (dst_bits.free) dst_bits.free( &dst_bits );
1443     return ret;
1444
1445 update_format:
1446     info->bmiHeader.biPlanes   = 1;
1447     info->bmiHeader.biBitCount = format->bits_per_pixel;
1448     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1449     set_color_info( vis, info, FALSE );
1450     return ERROR_BAD_FORMAT;
1451 }
1452
1453
1454 /***********************************************************************
1455  *           create_pixmap_from_image
1456  */
1457 Pixmap create_pixmap_from_image( HDC hdc, const XVisualInfo *vis, const BITMAPINFO *info,
1458                                  const struct gdi_image_bits *bits, UINT coloruse )
1459 {
1460     static const RGBQUAD default_colortable[2] = { { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff } };
1461     char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1462     char src_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1463     BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
1464     BITMAPINFO *src_info = (BITMAPINFO *)src_buffer;
1465     struct gdi_image_bits dst_bits;
1466     Pixmap pixmap;
1467     DWORD err;
1468     HBITMAP dib;
1469
1470     pixmap = XCreatePixmap( gdi_display, root_window,
1471                             info->bmiHeader.biWidth, abs(info->bmiHeader.biHeight), vis->depth );
1472     if (!pixmap) return 0;
1473
1474     memcpy( src_info, info, get_dib_info_size( info, coloruse ));
1475     memcpy( dst_info, info, get_dib_info_size( info, coloruse ));
1476
1477     if (coloruse == DIB_PAL_COLORS ||
1478         (err = put_pixmap_image( pixmap, vis, dst_info, bits )) == ERROR_BAD_FORMAT)
1479     {
1480         if (dst_info->bmiHeader.biBitCount == 1)  /* set a default color table for 1-bpp */
1481             memcpy( dst_info->bmiColors, default_colortable, sizeof(default_colortable) );
1482         dib = CreateDIBSection( hdc, dst_info, coloruse, &dst_bits.ptr, 0, 0 );
1483         if (dib)
1484         {
1485             if (src_info->bmiHeader.biBitCount == 1 && !src_info->bmiHeader.biClrUsed)
1486                 memcpy( src_info->bmiColors, default_colortable, sizeof(default_colortable) );
1487             SetDIBits( hdc, dib, 0, abs(info->bmiHeader.biHeight), bits->ptr, src_info, coloruse );
1488             dst_bits.free = NULL;
1489             dst_bits.is_copy = TRUE;
1490             err = put_pixmap_image( pixmap, vis, dst_info, &dst_bits );
1491             DeleteObject( dib );
1492         }
1493         else err = ERROR_OUTOFMEMORY;
1494     }
1495
1496     if (!err) return pixmap;
1497
1498     XFreePixmap( gdi_display, pixmap );
1499     return 0;
1500
1501 }
1502
1503
1504 /***********************************************************************
1505  *           get_pixmap_image
1506  *
1507  * Equivalent of X11DRV_GetImage that reads directly from a pixmap.
1508  */
1509 DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo *vis,
1510                         BITMAPINFO *info, struct gdi_image_bits *bits )
1511 {
1512     DWORD ret = ERROR_SUCCESS;
1513     XImage *image;
1514     struct gdi_image_bits src_bits;
1515     struct bitblt_coords coords;
1516     const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1517     const int *mapping = NULL;
1518
1519     if (!format) return ERROR_INVALID_PARAMETER;
1520
1521     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
1522     info->bmiHeader.biWidth         = width;
1523     info->bmiHeader.biHeight        = -height;
1524     info->bmiHeader.biPlanes        = 1;
1525     info->bmiHeader.biBitCount      = format->bits_per_pixel;
1526     info->bmiHeader.biXPelsPerMeter = 0;
1527     info->bmiHeader.biYPelsPerMeter = 0;
1528     info->bmiHeader.biClrImportant  = 0;
1529     set_color_info( vis, info, FALSE );
1530
1531     if (!bits) return ERROR_SUCCESS;  /* just querying the color information */
1532
1533     coords.x = 0;
1534     coords.y = 0;
1535     coords.width = width;
1536     coords.height = height;
1537     SetRect( &coords.visrect, 0, 0, width, height );
1538
1539     image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1540     if (!image) return ERROR_OUTOFMEMORY;
1541
1542     info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1543
1544     src_bits.ptr     = image->data;
1545     src_bits.is_copy = TRUE;
1546     ret = copy_image_bits( info, is_r8g8b8(vis), image, &src_bits, bits, &coords, mapping,
1547                            zeropad_masks[(width * image->bits_per_pixel) & 31] );
1548
1549     if (!ret && bits->ptr == image->data)
1550     {
1551         bits->free = free_ximage_bits;
1552         image->data = NULL;
1553     }
1554     XDestroyImage( image );
1555     return ret;
1556 }
1557
1558
1559 struct x11drv_window_surface
1560 {
1561     struct window_surface header;
1562     Window                window;
1563     GC                    gc;
1564     XImage               *image;
1565     RECT                  bounds;
1566     BOOL                  byteswap;
1567     BOOL                  is_argb;
1568     COLORREF              color_key;
1569     HRGN                  region;
1570     void                 *bits;
1571 #ifdef HAVE_LIBXXSHM
1572     XShmSegmentInfo       shminfo;
1573 #endif
1574     CRITICAL_SECTION      crit;
1575     BITMAPINFO            info;   /* variable size, must be last */
1576 };
1577
1578 static struct x11drv_window_surface *get_x11_surface( struct window_surface *surface )
1579 {
1580     return (struct x11drv_window_surface *)surface;
1581 }
1582
1583 static inline UINT get_color_component( UINT color, UINT mask )
1584 {
1585     int shift;
1586     for (shift = 0; !(mask & 1); shift++) mask >>= 1;
1587     return (color * mask / 255) << shift;
1588 }
1589
1590 static inline void flush_rgn_data( HRGN rgn, RGNDATA *data )
1591 {
1592     HRGN tmp = ExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data );
1593     CombineRgn( rgn, rgn, tmp, RGN_OR );
1594     DeleteObject( tmp );
1595     data->rdh.nCount = 0;
1596 }
1597
1598 static inline void add_row( HRGN rgn, RGNDATA *data, int x, int y, int len )
1599 {
1600     RECT *rect = (RECT *)data->Buffer + data->rdh.nCount;
1601
1602     if (len <= 0) return;
1603     rect->left   = x;
1604     rect->top    = y;
1605     rect->right  = x + len;
1606     rect->bottom = y + 1;
1607     data->rdh.nCount++;
1608     if (data->rdh.nCount * sizeof(RECT) > data->rdh.nRgnSize - sizeof(RECT))
1609         flush_rgn_data( rgn, data );
1610 }
1611
1612 /***********************************************************************
1613  *           update_surface_region
1614  */
1615 static void update_surface_region( struct x11drv_window_surface *surface )
1616 {
1617 #ifdef HAVE_LIBXSHAPE
1618     char buffer[4096];
1619     RGNDATA *data = (RGNDATA *)buffer;
1620     BITMAPINFO *info = &surface->info;
1621     UINT *masks = (UINT *)info->bmiColors;
1622     int x, y, start, width;
1623     HRGN rgn;
1624
1625     if (!shape_layered_windows) return;
1626
1627     if (!surface->is_argb && surface->color_key == CLR_INVALID)
1628     {
1629         XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, None, ShapeSet );
1630         return;
1631     }
1632
1633     data->rdh.dwSize = sizeof(data->rdh);
1634     data->rdh.iType  = RDH_RECTANGLES;
1635     data->rdh.nCount = 0;
1636     data->rdh.nRgnSize = sizeof(buffer) - sizeof(data->rdh);
1637
1638     rgn = CreateRectRgn( 0, 0, 0, 0 );
1639     width = surface->header.rect.right - surface->header.rect.left;
1640
1641     switch (info->bmiHeader.biBitCount)
1642     {
1643     case 16:
1644     {
1645         WORD *bits = surface->bits;
1646         int stride = (width + 1) & ~1;
1647         UINT mask = masks[0] | masks[1] | masks[2];
1648
1649         for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += stride)
1650         {
1651             x = 0;
1652             while (x < width)
1653             {
1654                 while (x < width && (bits[x] & mask) == surface->color_key) x++;
1655                 start = x;
1656                 while (x < width && (bits[x] & mask) != surface->color_key) x++;
1657                 add_row( rgn, data, surface->header.rect.left + start, y, x - start );
1658             }
1659         }
1660         break;
1661     }
1662     case 24:
1663     {
1664         BYTE *bits = surface->bits;
1665         int stride = (width * 3 + 3) & ~3;
1666
1667         for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += stride)
1668         {
1669             x = 0;
1670             while (x < width)
1671             {
1672                 while (x < width &&
1673                        (bits[x * 3] == GetBValue(surface->color_key)) &&
1674                        (bits[x * 3 + 1] == GetGValue(surface->color_key)) &&
1675                        (bits[x * 3 + 2] == GetRValue(surface->color_key)))
1676                     x++;
1677                 start = x;
1678                 while (x < width &&
1679                        ((bits[x * 3] != GetBValue(surface->color_key)) ||
1680                         (bits[x * 3 + 1] != GetGValue(surface->color_key)) ||
1681                         (bits[x * 3 + 2] != GetRValue(surface->color_key))))
1682                     x++;
1683                 add_row( rgn, data, surface->header.rect.left + start, y, x - start );
1684             }
1685         }
1686         break;
1687     }
1688     case 32:
1689     {
1690         DWORD *bits = surface->bits;
1691
1692         if (info->bmiHeader.biCompression == BI_RGB)
1693         {
1694             for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += width)
1695             {
1696                 x = 0;
1697                 while (x < width)
1698                 {
1699                     while (x < width &&
1700                            ((bits[x] & 0xffffff) == surface->color_key ||
1701                             (surface->is_argb && !(bits[x] & 0xff000000)))) x++;
1702                     start = x;
1703                     while (x < width &&
1704                            !((bits[x] & 0xffffff) == surface->color_key ||
1705                              (surface->is_argb && !(bits[x] & 0xff000000)))) x++;
1706                     add_row( rgn, data, surface->header.rect.left + start, y, x - start );
1707                 }
1708             }
1709         }
1710         else
1711         {
1712             UINT mask = masks[0] | masks[1] | masks[2];
1713             for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += width)
1714             {
1715                 x = 0;
1716                 while (x < width)
1717                 {
1718                     while (x < width && (bits[x] & mask) == surface->color_key) x++;
1719                     start = x;
1720                     while (x < width && (bits[x] & mask) != surface->color_key) x++;
1721                     add_row( rgn, data, surface->header.rect.left + start, y, x - start );
1722                 }
1723             }
1724         }
1725         break;
1726     }
1727     default:
1728         assert(0);
1729     }
1730
1731     if (data->rdh.nCount) flush_rgn_data( rgn, data );
1732
1733     if ((data = X11DRV_GetRegionData( rgn, 0 )))
1734     {
1735         XShapeCombineRectangles( gdi_display, surface->window, ShapeBounding, 0, 0,
1736                                  (XRectangle *)data->Buffer, data->rdh.nCount, ShapeSet, YXBanded );
1737         HeapFree( GetProcessHeap(), 0, data );
1738     }
1739
1740     DeleteObject( rgn );
1741 #endif
1742 }
1743
1744 /***********************************************************************
1745  *           set_color_key
1746  */
1747 static void set_color_key( struct x11drv_window_surface *surface, COLORREF key )
1748 {
1749     UINT *masks = (UINT *)surface->info.bmiColors;
1750
1751     if (key == CLR_INVALID)
1752         surface->color_key = CLR_INVALID;
1753     else if (surface->info.bmiHeader.biBitCount <= 8)
1754         surface->color_key = CLR_INVALID;
1755     else if (key & (1 << 24))  /* PALETTEINDEX */
1756         surface->color_key = 0;
1757     else if (key >> 16 == 0x10ff)  /* DIBINDEX */
1758         surface->color_key = 0;
1759     else if (surface->info.bmiHeader.biBitCount == 24)
1760         surface->color_key = key;
1761     else if (surface->info.bmiHeader.biCompression == BI_RGB)
1762         surface->color_key = (GetRValue(key) << 16) | (GetGValue(key) << 8) | GetBValue(key);
1763     else
1764         surface->color_key = get_color_component( GetRValue(key), masks[0] ) |
1765                              get_color_component( GetGValue(key), masks[1] ) |
1766                              get_color_component( GetBValue(key), masks[2] );
1767 }
1768
1769 #ifdef HAVE_LIBXXSHM
1770 static int xshm_error_handler( Display *display, XErrorEvent *event, void *arg )
1771 {
1772     return 1;  /* FIXME: should check event contents */
1773 }
1774
1775 static XImage *create_shm_image( const XVisualInfo *vis, int width, int height, XShmSegmentInfo *shminfo )
1776 {
1777     XImage *image;
1778
1779     shminfo->shmid = -1;
1780     image = XShmCreateImage( gdi_display, vis->visual, vis->depth, ZPixmap, NULL, shminfo, width, height );
1781     if (!image) return NULL;
1782     if (image->bytes_per_line & 3) goto failed;  /* we need 32-bit alignment */
1783
1784     shminfo->shmid = shmget( IPC_PRIVATE, image->bytes_per_line * height, IPC_CREAT | 0700 );
1785     if (shminfo->shmid == -1) goto failed;
1786
1787     shminfo->shmaddr = shmat( shminfo->shmid, 0, 0 );
1788     if (shminfo->shmaddr != (char *)-1)
1789     {
1790         BOOL ok;
1791
1792         shminfo->readOnly = True;
1793         X11DRV_expect_error( gdi_display, xshm_error_handler, NULL );
1794         ok = (XShmAttach( gdi_display, shminfo ) != 0);
1795         XSync( gdi_display, False );
1796         if (!X11DRV_check_error() && ok)
1797         {
1798             image->data = shminfo->shmaddr;
1799             shmctl( shminfo->shmid, IPC_RMID, 0 );
1800             return image;
1801         }
1802         shmdt( shminfo->shmaddr );
1803     }
1804     shmctl( shminfo->shmid, IPC_RMID, 0 );
1805     shminfo->shmid = -1;
1806
1807 failed:
1808     XDestroyImage( image );
1809     return NULL;
1810 }
1811 #endif /* HAVE_LIBXXSHM */
1812
1813 /***********************************************************************
1814  *           x11drv_surface_lock
1815  */
1816 static void x11drv_surface_lock( struct window_surface *window_surface )
1817 {
1818     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1819
1820     EnterCriticalSection( &surface->crit );
1821 }
1822
1823 /***********************************************************************
1824  *           x11drv_surface_unlock
1825  */
1826 static void x11drv_surface_unlock( struct window_surface *window_surface )
1827 {
1828     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1829
1830     LeaveCriticalSection( &surface->crit );
1831 }
1832
1833 /***********************************************************************
1834  *           x11drv_surface_get_bitmap_info
1835  */
1836 static void *x11drv_surface_get_bitmap_info( struct window_surface *window_surface, BITMAPINFO *info )
1837 {
1838     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1839
1840     memcpy( info, &surface->info, get_dib_info_size( &surface->info, DIB_RGB_COLORS ));
1841     return surface->bits;
1842 }
1843
1844 /***********************************************************************
1845  *           x11drv_surface_get_bounds
1846  */
1847 static RECT *x11drv_surface_get_bounds( struct window_surface *window_surface )
1848 {
1849     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1850
1851     return &surface->bounds;
1852 }
1853
1854 /***********************************************************************
1855  *           x11drv_surface_set_region
1856  */
1857 static void x11drv_surface_set_region( struct window_surface *window_surface, HRGN region )
1858 {
1859     RGNDATA *data;
1860     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1861
1862     TRACE( "updating surface %p with %p\n", surface, region );
1863
1864     window_surface->funcs->lock( window_surface );
1865     if (!region)
1866     {
1867         if (surface->region) DeleteObject( surface->region );
1868         surface->region = 0;
1869         XSetClipMask( gdi_display, surface->gc, None );
1870     }
1871     else
1872     {
1873         if (!surface->region) surface->region = CreateRectRgn( 0, 0, 0, 0 );
1874         CombineRgn( surface->region, region, 0, RGN_COPY );
1875         if ((data = X11DRV_GetRegionData( surface->region, 0 )))
1876         {
1877             XSetClipRectangles( gdi_display, surface->gc, 0, 0,
1878                                 (XRectangle *)data->Buffer, data->rdh.nCount, YXBanded );
1879             HeapFree( GetProcessHeap(), 0, data );
1880         }
1881     }
1882     window_surface->funcs->unlock( window_surface );
1883 }
1884
1885 /***********************************************************************
1886  *           x11drv_surface_flush
1887  */
1888 static void x11drv_surface_flush( struct window_surface *window_surface )
1889 {
1890     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1891     unsigned char *src = surface->bits;
1892     unsigned char *dst = (unsigned char *)surface->image->data;
1893     struct bitblt_coords coords;
1894
1895     window_surface->funcs->lock( window_surface );
1896     coords.x = 0;
1897     coords.y = 0;
1898     coords.width  = surface->header.rect.right - surface->header.rect.left;
1899     coords.height = surface->header.rect.bottom - surface->header.rect.top;
1900     SetRect( &coords.visrect, 0, 0, coords.width, coords.height );
1901     if (IntersectRect( &coords.visrect, &coords.visrect, &surface->bounds ))
1902     {
1903         TRACE( "flushing %p %dx%d bounds %s bits %p\n",
1904                surface, coords.width, coords.height,
1905                wine_dbgstr_rect( &surface->bounds ), surface->bits );
1906
1907         if (surface->is_argb || surface->color_key != CLR_INVALID) update_surface_region( surface );
1908
1909         if (src != dst)
1910         {
1911             const int *mapping = NULL;
1912             int width_bytes = surface->image->bytes_per_line;
1913
1914             if (surface->image->bits_per_pixel == 4 || surface->image->bits_per_pixel == 8)
1915                 mapping = X11DRV_PALETTE_PaletteToXPixel;
1916
1917             src += coords.visrect.top * width_bytes;
1918             dst += coords.visrect.top * width_bytes;
1919             copy_image_byteswap( &surface->info, src, dst, width_bytes, width_bytes,
1920                                  coords.visrect.bottom - coords.visrect.top,
1921                                  surface->byteswap, mapping, ~0u );
1922         }
1923
1924 #ifdef HAVE_LIBXXSHM
1925         if (surface->shminfo.shmid != -1)
1926             XShmPutImage( gdi_display, surface->window, surface->gc, surface->image,
1927                           coords.visrect.left, coords.visrect.top,
1928                           surface->header.rect.left + coords.visrect.left,
1929                           surface->header.rect.top + coords.visrect.top,
1930                           coords.visrect.right - coords.visrect.left,
1931                           coords.visrect.bottom - coords.visrect.top, False );
1932         else
1933 #endif
1934         XPutImage( gdi_display, surface->window, surface->gc, surface->image,
1935                    coords.visrect.left, coords.visrect.top,
1936                    surface->header.rect.left + coords.visrect.left,
1937                    surface->header.rect.top + coords.visrect.top,
1938                    coords.visrect.right - coords.visrect.left,
1939                    coords.visrect.bottom - coords.visrect.top );
1940     }
1941     reset_bounds( &surface->bounds );
1942     window_surface->funcs->unlock( window_surface );
1943 }
1944
1945 /***********************************************************************
1946  *           x11drv_surface_destroy
1947  */
1948 static void x11drv_surface_destroy( struct window_surface *window_surface )
1949 {
1950     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
1951
1952     TRACE( "freeing %p bits %p\n", surface, surface->bits );
1953     if (surface->gc) XFreeGC( gdi_display, surface->gc );
1954     if (surface->image)
1955     {
1956         if (surface->image->data != surface->bits) HeapFree( GetProcessHeap(), 0, surface->bits );
1957 #ifdef HAVE_LIBXXSHM
1958         if (surface->shminfo.shmid != -1)
1959         {
1960             XShmDetach( gdi_display, &surface->shminfo );
1961             shmdt( surface->shminfo.shmaddr );
1962         }
1963         else
1964 #endif
1965         HeapFree( GetProcessHeap(), 0, surface->image->data );
1966         surface->image->data = NULL;
1967         XDestroyImage( surface->image );
1968     }
1969     surface->crit.DebugInfo->Spare[0] = 0;
1970     DeleteCriticalSection( &surface->crit );
1971     if (surface->region) DeleteObject( surface->region );
1972     HeapFree( GetProcessHeap(), 0, surface );
1973 }
1974
1975 static const struct window_surface_funcs x11drv_surface_funcs =
1976 {
1977     x11drv_surface_lock,
1978     x11drv_surface_unlock,
1979     x11drv_surface_get_bitmap_info,
1980     x11drv_surface_get_bounds,
1981     x11drv_surface_set_region,
1982     x11drv_surface_flush,
1983     x11drv_surface_destroy
1984 };
1985
1986 /***********************************************************************
1987  *           create_surface
1988  */
1989 struct window_surface *create_surface( Window window, const XVisualInfo *vis, const RECT *rect,
1990                                        COLORREF color_key, BOOL use_alpha )
1991 {
1992     const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1993     struct x11drv_window_surface *surface;
1994     int width = rect->right - rect->left, height = rect->bottom - rect->top;
1995     int colors = format->bits_per_pixel <= 8 ? 1 << format->bits_per_pixel : 3;
1996
1997     surface = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1998                          FIELD_OFFSET( struct x11drv_window_surface, info.bmiColors[colors] ));
1999     if (!surface) return NULL;
2000     surface->info.bmiHeader.biSize        = sizeof(surface->info.bmiHeader);
2001     surface->info.bmiHeader.biWidth       = width;
2002     surface->info.bmiHeader.biHeight      = -height; /* top-down */
2003     surface->info.bmiHeader.biPlanes      = 1;
2004     surface->info.bmiHeader.biBitCount    = format->bits_per_pixel;
2005     surface->info.bmiHeader.biSizeImage   = get_dib_image_size( &surface->info );
2006     set_color_info( vis, &surface->info, use_alpha );
2007
2008     InitializeCriticalSection( &surface->crit );
2009     surface->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": surface");
2010
2011     surface->header.funcs = &x11drv_surface_funcs;
2012     surface->header.rect  = *rect;
2013     surface->header.ref   = 1;
2014     surface->window = window;
2015     surface->is_argb = (use_alpha && vis->depth == 32 && surface->info.bmiHeader.biCompression == BI_RGB);
2016     set_color_key( surface, color_key );
2017     reset_bounds( &surface->bounds );
2018
2019 #ifdef HAVE_LIBXXSHM
2020     surface->image = create_shm_image( vis, width, height, &surface->shminfo );
2021     if (!surface->image)
2022 #endif
2023     {
2024         surface->image = XCreateImage( gdi_display, vis->visual, vis->depth, ZPixmap, 0, NULL,
2025                                        width, height, 32, 0 );
2026         if (!surface->image) goto failed;
2027         surface->image->data = HeapAlloc( GetProcessHeap(), 0, surface->info.bmiHeader.biSizeImage );
2028         if (!surface->image->data) goto failed;
2029     }
2030
2031     surface->gc = XCreateGC( gdi_display, window, 0, NULL );
2032     surface->byteswap = image_needs_byteswap( surface->image, is_r8g8b8(vis), format->bits_per_pixel );
2033
2034     if (surface->byteswap || format->bits_per_pixel == 4 || format->bits_per_pixel == 8)
2035     {
2036         /* allocate separate surface bits if byte swapping or palette mapping is required */
2037         if (!(surface->bits  = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
2038                                           surface->info.bmiHeader.biSizeImage )))
2039             goto failed;
2040     }
2041     else surface->bits = surface->image->data;
2042
2043     TRACE( "created %p for %lx %s bits %p-%p image %p\n", surface, window, wine_dbgstr_rect(rect),
2044            surface->bits, (char *)surface->bits + surface->info.bmiHeader.biSizeImage,
2045            surface->image->data );
2046
2047     return &surface->header;
2048
2049 failed:
2050     x11drv_surface_destroy( &surface->header );
2051     return NULL;
2052 }
2053
2054 /***********************************************************************
2055  *           set_surface_color_key
2056  */
2057 void set_surface_color_key( struct window_surface *window_surface, COLORREF color_key )
2058 {
2059     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
2060     COLORREF prev;
2061
2062     window_surface->funcs->lock( window_surface );
2063     prev = surface->color_key;
2064     set_color_key( surface, color_key );
2065     if (surface->color_key != prev) update_surface_region( surface );
2066     window_surface->funcs->unlock( window_surface );
2067 }
2068
2069 /***********************************************************************
2070  *           expose_surface
2071  */
2072 HRGN expose_surface( struct window_surface *window_surface, const RECT *rect )
2073 {
2074     struct x11drv_window_surface *surface = get_x11_surface( window_surface );
2075     HRGN region = 0;
2076
2077     window_surface->funcs->lock( window_surface );
2078     add_bounds_rect( &surface->bounds, rect );
2079     if (surface->region)
2080     {
2081         region = CreateRectRgnIndirect( rect );
2082         if (CombineRgn( region, region, surface->region, RGN_DIFF ) <= NULLREGION)
2083         {
2084             DeleteObject( region );
2085             region = 0;
2086         }
2087     }
2088     window_surface->funcs->unlock( window_surface );
2089     return region;
2090 }