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