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