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