winex11: Use an X11 error handler to catch BadMatch errors from XGetImage.
[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 "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "winternl.h"
34 #include "x11drv.h"
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
38
39
40 #define DST 0   /* Destination drawable */
41 #define SRC 1   /* Source drawable */
42 #define TMP 2   /* Temporary drawable */
43 #define PAT 3   /* Pattern (brush) in destination DC */
44
45 #define OP(src,dst,rop)   (OP_ARGS(src,dst) << 4 | (rop))
46 #define OP_ARGS(src,dst)  (((src) << 2) | (dst))
47
48 #define OP_SRC(opcode)    ((opcode) >> 6)
49 #define OP_DST(opcode)    (((opcode) >> 4) & 3)
50 #define OP_SRCDST(opcode) ((opcode) >> 4)
51 #define OP_ROP(opcode)    ((opcode) & 0x0f)
52
53 #define MAX_OP_LEN  6  /* Longest opcode + 1 for the terminating 0 */
54
55 static const unsigned char BITBLT_Opcodes[256][MAX_OP_LEN] =
56 {
57     { OP(PAT,DST,GXclear) },                         /* 0x00  0              */
58     { OP(PAT,SRC,GXor), OP(SRC,DST,GXnor) },         /* 0x01  ~(D|(P|S))     */
59     { OP(PAT,SRC,GXnor), OP(SRC,DST,GXand) },        /* 0x02  D&~(P|S)       */
60     { OP(PAT,SRC,GXnor) },                           /* 0x03  ~(P|S)         */
61     { OP(PAT,DST,GXnor), OP(SRC,DST,GXand) },        /* 0x04  S&~(D|P)       */
62     { OP(PAT,DST,GXnor) },                           /* 0x05  ~(D|P)         */
63     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnor), },     /* 0x06  ~(P|~(D^S))    */
64     { OP(SRC,DST,GXand), OP(PAT,DST,GXnor) },        /* 0x07  ~(P|(D&S))     */
65     { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXand) },/* 0x08  S&D&~P         */
66     { OP(SRC,DST,GXxor), OP(PAT,DST,GXnor) },        /* 0x09  ~(P|(D^S))     */
67     { OP(PAT,DST,GXandInverted) },                   /* 0x0a  D&~P           */
68     { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXnor) }, /* 0x0b  ~(P|(S&~D))    */
69     { OP(PAT,SRC,GXandInverted) },                   /* 0x0c  S&~P           */
70     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXnor) },/* 0x0d  ~(P|(D&~S))    */
71     { OP(SRC,DST,GXnor), OP(PAT,DST,GXnor) },        /* 0x0e  ~(P|~(D|S))    */
72     { OP(PAT,DST,GXcopyInverted) },                  /* 0x0f  ~P             */
73     { OP(SRC,DST,GXnor), OP(PAT,DST,GXand) },        /* 0x10  P&~(S|D)       */
74     { OP(SRC,DST,GXnor) },                           /* 0x11  ~(D|S)         */
75     { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnor) },      /* 0x12  ~(S|~(D^P))    */
76     { OP(PAT,DST,GXand), OP(SRC,DST,GXnor) },        /* 0x13  ~(S|(D&P))     */
77     { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnor) },      /* 0x14  ~(D|~(P^S))    */
78     { OP(PAT,SRC,GXand), OP(SRC,DST,GXnor) },        /* 0x15  ~(D|(P&S))     */
79     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
80       OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
81       OP(PAT,DST,GXxor) },                           /* 0x16  P^S^(D&~(P&S)  */
82     { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
83       OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
84       OP(TMP,DST,GXequiv) },                         /* 0x17 ~S^((S^P)&(S^D))*/
85     { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
86         OP(SRC,DST,GXand) },                         /* 0x18  (S^P)&(D^P)    */
87     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
88       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x19  ~S^(D&~(P&S))  */
89     { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
90       OP(PAT,DST,GXxor) },                           /* 0x1a  P^(D|(S&P))    */
91     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
92       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x1b  ~S^(D&(P^S))   */
93     { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
94       OP(PAT,DST,GXxor) },                           /* 0x1c  P^(S|(D&P))    */
95     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
96       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x1d  ~D^(S&(D^P))   */
97     { OP(SRC,DST,GXor), OP(PAT,DST,GXxor) },         /* 0x1e  P^(D|S)        */
98     { OP(SRC,DST,GXor), OP(PAT,DST,GXnand) },        /* 0x1f  ~(P&(D|S))     */
99     { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXand) }, /* 0x20  D&(P&~S)       */
100     { OP(PAT,DST,GXxor), OP(SRC,DST,GXnor) },        /* 0x21  ~(S|(D^P))     */
101     { OP(SRC,DST,GXandInverted) },                   /* 0x22  ~S&D           */
102     { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x23  ~(S|(P&~D))    */
103     { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
104       OP(SRC,DST,GXand) },                           /* 0x24   (S^P)&(S^D)   */
105     { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand),
106       OP(PAT,DST,GXequiv) },                         /* 0x25  ~P^(D&~(S&P))  */
107     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
108       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x26  S^(D|(S&P))    */
109     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXequiv),
110       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x27  S^(D|~(P^S))   */
111     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand) },        /* 0x28  D&(P^S)        */
112     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
113       OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
114       OP(PAT,DST,GXequiv) },                         /* 0x29  ~P^S^(D|(P&S)) */
115     { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand) },       /* 0x2a  D&~(P&S)       */
116     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
117       OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
118       OP(TMP,DST,GXequiv) },                         /* 0x2b ~S^((P^S)&(P^D))*/
119     { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
120       OP(SRC,DST,GXxor) },                           /* 0x2c  S^(P&(S|D))    */
121     { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXxor) },  /* 0x2d  P^(S|~D)       */
122     { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
123       OP(PAT,DST,GXxor) },                           /* 0x2e  P^(S|(D^P))    */
124     { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXnand) }, /* 0x2f  ~(P&(S|~D))    */
125     { OP(PAT,SRC,GXandReverse) },                    /* 0x30  P&~S           */
126     { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXnor) },/* 0x31  ~(S|(D&~P))    */
127     { OP(SRC,DST,GXor), OP(PAT,DST,GXor),
128       OP(SRC,DST,GXxor) },                           /* 0x32  S^(D|P|S)      */
129     { OP(SRC,DST,GXcopyInverted) },                  /* 0x33  ~S             */
130     { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
131       OP(SRC,DST,GXxor) },                           /* 0x34  S^(P|(D&S))    */
132     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor),
133       OP(SRC,DST,GXxor) },                           /* 0x35  S^(P|~(D^S))   */
134     { OP(PAT,DST,GXor), OP(SRC,DST,GXxor) },         /* 0x36  S^(D|P)        */
135     { OP(PAT,DST,GXor), OP(SRC,DST,GXnand) },        /* 0x37  ~(S&(D|P))     */
136     { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
137       OP(PAT,DST,GXxor) },                           /* 0x38  P^(S&(D|P))    */
138     { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXxor) },  /* 0x39  S^(P|~D)       */
139     { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
140       OP(SRC,DST,GXxor) },                           /* 0x3a  S^(P|(D^S))    */
141     { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x3b  ~(S&(P|~D))    */
142     { OP(PAT,SRC,GXxor) },                           /* 0x3c  P^S            */
143     { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
144       OP(SRC,DST,GXxor) },                           /* 0x3d  S^(P|~(D|S))   */
145     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
146       OP(SRC,DST,GXxor) },                           /* 0x3e  S^(P|(D&~S))   */
147     { OP(PAT,SRC,GXnand) },                          /* 0x3f  ~(P&S)         */
148     { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXand) }, /* 0x40  P&S&~D         */
149     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnor) },        /* 0x41  ~(D|(P^S))     */
150     { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
151       OP(SRC,DST,GXand) },                           /* 0x42  (S^D)&(P^D)    */
152     { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
153       OP(SRC,DST,GXequiv) },                         /* 0x43  ~S^(P&~(D&S))  */
154     { OP(SRC,DST,GXandReverse) },                    /* 0x44  S&~D           */
155     { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x45  ~(D|(P&~S))    */
156     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
157       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x46  D^(S|(P&D))    */
158     { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
159       OP(PAT,DST,GXequiv) },                         /* 0x47  ~P^(S&(D^P))   */
160     { OP(PAT,DST,GXxor), OP(SRC,DST,GXand) },        /* 0x48  S&(P^D)        */
161     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
162       OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
163       OP(PAT,DST,GXequiv) },                         /* 0x49  ~P^D^(S|(P&D)) */
164     { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
165       OP(SRC,DST,GXxor) },                           /* 0x4a  D^(P&(S|D))    */
166     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXxor) }, /* 0x4b  P^(D|~S)       */
167     { OP(PAT,DST,GXnand), OP(SRC,DST,GXand) },       /* 0x4c  S&~(D&P)       */
168     { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
169       OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
170       OP(TMP,DST,GXequiv) },                         /* 0x4d ~S^((S^P)|(S^D))*/
171     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
172       OP(PAT,DST,GXxor) },                           /* 0x4e  P^(D|(S^P))    */
173     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXnand) },/* 0x4f  ~(P&(D|~S))    */
174     { OP(PAT,DST,GXandReverse) },                    /* 0x50  P&~D           */
175     { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXnor) },/* 0x51  ~(D|(S&~P))    */
176     { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
177       OP(SRC,DST,GXxor) },                           /* 0x52  D^(P|(S&D))    */
178     { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
179       OP(SRC,DST,GXequiv) },                         /* 0x53  ~S^(P&(D^S))   */
180     { OP(PAT,SRC,GXnor), OP(SRC,DST,GXnor) },        /* 0x54  ~(D|~(P|S))    */
181     { OP(PAT,DST,GXinvert) },                        /* 0x55  ~D             */
182     { OP(PAT,SRC,GXor), OP(SRC,DST,GXxor) },         /* 0x56  D^(P|S)        */
183     { OP(PAT,SRC,GXor), OP(SRC,DST,GXnand) },        /* 0x57  ~(D&(P|S))     */
184     { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
185       OP(PAT,DST,GXxor) },                           /* 0x58  P^(D&(P|S))    */
186     { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXxor) },  /* 0x59  D^(P|~S)       */
187     { OP(PAT,DST,GXxor) },                           /* 0x5a  D^P            */
188     { OP(DST,SRC,GXnor), OP(PAT,SRC,GXor),
189       OP(SRC,DST,GXxor) },                           /* 0x5b  D^(P|~(S|D))   */
190     { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
191       OP(SRC,DST,GXxor) },                           /* 0x5c  D^(P|(S^D))    */
192     { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x5d  ~(D&(P|~S))    */
193     { OP(DST,SRC,GXandInverted), OP(PAT,SRC,GXor),
194       OP(SRC,DST,GXxor) },                           /* 0x5e  D^(P|(S&~D))   */
195     { OP(PAT,DST,GXnand) },                          /* 0x5f  ~(D&P)         */
196     { OP(SRC,DST,GXxor), OP(PAT,DST,GXand) },        /* 0x60  P&(D^S)        */
197     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
198       OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
199       OP(TMP,DST,GXequiv) },                         /* 0x61  ~D^S^(P|(D&S)) */
200     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
201       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0x62  D^(S&(P|D))    */
202     { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x63  S^(D|~P)       */
203     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
204       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0x64  S^(D&(P|S))    */
205     { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x65  D^(S|~P)       */
206     { OP(SRC,DST,GXxor) },                           /* 0x66  S^D            */
207     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
208       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x67  S^(D|~(S|P)    */
209     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnor),
210       OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
211       OP(TMP,DST,GXequiv) },                         /* 0x68  ~D^S^(P|~(D|S))*/
212     { OP(SRC,DST,GXxor), OP(PAT,DST,GXequiv) },      /* 0x69  ~P^(D^S)       */
213     { OP(PAT,SRC,GXand), OP(SRC,DST,GXxor) },        /* 0x6a  D^(P&S)        */
214     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
215       OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
216       OP(PAT,DST,GXequiv) },                         /* 0x6b  ~P^S^(D&(P|S)) */
217     { OP(PAT,DST,GXand), OP(SRC,DST,GXxor) },        /* 0x6c  S^(D&P)        */
218     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
219       OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
220       OP(PAT,DST,GXequiv) },                         /* 0x6d  ~P^D^(S&(P|D)) */
221     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
222       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0x6e  S^(D&(P|~S))   */
223     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnand) },     /* 0x6f  ~(P&~(S^D))    */
224     { OP(SRC,DST,GXnand), OP(PAT,DST,GXand) },       /* 0x70  P&~(D&S)       */
225     { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
226       OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
227       OP(TMP,DST,GXequiv) },                         /* 0x71 ~S^((S^D)&(P^D))*/
228     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
229       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x72  S^(D|(P^S))    */
230     { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXnand) },/* 0x73  ~(S&(D|~P))    */
231     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
232       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x74   D^(S|(P^D))   */
233     { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXnand) },/* 0x75  ~(D&(S|~P))    */
234     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
235       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x76  S^(D|(P&~S))   */
236     { OP(SRC,DST,GXnand) },                          /* 0x77  ~(S&D)         */
237     { OP(SRC,DST,GXand), OP(PAT,DST,GXxor) },        /* 0x78  P^(D&S)        */
238     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
239       OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
240       OP(TMP,DST,GXequiv) },                         /* 0x79  ~D^S^(P&(D|S)) */
241     { OP(DST,SRC,GXorInverted), OP(PAT,SRC,GXand),
242       OP(SRC,DST,GXxor) },                           /* 0x7a  D^(P&(S|~D))   */
243     { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnand) },     /* 0x7b  ~(S&~(D^P))    */
244     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
245       OP(SRC,DST,GXxor) },                           /* 0x7c  S^(P&(D|~S))   */
246     { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnand) },     /* 0x7d  ~(D&~(P^S))    */
247     { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
248       OP(SRC,DST,GXor) },                            /* 0x7e  (S^P)|(S^D)    */
249     { OP(PAT,SRC,GXand), OP(SRC,DST,GXnand) },       /* 0x7f  ~(D&P&S)       */
250     { OP(PAT,SRC,GXand), OP(SRC,DST,GXand) },        /* 0x80  D&P&S          */
251     { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
252       OP(SRC,DST,GXnor) },                           /* 0x81  ~((S^P)|(S^D)) */
253     { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXand) },      /* 0x82  D&~(P^S)       */
254     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
255       OP(SRC,DST,GXequiv) },                         /* 0x83  ~S^(P&(D|~S))  */
256     { OP(PAT,DST,GXequiv), OP(SRC,DST,GXand) },      /* 0x84  S&~(D^P)       */
257     { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand),
258       OP(PAT,DST,GXequiv) },                         /* 0x85  ~P^(D&(S|~P))  */
259     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
260       OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
261       OP(TMP,DST,GXxor) },                           /* 0x86  D^S^(P&(D|S))  */
262     { OP(SRC,DST,GXand), OP(PAT,DST,GXequiv) },      /* 0x87  ~P^(D&S)       */
263     { OP(SRC,DST,GXand) },                           /* 0x88  S&D            */
264     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
265       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0x89  ~S^(D|(P&~S))  */
266     { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8a  D&(S|~P)       */
267     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
268       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0x8b  ~D^(S|(P^D))   */
269     { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8c  S&(D|~P)       */
270     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
271       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0x8d  ~S^(D|(P^S))   */
272     { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
273       OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
274       OP(TMP,DST,GXxor) },                           /* 0x8e  S^((S^D)&(P^D))*/
275     { OP(SRC,DST,GXnand), OP(PAT,DST,GXnand) },      /* 0x8f  ~(P&~(D&S))    */
276     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXand) },      /* 0x90  P&~(D^S)       */
277     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
278       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x91  ~S^(D&(P|~S))  */
279     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
280       OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
281       OP(TMP,DST,GXxor) },                           /* 0x92  D^P^(S&(D|P))  */
282     { OP(PAT,DST,GXand), OP(SRC,DST,GXequiv) },      /* 0x93  ~S^(P&D)       */
283     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
284       OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
285       OP(TMP,DST,GXxor) },                           /* 0x94  S^P^(D&(P|S))  */
286     { OP(PAT,SRC,GXand), OP(SRC,DST,GXequiv) },      /* 0x95  ~D^(P&S)       */
287     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXxor) },        /* 0x96  D^P^S          */
288     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
289       OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
290       OP(TMP,DST,GXxor) },                           /* 0x97  S^P^(D|~(P|S)) */
291     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
292       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0x98  ~S^(D|~(P|S))  */
293     { OP(SRC,DST,GXequiv) },                         /* 0x99  ~S^D           */
294     { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9a  D^(P&~S)       */
295     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
296       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x9b  ~S^(D&(P|S))   */
297     { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9c  S^(P&~D)       */
298     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
299       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x9d  ~D^(S&(P|D))   */
300     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
301       OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
302       OP(TMP,DST,GXxor) },                           /* 0x9e  D^S^(P|(D&S))  */
303     { OP(SRC,DST,GXxor), OP(PAT,DST,GXnand) },       /* 0x9f  ~(P&(D^S))     */
304     { OP(PAT,DST,GXand) },                           /* 0xa0  D&P            */
305     { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor),
306       OP(PAT,DST,GXequiv) },                         /* 0xa1  ~P^(D|(S&~P))  */
307     { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXand) },  /* 0xa2  D&(P|~S)       */
308     { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
309       OP(SRC,DST,GXequiv) },                         /* 0xa3  ~D^(P|(S^D))   */
310     { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor),
311       OP(PAT,DST,GXequiv) },                         /* 0xa4  ~P^(D|~(S|P))  */
312     { OP(PAT,DST,GXequiv) },                         /* 0xa5  ~P^D           */
313     { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXxor) },/* 0xa6  D^(S&~P)       */
314     { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
315       OP(PAT,DST,GXequiv) },                         /* 0xa7  ~P^(D&(S|P))   */
316     { OP(PAT,SRC,GXor), OP(SRC,DST,GXand) },         /* 0xa8  D&(P|S)        */
317     { OP(PAT,SRC,GXor), OP(SRC,DST,GXequiv) },       /* 0xa9  ~D^(P|S)       */
318     { OP(PAT,DST,GXnoop) },                          /* 0xaa  D              */
319     { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor) },         /* 0xab  D|~(P|S)       */
320     { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
321       OP(SRC,DST,GXxor) },                           /* 0xac  S^(P&(D^S))    */
322     { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
323       OP(SRC,DST,GXequiv) },                         /* 0xad  ~D^(P|(S&D))   */
324     { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor) }, /* 0xae  D|(S&~P)       */
325     { OP(PAT,DST,GXorInverted) },                    /* 0xaf  D|~P           */
326     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand) }, /* 0xb0  P&(D|~S)       */
327     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
328       OP(PAT,DST,GXequiv) },                         /* 0xb1  ~P^(D|(S^P))   */
329     { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
330       OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
331       OP(TMP,DST,GXxor) },                           /* 0xb2  S^((S^P)|(S^D))*/
332     { OP(PAT,DST,GXnand), OP(SRC,DST,GXnand) },      /* 0xb3  ~(S&~(D&P))    */
333     { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXxor) }, /* 0xb4  P^(S&~D)       */
334     { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
335       OP(SRC,DST,GXequiv) },                         /* 0xb5  ~D^(P&(S|D))   */
336     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
337       OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
338       OP(TMP,DST,GXxor) },                           /* 0xb6  D^P^(S|(D&P))  */
339     { OP(PAT,DST,GXxor), OP(SRC,DST,GXnand) },       /* 0xb7  ~(S&(D^P))     */
340     { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
341       OP(PAT,DST,GXxor) },                           /* 0xb8  P^(S&(D^P))    */
342     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
343       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0xb9  ~D^(S|(P&D))   */
344     { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXor) },  /* 0xba  D|(P&~S)       */
345     { OP(SRC,DST,GXorInverted) },                    /* 0xbb  ~S|D           */
346     { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
347       OP(SRC,DST,GXxor) },                           /* 0xbc  S^(P&~(D&S))   */
348     { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
349       OP(SRC,DST,GXnand) },                          /* 0xbd  ~((S^D)&(P^D)) */
350     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor) },         /* 0xbe  D|(P^S)        */
351     { OP(PAT,SRC,GXnand), OP(SRC,DST,GXor) },        /* 0xbf  D|~(P&S)       */
352     { OP(PAT,SRC,GXand) },                           /* 0xc0  P&S            */
353     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
354       OP(SRC,DST,GXequiv) },                         /* 0xc1  ~S^(P|(D&~S))  */
355     { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
356       OP(SRC,DST,GXequiv) },                         /* 0xc2  ~S^(P|~(D|S))  */
357     { OP(PAT,SRC,GXequiv) },                         /* 0xc3  ~P^S           */
358     { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXand) },  /* 0xc4  S&(P|~D)       */
359     { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
360       OP(SRC,DST,GXequiv) },                         /* 0xc5  ~S^(P|(D^S))   */
361     { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXxor) },/* 0xc6  S^(D&~P)       */
362     { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
363       OP(PAT,DST,GXequiv) },                         /* 0xc7  ~P^(S&(D|P))   */
364     { OP(PAT,DST,GXor), OP(SRC,DST,GXand) },         /* 0xc8  S&(D|P)        */
365     { OP(PAT,DST,GXor), OP(SRC,DST,GXequiv) },       /* 0xc9  ~S^(P|D)       */
366     { OP(DST,SRC,GXxor), OP(PAT,SRC,GXand),
367       OP(SRC,DST,GXxor) },                           /* 0xca  D^(P&(S^D))    */
368     { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
369       OP(SRC,DST,GXequiv) },                         /* 0xcb  ~S^(P|(D&S))   */
370     { OP(SRC,DST,GXcopy) },                          /* 0xcc  S              */
371     { OP(PAT,DST,GXnor), OP(SRC,DST,GXor) },         /* 0xcd  S|~(D|P)       */
372     { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXor) }, /* 0xce  S|(D&~P)       */
373     { OP(PAT,SRC,GXorInverted) },                    /* 0xcf  S|~P           */
374     { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXand) },  /* 0xd0  P&(S|~D)       */
375     { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
376       OP(PAT,DST,GXequiv) },                         /* 0xd1  ~P^(S|(D^P))   */
377     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXxor) },/* 0xd2  P^(D&~S)       */
378     { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
379       OP(SRC,DST,GXequiv) },                         /* 0xd3  ~S^(P&(D|S))   */
380     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
381       OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
382       OP(TMP,DST,GXxor) },                           /* 0xd4  S^((S^P)&(D^P))*/
383     { OP(PAT,SRC,GXnand), OP(SRC,DST,GXnand) },      /* 0xd5  ~(D&~(P&S))    */
384     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
385       OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
386       OP(TMP,DST,GXxor) },                           /* 0xd6  S^P^(D|(P&S))  */
387     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnand) },       /* 0xd7  ~(D&(P^S))     */
388     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
389       OP(PAT,DST,GXxor) },                           /* 0xd8  P^(D&(S^P))    */
390     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
391       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0xd9  ~S^(D|(P&S))   */
392     { OP(DST,SRC,GXnand), OP(PAT,SRC,GXand),
393       OP(SRC,DST,GXxor) },                           /* 0xda  D^(P&~(S&D))   */
394     { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
395       OP(SRC,DST,GXnand) },                          /* 0xdb  ~((S^P)&(S^D)) */
396     { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXor) },  /* 0xdc  S|(P&~D)       */
397     { OP(SRC,DST,GXorReverse) },                     /* 0xdd  S|~D           */
398     { OP(PAT,DST,GXxor), OP(SRC,DST,GXor) },         /* 0xde  S|(D^P)        */
399     { OP(PAT,DST,GXnand), OP(SRC,DST,GXor) },        /* 0xdf  S|~(D&P)       */
400     { OP(SRC,DST,GXor), OP(PAT,DST,GXand) },         /* 0xe0  P&(D|S)        */
401     { OP(SRC,DST,GXor), OP(PAT,DST,GXequiv) },       /* 0xe1  ~P^(D|S)       */
402     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
403       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0xe2  D^(S&(P^D))    */
404     { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
405       OP(PAT,DST,GXequiv) },                         /* 0xe3  ~P^(S|(D&P))   */
406     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
407       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0xe4  S^(D&(P^S))    */
408     { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
409       OP(PAT,DST,GXequiv) },                         /* 0xe5  ~P^(D|(S&P))   */
410     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
411       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0xe6  S^(D&~(P&S))   */
412     { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
413       OP(SRC,DST,GXnand) },                          /* 0xe7  ~((S^P)&(D^P)) */
414     { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
415       OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
416       OP(TMP,DST,GXxor) },                           /* 0xe8  S^((S^P)&(S^D))*/
417     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnand),
418       OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
419       OP(TMP,DST,GXequiv) },                         /* 0xe9  ~D^S^(P&~(S&D))*/
420     { OP(PAT,SRC,GXand), OP(SRC,DST,GXor) },         /* 0xea  D|(P&S)        */
421     { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXor) },       /* 0xeb  D|~(P^S)       */
422     { OP(PAT,DST,GXand), OP(SRC,DST,GXor) },         /* 0xec  S|(D&P)        */
423     { OP(PAT,DST,GXequiv), OP(SRC,DST,GXor) },       /* 0xed  S|~(D^P)       */
424     { OP(SRC,DST,GXor) },                            /* 0xee  S|D            */
425     { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXor) },  /* 0xef  S|D|~P         */
426     { OP(PAT,DST,GXcopy) },                          /* 0xf0  P              */
427     { OP(SRC,DST,GXnor), OP(PAT,DST,GXor) },         /* 0xf1  P|~(D|S)       */
428     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor) }, /* 0xf2  P|(D&~S)       */
429     { OP(PAT,SRC,GXorReverse) },                     /* 0xf3  P|~S           */
430     { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXor) },  /* 0xf4  P|(S&~D)       */
431     { OP(PAT,DST,GXorReverse) },                     /* 0xf5  P|~D           */
432     { OP(SRC,DST,GXxor), OP(PAT,DST,GXor) },         /* 0xf6  P|(D^S)        */
433     { OP(SRC,DST,GXnand), OP(PAT,DST,GXor) },        /* 0xf7  P|~(S&D)       */
434     { OP(SRC,DST,GXand), OP(PAT,DST,GXor) },         /* 0xf8  P|(D&S)        */
435     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor) },       /* 0xf9  P|~(D^S)       */
436     { OP(PAT,DST,GXor) },                            /* 0xfa  D|P            */
437     { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXor) },   /* 0xfb  D|P|~S         */
438     { OP(PAT,SRC,GXor) },                            /* 0xfc  P|S            */
439     { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXor) },   /* 0xfd  P|S|~D         */
440     { OP(SRC,DST,GXor), OP(PAT,DST,GXor) },          /* 0xfe  P|D|S          */
441     { OP(PAT,DST,GXset) }                            /* 0xff  1              */
442 };
443
444 static const unsigned char bit_swap[256] =
445 {
446     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
447     0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
448     0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
449     0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
450     0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
451     0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
452     0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
453     0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
454     0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
455     0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
456     0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
457     0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
458     0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
459     0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
460     0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
461     0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
462     0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
463     0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
464     0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
465     0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
466     0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
467     0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
468     0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
469     0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
470     0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
471     0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
472     0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
473     0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
474     0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
475     0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
476     0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
477     0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
478 };
479
480 #ifdef WORDS_BIGENDIAN
481 static const unsigned int zeropad_masks[32] =
482 {
483     0xffffffff, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
484     0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
485     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
486     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe
487 };
488 #else
489 static const unsigned int zeropad_masks[32] =
490 {
491     0xffffffff, 0x00000080, 0x000000c0, 0x000000e0, 0x000000f0, 0x000000f8, 0x000000fc, 0x000000fe,
492     0x000000ff, 0x000080ff, 0x0000c0ff, 0x0000e0ff, 0x0000f0ff, 0x0000f8ff, 0x0000fcff, 0x0000feff,
493     0x0000ffff, 0x0080ffff, 0x00c0ffff, 0x00e0ffff, 0x00f0ffff, 0x00f8ffff, 0x00fcffff, 0x00feffff,
494     0x00ffffff, 0x80ffffff, 0xc0ffffff, 0xe0ffffff, 0xf0ffffff, 0xf8ffffff, 0xfcffffff, 0xfeffffff
495 };
496 #endif
497
498 #ifdef BITBLT_TEST  /* Opcodes test */
499
500 static int do_bitop( int s, int d, int rop )
501 {
502     int res;
503     switch(rop)
504     {
505     case GXclear:        res = 0; break;
506     case GXand:          res = s & d; break;
507     case GXandReverse:   res = s & ~d; break;
508     case GXcopy:         res = s; break;
509     case GXandInverted:  res = ~s & d; break;
510     case GXnoop:         res = d; break;
511     case GXxor:          res = s ^ d; break;
512     case GXor:           res = s | d; break;
513     case GXnor:          res = ~(s | d); break;
514     case GXequiv:        res = ~s ^ d; break;
515     case GXinvert:       res = ~d; break;
516     case GXorReverse:    res = s | ~d; break;
517     case GXcopyInverted: res = ~s; break;
518     case GXorInverted:   res = ~s | d; break;
519     case GXnand:         res = ~(s & d); break;
520     case GXset:          res = 1; break;
521     }
522     return res & 1;
523 }
524
525 int main()
526 {
527     int rop, i, res, src, dst, pat, tmp, dstUsed;
528     const unsigned char *opcode;
529
530     for (rop = 0; rop < 256; rop++)
531     {
532         res = dstUsed = 0;
533         for (i = 0; i < 8; i++)
534         {
535             pat = (i >> 2) & 1;
536             src = (i >> 1) & 1;
537             dst = i & 1;
538             for (opcode = BITBLT_Opcodes[rop]; *opcode; opcode++)
539             {
540                 switch(*opcode >> 4)
541                 {
542                 case OP_ARGS(DST,TMP):
543                     tmp = do_bitop( dst, tmp, *opcode & 0xf );
544                     break;
545                 case OP_ARGS(DST,SRC):
546                     src = do_bitop( dst, src, *opcode & 0xf );
547                     break;
548                 case OP_ARGS(SRC,TMP):
549                     tmp = do_bitop( src, tmp, *opcode & 0xf );
550                     break;
551                 case OP_ARGS(SRC,DST):
552                     dst = do_bitop( src, dst, *opcode & 0xf );
553                     dstUsed = 1;
554                     break;
555                 case OP_ARGS(PAT,DST):
556                     dst = do_bitop( pat, dst, *opcode & 0xf );
557                     dstUsed = 1;
558                     break;
559                 case OP_ARGS(PAT,SRC):
560                     src = do_bitop( pat, src, *opcode & 0xf );
561                     break;
562                 case OP_ARGS(TMP,DST):
563                     dst = do_bitop( tmp, dst, *opcode & 0xf );
564                     dstUsed = 1;
565                     break;
566                 case OP_ARGS(TMP,SRC):
567                     src = do_bitop( tmp, src, *opcode & 0xf );
568                     break;
569                 default:
570                     printf( "Invalid opcode %x\n", *opcode );
571                 }
572             }
573             if (!dstUsed) dst = src;
574             if (dst) res |= 1 << i;
575         }
576         if (res != rop) printf( "%02x: ERROR, res=%02x\n", rop, res );
577     }
578
579     return 0;
580 }
581
582 #endif  /* BITBLT_TEST */
583
584
585 /* handler for XGetImage BadMatch errors */
586 static int XGetImage_handler( Display *dpy, XErrorEvent *event, void *arg )
587 {
588     return (event->request_code == X_GetImage && event->error_code == BadMatch);
589 }
590
591 /***********************************************************************
592  *           BITBLT_GetDstArea
593  *
594  * Retrieve an area from the destination DC, mapping all the
595  * pixels to Windows colors.
596  */
597 static int BITBLT_GetDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, GC gc, const RECT *visRectDst)
598 {
599     int exposures = 0;
600     INT width  = visRectDst->right - visRectDst->left;
601     INT height = visRectDst->bottom - visRectDst->top;
602     BOOL memdc = (GetObjectType( physDev->dev.hdc ) == OBJ_MEMDC);
603
604     wine_tsx11_lock();
605
606     if (!X11DRV_PALETTE_XPixelToPalette || (physDev->depth == 1) ||
607         (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
608     {
609         XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
610                    physDev->dc_rect.left + visRectDst->left, physDev->dc_rect.top + visRectDst->top,
611                    width, height, 0, 0 );
612         exposures++;
613     }
614     else
615     {
616         register INT x, y;
617         XImage *image;
618
619         if (memdc)
620             image = XGetImage( gdi_display, physDev->drawable,
621                                physDev->dc_rect.left + visRectDst->left,
622                                physDev->dc_rect.top + visRectDst->top,
623                                width, height, AllPlanes, ZPixmap );
624         else
625         {
626             /* Make sure we don't get a BadMatch error */
627             XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
628                        physDev->dc_rect.left + visRectDst->left,
629                        physDev->dc_rect.top + visRectDst->top,
630                        width, height, 0, 0);
631             exposures++;
632             image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
633                                AllPlanes, ZPixmap );
634         }
635         if (image)
636         {
637             for (y = 0; y < height; y++)
638                 for (x = 0; x < width; x++)
639                     XPutPixel( image, x, y,
640                                X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]);
641             XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height );
642             XDestroyImage( image );
643         }
644     }
645
646     wine_tsx11_unlock();
647     return exposures;
648 }
649
650
651 /***********************************************************************
652  *           BITBLT_PutDstArea
653  *
654  * Put an area back into the destination DC, mapping the pixel
655  * colors to X pixels.
656  */
657 static int BITBLT_PutDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, const RECT *visRectDst)
658 {
659     int exposures = 0;
660     INT width  = visRectDst->right - visRectDst->left;
661     INT height = visRectDst->bottom - visRectDst->top;
662
663     /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
664
665     if (!X11DRV_PALETTE_PaletteToXPixel || (physDev->depth == 1) ||
666         (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
667     {
668         XCopyArea( gdi_display, pixmap, physDev->drawable, physDev->gc, 0, 0, width, height,
669                    physDev->dc_rect.left + visRectDst->left,
670                    physDev->dc_rect.top + visRectDst->top );
671         exposures++;
672     }
673     else
674     {
675         register INT x, y;
676         XImage *image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
677                                    AllPlanes, ZPixmap );
678         for (y = 0; y < height; y++)
679             for (x = 0; x < width; x++)
680             {
681                 XPutPixel( image, x, y,
682                            X11DRV_PALETTE_PaletteToXPixel[XGetPixel( image, x, y )]);
683             }
684         XPutImage( gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
685                    physDev->dc_rect.left + visRectDst->left,
686                    physDev->dc_rect.top + visRectDst->top, width, height );
687         XDestroyImage( image );
688     }
689     return exposures;
690 }
691
692 static BOOL same_format(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst)
693 {
694     if (physDevSrc->depth != physDevDst->depth) return FALSE;
695     if (!physDevSrc->color_shifts && !physDevDst->color_shifts) return TRUE;
696     if (physDevSrc->color_shifts && physDevDst->color_shifts)
697         return !memcmp(physDevSrc->color_shifts, physDevDst->color_shifts, sizeof(ColorShifts));
698     return FALSE;
699 }
700
701 void execute_rop( X11DRV_PDEVICE *physdev, Pixmap src_pixmap, GC gc, const RECT *visrect, DWORD rop )
702 {
703     Pixmap pixmaps[3];
704     Pixmap result = src_pixmap;
705     BOOL null_brush;
706     const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
707     BOOL use_pat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
708     BOOL use_dst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
709     int width  = visrect->right - visrect->left;
710     int height = visrect->bottom - visrect->top;
711
712     pixmaps[SRC] = src_pixmap;
713     pixmaps[TMP] = 0;
714     wine_tsx11_lock();
715     pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
716     wine_tsx11_unlock();
717
718     if (use_dst) BITBLT_GetDstArea( physdev, pixmaps[DST], gc, visrect );
719     null_brush = use_pat && !X11DRV_SetupGCForPatBlt( physdev, gc, TRUE );
720
721     wine_tsx11_lock();
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     wine_tsx11_unlock();
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     X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod );
766
767     wine_tsx11_lock();
768     XSetFunction( gdi_display, physDev->gc, OP_ROP(*opcode) );
769
770     switch(rop)  /* a few special cases */
771     {
772     case BLACKNESS:  /* 0x00 */
773     case WHITENESS:  /* 0xff */
774         if ((physDev->depth != 1) && X11DRV_PALETTE_PaletteToXPixel)
775         {
776             XSetFunction( gdi_display, physDev->gc, GXcopy );
777             if (rop == BLACKNESS)
778                 XSetForeground( gdi_display, physDev->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
779             else
780                 XSetForeground( gdi_display, physDev->gc,
781                                 WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
782             XSetFillStyle( gdi_display, physDev->gc, FillSolid );
783         }
784         break;
785     case DSTINVERT:  /* 0x55 */
786         if (!(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL)))
787         {
788             /* Xor is much better when we do not have full colormap.   */
789             /* Using white^black ensures that we invert at least black */
790             /* and white. */
791             unsigned long xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
792                                      BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
793             XSetFunction( gdi_display, physDev->gc, GXxor );
794             XSetForeground( gdi_display, physDev->gc, xor_pix);
795             XSetFillStyle( gdi_display, physDev->gc, FillSolid );
796         }
797         break;
798     }
799     XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
800                     physDev->dc_rect.left + dst->visrect.left,
801                     physDev->dc_rect.top + dst->visrect.top,
802                     dst->visrect.right - dst->visrect.left,
803                     dst->visrect.bottom - dst->visrect.top );
804     wine_tsx11_unlock();
805
806     X11DRV_UnlockDIBSection( physDev, TRUE );
807     return TRUE;
808 }
809
810
811 /***********************************************************************
812  *           X11DRV_StretchBlt
813  */
814 BOOL X11DRV_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
815                         PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
816 {
817     X11DRV_PDEVICE *physDevDst = get_x11drv_dev( dst_dev );
818     X11DRV_PDEVICE *physDevSrc = get_x11drv_dev( src_dev );
819     INT width, height;
820     const BYTE *opcode;
821     Pixmap src_pixmap;
822     GC gc;
823
824     if (src_dev->funcs != dst_dev->funcs ||
825         src->width != dst->width || src->height != dst->height ||  /* no stretching with core X11 */
826         (physDevDst->depth == 1 && physDevSrc->depth != 1) ||  /* color -> mono done by hand */
827         (X11DRV_PALETTE_XPixelToPalette && physDevSrc->depth != 1))  /* needs palette mapping */
828     {
829         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
830         return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
831     }
832
833     width  = dst->visrect.right - dst->visrect.left;
834     height = dst->visrect.bottom - dst->visrect.top;
835
836     X11DRV_LockDIBSection( physDevDst, DIB_Status_GdiMod );
837     if (physDevDst != physDevSrc) X11DRV_LockDIBSection( physDevSrc, DIB_Status_GdiMod );
838
839     opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
840
841     /* a few optimizations for single-op ROPs */
842     if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
843     {
844         if (same_format(physDevSrc, physDevDst))
845         {
846             wine_tsx11_lock();
847             XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
848             XCopyArea( gdi_display, physDevSrc->drawable,
849                        physDevDst->drawable, physDevDst->gc,
850                        physDevSrc->dc_rect.left + src->visrect.left,
851                        physDevSrc->dc_rect.top + src->visrect.top,
852                        width, height,
853                        physDevDst->dc_rect.left + dst->visrect.left,
854                        physDevDst->dc_rect.top + dst->visrect.top );
855             physDevDst->exposures++;
856             wine_tsx11_unlock();
857             goto done;
858         }
859         if (physDevSrc->depth == 1)
860         {
861             wine_tsx11_lock();
862             XSetBackground( gdi_display, physDevDst->gc, physDevDst->textPixel );
863             XSetForeground( gdi_display, physDevDst->gc, physDevDst->backgroundPixel );
864             XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
865             XCopyPlane( gdi_display, physDevSrc->drawable,
866                         physDevDst->drawable, physDevDst->gc,
867                         physDevSrc->dc_rect.left + src->visrect.left,
868                         physDevSrc->dc_rect.top + src->visrect.top,
869                         width, height,
870                         physDevDst->dc_rect.left + dst->visrect.left,
871                         physDevDst->dc_rect.top + dst->visrect.top, 1 );
872             physDevDst->exposures++;
873             wine_tsx11_unlock();
874             goto done;
875         }
876     }
877
878     wine_tsx11_lock();
879     gc = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
880     XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
881     XSetGraphicsExposures( gdi_display, gc, False );
882
883     /* retrieve the source */
884
885     src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, physDevDst->depth );
886     if (physDevSrc->depth == 1)
887     {
888         /* MSDN says if StretchBlt must convert a bitmap from monochrome
889            to color or vice versa, the foreground and background color of
890            the device context are used.  In fact, it also applies to the
891            case when it is converted from mono to mono. */
892         if (X11DRV_PALETTE_XPixelToPalette && physDevDst->depth != 1)
893         {
894             XSetBackground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[physDevDst->textPixel] );
895             XSetForeground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[physDevDst->backgroundPixel]);
896         }
897         else
898         {
899             XSetBackground( gdi_display, gc, physDevDst->textPixel );
900             XSetForeground( gdi_display, gc, physDevDst->backgroundPixel );
901         }
902         XCopyPlane( gdi_display, physDevSrc->drawable, src_pixmap, gc,
903                     physDevSrc->dc_rect.left + src->visrect.left,
904                     physDevSrc->dc_rect.top + src->visrect.top,
905                     width, height, 0, 0, 1 );
906     }
907     else  /* color -> color */
908     {
909         XCopyArea( gdi_display, physDevSrc->drawable, src_pixmap, gc,
910                    physDevSrc->dc_rect.left + src->visrect.left,
911                    physDevSrc->dc_rect.top + src->visrect.top,
912                    width, height, 0, 0 );
913     }
914     wine_tsx11_unlock();
915
916     execute_rop( physDevDst, src_pixmap, gc, &dst->visrect, rop );
917
918     wine_tsx11_lock();
919     XFreePixmap( gdi_display, src_pixmap );
920     XFreeGC( gdi_display, gc );
921     wine_tsx11_unlock();
922
923 done:
924     if (physDevDst != physDevSrc) X11DRV_UnlockDIBSection( physDevSrc, FALSE );
925     X11DRV_UnlockDIBSection( physDevDst, TRUE );
926     return TRUE;
927 }
928
929
930 static void free_heap_bits( struct gdi_image_bits *bits )
931 {
932     HeapFree( GetProcessHeap(), 0, bits->ptr );
933 }
934
935 static void free_ximage_bits( struct gdi_image_bits *bits )
936 {
937     wine_tsx11_lock();
938     XFree( bits->ptr );
939     wine_tsx11_unlock();
940 }
941
942 /* store the palette or color mask data in the bitmap info structure */
943 static void set_color_info( PHYSDEV dev, const ColorShifts *color_shifts, BITMAPINFO *info )
944 {
945     DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
946
947     info->bmiHeader.biCompression = BI_RGB;
948     info->bmiHeader.biClrUsed = 0;
949
950     switch (info->bmiHeader.biBitCount)
951     {
952     case 4:
953     case 8:
954     {
955         RGBQUAD *rgb = (RGBQUAD *)colors;
956         PALETTEENTRY palette[256];
957         UINT i, count;
958
959         info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
960         count = X11DRV_GetSystemPaletteEntries( dev, 0, info->bmiHeader.biClrUsed, palette );
961         for (i = 0; i < count; i++)
962         {
963             rgb[i].rgbRed   = palette[i].peRed;
964             rgb[i].rgbGreen = palette[i].peGreen;
965             rgb[i].rgbBlue  = palette[i].peBlue;
966             rgb[i].rgbReserved = 0;
967         }
968         memset( &rgb[count], 0, (info->bmiHeader.biClrUsed - count) * sizeof(*rgb) );
969         break;
970     }
971     case 16:
972         colors[0] = color_shifts->logicalRed.max << color_shifts->logicalRed.shift;
973         colors[1] = color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift;
974         colors[2] = color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift;
975         info->bmiHeader.biCompression = BI_BITFIELDS;
976         break;
977     case 32:
978         colors[0] = color_shifts->logicalRed.max << color_shifts->logicalRed.shift;
979         colors[1] = color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift;
980         colors[2] = color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift;
981         if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff)
982             info->bmiHeader.biCompression = BI_BITFIELDS;
983         break;
984     }
985 }
986
987 /* check if the specified color info is suitable for PutImage */
988 static BOOL matching_color_info( PHYSDEV dev, const ColorShifts *color_shifts, const BITMAPINFO *info )
989 {
990     DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
991
992     switch (info->bmiHeader.biBitCount)
993     {
994     case 1:
995         if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
996         return !info->bmiHeader.biClrUsed;  /* color map not allowed */
997     case 4:
998     case 8:
999     {
1000         RGBQUAD *rgb = (RGBQUAD *)colors;
1001         PALETTEENTRY palette[256];
1002         UINT i, count;
1003
1004         if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
1005         count = X11DRV_GetSystemPaletteEntries( dev, 0, 1 << info->bmiHeader.biBitCount, palette );
1006         if (count != info->bmiHeader.biClrUsed) return FALSE;
1007         for (i = 0; i < count; i++)
1008         {
1009             if (rgb[i].rgbRed   != palette[i].peRed ||
1010                 rgb[i].rgbGreen != palette[i].peGreen ||
1011                 rgb[i].rgbBlue  != palette[i].peBlue) return FALSE;
1012         }
1013         return TRUE;
1014     }
1015     case 16:
1016         if (info->bmiHeader.biCompression == BI_BITFIELDS)
1017             return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == colors[0] &&
1018                     color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == colors[1] &&
1019                     color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == colors[2]);
1020         if (info->bmiHeader.biCompression == BI_RGB)
1021             return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift     == 0x7c00 &&
1022                     color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == 0x03e0 &&
1023                     color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift   == 0x001f);
1024         break;
1025     case 32:
1026         if (info->bmiHeader.biCompression == BI_BITFIELDS)
1027             return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == colors[0] &&
1028                     color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == colors[1] &&
1029                     color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == colors[2]);
1030         /* fall through */
1031     case 24:
1032         if (info->bmiHeader.biCompression == BI_RGB)
1033             return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift     == 0xff0000 &&
1034                     color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == 0x00ff00 &&
1035                     color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift   == 0x0000ff);
1036         break;
1037     }
1038     return FALSE;
1039 }
1040
1041 static inline BOOL is_r8g8b8( int depth, const ColorShifts *color_shifts )
1042 {
1043     return depth == 24 && color_shifts->logicalBlue.shift == 0 && color_shifts->logicalRed.shift == 16;
1044 }
1045
1046 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1047 DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
1048                        const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
1049                        struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
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     BOOL need_byteswap;
1057     int x, y, height = coords->visrect.bottom - coords->visrect.top;
1058     int width_bytes = image->bytes_per_line;
1059     int padding_pos;
1060     unsigned char *src, *dst;
1061
1062     switch (info->bmiHeader.biBitCount)
1063     {
1064     case 1:
1065         need_byteswap = (image->bitmap_bit_order != MSBFirst);
1066         break;
1067     case 4:
1068         need_byteswap = (image->byte_order != MSBFirst);
1069         break;
1070     case 16:
1071     case 32:
1072         need_byteswap = (image->byte_order != client_byte_order);
1073         break;
1074     case 24:
1075         need_byteswap = (image->byte_order == MSBFirst) ^ !is_r8g8b8;
1076         break;
1077     default:
1078         need_byteswap = FALSE;
1079         break;
1080     }
1081
1082     src = src_bits->ptr;
1083     if (info->bmiHeader.biHeight > 0)
1084         src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes;
1085     else
1086         src += coords->visrect.top * width_bytes;
1087
1088     if ((need_byteswap && !src_bits->is_copy) ||  /* need to swap bytes */
1089         (zeropad_mask != ~0u && !src_bits->is_copy) ||  /* need to clear padding bytes */
1090         (mapping && !src_bits->is_copy) ||  /* need to remap pixels */
1091         (width_bytes & 3) ||  /* need to fixup line alignment */
1092         (info->bmiHeader.biHeight > 0))  /* need to flip vertically */
1093     {
1094         width_bytes = (width_bytes + 3) & ~3;
1095         info->bmiHeader.biSizeImage = height * width_bytes;
1096         if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
1097             return ERROR_OUTOFMEMORY;
1098         dst_bits->is_copy = TRUE;
1099         dst_bits->free = free_heap_bits;
1100     }
1101     else
1102     {
1103         /* swap bits in place */
1104         dst_bits->ptr = src;
1105         dst_bits->is_copy = src_bits->is_copy;
1106         dst_bits->free = NULL;
1107         if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS;  /* nothing to do */
1108     }
1109
1110     dst = dst_bits->ptr;
1111     padding_pos = width_bytes/sizeof(unsigned int) - 1;
1112
1113     if (info->bmiHeader.biHeight > 0)
1114     {
1115         dst += (height - 1) * width_bytes;
1116         width_bytes = -width_bytes;
1117     }
1118
1119     if (need_byteswap || mapping)
1120     {
1121         switch (info->bmiHeader.biBitCount)
1122         {
1123         case 1:
1124             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1125             {
1126                 for (x = 0; x < image->bytes_per_line; x++)
1127                     dst[x] = bit_swap[src[x]];
1128                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1129             }
1130             break;
1131         case 4:
1132             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1133             {
1134                 if (mapping)
1135                     for (x = 0; x < image->bytes_per_line; x++)
1136                         dst[x] = (mapping[src[x] & 0x0f] << 4) | mapping[src[x] >> 4];
1137                 else
1138                     for (x = 0; x < image->bytes_per_line; x++)
1139                         dst[x] = (src[x] << 4) | (src[x] >> 4);
1140                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1141             }
1142             break;
1143         case 8:
1144             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1145             {
1146                 for (x = 0; x < image->bytes_per_line; x++)
1147                     dst[x] = mapping[src[x]];
1148                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1149             }
1150             break;
1151         case 16:
1152             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1153             {
1154                 for (x = 0; x < info->bmiHeader.biWidth; x++)
1155                     ((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] );
1156                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1157             }
1158             break;
1159         case 24:
1160             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1161             {
1162                 for (x = 0; x < info->bmiHeader.biWidth; x++)
1163                 {
1164                     unsigned char tmp = src[3 * x];
1165                     dst[3 * x]     = src[3 * x + 2];
1166                     dst[3 * x + 1] = src[3 * x + 1];
1167                     dst[3 * x + 2] = tmp;
1168                 }
1169                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1170             }
1171             break;
1172         case 32:
1173             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1174                 for (x = 0; x < info->bmiHeader.biWidth; x++)
1175                     ((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] );
1176             break;
1177         }
1178     }
1179     else if (src != dst)
1180     {
1181         for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1182         {
1183             memcpy( dst, src, image->bytes_per_line );
1184             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1185         }
1186     }
1187     else  /* only need to clear the padding */
1188     {
1189         for (y = 0; y < height; y++, dst += width_bytes)
1190             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1191     }
1192     return ERROR_SUCCESS;
1193 }
1194
1195 /***********************************************************************
1196  *           X11DRV_PutImage
1197  */
1198 DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
1199                        const struct gdi_image_bits *bits, struct bitblt_coords *src,
1200                        struct bitblt_coords *dst, DWORD rop )
1201 {
1202     X11DRV_PDEVICE *physdev;
1203     X_PHYSBITMAP *bitmap;
1204     DWORD ret;
1205     XImage *image;
1206     int depth;
1207     struct gdi_image_bits dst_bits;
1208     const XPixmapFormatValues *format;
1209     const ColorShifts *color_shifts;
1210     const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1211     const int *mapping = NULL;
1212
1213     if (hbitmap)
1214     {
1215         if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
1216         physdev = NULL;
1217         depth = bitmap->depth;
1218         color_shifts = &bitmap->color_shifts;
1219     }
1220     else
1221     {
1222         physdev = get_x11drv_dev( dev );
1223         bitmap = NULL;
1224         depth = physdev->depth;
1225         color_shifts = physdev->color_shifts;
1226     }
1227     format = pixmap_formats[depth];
1228
1229     if (info->bmiHeader.biPlanes != 1) goto update_format;
1230     if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1231     /* FIXME: could try to handle 1-bpp using XCopyPlane */
1232     if (!matching_color_info( dev, color_shifts, info )) goto update_format;
1233     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
1234     if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
1235
1236     wine_tsx11_lock();
1237     image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0, NULL,
1238                           info->bmiHeader.biWidth, src->visrect.bottom - src->visrect.top, 32, 0 );
1239     wine_tsx11_unlock();
1240     if (!image) return ERROR_OUTOFMEMORY;
1241
1242     if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1243     {
1244         if (bitmap || (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST)))
1245             mapping = X11DRV_PALETTE_PaletteToXPixel;
1246     }
1247
1248     ret = copy_image_bits( info, is_r8g8b8(depth,color_shifts), image, bits, &dst_bits, src, mapping, ~0u );
1249
1250     if (!ret)
1251     {
1252         int width = dst->visrect.right - dst->visrect.left;
1253         int height = dst->visrect.bottom - dst->visrect.top;
1254
1255         image->data = dst_bits.ptr;
1256         /* hack: make sure the bits are readable if we are reading from a DIB section */
1257         /* to be removed once we get rid of DIB access protections */
1258         if (!dst_bits.is_copy) IsBadReadPtr( dst_bits.ptr, height * image->bytes_per_line );
1259
1260         if (bitmap)
1261         {
1262             RGNDATA *clip_data = NULL;
1263             GC gc;
1264
1265             if (clip) clip_data = X11DRV_GetRegionData( clip, 0 );
1266             X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
1267
1268             wine_tsx11_lock();
1269             gc = XCreateGC( gdi_display, bitmap->pixmap, 0, NULL );
1270             XSetGraphicsExposures( gdi_display, gc, False );
1271             if (clip_data) XSetClipRectangles( gdi_display, gc, 0, 0, (XRectangle *)clip_data->Buffer,
1272                                                clip_data->rdh.nCount, YXBanded );
1273             XPutImage( gdi_display, bitmap->pixmap, gc, image, src->visrect.left, 0,
1274                        dst->visrect.left, dst->visrect.top, width, height );
1275             XFreeGC( gdi_display, gc );
1276             wine_tsx11_unlock();
1277
1278             X11DRV_DIB_Unlock( bitmap, TRUE );
1279             HeapFree( GetProcessHeap(), 0, clip_data );
1280         }
1281         else
1282         {
1283             RGNDATA *saved_region = NULL;
1284
1285             if (clip) saved_region = add_extra_clipping_region( physdev, clip );
1286             X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
1287
1288             /* optimization for single-op ROPs */
1289             if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1290             {
1291                 wine_tsx11_lock();
1292                 XSetFunction( gdi_display, physdev->gc, OP_ROP(*opcode) );
1293                 XPutImage( gdi_display, physdev->drawable, physdev->gc, image, src->visrect.left, 0,
1294                            physdev->dc_rect.left + dst->visrect.left,
1295                            physdev->dc_rect.top + dst->visrect.top, width, height );
1296                 wine_tsx11_unlock();
1297             }
1298             else
1299             {
1300                 Pixmap src_pixmap;
1301                 GC gc;
1302
1303                 wine_tsx11_lock();
1304                 gc = XCreateGC( gdi_display, physdev->drawable, 0, NULL );
1305                 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
1306                 XSetGraphicsExposures( gdi_display, gc, False );
1307                 src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1308                 XPutImage( gdi_display, src_pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
1309                 wine_tsx11_unlock();
1310
1311                 execute_rop( physdev, src_pixmap, gc, &dst->visrect, rop );
1312
1313                 wine_tsx11_lock();
1314                 XFreePixmap( gdi_display, src_pixmap );
1315                 XFreeGC( gdi_display, gc );
1316                 wine_tsx11_unlock();
1317             }
1318
1319             X11DRV_UnlockDIBSection( physdev, !ret );
1320             restore_clipping_region( physdev, saved_region );
1321         }
1322         image->data = NULL;
1323     }
1324
1325     wine_tsx11_lock();
1326     XDestroyImage( image );
1327     wine_tsx11_unlock();
1328     if (dst_bits.free) dst_bits.free( &dst_bits );
1329     return ret;
1330
1331 update_format:
1332     info->bmiHeader.biPlanes   = 1;
1333     info->bmiHeader.biBitCount = format->bits_per_pixel;
1334     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1335     set_color_info( dev, color_shifts, info );
1336     return ERROR_BAD_FORMAT;
1337 }
1338
1339 /***********************************************************************
1340  *           X11DRV_GetImage
1341  */
1342 DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
1343                        struct gdi_image_bits *bits, struct bitblt_coords *src )
1344 {
1345     X11DRV_PDEVICE *physdev;
1346     X_PHYSBITMAP *bitmap;
1347     DWORD ret = ERROR_SUCCESS;
1348     XImage *image;
1349     UINT align, x, y, width, height;
1350     int depth;
1351     struct gdi_image_bits src_bits;
1352     const XPixmapFormatValues *format;
1353     const ColorShifts *color_shifts;
1354     const int *mapping = NULL;
1355
1356     if (hbitmap)
1357     {
1358         if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
1359         physdev = NULL;
1360         depth = bitmap->depth;
1361         color_shifts = &bitmap->color_shifts;
1362     }
1363     else
1364     {
1365         physdev = get_x11drv_dev( dev );
1366         bitmap = NULL;
1367         depth = physdev->depth;
1368         color_shifts = physdev->color_shifts;
1369     }
1370     format = pixmap_formats[depth];
1371
1372     /* align start and width to 32-bit boundary */
1373     switch (format->bits_per_pixel)
1374     {
1375     case 1:  align = 32; break;
1376     case 4:  align = 8;  mapping = X11DRV_PALETTE_XPixelToPalette; break;
1377     case 8:  align = 4;  mapping = X11DRV_PALETTE_XPixelToPalette; break;
1378     case 16: align = 2;  break;
1379     case 24: align = 4;  break;
1380     case 32: align = 1;  break;
1381     default:
1382         FIXME( "depth %u bpp %u not supported yet\n", depth, format->bits_per_pixel );
1383         return ERROR_BAD_FORMAT;
1384     }
1385
1386     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
1387     info->bmiHeader.biPlanes        = 1;
1388     info->bmiHeader.biBitCount      = format->bits_per_pixel;
1389     info->bmiHeader.biXPelsPerMeter = 0;
1390     info->bmiHeader.biYPelsPerMeter = 0;
1391     info->bmiHeader.biClrImportant  = 0;
1392     set_color_info( dev, color_shifts, info );
1393
1394     if (!bits) return ERROR_SUCCESS;  /* just querying the color information */
1395
1396     x = src->visrect.left & ~(align - 1);
1397     y = src->visrect.top;
1398     width = src->visrect.right - x;
1399     height = src->visrect.bottom - src->visrect.top;
1400     if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
1401     /* make the source rectangle relative to the returned bits */
1402     src->x -= x;
1403     src->y -= y;
1404     OffsetRect( &src->visrect, -x, -y );
1405
1406     if (bitmap)
1407     {
1408         BITMAP bm;
1409         GetObjectW( hbitmap, sizeof(bm), &bm );
1410         width = min( width, bm.bmWidth - x );
1411         height = min( height, bm.bmHeight - y );
1412         X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
1413         wine_tsx11_lock();
1414         image = XGetImage( gdi_display, bitmap->pixmap, x, y, width, height, AllPlanes, ZPixmap );
1415         wine_tsx11_unlock();
1416         X11DRV_DIB_Unlock( bitmap, TRUE );
1417     }
1418     else if (GetObjectType( dev->hdc ) == OBJ_MEMDC)
1419     {
1420         X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
1421         width = min( width, physdev->dc_rect.right - physdev->dc_rect.left - x );
1422         height = min( height, physdev->dc_rect.bottom - physdev->dc_rect.top - y );
1423         wine_tsx11_lock();
1424         image = XGetImage( gdi_display, physdev->drawable,
1425                            physdev->dc_rect.left + x, physdev->dc_rect.top + y,
1426                            width, height, AllPlanes, ZPixmap );
1427         wine_tsx11_unlock();
1428         X11DRV_UnlockDIBSection( physdev, FALSE );
1429     }
1430     else
1431     {
1432         X11DRV_expect_error( gdi_display, XGetImage_handler, NULL );
1433         image = XGetImage( gdi_display, physdev->drawable,
1434                            physdev->dc_rect.left + x, physdev->dc_rect.top + y,
1435                            width, height, AllPlanes, ZPixmap );
1436         if (X11DRV_check_error())
1437         {
1438             /* use a temporary pixmap to avoid the BadMatch error */
1439             Pixmap pixmap;
1440
1441             wine_tsx11_lock();
1442             pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1443             XCopyArea( gdi_display, physdev->drawable, pixmap, get_bitmap_gc(depth),
1444                        physdev->dc_rect.left + x, physdev->dc_rect.top + y, width, height, 0, 0 );
1445             image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1446             XFreePixmap( gdi_display, pixmap );
1447             wine_tsx11_unlock();
1448         }
1449     }
1450     if (!image) return ERROR_OUTOFMEMORY;
1451
1452     info->bmiHeader.biWidth     = width;
1453     info->bmiHeader.biHeight    = -height;
1454     info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1455
1456     src_bits.ptr     = image->data;
1457     src_bits.is_copy = TRUE;
1458     ret = copy_image_bits( info, is_r8g8b8(depth,color_shifts), image, &src_bits, bits, src, mapping,
1459                            zeropad_masks[(width * image->bits_per_pixel) & 31] );
1460
1461     if (!ret && bits->ptr == image->data)
1462     {
1463         bits->free = free_ximage_bits;
1464         image->data = NULL;
1465     }
1466     wine_tsx11_lock();
1467     XDestroyImage( image );
1468     wine_tsx11_unlock();
1469     return ret;
1470 }