winealsa: Fix AudioRenderClient Get/ReleaseBuffer protocol.
[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     wine_tsx11_lock();
766     XSetFunction( gdi_display, physDev->gc, OP_ROP(*opcode) );
767
768     switch(rop)  /* a few special cases */
769     {
770     case BLACKNESS:  /* 0x00 */
771     case WHITENESS:  /* 0xff */
772         if ((physDev->depth != 1) && X11DRV_PALETTE_PaletteToXPixel)
773         {
774             XSetFunction( gdi_display, physDev->gc, GXcopy );
775             if (rop == BLACKNESS)
776                 XSetForeground( gdi_display, physDev->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
777             else
778                 XSetForeground( gdi_display, physDev->gc,
779                                 WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
780             XSetFillStyle( gdi_display, physDev->gc, FillSolid );
781         }
782         break;
783     case DSTINVERT:  /* 0x55 */
784         if (!(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL)))
785         {
786             /* Xor is much better when we do not have full colormap.   */
787             /* Using white^black ensures that we invert at least black */
788             /* and white. */
789             unsigned long xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
790                                      BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
791             XSetFunction( gdi_display, physDev->gc, GXxor );
792             XSetForeground( gdi_display, physDev->gc, xor_pix);
793             XSetFillStyle( gdi_display, physDev->gc, FillSolid );
794         }
795         break;
796     }
797     XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
798                     physDev->dc_rect.left + dst->visrect.left,
799                     physDev->dc_rect.top + dst->visrect.top,
800                     dst->visrect.right - dst->visrect.left,
801                     dst->visrect.bottom - dst->visrect.top );
802     wine_tsx11_unlock();
803     return TRUE;
804 }
805
806
807 /***********************************************************************
808  *           X11DRV_StretchBlt
809  */
810 BOOL X11DRV_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
811                         PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
812 {
813     X11DRV_PDEVICE *physDevDst = get_x11drv_dev( dst_dev );
814     X11DRV_PDEVICE *physDevSrc = get_x11drv_dev( src_dev );
815     INT width, height;
816     const BYTE *opcode;
817     Pixmap src_pixmap;
818     GC gc;
819
820     if (src_dev->funcs != dst_dev->funcs ||
821         src->width != dst->width || src->height != dst->height ||  /* no stretching with core X11 */
822         (physDevDst->depth == 1 && physDevSrc->depth != 1) ||  /* color -> mono done by hand */
823         (X11DRV_PALETTE_XPixelToPalette && physDevSrc->depth != 1))  /* needs palette mapping */
824     {
825         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
826         return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
827     }
828
829     width  = dst->visrect.right - dst->visrect.left;
830     height = dst->visrect.bottom - dst->visrect.top;
831     opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
832
833     /* a few optimizations for single-op ROPs */
834     if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
835     {
836         if (same_format(physDevSrc, physDevDst))
837         {
838             wine_tsx11_lock();
839             XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
840             XCopyArea( gdi_display, physDevSrc->drawable,
841                        physDevDst->drawable, physDevDst->gc,
842                        physDevSrc->dc_rect.left + src->visrect.left,
843                        physDevSrc->dc_rect.top + src->visrect.top,
844                        width, height,
845                        physDevDst->dc_rect.left + dst->visrect.left,
846                        physDevDst->dc_rect.top + dst->visrect.top );
847             physDevDst->exposures++;
848             wine_tsx11_unlock();
849             return TRUE;
850         }
851         if (physDevSrc->depth == 1)
852         {
853             wine_tsx11_lock();
854             XSetBackground( gdi_display, physDevDst->gc, physDevDst->textPixel );
855             XSetForeground( gdi_display, physDevDst->gc, physDevDst->backgroundPixel );
856             XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
857             XCopyPlane( gdi_display, physDevSrc->drawable,
858                         physDevDst->drawable, physDevDst->gc,
859                         physDevSrc->dc_rect.left + src->visrect.left,
860                         physDevSrc->dc_rect.top + src->visrect.top,
861                         width, height,
862                         physDevDst->dc_rect.left + dst->visrect.left,
863                         physDevDst->dc_rect.top + dst->visrect.top, 1 );
864             physDevDst->exposures++;
865             wine_tsx11_unlock();
866             return TRUE;
867         }
868     }
869
870     wine_tsx11_lock();
871     gc = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
872     XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
873     XSetGraphicsExposures( gdi_display, gc, False );
874
875     /* retrieve the source */
876
877     src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, physDevDst->depth );
878     if (physDevSrc->depth == 1)
879     {
880         /* MSDN says if StretchBlt must convert a bitmap from monochrome
881            to color or vice versa, the foreground and background color of
882            the device context are used.  In fact, it also applies to the
883            case when it is converted from mono to mono. */
884         if (X11DRV_PALETTE_XPixelToPalette && physDevDst->depth != 1)
885         {
886             XSetBackground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[physDevDst->textPixel] );
887             XSetForeground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[physDevDst->backgroundPixel]);
888         }
889         else
890         {
891             XSetBackground( gdi_display, gc, physDevDst->textPixel );
892             XSetForeground( gdi_display, gc, physDevDst->backgroundPixel );
893         }
894         XCopyPlane( gdi_display, physDevSrc->drawable, src_pixmap, gc,
895                     physDevSrc->dc_rect.left + src->visrect.left,
896                     physDevSrc->dc_rect.top + src->visrect.top,
897                     width, height, 0, 0, 1 );
898     }
899     else  /* color -> color */
900     {
901         XCopyArea( gdi_display, physDevSrc->drawable, src_pixmap, gc,
902                    physDevSrc->dc_rect.left + src->visrect.left,
903                    physDevSrc->dc_rect.top + src->visrect.top,
904                    width, height, 0, 0 );
905     }
906     wine_tsx11_unlock();
907
908     execute_rop( physDevDst, src_pixmap, gc, &dst->visrect, rop );
909
910     wine_tsx11_lock();
911     XFreePixmap( gdi_display, src_pixmap );
912     XFreeGC( gdi_display, gc );
913     wine_tsx11_unlock();
914     return TRUE;
915 }
916
917
918 static void free_heap_bits( struct gdi_image_bits *bits )
919 {
920     HeapFree( GetProcessHeap(), 0, bits->ptr );
921 }
922
923 static void free_ximage_bits( struct gdi_image_bits *bits )
924 {
925     wine_tsx11_lock();
926     XFree( bits->ptr );
927     wine_tsx11_unlock();
928 }
929
930 /* store the palette or color mask data in the bitmap info structure */
931 static void set_color_info( PHYSDEV dev, const ColorShifts *color_shifts, BITMAPINFO *info )
932 {
933     DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
934
935     info->bmiHeader.biCompression = BI_RGB;
936     info->bmiHeader.biClrUsed = 0;
937
938     switch (info->bmiHeader.biBitCount)
939     {
940     case 4:
941     case 8:
942     {
943         RGBQUAD *rgb = (RGBQUAD *)colors;
944         PALETTEENTRY palette[256];
945         UINT i, count;
946
947         info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
948         count = X11DRV_GetSystemPaletteEntries( dev, 0, info->bmiHeader.biClrUsed, palette );
949         for (i = 0; i < count; i++)
950         {
951             rgb[i].rgbRed   = palette[i].peRed;
952             rgb[i].rgbGreen = palette[i].peGreen;
953             rgb[i].rgbBlue  = palette[i].peBlue;
954             rgb[i].rgbReserved = 0;
955         }
956         memset( &rgb[count], 0, (info->bmiHeader.biClrUsed - count) * sizeof(*rgb) );
957         break;
958     }
959     case 16:
960         colors[0] = color_shifts->logicalRed.max << color_shifts->logicalRed.shift;
961         colors[1] = color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift;
962         colors[2] = color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift;
963         info->bmiHeader.biCompression = BI_BITFIELDS;
964         break;
965     case 32:
966         colors[0] = color_shifts->logicalRed.max << color_shifts->logicalRed.shift;
967         colors[1] = color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift;
968         colors[2] = color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift;
969         if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff)
970             info->bmiHeader.biCompression = BI_BITFIELDS;
971         break;
972     }
973 }
974
975 /* check if the specified color info is suitable for PutImage */
976 static BOOL matching_color_info( PHYSDEV dev, const ColorShifts *color_shifts, const BITMAPINFO *info )
977 {
978     DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
979
980     switch (info->bmiHeader.biBitCount)
981     {
982     case 1:
983         if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
984         return !info->bmiHeader.biClrUsed;  /* color map not allowed */
985     case 4:
986     case 8:
987     {
988         RGBQUAD *rgb = (RGBQUAD *)colors;
989         PALETTEENTRY palette[256];
990         UINT i, count;
991
992         if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
993         count = X11DRV_GetSystemPaletteEntries( dev, 0, 1 << info->bmiHeader.biBitCount, palette );
994         if (count != info->bmiHeader.biClrUsed) return FALSE;
995         for (i = 0; i < count; i++)
996         {
997             if (rgb[i].rgbRed   != palette[i].peRed ||
998                 rgb[i].rgbGreen != palette[i].peGreen ||
999                 rgb[i].rgbBlue  != palette[i].peBlue) return FALSE;
1000         }
1001         return TRUE;
1002     }
1003     case 16:
1004         if (info->bmiHeader.biCompression == BI_BITFIELDS)
1005             return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == colors[0] &&
1006                     color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == colors[1] &&
1007                     color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == colors[2]);
1008         if (info->bmiHeader.biCompression == BI_RGB)
1009             return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift     == 0x7c00 &&
1010                     color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == 0x03e0 &&
1011                     color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift   == 0x001f);
1012         break;
1013     case 32:
1014         if (info->bmiHeader.biCompression == BI_BITFIELDS)
1015             return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift == colors[0] &&
1016                     color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == colors[1] &&
1017                     color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift == colors[2]);
1018         /* fall through */
1019     case 24:
1020         if (info->bmiHeader.biCompression == BI_RGB)
1021             return (color_shifts->logicalRed.max << color_shifts->logicalRed.shift     == 0xff0000 &&
1022                     color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift == 0x00ff00 &&
1023                     color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift   == 0x0000ff);
1024         break;
1025     }
1026     return FALSE;
1027 }
1028
1029 static inline BOOL is_r8g8b8( int depth, const ColorShifts *color_shifts )
1030 {
1031     return depth == 24 && color_shifts->logicalBlue.shift == 0 && color_shifts->logicalRed.shift == 16;
1032 }
1033
1034 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1035 DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
1036                        const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
1037                        struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
1038 {
1039 #ifdef WORDS_BIGENDIAN
1040     static const int client_byte_order = MSBFirst;
1041 #else
1042     static const int client_byte_order = LSBFirst;
1043 #endif
1044     BOOL need_byteswap;
1045     int x, y, height = coords->visrect.bottom - coords->visrect.top;
1046     int width_bytes = image->bytes_per_line;
1047     int padding_pos;
1048     unsigned char *src, *dst;
1049
1050     switch (info->bmiHeader.biBitCount)
1051     {
1052     case 1:
1053         need_byteswap = (image->bitmap_bit_order != MSBFirst);
1054         break;
1055     case 4:
1056         need_byteswap = (image->byte_order != MSBFirst);
1057         break;
1058     case 16:
1059     case 32:
1060         need_byteswap = (image->byte_order != client_byte_order);
1061         break;
1062     case 24:
1063         need_byteswap = (image->byte_order == MSBFirst) ^ !is_r8g8b8;
1064         break;
1065     default:
1066         need_byteswap = FALSE;
1067         break;
1068     }
1069
1070     src = src_bits->ptr;
1071     if (info->bmiHeader.biHeight > 0)
1072         src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes;
1073     else
1074         src += coords->visrect.top * width_bytes;
1075
1076     if ((need_byteswap && !src_bits->is_copy) ||  /* need to swap bytes */
1077         (zeropad_mask != ~0u && !src_bits->is_copy) ||  /* need to clear padding bytes */
1078         (mapping && !src_bits->is_copy) ||  /* need to remap pixels */
1079         (width_bytes & 3) ||  /* need to fixup line alignment */
1080         (info->bmiHeader.biHeight > 0))  /* need to flip vertically */
1081     {
1082         width_bytes = (width_bytes + 3) & ~3;
1083         info->bmiHeader.biSizeImage = height * width_bytes;
1084         if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
1085             return ERROR_OUTOFMEMORY;
1086         dst_bits->is_copy = TRUE;
1087         dst_bits->free = free_heap_bits;
1088     }
1089     else
1090     {
1091         /* swap bits in place */
1092         dst_bits->ptr = src;
1093         dst_bits->is_copy = src_bits->is_copy;
1094         dst_bits->free = NULL;
1095         if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS;  /* nothing to do */
1096     }
1097
1098     dst = dst_bits->ptr;
1099     padding_pos = width_bytes/sizeof(unsigned int) - 1;
1100
1101     if (info->bmiHeader.biHeight > 0)
1102     {
1103         dst += (height - 1) * width_bytes;
1104         width_bytes = -width_bytes;
1105     }
1106
1107     if (need_byteswap || mapping)
1108     {
1109         switch (info->bmiHeader.biBitCount)
1110         {
1111         case 1:
1112             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1113             {
1114                 for (x = 0; x < image->bytes_per_line; x++)
1115                     dst[x] = bit_swap[src[x]];
1116                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1117             }
1118             break;
1119         case 4:
1120             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1121             {
1122                 if (mapping)
1123                     for (x = 0; x < image->bytes_per_line; x++)
1124                         dst[x] = (mapping[src[x] & 0x0f] << 4) | mapping[src[x] >> 4];
1125                 else
1126                     for (x = 0; x < image->bytes_per_line; x++)
1127                         dst[x] = (src[x] << 4) | (src[x] >> 4);
1128                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1129             }
1130             break;
1131         case 8:
1132             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1133             {
1134                 for (x = 0; x < image->bytes_per_line; x++)
1135                     dst[x] = mapping[src[x]];
1136                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1137             }
1138             break;
1139         case 16:
1140             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1141             {
1142                 for (x = 0; x < info->bmiHeader.biWidth; x++)
1143                     ((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] );
1144                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1145             }
1146             break;
1147         case 24:
1148             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1149             {
1150                 for (x = 0; x < info->bmiHeader.biWidth; x++)
1151                 {
1152                     unsigned char tmp = src[3 * x];
1153                     dst[3 * x]     = src[3 * x + 2];
1154                     dst[3 * x + 1] = src[3 * x + 1];
1155                     dst[3 * x + 2] = tmp;
1156                 }
1157                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1158             }
1159             break;
1160         case 32:
1161             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1162                 for (x = 0; x < info->bmiHeader.biWidth; x++)
1163                     ((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] );
1164             break;
1165         }
1166     }
1167     else if (src != dst)
1168     {
1169         for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1170         {
1171             memcpy( dst, src, image->bytes_per_line );
1172             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1173         }
1174     }
1175     else  /* only need to clear the padding */
1176     {
1177         for (y = 0; y < height; y++, dst += width_bytes)
1178             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1179     }
1180     return ERROR_SUCCESS;
1181 }
1182
1183 /***********************************************************************
1184  *           X11DRV_PutImage
1185  */
1186 DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
1187                        const struct gdi_image_bits *bits, struct bitblt_coords *src,
1188                        struct bitblt_coords *dst, DWORD rop )
1189 {
1190     X11DRV_PDEVICE *physdev;
1191     X_PHYSBITMAP *bitmap;
1192     DWORD ret;
1193     XImage *image;
1194     int depth;
1195     struct gdi_image_bits dst_bits;
1196     const XPixmapFormatValues *format;
1197     const ColorShifts *color_shifts;
1198     const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1199     const int *mapping = NULL;
1200
1201     if (hbitmap)
1202     {
1203         if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
1204         physdev = NULL;
1205         depth = bitmap->depth;
1206         color_shifts = &bitmap->color_shifts;
1207     }
1208     else
1209     {
1210         physdev = get_x11drv_dev( dev );
1211         bitmap = NULL;
1212         depth = physdev->depth;
1213         color_shifts = physdev->color_shifts;
1214     }
1215     format = pixmap_formats[depth];
1216
1217     if (info->bmiHeader.biPlanes != 1) goto update_format;
1218     if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1219     /* FIXME: could try to handle 1-bpp using XCopyPlane */
1220     if (!matching_color_info( dev, color_shifts, info )) goto update_format;
1221     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
1222     if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
1223
1224     wine_tsx11_lock();
1225     image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0, NULL,
1226                           info->bmiHeader.biWidth, src->visrect.bottom - src->visrect.top, 32, 0 );
1227     wine_tsx11_unlock();
1228     if (!image) return ERROR_OUTOFMEMORY;
1229
1230     if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1231     {
1232         if (bitmap || (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST)))
1233             mapping = X11DRV_PALETTE_PaletteToXPixel;
1234     }
1235
1236     ret = copy_image_bits( info, is_r8g8b8(depth,color_shifts), image, bits, &dst_bits, src, mapping, ~0u );
1237
1238     if (!ret)
1239     {
1240         int width = dst->visrect.right - dst->visrect.left;
1241         int height = dst->visrect.bottom - dst->visrect.top;
1242
1243         image->data = dst_bits.ptr;
1244         /* hack: make sure the bits are readable if we are reading from a DIB section */
1245         /* to be removed once we get rid of DIB access protections */
1246         if (!dst_bits.is_copy) IsBadReadPtr( dst_bits.ptr, height * image->bytes_per_line );
1247
1248         if (bitmap)
1249         {
1250             RGNDATA *clip_data = NULL;
1251             GC gc;
1252
1253             if (clip) clip_data = X11DRV_GetRegionData( clip, 0 );
1254
1255             wine_tsx11_lock();
1256             gc = XCreateGC( gdi_display, bitmap->pixmap, 0, NULL );
1257             XSetGraphicsExposures( gdi_display, gc, False );
1258             if (clip_data) XSetClipRectangles( gdi_display, gc, 0, 0, (XRectangle *)clip_data->Buffer,
1259                                                clip_data->rdh.nCount, YXBanded );
1260             XPutImage( gdi_display, bitmap->pixmap, gc, image, src->visrect.left, 0,
1261                        dst->visrect.left, dst->visrect.top, width, height );
1262             XFreeGC( gdi_display, gc );
1263             wine_tsx11_unlock();
1264             HeapFree( GetProcessHeap(), 0, clip_data );
1265         }
1266         else
1267         {
1268             BOOL restore_region = add_extra_clipping_region( physdev, clip );
1269
1270             /* optimization for single-op ROPs */
1271             if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1272             {
1273                 wine_tsx11_lock();
1274                 XSetFunction( gdi_display, physdev->gc, OP_ROP(*opcode) );
1275                 XPutImage( gdi_display, physdev->drawable, physdev->gc, image, src->visrect.left, 0,
1276                            physdev->dc_rect.left + dst->visrect.left,
1277                            physdev->dc_rect.top + dst->visrect.top, width, height );
1278                 wine_tsx11_unlock();
1279             }
1280             else
1281             {
1282                 Pixmap src_pixmap;
1283                 GC gc;
1284
1285                 wine_tsx11_lock();
1286                 gc = XCreateGC( gdi_display, physdev->drawable, 0, NULL );
1287                 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
1288                 XSetGraphicsExposures( gdi_display, gc, False );
1289                 src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1290                 XPutImage( gdi_display, src_pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
1291                 wine_tsx11_unlock();
1292
1293                 execute_rop( physdev, src_pixmap, gc, &dst->visrect, rop );
1294
1295                 wine_tsx11_lock();
1296                 XFreePixmap( gdi_display, src_pixmap );
1297                 XFreeGC( gdi_display, gc );
1298                 wine_tsx11_unlock();
1299             }
1300
1301             if (restore_region) restore_clipping_region( physdev );
1302         }
1303         image->data = NULL;
1304     }
1305
1306     wine_tsx11_lock();
1307     XDestroyImage( image );
1308     wine_tsx11_unlock();
1309     if (dst_bits.free) dst_bits.free( &dst_bits );
1310     return ret;
1311
1312 update_format:
1313     info->bmiHeader.biPlanes   = 1;
1314     info->bmiHeader.biBitCount = format->bits_per_pixel;
1315     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1316     set_color_info( dev, color_shifts, info );
1317     return ERROR_BAD_FORMAT;
1318 }
1319
1320 /***********************************************************************
1321  *           X11DRV_GetImage
1322  */
1323 DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
1324                        struct gdi_image_bits *bits, struct bitblt_coords *src )
1325 {
1326     X11DRV_PDEVICE *physdev;
1327     X_PHYSBITMAP *bitmap;
1328     DWORD ret = ERROR_SUCCESS;
1329     XImage *image;
1330     UINT align, x, y, width, height;
1331     int depth;
1332     struct gdi_image_bits src_bits;
1333     const XPixmapFormatValues *format;
1334     const ColorShifts *color_shifts;
1335     const int *mapping = NULL;
1336
1337     if (hbitmap)
1338     {
1339         if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
1340         physdev = NULL;
1341         depth = bitmap->depth;
1342         color_shifts = &bitmap->color_shifts;
1343     }
1344     else
1345     {
1346         physdev = get_x11drv_dev( dev );
1347         bitmap = NULL;
1348         depth = physdev->depth;
1349         color_shifts = physdev->color_shifts;
1350     }
1351     format = pixmap_formats[depth];
1352
1353     /* align start and width to 32-bit boundary */
1354     switch (format->bits_per_pixel)
1355     {
1356     case 1:  align = 32; break;
1357     case 4:  align = 8;  mapping = X11DRV_PALETTE_XPixelToPalette; break;
1358     case 8:  align = 4;  mapping = X11DRV_PALETTE_XPixelToPalette; break;
1359     case 16: align = 2;  break;
1360     case 24: align = 4;  break;
1361     case 32: align = 1;  break;
1362     default:
1363         FIXME( "depth %u bpp %u not supported yet\n", depth, format->bits_per_pixel );
1364         return ERROR_BAD_FORMAT;
1365     }
1366
1367     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
1368     info->bmiHeader.biPlanes        = 1;
1369     info->bmiHeader.biBitCount      = format->bits_per_pixel;
1370     info->bmiHeader.biXPelsPerMeter = 0;
1371     info->bmiHeader.biYPelsPerMeter = 0;
1372     info->bmiHeader.biClrImportant  = 0;
1373     set_color_info( dev, color_shifts, info );
1374
1375     if (!bits) return ERROR_SUCCESS;  /* just querying the color information */
1376
1377     x = src->visrect.left & ~(align - 1);
1378     y = src->visrect.top;
1379     width = src->visrect.right - x;
1380     height = src->visrect.bottom - src->visrect.top;
1381     if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
1382     /* make the source rectangle relative to the returned bits */
1383     src->x -= x;
1384     src->y -= y;
1385     OffsetRect( &src->visrect, -x, -y );
1386
1387     if (bitmap)
1388     {
1389         BITMAP bm;
1390         GetObjectW( hbitmap, sizeof(bm), &bm );
1391         width = min( width, bm.bmWidth - x );
1392         height = min( height, bm.bmHeight - y );
1393         wine_tsx11_lock();
1394         image = XGetImage( gdi_display, bitmap->pixmap, x, y, width, height, AllPlanes, ZPixmap );
1395         wine_tsx11_unlock();
1396     }
1397     else if (GetObjectType( dev->hdc ) == OBJ_MEMDC)
1398     {
1399         width = min( width, physdev->dc_rect.right - physdev->dc_rect.left - x );
1400         height = min( height, physdev->dc_rect.bottom - physdev->dc_rect.top - y );
1401         wine_tsx11_lock();
1402         image = XGetImage( gdi_display, physdev->drawable,
1403                            physdev->dc_rect.left + x, physdev->dc_rect.top + y,
1404                            width, height, AllPlanes, ZPixmap );
1405         wine_tsx11_unlock();
1406     }
1407     else
1408     {
1409         X11DRV_expect_error( gdi_display, XGetImage_handler, NULL );
1410         image = XGetImage( gdi_display, physdev->drawable,
1411                            physdev->dc_rect.left + x, physdev->dc_rect.top + y,
1412                            width, height, AllPlanes, ZPixmap );
1413         if (X11DRV_check_error())
1414         {
1415             /* use a temporary pixmap to avoid the BadMatch error */
1416             Pixmap pixmap;
1417
1418             wine_tsx11_lock();
1419             pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
1420             XCopyArea( gdi_display, physdev->drawable, pixmap, get_bitmap_gc(depth),
1421                        physdev->dc_rect.left + x, physdev->dc_rect.top + y, width, height, 0, 0 );
1422             image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1423             XFreePixmap( gdi_display, pixmap );
1424             wine_tsx11_unlock();
1425         }
1426     }
1427     if (!image) return ERROR_OUTOFMEMORY;
1428
1429     info->bmiHeader.biWidth     = width;
1430     info->bmiHeader.biHeight    = -height;
1431     info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1432
1433     src_bits.ptr     = image->data;
1434     src_bits.is_copy = TRUE;
1435     ret = copy_image_bits( info, is_r8g8b8(depth,color_shifts), image, &src_bits, bits, src, mapping,
1436                            zeropad_masks[(width * image->bits_per_pixel) & 31] );
1437
1438     if (!ret && bits->ptr == image->data)
1439     {
1440         bits->free = free_ximage_bits;
1441         image->data = NULL;
1442     }
1443     wine_tsx11_lock();
1444     XDestroyImage( image );
1445     wine_tsx11_unlock();
1446     return ret;
1447 }