windowscodecs: Avoid using uninitialized value (LLVM/Clang).
[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
603     wine_tsx11_lock();
604
605     if (!X11DRV_PALETTE_XPixelToPalette || (physDev->depth == 1) ||
606         (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
607     {
608         XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
609                    physDev->dc_rect.left + visRectDst->left, physDev->dc_rect.top + visRectDst->top,
610                    width, height, 0, 0 );
611         exposures++;
612     }
613     else
614     {
615         INT x, y;
616         XImage *image;
617
618         /* Make sure we don't get a BadMatch error */
619         XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
620                    physDev->dc_rect.left + visRectDst->left,
621                    physDev->dc_rect.top + visRectDst->top,
622                    width, height, 0, 0);
623         exposures++;
624         image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
625                            AllPlanes, ZPixmap );
626         if (image)
627         {
628             for (y = 0; y < height; y++)
629                 for (x = 0; x < width; x++)
630                     XPutPixel( image, x, y,
631                                X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]);
632             XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height );
633             XDestroyImage( image );
634         }
635     }
636
637     wine_tsx11_unlock();
638     return exposures;
639 }
640
641
642 /***********************************************************************
643  *           BITBLT_PutDstArea
644  *
645  * Put an area back into the destination DC, mapping the pixel
646  * colors to X pixels.
647  */
648 static int BITBLT_PutDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, const RECT *visRectDst)
649 {
650     int exposures = 0;
651     INT width  = visRectDst->right - visRectDst->left;
652     INT height = visRectDst->bottom - visRectDst->top;
653
654     /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
655
656     if (!X11DRV_PALETTE_PaletteToXPixel || (physDev->depth == 1) ||
657         (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
658     {
659         XCopyArea( gdi_display, pixmap, physDev->drawable, physDev->gc, 0, 0, width, height,
660                    physDev->dc_rect.left + visRectDst->left,
661                    physDev->dc_rect.top + visRectDst->top );
662         exposures++;
663     }
664     else
665     {
666         register INT x, y;
667         XImage *image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
668                                    AllPlanes, ZPixmap );
669         for (y = 0; y < height; y++)
670             for (x = 0; x < width; x++)
671             {
672                 XPutPixel( image, x, y,
673                            X11DRV_PALETTE_PaletteToXPixel[XGetPixel( image, x, y )]);
674             }
675         XPutImage( gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
676                    physDev->dc_rect.left + visRectDst->left,
677                    physDev->dc_rect.top + visRectDst->top, width, height );
678         XDestroyImage( image );
679     }
680     return exposures;
681 }
682
683 static BOOL same_format(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst)
684 {
685     if (physDevSrc->depth != physDevDst->depth) return FALSE;
686     if (!physDevSrc->color_shifts && !physDevDst->color_shifts) return TRUE;
687     if (physDevSrc->color_shifts && physDevDst->color_shifts)
688         return !memcmp(physDevSrc->color_shifts, physDevDst->color_shifts, sizeof(ColorShifts));
689     return FALSE;
690 }
691
692 void execute_rop( X11DRV_PDEVICE *physdev, Pixmap src_pixmap, GC gc, const RECT *visrect, DWORD rop )
693 {
694     Pixmap pixmaps[3];
695     Pixmap result = src_pixmap;
696     BOOL null_brush;
697     const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
698     BOOL use_pat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
699     BOOL use_dst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
700     int width  = visrect->right - visrect->left;
701     int height = visrect->bottom - visrect->top;
702
703     pixmaps[SRC] = src_pixmap;
704     pixmaps[TMP] = 0;
705     wine_tsx11_lock();
706     pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
707     wine_tsx11_unlock();
708
709     if (use_dst) BITBLT_GetDstArea( physdev, pixmaps[DST], gc, visrect );
710     null_brush = use_pat && !X11DRV_SetupGCForPatBlt( physdev, gc, TRUE );
711
712     wine_tsx11_lock();
713     for ( ; *opcode; opcode++)
714     {
715         if (OP_DST(*opcode) == DST) result = pixmaps[DST];
716         XSetFunction( gdi_display, gc, OP_ROP(*opcode) );
717         switch(OP_SRCDST(*opcode))
718         {
719         case OP_ARGS(DST,TMP):
720         case OP_ARGS(SRC,TMP):
721             if (!pixmaps[TMP])
722                 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
723             /* fall through */
724         case OP_ARGS(DST,SRC):
725         case OP_ARGS(SRC,DST):
726         case OP_ARGS(TMP,SRC):
727         case OP_ARGS(TMP,DST):
728             XCopyArea( gdi_display, pixmaps[OP_SRC(*opcode)], pixmaps[OP_DST(*opcode)], gc,
729                        0, 0, width, height, 0, 0 );
730             break;
731         case OP_ARGS(PAT,DST):
732         case OP_ARGS(PAT,SRC):
733             if (!null_brush)
734                 XFillRectangle( gdi_display, pixmaps[OP_DST(*opcode)], gc, 0, 0, width, height );
735             break;
736         }
737     }
738     XSetFunction( gdi_display, physdev->gc, GXcopy );
739     physdev->exposures += BITBLT_PutDstArea( physdev, result, visrect );
740     XFreePixmap( gdi_display, pixmaps[DST] );
741     if (pixmaps[TMP]) XFreePixmap( gdi_display, pixmaps[TMP] );
742     wine_tsx11_unlock();
743     add_device_bounds( physdev, visrect );
744 }
745
746 /***********************************************************************
747  *           X11DRV_PatBlt
748  */
749 BOOL X11DRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
750 {
751     X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
752     BOOL usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
753     const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
754
755     if (usePat && !X11DRV_SetupGCForBrush( physDev )) return TRUE;
756
757     wine_tsx11_lock();
758     XSetFunction( gdi_display, physDev->gc, OP_ROP(*opcode) );
759
760     switch(rop)  /* a few special cases */
761     {
762     case BLACKNESS:  /* 0x00 */
763     case WHITENESS:  /* 0xff */
764         if ((physDev->depth != 1) && X11DRV_PALETTE_PaletteToXPixel)
765         {
766             XSetFunction( gdi_display, physDev->gc, GXcopy );
767             if (rop == BLACKNESS)
768                 XSetForeground( gdi_display, physDev->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
769             else
770                 XSetForeground( gdi_display, physDev->gc,
771                                 WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
772             XSetFillStyle( gdi_display, physDev->gc, FillSolid );
773         }
774         break;
775     case DSTINVERT:  /* 0x55 */
776         if (!(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL)))
777         {
778             /* Xor is much better when we do not have full colormap.   */
779             /* Using white^black ensures that we invert at least black */
780             /* and white. */
781             unsigned long xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
782                                      BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
783             XSetFunction( gdi_display, physDev->gc, GXxor );
784             XSetForeground( gdi_display, physDev->gc, xor_pix);
785             XSetFillStyle( gdi_display, physDev->gc, FillSolid );
786         }
787         break;
788     }
789     XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
790                     physDev->dc_rect.left + dst->visrect.left,
791                     physDev->dc_rect.top + dst->visrect.top,
792                     dst->visrect.right - dst->visrect.left,
793                     dst->visrect.bottom - dst->visrect.top );
794     wine_tsx11_unlock();
795     add_device_bounds( physDev, &dst->visrect );
796     return TRUE;
797 }
798
799
800 /***********************************************************************
801  *           X11DRV_StretchBlt
802  */
803 BOOL X11DRV_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
804                         PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
805 {
806     X11DRV_PDEVICE *physDevDst = get_x11drv_dev( dst_dev );
807     X11DRV_PDEVICE *physDevSrc = get_x11drv_dev( src_dev );
808     INT width, height;
809     const BYTE *opcode;
810     Pixmap src_pixmap;
811     GC gc;
812
813     if (src_dev->funcs != dst_dev->funcs ||
814         src->width != dst->width || src->height != dst->height ||  /* no stretching with core X11 */
815         (physDevDst->depth == 1 && physDevSrc->depth != 1) ||  /* color -> mono done by hand */
816         (X11DRV_PALETTE_XPixelToPalette && physDevSrc->depth != 1))  /* needs palette mapping */
817     {
818         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
819         return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
820     }
821
822     width  = dst->visrect.right - dst->visrect.left;
823     height = dst->visrect.bottom - dst->visrect.top;
824     opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
825
826     add_device_bounds( physDevDst, &dst->visrect );
827
828     /* a few optimizations for single-op ROPs */
829     if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
830     {
831         if (same_format(physDevSrc, physDevDst))
832         {
833             wine_tsx11_lock();
834             XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
835             XCopyArea( gdi_display, physDevSrc->drawable,
836                        physDevDst->drawable, physDevDst->gc,
837                        physDevSrc->dc_rect.left + src->visrect.left,
838                        physDevSrc->dc_rect.top + src->visrect.top,
839                        width, height,
840                        physDevDst->dc_rect.left + dst->visrect.left,
841                        physDevDst->dc_rect.top + dst->visrect.top );
842             physDevDst->exposures++;
843             wine_tsx11_unlock();
844             return TRUE;
845         }
846         if (physDevSrc->depth == 1)
847         {
848             int text_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetTextColor(physDevDst->dev.hdc) );
849             int bkgnd_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetBkColor(physDevDst->dev.hdc) );
850
851             wine_tsx11_lock();
852             XSetBackground( gdi_display, physDevDst->gc, text_pixel );
853             XSetForeground( gdi_display, physDevDst->gc, bkgnd_pixel );
854             XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
855             XCopyPlane( gdi_display, physDevSrc->drawable,
856                         physDevDst->drawable, physDevDst->gc,
857                         physDevSrc->dc_rect.left + src->visrect.left,
858                         physDevSrc->dc_rect.top + src->visrect.top,
859                         width, height,
860                         physDevDst->dc_rect.left + dst->visrect.left,
861                         physDevDst->dc_rect.top + dst->visrect.top, 1 );
862             physDevDst->exposures++;
863             wine_tsx11_unlock();
864             return TRUE;
865         }
866     }
867
868     wine_tsx11_lock();
869     gc = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
870     XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
871     XSetGraphicsExposures( gdi_display, gc, False );
872
873     /* retrieve the source */
874
875     src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, physDevDst->depth );
876     if (physDevSrc->depth == 1)
877     {
878         /* MSDN says if StretchBlt must convert a bitmap from monochrome
879            to color or vice versa, the foreground and background color of
880            the device context are used.  In fact, it also applies to the
881            case when it is converted from mono to mono. */
882         int text_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetTextColor(physDevDst->dev.hdc) );
883         int bkgnd_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetBkColor(physDevDst->dev.hdc) );
884
885         if (X11DRV_PALETTE_XPixelToPalette && physDevDst->depth != 1)
886         {
887             XSetBackground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[text_pixel] );
888             XSetForeground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[bkgnd_pixel]);
889         }
890         else
891         {
892             XSetBackground( gdi_display, gc, text_pixel );
893             XSetForeground( gdi_display, gc, bkgnd_pixel );
894         }
895         XCopyPlane( gdi_display, physDevSrc->drawable, src_pixmap, gc,
896                     physDevSrc->dc_rect.left + src->visrect.left,
897                     physDevSrc->dc_rect.top + src->visrect.top,
898                     width, height, 0, 0, 1 );
899     }
900     else  /* color -> color */
901     {
902         XCopyArea( 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 );
906     }
907     wine_tsx11_unlock();
908
909     execute_rop( physDevDst, src_pixmap, gc, &dst->visrect, rop );
910
911     wine_tsx11_lock();
912     XFreePixmap( gdi_display, src_pixmap );
913     XFreeGC( gdi_display, gc );
914     wine_tsx11_unlock();
915     return TRUE;
916 }
917
918
919 static void free_heap_bits( struct gdi_image_bits *bits )
920 {
921     HeapFree( GetProcessHeap(), 0, bits->ptr );
922 }
923
924 static void free_ximage_bits( struct gdi_image_bits *bits )
925 {
926     wine_tsx11_lock();
927     XFree( bits->ptr );
928     wine_tsx11_unlock();
929 }
930
931 /* only for use on sanitized BITMAPINFO structures */
932 static inline int get_dib_info_size( const BITMAPINFO *info, UINT coloruse )
933 {
934     if (info->bmiHeader.biCompression == BI_BITFIELDS)
935         return sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD);
936     if (coloruse == DIB_PAL_COLORS)
937         return sizeof(BITMAPINFOHEADER) + info->bmiHeader.biClrUsed * sizeof(WORD);
938     return FIELD_OFFSET( BITMAPINFO, bmiColors[info->bmiHeader.biClrUsed] );
939 }
940
941 /* store the palette or color mask data in the bitmap info structure */
942 static void set_color_info( const XVisualInfo *vis, BITMAPINFO *info )
943 {
944     DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
945
946     info->bmiHeader.biCompression = BI_RGB;
947     info->bmiHeader.biClrUsed = 0;
948
949     switch (info->bmiHeader.biBitCount)
950     {
951     case 4:
952     case 8:
953     {
954         RGBQUAD *rgb = (RGBQUAD *)colors;
955         PALETTEENTRY palette[256];
956         UINT i, count;
957
958         info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
959         count = X11DRV_GetSystemPaletteEntries( NULL, 0, info->bmiHeader.biClrUsed, palette );
960         for (i = 0; i < count; i++)
961         {
962             rgb[i].rgbRed   = palette[i].peRed;
963             rgb[i].rgbGreen = palette[i].peGreen;
964             rgb[i].rgbBlue  = palette[i].peBlue;
965             rgb[i].rgbReserved = 0;
966         }
967         memset( &rgb[count], 0, (info->bmiHeader.biClrUsed - count) * sizeof(*rgb) );
968         break;
969     }
970     case 16:
971         colors[0] = vis->red_mask;
972         colors[1] = vis->green_mask;
973         colors[2] = vis->blue_mask;
974         info->bmiHeader.biCompression = BI_BITFIELDS;
975         break;
976     case 32:
977         colors[0] = vis->red_mask;
978         colors[1] = vis->green_mask;
979         colors[2] = vis->blue_mask;
980         if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff)
981             info->bmiHeader.biCompression = BI_BITFIELDS;
982         break;
983     }
984 }
985
986 /* check if the specified color info is suitable for PutImage */
987 static BOOL matching_color_info( const XVisualInfo *vis, const BITMAPINFO *info )
988 {
989     DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
990
991     switch (info->bmiHeader.biBitCount)
992     {
993     case 1:
994         if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
995         return !info->bmiHeader.biClrUsed;  /* color map not allowed */
996     case 4:
997     case 8:
998     {
999         RGBQUAD *rgb = (RGBQUAD *)colors;
1000         PALETTEENTRY palette[256];
1001         UINT i, count;
1002
1003         if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
1004         count = X11DRV_GetSystemPaletteEntries( NULL, 0, 1 << info->bmiHeader.biBitCount, palette );
1005         if (count != info->bmiHeader.biClrUsed) return FALSE;
1006         for (i = 0; i < count; i++)
1007         {
1008             if (rgb[i].rgbRed   != palette[i].peRed ||
1009                 rgb[i].rgbGreen != palette[i].peGreen ||
1010                 rgb[i].rgbBlue  != palette[i].peBlue) return FALSE;
1011         }
1012         return TRUE;
1013     }
1014     case 16:
1015         if (info->bmiHeader.biCompression == BI_BITFIELDS)
1016             return (vis->red_mask == colors[0] &&
1017                     vis->green_mask == colors[1] &&
1018                     vis->blue_mask == colors[2]);
1019         if (info->bmiHeader.biCompression == BI_RGB)
1020             return (vis->red_mask == 0x7c00 && vis->green_mask == 0x03e0 && vis->blue_mask == 0x001f);
1021         break;
1022     case 32:
1023         if (info->bmiHeader.biCompression == BI_BITFIELDS)
1024             return (vis->red_mask == colors[0] &&
1025                     vis->green_mask == colors[1] &&
1026                     vis->blue_mask == colors[2]);
1027         /* fall through */
1028     case 24:
1029         if (info->bmiHeader.biCompression == BI_RGB)
1030             return (vis->red_mask == 0xff0000 && vis->green_mask == 0x00ff00 && vis->blue_mask == 0x0000ff);
1031         break;
1032     }
1033     return FALSE;
1034 }
1035
1036 static inline BOOL is_r8g8b8( const XVisualInfo *vis )
1037 {
1038     return vis->depth == 24 && vis->red_mask == 0xff0000 && vis->blue_mask == 0x0000ff;
1039 }
1040
1041 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1042 DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
1043                        const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
1044                        struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
1045 {
1046 #ifdef WORDS_BIGENDIAN
1047     static const int client_byte_order = MSBFirst;
1048 #else
1049     static const int client_byte_order = LSBFirst;
1050 #endif
1051     BOOL need_byteswap;
1052     int x, y, height = coords->visrect.bottom - coords->visrect.top;
1053     int width_bytes = image->bytes_per_line;
1054     int padding_pos;
1055     unsigned char *src, *dst;
1056
1057     switch (info->bmiHeader.biBitCount)
1058     {
1059     case 1:
1060         need_byteswap = (image->bitmap_bit_order != MSBFirst);
1061         break;
1062     case 4:
1063         need_byteswap = (image->byte_order != MSBFirst);
1064         break;
1065     case 16:
1066     case 32:
1067         need_byteswap = (image->byte_order != client_byte_order);
1068         break;
1069     case 24:
1070         need_byteswap = (image->byte_order == MSBFirst) ^ !is_r8g8b8;
1071         break;
1072     default:
1073         need_byteswap = FALSE;
1074         break;
1075     }
1076
1077     src = src_bits->ptr;
1078     if (info->bmiHeader.biHeight > 0)
1079         src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes;
1080     else
1081         src += coords->visrect.top * width_bytes;
1082
1083     if ((need_byteswap && !src_bits->is_copy) ||  /* need to swap bytes */
1084         (zeropad_mask != ~0u && !src_bits->is_copy) ||  /* need to clear padding bytes */
1085         (mapping && !src_bits->is_copy) ||  /* need to remap pixels */
1086         (width_bytes & 3) ||  /* need to fixup line alignment */
1087         (info->bmiHeader.biHeight > 0))  /* need to flip vertically */
1088     {
1089         width_bytes = (width_bytes + 3) & ~3;
1090         info->bmiHeader.biSizeImage = height * width_bytes;
1091         if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
1092             return ERROR_OUTOFMEMORY;
1093         dst_bits->is_copy = TRUE;
1094         dst_bits->free = free_heap_bits;
1095     }
1096     else
1097     {
1098         /* swap bits in place */
1099         dst_bits->ptr = src;
1100         dst_bits->is_copy = src_bits->is_copy;
1101         dst_bits->free = NULL;
1102         if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS;  /* nothing to do */
1103     }
1104
1105     dst = dst_bits->ptr;
1106     padding_pos = width_bytes/sizeof(unsigned int) - 1;
1107
1108     if (info->bmiHeader.biHeight > 0)
1109     {
1110         dst += (height - 1) * width_bytes;
1111         width_bytes = -width_bytes;
1112     }
1113
1114     if (need_byteswap || mapping)
1115     {
1116         switch (info->bmiHeader.biBitCount)
1117         {
1118         case 1:
1119             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1120             {
1121                 for (x = 0; x < image->bytes_per_line; x++)
1122                     dst[x] = bit_swap[src[x]];
1123                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1124             }
1125             break;
1126         case 4:
1127             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1128             {
1129                 if (mapping)
1130                     for (x = 0; x < image->bytes_per_line; x++)
1131                         dst[x] = (mapping[src[x] & 0x0f] << 4) | mapping[src[x] >> 4];
1132                 else
1133                     for (x = 0; x < image->bytes_per_line; x++)
1134                         dst[x] = (src[x] << 4) | (src[x] >> 4);
1135                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1136             }
1137             break;
1138         case 8:
1139             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1140             {
1141                 for (x = 0; x < image->bytes_per_line; x++)
1142                     dst[x] = mapping[src[x]];
1143                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1144             }
1145             break;
1146         case 16:
1147             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1148             {
1149                 for (x = 0; x < info->bmiHeader.biWidth; x++)
1150                     ((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] );
1151                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1152             }
1153             break;
1154         case 24:
1155             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1156             {
1157                 for (x = 0; x < info->bmiHeader.biWidth; x++)
1158                 {
1159                     unsigned char tmp = src[3 * x];
1160                     dst[3 * x]     = src[3 * x + 2];
1161                     dst[3 * x + 1] = src[3 * x + 1];
1162                     dst[3 * x + 2] = tmp;
1163                 }
1164                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1165             }
1166             break;
1167         case 32:
1168             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1169                 for (x = 0; x < info->bmiHeader.biWidth; x++)
1170                     ((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] );
1171             break;
1172         }
1173     }
1174     else if (src != dst)
1175     {
1176         for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1177         {
1178             memcpy( dst, src, image->bytes_per_line );
1179             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1180         }
1181     }
1182     else  /* only need to clear the padding */
1183     {
1184         for (y = 0; y < height; y++, dst += width_bytes)
1185             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1186     }
1187     return ERROR_SUCCESS;
1188 }
1189
1190 /***********************************************************************
1191  *           X11DRV_PutImage
1192  */
1193 DWORD X11DRV_PutImage( PHYSDEV dev, HRGN clip, BITMAPINFO *info,
1194                        const struct gdi_image_bits *bits, struct bitblt_coords *src,
1195                        struct bitblt_coords *dst, DWORD rop )
1196 {
1197     X11DRV_PDEVICE *physdev = get_x11drv_dev( dev );
1198     DWORD ret;
1199     XImage *image;
1200     XVisualInfo vis;
1201     struct gdi_image_bits dst_bits;
1202     const XPixmapFormatValues *format;
1203     const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1204     const int *mapping = NULL;
1205
1206     vis.depth = physdev->depth;
1207     if (physdev->color_shifts)
1208     {
1209         vis.red_mask   = physdev->color_shifts->logicalRed.max   << physdev->color_shifts->logicalRed.shift;
1210         vis.green_mask = physdev->color_shifts->logicalGreen.max << physdev->color_shifts->logicalGreen.shift;
1211         vis.blue_mask  = physdev->color_shifts->logicalBlue.max  << physdev->color_shifts->logicalBlue.shift;
1212     }
1213     format = pixmap_formats[vis.depth];
1214
1215     if (info->bmiHeader.biPlanes != 1) goto update_format;
1216     if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1217     /* FIXME: could try to handle 1-bpp using XCopyPlane */
1218     if (!matching_color_info( &vis, info )) goto update_format;
1219     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
1220     if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
1221
1222     wine_tsx11_lock();
1223     image = XCreateImage( gdi_display, visual, vis.depth, ZPixmap, 0, NULL,
1224                           info->bmiHeader.biWidth, src->visrect.bottom - src->visrect.top, 32, 0 );
1225     wine_tsx11_unlock();
1226     if (!image) return ERROR_OUTOFMEMORY;
1227
1228     if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1229     {
1230         if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1231             mapping = X11DRV_PALETTE_PaletteToXPixel;
1232     }
1233
1234     ret = copy_image_bits( info, is_r8g8b8(&vis), image, bits, &dst_bits, src, mapping, ~0u );
1235
1236     if (!ret)
1237     {
1238         BOOL restore_region = add_extra_clipping_region( physdev, clip );
1239         int width = dst->visrect.right - dst->visrect.left;
1240         int height = dst->visrect.bottom - dst->visrect.top;
1241
1242         image->data = dst_bits.ptr;
1243
1244         /* optimization for single-op ROPs */
1245         if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1246         {
1247             wine_tsx11_lock();
1248             XSetFunction( gdi_display, physdev->gc, OP_ROP(*opcode) );
1249             XPutImage( gdi_display, physdev->drawable, physdev->gc, image, src->visrect.left, 0,
1250                        physdev->dc_rect.left + dst->visrect.left,
1251                        physdev->dc_rect.top + dst->visrect.top, width, height );
1252             wine_tsx11_unlock();
1253         }
1254         else
1255         {
1256             Pixmap src_pixmap;
1257             GC gc;
1258
1259             wine_tsx11_lock();
1260             gc = XCreateGC( gdi_display, physdev->drawable, 0, NULL );
1261             XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
1262             XSetGraphicsExposures( gdi_display, gc, False );
1263             src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, vis.depth );
1264             XPutImage( gdi_display, src_pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
1265             wine_tsx11_unlock();
1266
1267             execute_rop( physdev, src_pixmap, gc, &dst->visrect, rop );
1268
1269             wine_tsx11_lock();
1270             XFreePixmap( gdi_display, src_pixmap );
1271             XFreeGC( gdi_display, gc );
1272             wine_tsx11_unlock();
1273         }
1274
1275         if (restore_region) restore_clipping_region( physdev );
1276         add_device_bounds( physdev, &dst->visrect );
1277         image->data = NULL;
1278     }
1279
1280     wine_tsx11_lock();
1281     XDestroyImage( image );
1282     wine_tsx11_unlock();
1283     if (dst_bits.free) dst_bits.free( &dst_bits );
1284     return ret;
1285
1286 update_format:
1287     info->bmiHeader.biPlanes   = 1;
1288     info->bmiHeader.biBitCount = format->bits_per_pixel;
1289     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1290     set_color_info( &vis, info );
1291     return ERROR_BAD_FORMAT;
1292 }
1293
1294 /***********************************************************************
1295  *           X11DRV_GetImage
1296  */
1297 DWORD X11DRV_GetImage( PHYSDEV dev, BITMAPINFO *info,
1298                        struct gdi_image_bits *bits, struct bitblt_coords *src )
1299 {
1300     X11DRV_PDEVICE *physdev = get_x11drv_dev( dev );
1301     DWORD ret = ERROR_SUCCESS;
1302     XImage *image;
1303     XVisualInfo vis;
1304     UINT align, x, y, width, height;
1305     struct gdi_image_bits src_bits;
1306     const XPixmapFormatValues *format;
1307     const int *mapping = NULL;
1308
1309     vis.depth = physdev->depth;
1310     if (physdev->color_shifts)
1311     {
1312         vis.red_mask   = physdev->color_shifts->logicalRed.max   << physdev->color_shifts->logicalRed.shift;
1313         vis.green_mask = physdev->color_shifts->logicalGreen.max << physdev->color_shifts->logicalGreen.shift;
1314         vis.blue_mask  = physdev->color_shifts->logicalBlue.max  << physdev->color_shifts->logicalBlue.shift;
1315     }
1316     format = pixmap_formats[vis.depth];
1317
1318     /* align start and width to 32-bit boundary */
1319     switch (format->bits_per_pixel)
1320     {
1321     case 1:  align = 32; break;
1322     case 4:  align = 8;  mapping = X11DRV_PALETTE_XPixelToPalette; break;
1323     case 8:  align = 4;  mapping = X11DRV_PALETTE_XPixelToPalette; break;
1324     case 16: align = 2;  break;
1325     case 24: align = 4;  break;
1326     case 32: align = 1;  break;
1327     default:
1328         FIXME( "depth %u bpp %u not supported yet\n", vis.depth, format->bits_per_pixel );
1329         return ERROR_BAD_FORMAT;
1330     }
1331
1332     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
1333     info->bmiHeader.biPlanes        = 1;
1334     info->bmiHeader.biBitCount      = format->bits_per_pixel;
1335     info->bmiHeader.biXPelsPerMeter = 0;
1336     info->bmiHeader.biYPelsPerMeter = 0;
1337     info->bmiHeader.biClrImportant  = 0;
1338     set_color_info( &vis, info );
1339
1340     if (!bits) return ERROR_SUCCESS;  /* just querying the color information */
1341
1342     x = src->visrect.left & ~(align - 1);
1343     y = src->visrect.top;
1344     width = src->visrect.right - x;
1345     height = src->visrect.bottom - src->visrect.top;
1346     if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
1347     /* make the source rectangle relative to the returned bits */
1348     src->x -= x;
1349     src->y -= y;
1350     OffsetRect( &src->visrect, -x, -y );
1351
1352     X11DRV_expect_error( gdi_display, XGetImage_handler, NULL );
1353     image = XGetImage( gdi_display, physdev->drawable,
1354                        physdev->dc_rect.left + x, physdev->dc_rect.top + y,
1355                        width, height, AllPlanes, ZPixmap );
1356     if (X11DRV_check_error())
1357     {
1358         /* use a temporary pixmap to avoid the BadMatch error */
1359         GC gc;
1360         Pixmap pixmap;
1361
1362         wine_tsx11_lock();
1363         pixmap = XCreatePixmap( gdi_display, root_window, width, height, vis.depth );
1364         gc = XCreateGC( gdi_display, pixmap, 0, NULL );
1365         XSetGraphicsExposures( gdi_display, gc, False );
1366         XCopyArea( gdi_display, physdev->drawable, pixmap, gc,
1367                    physdev->dc_rect.left + x, physdev->dc_rect.top + y, width, height, 0, 0 );
1368         image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1369         XFreePixmap( gdi_display, pixmap );
1370         XFreeGC( gdi_display, gc );
1371         wine_tsx11_unlock();
1372     }
1373
1374     if (!image) return ERROR_OUTOFMEMORY;
1375
1376     info->bmiHeader.biWidth     = width;
1377     info->bmiHeader.biHeight    = -height;
1378     info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1379
1380     src_bits.ptr     = image->data;
1381     src_bits.is_copy = TRUE;
1382     ret = copy_image_bits( info, is_r8g8b8(&vis), image, &src_bits, bits, src, mapping,
1383                            zeropad_masks[(width * image->bits_per_pixel) & 31] );
1384
1385     if (!ret && bits->ptr == image->data)
1386     {
1387         bits->free = free_ximage_bits;
1388         image->data = NULL;
1389     }
1390     wine_tsx11_lock();
1391     XDestroyImage( image );
1392     wine_tsx11_unlock();
1393     return ret;
1394 }
1395
1396
1397 /***********************************************************************
1398  *           put_pixmap_image
1399  *
1400  * Simplified equivalent of X11DRV_PutImage that writes directly to a pixmap.
1401  */
1402 static DWORD put_pixmap_image( Pixmap pixmap, const XVisualInfo *vis,
1403                                BITMAPINFO *info, const struct gdi_image_bits *bits )
1404 {
1405     DWORD ret;
1406     XImage *image;
1407     GC gc;
1408     struct bitblt_coords coords;
1409     struct gdi_image_bits dst_bits;
1410     const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1411     const int *mapping = NULL;
1412
1413     if (!format) return ERROR_INVALID_PARAMETER;
1414     if (info->bmiHeader.biPlanes != 1) goto update_format;
1415     if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1416     /* FIXME: could try to handle 1-bpp using XCopyPlane */
1417     if (!matching_color_info( vis, info )) goto update_format;
1418     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
1419
1420     coords.x = 0;
1421     coords.y = 0;
1422     coords.width = info->bmiHeader.biWidth;
1423     coords.height = abs( info->bmiHeader.biHeight );
1424     SetRect( &coords.visrect, 0, 0, coords.width, coords.height );
1425
1426     wine_tsx11_lock();
1427     image = XCreateImage( gdi_display, visual, vis->depth, ZPixmap, 0, NULL,
1428                           coords.width, coords.height, 32, 0 );
1429     wine_tsx11_unlock();
1430     if (!image) return ERROR_OUTOFMEMORY;
1431
1432     if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1433         mapping = X11DRV_PALETTE_PaletteToXPixel;
1434
1435     if (!(ret = copy_image_bits( info, is_r8g8b8(vis), image, bits, &dst_bits, &coords, mapping, ~0u )))
1436     {
1437         image->data = dst_bits.ptr;
1438         wine_tsx11_lock();
1439         gc = XCreateGC( gdi_display, pixmap, 0, NULL );
1440         XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, coords.width, coords.height );
1441         XFreeGC( gdi_display, gc );
1442         wine_tsx11_unlock();
1443         image->data = NULL;
1444     }
1445
1446     wine_tsx11_lock();
1447     XDestroyImage( image );
1448     wine_tsx11_unlock();
1449     if (dst_bits.free) dst_bits.free( &dst_bits );
1450     return ret;
1451
1452 update_format:
1453     info->bmiHeader.biPlanes   = 1;
1454     info->bmiHeader.biBitCount = format->bits_per_pixel;
1455     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1456     set_color_info( vis, info );
1457     return ERROR_BAD_FORMAT;
1458 }
1459
1460
1461 /***********************************************************************
1462  *           create_pixmap_from_image
1463  */
1464 Pixmap create_pixmap_from_image( HDC hdc, const XVisualInfo *vis, const BITMAPINFO *info,
1465                                  const struct gdi_image_bits *bits, UINT coloruse )
1466 {
1467     static const RGBQUAD default_colortable[2] = { { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff } };
1468     char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1469     char src_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1470     BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
1471     BITMAPINFO *src_info = (BITMAPINFO *)src_buffer;
1472     struct gdi_image_bits dst_bits;
1473     Pixmap pixmap;
1474     DWORD err;
1475     HBITMAP dib;
1476
1477     wine_tsx11_lock();
1478     pixmap = XCreatePixmap( gdi_display, root_window,
1479                             info->bmiHeader.biWidth, abs(info->bmiHeader.biHeight), vis->depth );
1480     wine_tsx11_unlock();
1481     if (!pixmap) return 0;
1482
1483     memcpy( src_info, info, get_dib_info_size( info, coloruse ));
1484     memcpy( dst_info, info, get_dib_info_size( info, coloruse ));
1485
1486     if (coloruse == DIB_PAL_COLORS ||
1487         (err = put_pixmap_image( pixmap, vis, dst_info, bits )) == ERROR_BAD_FORMAT)
1488     {
1489         if (dst_info->bmiHeader.biBitCount == 1)  /* set a default color table for 1-bpp */
1490             memcpy( dst_info->bmiColors, default_colortable, sizeof(default_colortable) );
1491         dib = CreateDIBSection( hdc, dst_info, coloruse, &dst_bits.ptr, 0, 0 );
1492         if (dib)
1493         {
1494             if (src_info->bmiHeader.biBitCount == 1 && !src_info->bmiHeader.biClrUsed)
1495                 memcpy( src_info->bmiColors, default_colortable, sizeof(default_colortable) );
1496             SetDIBits( hdc, dib, 0, abs(info->bmiHeader.biHeight), bits->ptr, src_info, coloruse );
1497             dst_bits.free = NULL;
1498             dst_bits.is_copy = TRUE;
1499             err = put_pixmap_image( pixmap, vis, dst_info, &dst_bits );
1500             DeleteObject( dib );
1501         }
1502         else err = ERROR_OUTOFMEMORY;
1503     }
1504
1505     if (!err) return pixmap;
1506
1507     wine_tsx11_lock();
1508     XFreePixmap( gdi_display, pixmap );
1509     wine_tsx11_unlock();
1510     return 0;
1511
1512 }
1513
1514
1515 /***********************************************************************
1516  *           get_pixmap_image
1517  *
1518  * Equivalent of X11DRV_GetImage that reads directly from a pixmap.
1519  */
1520 DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo *vis,
1521                         BITMAPINFO *info, struct gdi_image_bits *bits )
1522 {
1523     DWORD ret = ERROR_SUCCESS;
1524     XImage *image;
1525     struct gdi_image_bits src_bits;
1526     struct bitblt_coords coords;
1527     const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1528     const int *mapping = NULL;
1529
1530     if (!format) return ERROR_INVALID_PARAMETER;
1531
1532     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
1533     info->bmiHeader.biWidth         = width;
1534     info->bmiHeader.biHeight        = -height;
1535     info->bmiHeader.biPlanes        = 1;
1536     info->bmiHeader.biBitCount      = format->bits_per_pixel;
1537     info->bmiHeader.biXPelsPerMeter = 0;
1538     info->bmiHeader.biYPelsPerMeter = 0;
1539     info->bmiHeader.biClrImportant  = 0;
1540     set_color_info( vis, info );
1541
1542     if (!bits) return ERROR_SUCCESS;  /* just querying the color information */
1543
1544     coords.x = 0;
1545     coords.y = 0;
1546     coords.width = width;
1547     coords.height = height;
1548     SetRect( &coords.visrect, 0, 0, width, height );
1549
1550     wine_tsx11_lock();
1551     image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1552     wine_tsx11_unlock();
1553     if (!image) return ERROR_OUTOFMEMORY;
1554
1555     info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1556
1557     src_bits.ptr     = image->data;
1558     src_bits.is_copy = TRUE;
1559     ret = copy_image_bits( info, is_r8g8b8(vis), image, &src_bits, bits, &coords, mapping,
1560                            zeropad_masks[(width * image->bits_per_pixel) & 31] );
1561
1562     if (!ret && bits->ptr == image->data)
1563     {
1564         bits->free = free_ximage_bits;
1565         image->data = NULL;
1566     }
1567     wine_tsx11_lock();
1568     XDestroyImage( image );
1569     wine_tsx11_unlock();
1570     return ret;
1571 }