winex11: Try XRandR 1.0 if 1.2 fails.
[wine] / dlls / winex11.drv / bitblt.c
1 /*
2  * GDI bit-blit operations
3  *
4  * Copyright 1993, 1994, 2011 Alexandre Julliard
5  * Copyright 2006 Damjan Jovanovic
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "winternl.h"
34 #include "x11drv.h"
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
38
39
40 #define DST 0   /* Destination drawable */
41 #define SRC 1   /* Source drawable */
42 #define TMP 2   /* Temporary drawable */
43 #define PAT 3   /* Pattern (brush) in destination DC */
44
45 #define OP(src,dst,rop)   (OP_ARGS(src,dst) << 4 | (rop))
46 #define OP_ARGS(src,dst)  (((src) << 2) | (dst))
47
48 #define OP_SRC(opcode)    ((opcode) >> 6)
49 #define OP_DST(opcode)    (((opcode) >> 4) & 3)
50 #define OP_SRCDST(opcode) ((opcode) >> 4)
51 #define OP_ROP(opcode)    ((opcode) & 0x0f)
52
53 #define MAX_OP_LEN  6  /* Longest opcode + 1 for the terminating 0 */
54
55 static const unsigned char BITBLT_Opcodes[256][MAX_OP_LEN] =
56 {
57     { OP(PAT,DST,GXclear) },                         /* 0x00  0              */
58     { OP(PAT,SRC,GXor), OP(SRC,DST,GXnor) },         /* 0x01  ~(D|(P|S))     */
59     { OP(PAT,SRC,GXnor), OP(SRC,DST,GXand) },        /* 0x02  D&~(P|S)       */
60     { OP(PAT,SRC,GXnor) },                           /* 0x03  ~(P|S)         */
61     { OP(PAT,DST,GXnor), OP(SRC,DST,GXand) },        /* 0x04  S&~(D|P)       */
62     { OP(PAT,DST,GXnor) },                           /* 0x05  ~(D|P)         */
63     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnor), },     /* 0x06  ~(P|~(D^S))    */
64     { OP(SRC,DST,GXand), OP(PAT,DST,GXnor) },        /* 0x07  ~(P|(D&S))     */
65     { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXand) },/* 0x08  S&D&~P         */
66     { OP(SRC,DST,GXxor), OP(PAT,DST,GXnor) },        /* 0x09  ~(P|(D^S))     */
67     { OP(PAT,DST,GXandInverted) },                   /* 0x0a  D&~P           */
68     { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXnor) }, /* 0x0b  ~(P|(S&~D))    */
69     { OP(PAT,SRC,GXandInverted) },                   /* 0x0c  S&~P           */
70     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXnor) },/* 0x0d  ~(P|(D&~S))    */
71     { OP(SRC,DST,GXnor), OP(PAT,DST,GXnor) },        /* 0x0e  ~(P|~(D|S))    */
72     { OP(PAT,DST,GXcopyInverted) },                  /* 0x0f  ~P             */
73     { OP(SRC,DST,GXnor), OP(PAT,DST,GXand) },        /* 0x10  P&~(S|D)       */
74     { OP(SRC,DST,GXnor) },                           /* 0x11  ~(D|S)         */
75     { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnor) },      /* 0x12  ~(S|~(D^P))    */
76     { OP(PAT,DST,GXand), OP(SRC,DST,GXnor) },        /* 0x13  ~(S|(D&P))     */
77     { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnor) },      /* 0x14  ~(D|~(P^S))    */
78     { OP(PAT,SRC,GXand), OP(SRC,DST,GXnor) },        /* 0x15  ~(D|(P&S))     */
79     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
80       OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
81       OP(PAT,DST,GXxor) },                           /* 0x16  P^S^(D&~(P&S)  */
82     { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
83       OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
84       OP(TMP,DST,GXequiv) },                         /* 0x17 ~S^((S^P)&(S^D))*/
85     { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
86         OP(SRC,DST,GXand) },                         /* 0x18  (S^P)&(D^P)    */
87     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
88       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x19  ~S^(D&~(P&S))  */
89     { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
90       OP(PAT,DST,GXxor) },                           /* 0x1a  P^(D|(S&P))    */
91     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
92       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x1b  ~S^(D&(P^S))   */
93     { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
94       OP(PAT,DST,GXxor) },                           /* 0x1c  P^(S|(D&P))    */
95     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
96       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x1d  ~D^(S&(D^P))   */
97     { OP(SRC,DST,GXor), OP(PAT,DST,GXxor) },         /* 0x1e  P^(D|S)        */
98     { OP(SRC,DST,GXor), OP(PAT,DST,GXnand) },        /* 0x1f  ~(P&(D|S))     */
99     { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXand) }, /* 0x20  D&(P&~S)       */
100     { OP(PAT,DST,GXxor), OP(SRC,DST,GXnor) },        /* 0x21  ~(S|(D^P))     */
101     { OP(SRC,DST,GXandInverted) },                   /* 0x22  ~S&D           */
102     { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x23  ~(S|(P&~D))    */
103     { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
104       OP(SRC,DST,GXand) },                           /* 0x24   (S^P)&(S^D)   */
105     { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand),
106       OP(PAT,DST,GXequiv) },                         /* 0x25  ~P^(D&~(S&P))  */
107     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
108       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x26  S^(D|(S&P))    */
109     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXequiv),
110       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x27  S^(D|~(P^S))   */
111     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand) },        /* 0x28  D&(P^S)        */
112     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
113       OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
114       OP(PAT,DST,GXequiv) },                         /* 0x29  ~P^S^(D|(P&S)) */
115     { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand) },       /* 0x2a  D&~(P&S)       */
116     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
117       OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
118       OP(TMP,DST,GXequiv) },                         /* 0x2b ~S^((P^S)&(P^D))*/
119     { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
120       OP(SRC,DST,GXxor) },                           /* 0x2c  S^(P&(S|D))    */
121     { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXxor) },  /* 0x2d  P^(S|~D)       */
122     { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
123       OP(PAT,DST,GXxor) },                           /* 0x2e  P^(S|(D^P))    */
124     { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXnand) }, /* 0x2f  ~(P&(S|~D))    */
125     { OP(PAT,SRC,GXandReverse) },                    /* 0x30  P&~S           */
126     { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXnor) },/* 0x31  ~(S|(D&~P))    */
127     { OP(SRC,DST,GXor), OP(PAT,DST,GXor),
128       OP(SRC,DST,GXxor) },                           /* 0x32  S^(D|P|S)      */
129     { OP(SRC,DST,GXcopyInverted) },                  /* 0x33  ~S             */
130     { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
131       OP(SRC,DST,GXxor) },                           /* 0x34  S^(P|(D&S))    */
132     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor),
133       OP(SRC,DST,GXxor) },                           /* 0x35  S^(P|~(D^S))   */
134     { OP(PAT,DST,GXor), OP(SRC,DST,GXxor) },         /* 0x36  S^(D|P)        */
135     { OP(PAT,DST,GXor), OP(SRC,DST,GXnand) },        /* 0x37  ~(S&(D|P))     */
136     { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
137       OP(PAT,DST,GXxor) },                           /* 0x38  P^(S&(D|P))    */
138     { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXxor) },  /* 0x39  S^(P|~D)       */
139     { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
140       OP(SRC,DST,GXxor) },                           /* 0x3a  S^(P|(D^S))    */
141     { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x3b  ~(S&(P|~D))    */
142     { OP(PAT,SRC,GXxor) },                           /* 0x3c  P^S            */
143     { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
144       OP(SRC,DST,GXxor) },                           /* 0x3d  S^(P|~(D|S))   */
145     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
146       OP(SRC,DST,GXxor) },                           /* 0x3e  S^(P|(D&~S))   */
147     { OP(PAT,SRC,GXnand) },                          /* 0x3f  ~(P&S)         */
148     { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXand) }, /* 0x40  P&S&~D         */
149     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnor) },        /* 0x41  ~(D|(P^S))     */
150     { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
151       OP(SRC,DST,GXand) },                           /* 0x42  (S^D)&(P^D)    */
152     { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
153       OP(SRC,DST,GXequiv) },                         /* 0x43  ~S^(P&~(D&S))  */
154     { OP(SRC,DST,GXandReverse) },                    /* 0x44  S&~D           */
155     { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x45  ~(D|(P&~S))    */
156     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
157       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x46  D^(S|(P&D))    */
158     { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
159       OP(PAT,DST,GXequiv) },                         /* 0x47  ~P^(S&(D^P))   */
160     { OP(PAT,DST,GXxor), OP(SRC,DST,GXand) },        /* 0x48  S&(P^D)        */
161     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
162       OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
163       OP(PAT,DST,GXequiv) },                         /* 0x49  ~P^D^(S|(P&D)) */
164     { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
165       OP(SRC,DST,GXxor) },                           /* 0x4a  D^(P&(S|D))    */
166     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXxor) }, /* 0x4b  P^(D|~S)       */
167     { OP(PAT,DST,GXnand), OP(SRC,DST,GXand) },       /* 0x4c  S&~(D&P)       */
168     { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
169       OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
170       OP(TMP,DST,GXequiv) },                         /* 0x4d ~S^((S^P)|(S^D))*/
171     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
172       OP(PAT,DST,GXxor) },                           /* 0x4e  P^(D|(S^P))    */
173     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXnand) },/* 0x4f  ~(P&(D|~S))    */
174     { OP(PAT,DST,GXandReverse) },                    /* 0x50  P&~D           */
175     { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXnor) },/* 0x51  ~(D|(S&~P))    */
176     { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
177       OP(SRC,DST,GXxor) },                           /* 0x52  D^(P|(S&D))    */
178     { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
179       OP(SRC,DST,GXequiv) },                         /* 0x53  ~S^(P&(D^S))   */
180     { OP(PAT,SRC,GXnor), OP(SRC,DST,GXnor) },        /* 0x54  ~(D|~(P|S))    */
181     { OP(PAT,DST,GXinvert) },                        /* 0x55  ~D             */
182     { OP(PAT,SRC,GXor), OP(SRC,DST,GXxor) },         /* 0x56  D^(P|S)        */
183     { OP(PAT,SRC,GXor), OP(SRC,DST,GXnand) },        /* 0x57  ~(D&(P|S))     */
184     { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
185       OP(PAT,DST,GXxor) },                           /* 0x58  P^(D&(P|S))    */
186     { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXxor) },  /* 0x59  D^(P|~S)       */
187     { OP(PAT,DST,GXxor) },                           /* 0x5a  D^P            */
188     { OP(DST,SRC,GXnor), OP(PAT,SRC,GXor),
189       OP(SRC,DST,GXxor) },                           /* 0x5b  D^(P|~(S|D))   */
190     { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
191       OP(SRC,DST,GXxor) },                           /* 0x5c  D^(P|(S^D))    */
192     { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x5d  ~(D&(P|~S))    */
193     { OP(DST,SRC,GXandInverted), OP(PAT,SRC,GXor),
194       OP(SRC,DST,GXxor) },                           /* 0x5e  D^(P|(S&~D))   */
195     { OP(PAT,DST,GXnand) },                          /* 0x5f  ~(D&P)         */
196     { OP(SRC,DST,GXxor), OP(PAT,DST,GXand) },        /* 0x60  P&(D^S)        */
197     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
198       OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
199       OP(TMP,DST,GXequiv) },                         /* 0x61  ~D^S^(P|(D&S)) */
200     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
201       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0x62  D^(S&(P|D))    */
202     { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x63  S^(D|~P)       */
203     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
204       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0x64  S^(D&(P|S))    */
205     { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x65  D^(S|~P)       */
206     { OP(SRC,DST,GXxor) },                           /* 0x66  S^D            */
207     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
208       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x67  S^(D|~(S|P)    */
209     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnor),
210       OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
211       OP(TMP,DST,GXequiv) },                         /* 0x68  ~D^S^(P|~(D|S))*/
212     { OP(SRC,DST,GXxor), OP(PAT,DST,GXequiv) },      /* 0x69  ~P^(D^S)       */
213     { OP(PAT,SRC,GXand), OP(SRC,DST,GXxor) },        /* 0x6a  D^(P&S)        */
214     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
215       OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
216       OP(PAT,DST,GXequiv) },                         /* 0x6b  ~P^S^(D&(P|S)) */
217     { OP(PAT,DST,GXand), OP(SRC,DST,GXxor) },        /* 0x6c  S^(D&P)        */
218     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
219       OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
220       OP(PAT,DST,GXequiv) },                         /* 0x6d  ~P^D^(S&(P|D)) */
221     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
222       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0x6e  S^(D&(P|~S))   */
223     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnand) },     /* 0x6f  ~(P&~(S^D))    */
224     { OP(SRC,DST,GXnand), OP(PAT,DST,GXand) },       /* 0x70  P&~(D&S)       */
225     { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
226       OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
227       OP(TMP,DST,GXequiv) },                         /* 0x71 ~S^((S^D)&(P^D))*/
228     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
229       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x72  S^(D|(P^S))    */
230     { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXnand) },/* 0x73  ~(S&(D|~P))    */
231     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
232       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x74   D^(S|(P^D))   */
233     { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXnand) },/* 0x75  ~(D&(S|~P))    */
234     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
235       OP(SRC,DST,GXor), OP(TMP,DST,GXxor) },         /* 0x76  S^(D|(P&~S))   */
236     { OP(SRC,DST,GXnand) },                          /* 0x77  ~(S&D)         */
237     { OP(SRC,DST,GXand), OP(PAT,DST,GXxor) },        /* 0x78  P^(D&S)        */
238     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
239       OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
240       OP(TMP,DST,GXequiv) },                         /* 0x79  ~D^S^(P&(D|S)) */
241     { OP(DST,SRC,GXorInverted), OP(PAT,SRC,GXand),
242       OP(SRC,DST,GXxor) },                           /* 0x7a  D^(P&(S|~D))   */
243     { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnand) },     /* 0x7b  ~(S&~(D^P))    */
244     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
245       OP(SRC,DST,GXxor) },                           /* 0x7c  S^(P&(D|~S))   */
246     { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnand) },     /* 0x7d  ~(D&~(P^S))    */
247     { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
248       OP(SRC,DST,GXor) },                            /* 0x7e  (S^P)|(S^D)    */
249     { OP(PAT,SRC,GXand), OP(SRC,DST,GXnand) },       /* 0x7f  ~(D&P&S)       */
250     { OP(PAT,SRC,GXand), OP(SRC,DST,GXand) },        /* 0x80  D&P&S          */
251     { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
252       OP(SRC,DST,GXnor) },                           /* 0x81  ~((S^P)|(S^D)) */
253     { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXand) },      /* 0x82  D&~(P^S)       */
254     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
255       OP(SRC,DST,GXequiv) },                         /* 0x83  ~S^(P&(D|~S))  */
256     { OP(PAT,DST,GXequiv), OP(SRC,DST,GXand) },      /* 0x84  S&~(D^P)       */
257     { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand),
258       OP(PAT,DST,GXequiv) },                         /* 0x85  ~P^(D&(S|~P))  */
259     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
260       OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
261       OP(TMP,DST,GXxor) },                           /* 0x86  D^S^(P&(D|S))  */
262     { OP(SRC,DST,GXand), OP(PAT,DST,GXequiv) },      /* 0x87  ~P^(D&S)       */
263     { OP(SRC,DST,GXand) },                           /* 0x88  S&D            */
264     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
265       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0x89  ~S^(D|(P&~S))  */
266     { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8a  D&(S|~P)       */
267     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
268       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0x8b  ~D^(S|(P^D))   */
269     { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8c  S&(D|~P)       */
270     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
271       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0x8d  ~S^(D|(P^S))   */
272     { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
273       OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
274       OP(TMP,DST,GXxor) },                           /* 0x8e  S^((S^D)&(P^D))*/
275     { OP(SRC,DST,GXnand), OP(PAT,DST,GXnand) },      /* 0x8f  ~(P&~(D&S))    */
276     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXand) },      /* 0x90  P&~(D^S)       */
277     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
278       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x91  ~S^(D&(P|~S))  */
279     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
280       OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
281       OP(TMP,DST,GXxor) },                           /* 0x92  D^P^(S&(D|P))  */
282     { OP(PAT,DST,GXand), OP(SRC,DST,GXequiv) },      /* 0x93  ~S^(P&D)       */
283     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
284       OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
285       OP(TMP,DST,GXxor) },                           /* 0x94  S^P^(D&(P|S))  */
286     { OP(PAT,SRC,GXand), OP(SRC,DST,GXequiv) },      /* 0x95  ~D^(P&S)       */
287     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXxor) },        /* 0x96  D^P^S          */
288     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
289       OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
290       OP(TMP,DST,GXxor) },                           /* 0x97  S^P^(D|~(P|S)) */
291     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
292       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0x98  ~S^(D|~(P|S))  */
293     { OP(SRC,DST,GXequiv) },                         /* 0x99  ~S^D           */
294     { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9a  D^(P&~S)       */
295     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
296       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x9b  ~S^(D&(P|S))   */
297     { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9c  S^(P&~D)       */
298     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
299       OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) },      /* 0x9d  ~D^(S&(P|D))   */
300     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
301       OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
302       OP(TMP,DST,GXxor) },                           /* 0x9e  D^S^(P|(D&S))  */
303     { OP(SRC,DST,GXxor), OP(PAT,DST,GXnand) },       /* 0x9f  ~(P&(D^S))     */
304     { OP(PAT,DST,GXand) },                           /* 0xa0  D&P            */
305     { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor),
306       OP(PAT,DST,GXequiv) },                         /* 0xa1  ~P^(D|(S&~P))  */
307     { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXand) },  /* 0xa2  D&(P|~S)       */
308     { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
309       OP(SRC,DST,GXequiv) },                         /* 0xa3  ~D^(P|(S^D))   */
310     { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor),
311       OP(PAT,DST,GXequiv) },                         /* 0xa4  ~P^(D|~(S|P))  */
312     { OP(PAT,DST,GXequiv) },                         /* 0xa5  ~P^D           */
313     { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXxor) },/* 0xa6  D^(S&~P)       */
314     { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
315       OP(PAT,DST,GXequiv) },                         /* 0xa7  ~P^(D&(S|P))   */
316     { OP(PAT,SRC,GXor), OP(SRC,DST,GXand) },         /* 0xa8  D&(P|S)        */
317     { OP(PAT,SRC,GXor), OP(SRC,DST,GXequiv) },       /* 0xa9  ~D^(P|S)       */
318     { OP(PAT,DST,GXnoop) },                          /* 0xaa  D              */
319     { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor) },         /* 0xab  D|~(P|S)       */
320     { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
321       OP(SRC,DST,GXxor) },                           /* 0xac  S^(P&(D^S))    */
322     { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
323       OP(SRC,DST,GXequiv) },                         /* 0xad  ~D^(P|(S&D))   */
324     { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor) }, /* 0xae  D|(S&~P)       */
325     { OP(PAT,DST,GXorInverted) },                    /* 0xaf  D|~P           */
326     { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand) }, /* 0xb0  P&(D|~S)       */
327     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
328       OP(PAT,DST,GXequiv) },                         /* 0xb1  ~P^(D|(S^P))   */
329     { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
330       OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
331       OP(TMP,DST,GXxor) },                           /* 0xb2  S^((S^P)|(S^D))*/
332     { OP(PAT,DST,GXnand), OP(SRC,DST,GXnand) },      /* 0xb3  ~(S&~(D&P))    */
333     { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXxor) }, /* 0xb4  P^(S&~D)       */
334     { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
335       OP(SRC,DST,GXequiv) },                         /* 0xb5  ~D^(P&(S|D))   */
336     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
337       OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
338       OP(TMP,DST,GXxor) },                           /* 0xb6  D^P^(S|(D&P))  */
339     { OP(PAT,DST,GXxor), OP(SRC,DST,GXnand) },       /* 0xb7  ~(S&(D^P))     */
340     { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
341       OP(PAT,DST,GXxor) },                           /* 0xb8  P^(S&(D^P))    */
342     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
343       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0xb9  ~D^(S|(P&D))   */
344     { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXor) },  /* 0xba  D|(P&~S)       */
345     { OP(SRC,DST,GXorInverted) },                    /* 0xbb  ~S|D           */
346     { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
347       OP(SRC,DST,GXxor) },                           /* 0xbc  S^(P&~(D&S))   */
348     { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
349       OP(SRC,DST,GXnand) },                          /* 0xbd  ~((S^D)&(P^D)) */
350     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor) },         /* 0xbe  D|(P^S)        */
351     { OP(PAT,SRC,GXnand), OP(SRC,DST,GXor) },        /* 0xbf  D|~(P&S)       */
352     { OP(PAT,SRC,GXand) },                           /* 0xc0  P&S            */
353     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
354       OP(SRC,DST,GXequiv) },                         /* 0xc1  ~S^(P|(D&~S))  */
355     { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
356       OP(SRC,DST,GXequiv) },                         /* 0xc2  ~S^(P|~(D|S))  */
357     { OP(PAT,SRC,GXequiv) },                         /* 0xc3  ~P^S           */
358     { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXand) },  /* 0xc4  S&(P|~D)       */
359     { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
360       OP(SRC,DST,GXequiv) },                         /* 0xc5  ~S^(P|(D^S))   */
361     { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXxor) },/* 0xc6  S^(D&~P)       */
362     { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
363       OP(PAT,DST,GXequiv) },                         /* 0xc7  ~P^(S&(D|P))   */
364     { OP(PAT,DST,GXor), OP(SRC,DST,GXand) },         /* 0xc8  S&(D|P)        */
365     { OP(PAT,DST,GXor), OP(SRC,DST,GXequiv) },       /* 0xc9  ~S^(P|D)       */
366     { OP(DST,SRC,GXxor), OP(PAT,SRC,GXand),
367       OP(SRC,DST,GXxor) },                           /* 0xca  D^(P&(S^D))    */
368     { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
369       OP(SRC,DST,GXequiv) },                         /* 0xcb  ~S^(P|(D&S))   */
370     { OP(SRC,DST,GXcopy) },                          /* 0xcc  S              */
371     { OP(PAT,DST,GXnor), OP(SRC,DST,GXor) },         /* 0xcd  S|~(D|P)       */
372     { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXor) }, /* 0xce  S|(D&~P)       */
373     { OP(PAT,SRC,GXorInverted) },                    /* 0xcf  S|~P           */
374     { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXand) },  /* 0xd0  P&(S|~D)       */
375     { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
376       OP(PAT,DST,GXequiv) },                         /* 0xd1  ~P^(S|(D^P))   */
377     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXxor) },/* 0xd2  P^(D&~S)       */
378     { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
379       OP(SRC,DST,GXequiv) },                         /* 0xd3  ~S^(P&(D|S))   */
380     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
381       OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
382       OP(TMP,DST,GXxor) },                           /* 0xd4  S^((S^P)&(D^P))*/
383     { OP(PAT,SRC,GXnand), OP(SRC,DST,GXnand) },      /* 0xd5  ~(D&~(P&S))    */
384     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
385       OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
386       OP(TMP,DST,GXxor) },                           /* 0xd6  S^P^(D|(P&S))  */
387     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnand) },       /* 0xd7  ~(D&(P^S))     */
388     { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
389       OP(PAT,DST,GXxor) },                           /* 0xd8  P^(D&(S^P))    */
390     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
391       OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) },       /* 0xd9  ~S^(D|(P&S))   */
392     { OP(DST,SRC,GXnand), OP(PAT,SRC,GXand),
393       OP(SRC,DST,GXxor) },                           /* 0xda  D^(P&~(S&D))   */
394     { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
395       OP(SRC,DST,GXnand) },                          /* 0xdb  ~((S^P)&(S^D)) */
396     { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXor) },  /* 0xdc  S|(P&~D)       */
397     { OP(SRC,DST,GXorReverse) },                     /* 0xdd  S|~D           */
398     { OP(PAT,DST,GXxor), OP(SRC,DST,GXor) },         /* 0xde  S|(D^P)        */
399     { OP(PAT,DST,GXnand), OP(SRC,DST,GXor) },        /* 0xdf  S|~(D&P)       */
400     { OP(SRC,DST,GXor), OP(PAT,DST,GXand) },         /* 0xe0  P&(D|S)        */
401     { OP(SRC,DST,GXor), OP(PAT,DST,GXequiv) },       /* 0xe1  ~P^(D|S)       */
402     { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
403       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0xe2  D^(S&(P^D))    */
404     { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
405       OP(PAT,DST,GXequiv) },                         /* 0xe3  ~P^(S|(D&P))   */
406     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
407       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0xe4  S^(D&(P^S))    */
408     { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
409       OP(PAT,DST,GXequiv) },                         /* 0xe5  ~P^(D|(S&P))   */
410     { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
411       OP(SRC,DST,GXand), OP(TMP,DST,GXxor) },        /* 0xe6  S^(D&~(P&S))   */
412     { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
413       OP(SRC,DST,GXnand) },                          /* 0xe7  ~((S^P)&(D^P)) */
414     { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
415       OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
416       OP(TMP,DST,GXxor) },                           /* 0xe8  S^((S^P)&(S^D))*/
417     { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnand),
418       OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
419       OP(TMP,DST,GXequiv) },                         /* 0xe9  ~D^S^(P&~(S&D))*/
420     { OP(PAT,SRC,GXand), OP(SRC,DST,GXor) },         /* 0xea  D|(P&S)        */
421     { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXor) },       /* 0xeb  D|~(P^S)       */
422     { OP(PAT,DST,GXand), OP(SRC,DST,GXor) },         /* 0xec  S|(D&P)        */
423     { OP(PAT,DST,GXequiv), OP(SRC,DST,GXor) },       /* 0xed  S|~(D^P)       */
424     { OP(SRC,DST,GXor) },                            /* 0xee  S|D            */
425     { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXor) },  /* 0xef  S|D|~P         */
426     { OP(PAT,DST,GXcopy) },                          /* 0xf0  P              */
427     { OP(SRC,DST,GXnor), OP(PAT,DST,GXor) },         /* 0xf1  P|~(D|S)       */
428     { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor) }, /* 0xf2  P|(D&~S)       */
429     { OP(PAT,SRC,GXorReverse) },                     /* 0xf3  P|~S           */
430     { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXor) },  /* 0xf4  P|(S&~D)       */
431     { OP(PAT,DST,GXorReverse) },                     /* 0xf5  P|~D           */
432     { OP(SRC,DST,GXxor), OP(PAT,DST,GXor) },         /* 0xf6  P|(D^S)        */
433     { OP(SRC,DST,GXnand), OP(PAT,DST,GXor) },        /* 0xf7  P|~(S&D)       */
434     { OP(SRC,DST,GXand), OP(PAT,DST,GXor) },         /* 0xf8  P|(D&S)        */
435     { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor) },       /* 0xf9  P|~(D^S)       */
436     { OP(PAT,DST,GXor) },                            /* 0xfa  D|P            */
437     { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXor) },   /* 0xfb  D|P|~S         */
438     { OP(PAT,SRC,GXor) },                            /* 0xfc  P|S            */
439     { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXor) },   /* 0xfd  P|S|~D         */
440     { OP(SRC,DST,GXor), OP(PAT,DST,GXor) },          /* 0xfe  P|D|S          */
441     { OP(PAT,DST,GXset) }                            /* 0xff  1              */
442 };
443
444 static const unsigned char bit_swap[256] =
445 {
446     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
447     0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
448     0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
449     0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
450     0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
451     0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
452     0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
453     0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
454     0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
455     0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
456     0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
457     0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
458     0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
459     0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
460     0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
461     0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
462     0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
463     0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
464     0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
465     0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
466     0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
467     0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
468     0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
469     0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
470     0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
471     0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
472     0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
473     0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
474     0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
475     0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
476     0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
477     0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
478 };
479
480 #ifdef WORDS_BIGENDIAN
481 static const unsigned int zeropad_masks[32] =
482 {
483     0xffffffff, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
484     0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
485     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
486     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe
487 };
488 #else
489 static const unsigned int zeropad_masks[32] =
490 {
491     0xffffffff, 0x00000080, 0x000000c0, 0x000000e0, 0x000000f0, 0x000000f8, 0x000000fc, 0x000000fe,
492     0x000000ff, 0x000080ff, 0x0000c0ff, 0x0000e0ff, 0x0000f0ff, 0x0000f8ff, 0x0000fcff, 0x0000feff,
493     0x0000ffff, 0x0080ffff, 0x00c0ffff, 0x00e0ffff, 0x00f0ffff, 0x00f8ffff, 0x00fcffff, 0x00feffff,
494     0x00ffffff, 0x80ffffff, 0xc0ffffff, 0xe0ffffff, 0xf0ffffff, 0xf8ffffff, 0xfcffffff, 0xfeffffff
495 };
496 #endif
497
498 #ifdef BITBLT_TEST  /* Opcodes test */
499
500 static int do_bitop( int s, int d, int rop )
501 {
502     int res;
503     switch(rop)
504     {
505     case GXclear:        res = 0; break;
506     case GXand:          res = s & d; break;
507     case GXandReverse:   res = s & ~d; break;
508     case GXcopy:         res = s; break;
509     case GXandInverted:  res = ~s & d; break;
510     case GXnoop:         res = d; break;
511     case GXxor:          res = s ^ d; break;
512     case GXor:           res = s | d; break;
513     case GXnor:          res = ~(s | d); break;
514     case GXequiv:        res = ~s ^ d; break;
515     case GXinvert:       res = ~d; break;
516     case GXorReverse:    res = s | ~d; break;
517     case GXcopyInverted: res = ~s; break;
518     case GXorInverted:   res = ~s | d; break;
519     case GXnand:         res = ~(s & d); break;
520     case GXset:          res = 1; break;
521     }
522     return res & 1;
523 }
524
525 int main()
526 {
527     int rop, i, res, src, dst, pat, tmp, dstUsed;
528     const unsigned char *opcode;
529
530     for (rop = 0; rop < 256; rop++)
531     {
532         res = dstUsed = 0;
533         for (i = 0; i < 8; i++)
534         {
535             pat = (i >> 2) & 1;
536             src = (i >> 1) & 1;
537             dst = i & 1;
538             for (opcode = BITBLT_Opcodes[rop]; *opcode; opcode++)
539             {
540                 switch(*opcode >> 4)
541                 {
542                 case OP_ARGS(DST,TMP):
543                     tmp = do_bitop( dst, tmp, *opcode & 0xf );
544                     break;
545                 case OP_ARGS(DST,SRC):
546                     src = do_bitop( dst, src, *opcode & 0xf );
547                     break;
548                 case OP_ARGS(SRC,TMP):
549                     tmp = do_bitop( src, tmp, *opcode & 0xf );
550                     break;
551                 case OP_ARGS(SRC,DST):
552                     dst = do_bitop( src, dst, *opcode & 0xf );
553                     dstUsed = 1;
554                     break;
555                 case OP_ARGS(PAT,DST):
556                     dst = do_bitop( pat, dst, *opcode & 0xf );
557                     dstUsed = 1;
558                     break;
559                 case OP_ARGS(PAT,SRC):
560                     src = do_bitop( pat, src, *opcode & 0xf );
561                     break;
562                 case OP_ARGS(TMP,DST):
563                     dst = do_bitop( tmp, dst, *opcode & 0xf );
564                     dstUsed = 1;
565                     break;
566                 case OP_ARGS(TMP,SRC):
567                     src = do_bitop( tmp, src, *opcode & 0xf );
568                     break;
569                 default:
570                     printf( "Invalid opcode %x\n", *opcode );
571                 }
572             }
573             if (!dstUsed) dst = src;
574             if (dst) res |= 1 << i;
575         }
576         if (res != rop) printf( "%02x: ERROR, res=%02x\n", rop, res );
577     }
578
579     return 0;
580 }
581
582 #endif  /* BITBLT_TEST */
583
584
585 /* handler for XGetImage BadMatch errors */
586 static int XGetImage_handler( Display *dpy, XErrorEvent *event, void *arg )
587 {
588     return (event->request_code == X_GetImage && event->error_code == BadMatch);
589 }
590
591 /***********************************************************************
592  *           BITBLT_GetDstArea
593  *
594  * Retrieve an area from the destination DC, mapping all the
595  * pixels to Windows colors.
596  */
597 static int BITBLT_GetDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, GC gc, const RECT *visRectDst)
598 {
599     int exposures = 0;
600     INT width  = visRectDst->right - visRectDst->left;
601     INT height = visRectDst->bottom - visRectDst->top;
602
603     if (!X11DRV_PALETTE_XPixelToPalette || (physDev->depth == 1) ||
604         (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
605     {
606         XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
607                    physDev->dc_rect.left + visRectDst->left, physDev->dc_rect.top + visRectDst->top,
608                    width, height, 0, 0 );
609         exposures++;
610     }
611     else
612     {
613         INT x, y;
614         XImage *image;
615
616         /* Make sure we don't get a BadMatch error */
617         XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
618                    physDev->dc_rect.left + visRectDst->left,
619                    physDev->dc_rect.top + visRectDst->top,
620                    width, height, 0, 0);
621         exposures++;
622         image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
623                            AllPlanes, ZPixmap );
624         if (image)
625         {
626             for (y = 0; y < height; y++)
627                 for (x = 0; x < width; x++)
628                     XPutPixel( image, x, y,
629                                X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]);
630             XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height );
631             XDestroyImage( image );
632         }
633     }
634     return exposures;
635 }
636
637
638 /***********************************************************************
639  *           BITBLT_PutDstArea
640  *
641  * Put an area back into the destination DC, mapping the pixel
642  * colors to X pixels.
643  */
644 static int BITBLT_PutDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, const RECT *visRectDst)
645 {
646     int exposures = 0;
647     INT width  = visRectDst->right - visRectDst->left;
648     INT height = visRectDst->bottom - visRectDst->top;
649
650     /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
651
652     if (!X11DRV_PALETTE_PaletteToXPixel || (physDev->depth == 1) ||
653         (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
654     {
655         XCopyArea( gdi_display, pixmap, physDev->drawable, physDev->gc, 0, 0, width, height,
656                    physDev->dc_rect.left + visRectDst->left,
657                    physDev->dc_rect.top + visRectDst->top );
658         exposures++;
659     }
660     else
661     {
662         register INT x, y;
663         XImage *image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
664                                    AllPlanes, ZPixmap );
665         for (y = 0; y < height; y++)
666             for (x = 0; x < width; x++)
667             {
668                 XPutPixel( image, x, y,
669                            X11DRV_PALETTE_PaletteToXPixel[XGetPixel( image, x, y )]);
670             }
671         XPutImage( gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
672                    physDev->dc_rect.left + visRectDst->left,
673                    physDev->dc_rect.top + visRectDst->top, width, height );
674         XDestroyImage( image );
675     }
676     return exposures;
677 }
678
679 static BOOL same_format(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst)
680 {
681     if (physDevSrc->depth != physDevDst->depth) return FALSE;
682     if (!physDevSrc->color_shifts && !physDevDst->color_shifts) return TRUE;
683     if (physDevSrc->color_shifts && physDevDst->color_shifts)
684         return !memcmp(physDevSrc->color_shifts, physDevDst->color_shifts, sizeof(ColorShifts));
685     return FALSE;
686 }
687
688 void execute_rop( X11DRV_PDEVICE *physdev, Pixmap src_pixmap, GC gc, const RECT *visrect, DWORD rop )
689 {
690     Pixmap pixmaps[3];
691     Pixmap result = src_pixmap;
692     BOOL null_brush;
693     const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
694     BOOL use_pat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
695     BOOL use_dst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
696     int width  = visrect->right - visrect->left;
697     int height = visrect->bottom - visrect->top;
698
699     pixmaps[SRC] = src_pixmap;
700     pixmaps[TMP] = 0;
701     pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
702
703     if (use_dst) BITBLT_GetDstArea( physdev, pixmaps[DST], gc, visrect );
704     null_brush = use_pat && !X11DRV_SetupGCForPatBlt( physdev, gc, TRUE );
705
706     for ( ; *opcode; opcode++)
707     {
708         if (OP_DST(*opcode) == DST) result = pixmaps[DST];
709         XSetFunction( gdi_display, gc, OP_ROP(*opcode) );
710         switch(OP_SRCDST(*opcode))
711         {
712         case OP_ARGS(DST,TMP):
713         case OP_ARGS(SRC,TMP):
714             if (!pixmaps[TMP])
715                 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window, width, height, physdev->depth );
716             /* fall through */
717         case OP_ARGS(DST,SRC):
718         case OP_ARGS(SRC,DST):
719         case OP_ARGS(TMP,SRC):
720         case OP_ARGS(TMP,DST):
721             XCopyArea( gdi_display, pixmaps[OP_SRC(*opcode)], pixmaps[OP_DST(*opcode)], gc,
722                        0, 0, width, height, 0, 0 );
723             break;
724         case OP_ARGS(PAT,DST):
725         case OP_ARGS(PAT,SRC):
726             if (!null_brush)
727                 XFillRectangle( gdi_display, pixmaps[OP_DST(*opcode)], gc, 0, 0, width, height );
728             break;
729         }
730     }
731     XSetFunction( gdi_display, physdev->gc, GXcopy );
732     physdev->exposures += BITBLT_PutDstArea( physdev, result, visrect );
733     XFreePixmap( gdi_display, pixmaps[DST] );
734     if (pixmaps[TMP]) XFreePixmap( gdi_display, pixmaps[TMP] );
735     add_device_bounds( physdev, visrect );
736 }
737
738 /***********************************************************************
739  *           X11DRV_PatBlt
740  */
741 BOOL X11DRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
742 {
743     X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
744     BOOL usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
745     const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
746
747     if (usePat && !X11DRV_SetupGCForBrush( physDev )) return TRUE;
748
749     XSetFunction( gdi_display, physDev->gc, OP_ROP(*opcode) );
750
751     switch(rop)  /* a few special cases */
752     {
753     case BLACKNESS:  /* 0x00 */
754     case WHITENESS:  /* 0xff */
755         if ((physDev->depth != 1) && X11DRV_PALETTE_PaletteToXPixel)
756         {
757             XSetFunction( gdi_display, physDev->gc, GXcopy );
758             if (rop == BLACKNESS)
759                 XSetForeground( gdi_display, physDev->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
760             else
761                 XSetForeground( gdi_display, physDev->gc,
762                                 WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
763             XSetFillStyle( gdi_display, physDev->gc, FillSolid );
764         }
765         break;
766     case DSTINVERT:  /* 0x55 */
767         if (!(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL)))
768         {
769             /* Xor is much better when we do not have full colormap.   */
770             /* Using white^black ensures that we invert at least black */
771             /* and white. */
772             unsigned long xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
773                                      BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
774             XSetFunction( gdi_display, physDev->gc, GXxor );
775             XSetForeground( gdi_display, physDev->gc, xor_pix);
776             XSetFillStyle( gdi_display, physDev->gc, FillSolid );
777         }
778         break;
779     }
780     XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
781                     physDev->dc_rect.left + dst->visrect.left,
782                     physDev->dc_rect.top + dst->visrect.top,
783                     dst->visrect.right - dst->visrect.left,
784                     dst->visrect.bottom - dst->visrect.top );
785     add_device_bounds( physDev, &dst->visrect );
786     return TRUE;
787 }
788
789
790 /***********************************************************************
791  *           X11DRV_StretchBlt
792  */
793 BOOL X11DRV_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
794                         PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
795 {
796     X11DRV_PDEVICE *physDevDst = get_x11drv_dev( dst_dev );
797     X11DRV_PDEVICE *physDevSrc = get_x11drv_dev( src_dev );
798     INT width, height;
799     const BYTE *opcode;
800     Pixmap src_pixmap;
801     GC gc;
802
803     if (src_dev->funcs != dst_dev->funcs ||
804         src->width != dst->width || src->height != dst->height ||  /* no stretching with core X11 */
805         (physDevDst->depth == 1 && physDevSrc->depth != 1) ||  /* color -> mono done by hand */
806         (X11DRV_PALETTE_XPixelToPalette && physDevSrc->depth != 1))  /* needs palette mapping */
807     {
808         dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
809         return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
810     }
811
812     width  = dst->visrect.right - dst->visrect.left;
813     height = dst->visrect.bottom - dst->visrect.top;
814     opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
815
816     add_device_bounds( physDevDst, &dst->visrect );
817
818     /* a few optimizations for single-op ROPs */
819     if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
820     {
821         if (same_format(physDevSrc, physDevDst))
822         {
823             XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
824             XCopyArea( gdi_display, physDevSrc->drawable,
825                        physDevDst->drawable, physDevDst->gc,
826                        physDevSrc->dc_rect.left + src->visrect.left,
827                        physDevSrc->dc_rect.top + src->visrect.top,
828                        width, height,
829                        physDevDst->dc_rect.left + dst->visrect.left,
830                        physDevDst->dc_rect.top + dst->visrect.top );
831             physDevDst->exposures++;
832             return TRUE;
833         }
834         if (physDevSrc->depth == 1)
835         {
836             int text_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetTextColor(physDevDst->dev.hdc) );
837             int bkgnd_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetBkColor(physDevDst->dev.hdc) );
838
839             XSetBackground( gdi_display, physDevDst->gc, text_pixel );
840             XSetForeground( gdi_display, physDevDst->gc, bkgnd_pixel );
841             XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
842             XCopyPlane( gdi_display, physDevSrc->drawable,
843                         physDevDst->drawable, physDevDst->gc,
844                         physDevSrc->dc_rect.left + src->visrect.left,
845                         physDevSrc->dc_rect.top + src->visrect.top,
846                         width, height,
847                         physDevDst->dc_rect.left + dst->visrect.left,
848                         physDevDst->dc_rect.top + dst->visrect.top, 1 );
849             physDevDst->exposures++;
850             return TRUE;
851         }
852     }
853
854     gc = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
855     XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
856     XSetGraphicsExposures( gdi_display, gc, False );
857
858     /* retrieve the source */
859
860     src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, physDevDst->depth );
861     if (physDevSrc->depth == 1)
862     {
863         /* MSDN says if StretchBlt must convert a bitmap from monochrome
864            to color or vice versa, the foreground and background color of
865            the device context are used.  In fact, it also applies to the
866            case when it is converted from mono to mono. */
867         int text_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetTextColor(physDevDst->dev.hdc) );
868         int bkgnd_pixel = X11DRV_PALETTE_ToPhysical( physDevDst, GetBkColor(physDevDst->dev.hdc) );
869
870         if (X11DRV_PALETTE_XPixelToPalette && physDevDst->depth != 1)
871         {
872             XSetBackground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[text_pixel] );
873             XSetForeground( gdi_display, gc, X11DRV_PALETTE_XPixelToPalette[bkgnd_pixel]);
874         }
875         else
876         {
877             XSetBackground( gdi_display, gc, text_pixel );
878             XSetForeground( gdi_display, gc, bkgnd_pixel );
879         }
880         XCopyPlane( gdi_display, physDevSrc->drawable, src_pixmap, gc,
881                     physDevSrc->dc_rect.left + src->visrect.left,
882                     physDevSrc->dc_rect.top + src->visrect.top,
883                     width, height, 0, 0, 1 );
884     }
885     else  /* color -> color */
886     {
887         XCopyArea( gdi_display, physDevSrc->drawable, src_pixmap, gc,
888                    physDevSrc->dc_rect.left + src->visrect.left,
889                    physDevSrc->dc_rect.top + src->visrect.top,
890                    width, height, 0, 0 );
891     }
892
893     execute_rop( physDevDst, src_pixmap, gc, &dst->visrect, rop );
894
895     XFreePixmap( gdi_display, src_pixmap );
896     XFreeGC( gdi_display, gc );
897     return TRUE;
898 }
899
900
901 static void free_heap_bits( struct gdi_image_bits *bits )
902 {
903     HeapFree( GetProcessHeap(), 0, bits->ptr );
904 }
905
906 static void free_ximage_bits( struct gdi_image_bits *bits )
907 {
908     XFree( bits->ptr );
909 }
910
911 /* only for use on sanitized BITMAPINFO structures */
912 static inline int get_dib_info_size( const BITMAPINFO *info, UINT coloruse )
913 {
914     if (info->bmiHeader.biCompression == BI_BITFIELDS)
915         return sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD);
916     if (coloruse == DIB_PAL_COLORS)
917         return sizeof(BITMAPINFOHEADER) + info->bmiHeader.biClrUsed * sizeof(WORD);
918     return FIELD_OFFSET( BITMAPINFO, bmiColors[info->bmiHeader.biClrUsed] );
919 }
920
921 /* store the palette or color mask data in the bitmap info structure */
922 static void set_color_info( const XVisualInfo *vis, BITMAPINFO *info )
923 {
924     DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
925
926     info->bmiHeader.biCompression = BI_RGB;
927     info->bmiHeader.biClrUsed = 0;
928
929     switch (info->bmiHeader.biBitCount)
930     {
931     case 4:
932     case 8:
933     {
934         RGBQUAD *rgb = (RGBQUAD *)colors;
935         PALETTEENTRY palette[256];
936         UINT i, count;
937
938         info->bmiHeader.biClrUsed = 1 << info->bmiHeader.biBitCount;
939         count = X11DRV_GetSystemPaletteEntries( NULL, 0, info->bmiHeader.biClrUsed, palette );
940         for (i = 0; i < count; i++)
941         {
942             rgb[i].rgbRed   = palette[i].peRed;
943             rgb[i].rgbGreen = palette[i].peGreen;
944             rgb[i].rgbBlue  = palette[i].peBlue;
945             rgb[i].rgbReserved = 0;
946         }
947         memset( &rgb[count], 0, (info->bmiHeader.biClrUsed - count) * sizeof(*rgb) );
948         break;
949     }
950     case 16:
951         colors[0] = vis->red_mask;
952         colors[1] = vis->green_mask;
953         colors[2] = vis->blue_mask;
954         info->bmiHeader.biCompression = BI_BITFIELDS;
955         break;
956     case 32:
957         colors[0] = vis->red_mask;
958         colors[1] = vis->green_mask;
959         colors[2] = vis->blue_mask;
960         if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff)
961             info->bmiHeader.biCompression = BI_BITFIELDS;
962         break;
963     }
964 }
965
966 /* check if the specified color info is suitable for PutImage */
967 static BOOL matching_color_info( const XVisualInfo *vis, const BITMAPINFO *info )
968 {
969     DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
970
971     switch (info->bmiHeader.biBitCount)
972     {
973     case 1:
974         if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
975         return !info->bmiHeader.biClrUsed;  /* color map not allowed */
976     case 4:
977     case 8:
978     {
979         RGBQUAD *rgb = (RGBQUAD *)colors;
980         PALETTEENTRY palette[256];
981         UINT i, count;
982
983         if (info->bmiHeader.biCompression != BI_RGB) return FALSE;
984         count = X11DRV_GetSystemPaletteEntries( NULL, 0, 1 << info->bmiHeader.biBitCount, palette );
985         if (count != info->bmiHeader.biClrUsed) return FALSE;
986         for (i = 0; i < count; i++)
987         {
988             if (rgb[i].rgbRed   != palette[i].peRed ||
989                 rgb[i].rgbGreen != palette[i].peGreen ||
990                 rgb[i].rgbBlue  != palette[i].peBlue) return FALSE;
991         }
992         return TRUE;
993     }
994     case 16:
995         if (info->bmiHeader.biCompression == BI_BITFIELDS)
996             return (vis->red_mask == colors[0] &&
997                     vis->green_mask == colors[1] &&
998                     vis->blue_mask == colors[2]);
999         if (info->bmiHeader.biCompression == BI_RGB)
1000             return (vis->red_mask == 0x7c00 && vis->green_mask == 0x03e0 && vis->blue_mask == 0x001f);
1001         break;
1002     case 32:
1003         if (info->bmiHeader.biCompression == BI_BITFIELDS)
1004             return (vis->red_mask == colors[0] &&
1005                     vis->green_mask == colors[1] &&
1006                     vis->blue_mask == colors[2]);
1007         /* fall through */
1008     case 24:
1009         if (info->bmiHeader.biCompression == BI_RGB)
1010             return (vis->red_mask == 0xff0000 && vis->green_mask == 0x00ff00 && vis->blue_mask == 0x0000ff);
1011         break;
1012     }
1013     return FALSE;
1014 }
1015
1016 static inline BOOL is_r8g8b8( const XVisualInfo *vis )
1017 {
1018     return vis->depth == 24 && vis->red_mask == 0xff0000 && vis->blue_mask == 0x0000ff;
1019 }
1020
1021 /* copy the image bits, fixing up alignment and byte swapping as necessary */
1022 DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
1023                        const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
1024                        struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
1025 {
1026 #ifdef WORDS_BIGENDIAN
1027     static const int client_byte_order = MSBFirst;
1028 #else
1029     static const int client_byte_order = LSBFirst;
1030 #endif
1031     BOOL need_byteswap;
1032     int x, y, height = coords->visrect.bottom - coords->visrect.top;
1033     int width_bytes = image->bytes_per_line;
1034     int padding_pos;
1035     unsigned char *src, *dst;
1036
1037     switch (info->bmiHeader.biBitCount)
1038     {
1039     case 1:
1040         need_byteswap = (image->bitmap_bit_order != MSBFirst);
1041         break;
1042     case 4:
1043         need_byteswap = (image->byte_order != MSBFirst);
1044         break;
1045     case 16:
1046     case 32:
1047         need_byteswap = (image->byte_order != client_byte_order);
1048         break;
1049     case 24:
1050         need_byteswap = (image->byte_order == MSBFirst) ^ !is_r8g8b8;
1051         break;
1052     default:
1053         need_byteswap = FALSE;
1054         break;
1055     }
1056
1057     src = src_bits->ptr;
1058     if (info->bmiHeader.biHeight > 0)
1059         src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes;
1060     else
1061         src += coords->visrect.top * width_bytes;
1062
1063     if ((need_byteswap && !src_bits->is_copy) ||  /* need to swap bytes */
1064         (zeropad_mask != ~0u && !src_bits->is_copy) ||  /* need to clear padding bytes */
1065         (mapping && !src_bits->is_copy) ||  /* need to remap pixels */
1066         (width_bytes & 3) ||  /* need to fixup line alignment */
1067         (info->bmiHeader.biHeight > 0))  /* need to flip vertically */
1068     {
1069         width_bytes = (width_bytes + 3) & ~3;
1070         info->bmiHeader.biSizeImage = height * width_bytes;
1071         if (!(dst_bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
1072             return ERROR_OUTOFMEMORY;
1073         dst_bits->is_copy = TRUE;
1074         dst_bits->free = free_heap_bits;
1075     }
1076     else
1077     {
1078         /* swap bits in place */
1079         dst_bits->ptr = src;
1080         dst_bits->is_copy = src_bits->is_copy;
1081         dst_bits->free = NULL;
1082         if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS;  /* nothing to do */
1083     }
1084
1085     dst = dst_bits->ptr;
1086     padding_pos = width_bytes/sizeof(unsigned int) - 1;
1087
1088     if (info->bmiHeader.biHeight > 0)
1089     {
1090         dst += (height - 1) * width_bytes;
1091         width_bytes = -width_bytes;
1092     }
1093
1094     if (need_byteswap || mapping)
1095     {
1096         switch (info->bmiHeader.biBitCount)
1097         {
1098         case 1:
1099             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1100             {
1101                 for (x = 0; x < image->bytes_per_line; x++)
1102                     dst[x] = bit_swap[src[x]];
1103                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1104             }
1105             break;
1106         case 4:
1107             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1108             {
1109                 if (mapping)
1110                     for (x = 0; x < image->bytes_per_line; x++)
1111                         dst[x] = (mapping[src[x] & 0x0f] << 4) | mapping[src[x] >> 4];
1112                 else
1113                     for (x = 0; x < image->bytes_per_line; x++)
1114                         dst[x] = (src[x] << 4) | (src[x] >> 4);
1115                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1116             }
1117             break;
1118         case 8:
1119             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1120             {
1121                 for (x = 0; x < image->bytes_per_line; x++)
1122                     dst[x] = mapping[src[x]];
1123                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1124             }
1125             break;
1126         case 16:
1127             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1128             {
1129                 for (x = 0; x < info->bmiHeader.biWidth; x++)
1130                     ((USHORT *)dst)[x] = RtlUshortByteSwap( ((const USHORT *)src)[x] );
1131                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1132             }
1133             break;
1134         case 24:
1135             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1136             {
1137                 for (x = 0; x < info->bmiHeader.biWidth; x++)
1138                 {
1139                     unsigned char tmp = src[3 * x];
1140                     dst[3 * x]     = src[3 * x + 2];
1141                     dst[3 * x + 1] = src[3 * x + 1];
1142                     dst[3 * x + 2] = tmp;
1143                 }
1144                 ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1145             }
1146             break;
1147         case 32:
1148             for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1149                 for (x = 0; x < info->bmiHeader.biWidth; x++)
1150                     ((ULONG *)dst)[x] = RtlUlongByteSwap( ((const ULONG *)src)[x] );
1151             break;
1152         }
1153     }
1154     else if (src != dst)
1155     {
1156         for (y = 0; y < height; y++, src += image->bytes_per_line, dst += width_bytes)
1157         {
1158             memcpy( dst, src, image->bytes_per_line );
1159             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1160         }
1161     }
1162     else  /* only need to clear the padding */
1163     {
1164         for (y = 0; y < height; y++, dst += width_bytes)
1165             ((unsigned int *)dst)[padding_pos] &= zeropad_mask;
1166     }
1167     return ERROR_SUCCESS;
1168 }
1169
1170 /***********************************************************************
1171  *           X11DRV_PutImage
1172  */
1173 DWORD X11DRV_PutImage( PHYSDEV dev, HRGN clip, BITMAPINFO *info,
1174                        const struct gdi_image_bits *bits, struct bitblt_coords *src,
1175                        struct bitblt_coords *dst, DWORD rop )
1176 {
1177     X11DRV_PDEVICE *physdev = get_x11drv_dev( dev );
1178     DWORD ret;
1179     XImage *image;
1180     XVisualInfo vis;
1181     struct gdi_image_bits dst_bits;
1182     const XPixmapFormatValues *format;
1183     const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1184     const int *mapping = NULL;
1185
1186     vis.depth = physdev->depth;
1187     if (physdev->color_shifts)
1188     {
1189         vis.red_mask   = physdev->color_shifts->logicalRed.max   << physdev->color_shifts->logicalRed.shift;
1190         vis.green_mask = physdev->color_shifts->logicalGreen.max << physdev->color_shifts->logicalGreen.shift;
1191         vis.blue_mask  = physdev->color_shifts->logicalBlue.max  << physdev->color_shifts->logicalBlue.shift;
1192     }
1193     format = pixmap_formats[vis.depth];
1194
1195     if (info->bmiHeader.biPlanes != 1) goto update_format;
1196     if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1197     /* FIXME: could try to handle 1-bpp using XCopyPlane */
1198     if (!matching_color_info( &vis, info )) goto update_format;
1199     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
1200     if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED;
1201
1202     image = XCreateImage( gdi_display, visual, vis.depth, ZPixmap, 0, NULL,
1203                           info->bmiHeader.biWidth, src->visrect.bottom - src->visrect.top, 32, 0 );
1204     if (!image) return ERROR_OUTOFMEMORY;
1205
1206     if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1207     {
1208         if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1209             mapping = X11DRV_PALETTE_PaletteToXPixel;
1210     }
1211
1212     ret = copy_image_bits( info, is_r8g8b8(&vis), image, bits, &dst_bits, src, mapping, ~0u );
1213
1214     if (!ret)
1215     {
1216         BOOL restore_region = add_extra_clipping_region( physdev, clip );
1217         int width = dst->visrect.right - dst->visrect.left;
1218         int height = dst->visrect.bottom - dst->visrect.top;
1219
1220         image->data = dst_bits.ptr;
1221
1222         /* optimization for single-op ROPs */
1223         if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
1224         {
1225             XSetFunction( gdi_display, physdev->gc, OP_ROP(*opcode) );
1226             XPutImage( gdi_display, physdev->drawable, physdev->gc, image, src->visrect.left, 0,
1227                        physdev->dc_rect.left + dst->visrect.left,
1228                        physdev->dc_rect.top + dst->visrect.top, width, height );
1229         }
1230         else
1231         {
1232             GC gc = XCreateGC( gdi_display, physdev->drawable, 0, NULL );
1233             Pixmap src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, vis.depth );
1234
1235             XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
1236             XSetGraphicsExposures( gdi_display, gc, False );
1237             XPutImage( gdi_display, src_pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
1238
1239             execute_rop( physdev, src_pixmap, gc, &dst->visrect, rop );
1240
1241             XFreePixmap( gdi_display, src_pixmap );
1242             XFreeGC( gdi_display, gc );
1243         }
1244
1245         if (restore_region) restore_clipping_region( physdev );
1246         add_device_bounds( physdev, &dst->visrect );
1247         image->data = NULL;
1248     }
1249
1250     XDestroyImage( image );
1251     if (dst_bits.free) dst_bits.free( &dst_bits );
1252     return ret;
1253
1254 update_format:
1255     info->bmiHeader.biPlanes   = 1;
1256     info->bmiHeader.biBitCount = format->bits_per_pixel;
1257     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1258     set_color_info( &vis, info );
1259     return ERROR_BAD_FORMAT;
1260 }
1261
1262 /***********************************************************************
1263  *           X11DRV_GetImage
1264  */
1265 DWORD X11DRV_GetImage( PHYSDEV dev, BITMAPINFO *info,
1266                        struct gdi_image_bits *bits, struct bitblt_coords *src )
1267 {
1268     X11DRV_PDEVICE *physdev = get_x11drv_dev( dev );
1269     DWORD ret = ERROR_SUCCESS;
1270     XImage *image;
1271     XVisualInfo vis;
1272     UINT align, x, y, width, height;
1273     struct gdi_image_bits src_bits;
1274     const XPixmapFormatValues *format;
1275     const int *mapping = NULL;
1276
1277     vis.depth = physdev->depth;
1278     if (physdev->color_shifts)
1279     {
1280         vis.red_mask   = physdev->color_shifts->logicalRed.max   << physdev->color_shifts->logicalRed.shift;
1281         vis.green_mask = physdev->color_shifts->logicalGreen.max << physdev->color_shifts->logicalGreen.shift;
1282         vis.blue_mask  = physdev->color_shifts->logicalBlue.max  << physdev->color_shifts->logicalBlue.shift;
1283     }
1284     format = pixmap_formats[vis.depth];
1285
1286     /* align start and width to 32-bit boundary */
1287     switch (format->bits_per_pixel)
1288     {
1289     case 1:  align = 32; break;
1290     case 4:  align = 8;  mapping = X11DRV_PALETTE_XPixelToPalette; break;
1291     case 8:  align = 4;  mapping = X11DRV_PALETTE_XPixelToPalette; break;
1292     case 16: align = 2;  break;
1293     case 24: align = 4;  break;
1294     case 32: align = 1;  break;
1295     default:
1296         FIXME( "depth %u bpp %u not supported yet\n", vis.depth, format->bits_per_pixel );
1297         return ERROR_BAD_FORMAT;
1298     }
1299
1300     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
1301     info->bmiHeader.biPlanes        = 1;
1302     info->bmiHeader.biBitCount      = format->bits_per_pixel;
1303     info->bmiHeader.biXPelsPerMeter = 0;
1304     info->bmiHeader.biYPelsPerMeter = 0;
1305     info->bmiHeader.biClrImportant  = 0;
1306     set_color_info( &vis, info );
1307
1308     if (!bits) return ERROR_SUCCESS;  /* just querying the color information */
1309
1310     x = src->visrect.left & ~(align - 1);
1311     y = src->visrect.top;
1312     width = src->visrect.right - x;
1313     height = src->visrect.bottom - src->visrect.top;
1314     if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
1315     /* make the source rectangle relative to the returned bits */
1316     src->x -= x;
1317     src->y -= y;
1318     OffsetRect( &src->visrect, -x, -y );
1319
1320     X11DRV_expect_error( gdi_display, XGetImage_handler, NULL );
1321     image = XGetImage( gdi_display, physdev->drawable,
1322                        physdev->dc_rect.left + x, physdev->dc_rect.top + y,
1323                        width, height, AllPlanes, ZPixmap );
1324     if (X11DRV_check_error())
1325     {
1326         /* use a temporary pixmap to avoid the BadMatch error */
1327         Pixmap pixmap = XCreatePixmap( gdi_display, root_window, width, height, vis.depth );
1328         GC gc = XCreateGC( gdi_display, pixmap, 0, NULL );
1329
1330         XSetGraphicsExposures( gdi_display, gc, False );
1331         XCopyArea( gdi_display, physdev->drawable, pixmap, gc,
1332                    physdev->dc_rect.left + x, physdev->dc_rect.top + y, width, height, 0, 0 );
1333         image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1334         XFreePixmap( gdi_display, pixmap );
1335         XFreeGC( gdi_display, gc );
1336     }
1337
1338     if (!image) return ERROR_OUTOFMEMORY;
1339
1340     info->bmiHeader.biWidth     = width;
1341     info->bmiHeader.biHeight    = -height;
1342     info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1343
1344     src_bits.ptr     = image->data;
1345     src_bits.is_copy = TRUE;
1346     ret = copy_image_bits( info, is_r8g8b8(&vis), image, &src_bits, bits, src, mapping,
1347                            zeropad_masks[(width * image->bits_per_pixel) & 31] );
1348
1349     if (!ret && bits->ptr == image->data)
1350     {
1351         bits->free = free_ximage_bits;
1352         image->data = NULL;
1353     }
1354     XDestroyImage( image );
1355     return ret;
1356 }
1357
1358
1359 /***********************************************************************
1360  *           put_pixmap_image
1361  *
1362  * Simplified equivalent of X11DRV_PutImage that writes directly to a pixmap.
1363  */
1364 static DWORD put_pixmap_image( Pixmap pixmap, const XVisualInfo *vis,
1365                                BITMAPINFO *info, const struct gdi_image_bits *bits )
1366 {
1367     DWORD ret;
1368     XImage *image;
1369     GC gc;
1370     struct bitblt_coords coords;
1371     struct gdi_image_bits dst_bits;
1372     const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1373     const int *mapping = NULL;
1374
1375     if (!format) return ERROR_INVALID_PARAMETER;
1376     if (info->bmiHeader.biPlanes != 1) goto update_format;
1377     if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format;
1378     /* FIXME: could try to handle 1-bpp using XCopyPlane */
1379     if (!matching_color_info( vis, info )) goto update_format;
1380     if (!bits) return ERROR_SUCCESS;  /* just querying the format */
1381
1382     coords.x = 0;
1383     coords.y = 0;
1384     coords.width = info->bmiHeader.biWidth;
1385     coords.height = abs( info->bmiHeader.biHeight );
1386     SetRect( &coords.visrect, 0, 0, coords.width, coords.height );
1387
1388     image = XCreateImage( gdi_display, visual, vis->depth, ZPixmap, 0, NULL,
1389                           coords.width, coords.height, 32, 0 );
1390     if (!image) return ERROR_OUTOFMEMORY;
1391
1392     if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8)
1393         mapping = X11DRV_PALETTE_PaletteToXPixel;
1394
1395     if (!(ret = copy_image_bits( info, is_r8g8b8(vis), image, bits, &dst_bits, &coords, mapping, ~0u )))
1396     {
1397         image->data = dst_bits.ptr;
1398         gc = XCreateGC( gdi_display, pixmap, 0, NULL );
1399         XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, coords.width, coords.height );
1400         XFreeGC( gdi_display, gc );
1401         image->data = NULL;
1402     }
1403
1404     XDestroyImage( image );
1405     if (dst_bits.free) dst_bits.free( &dst_bits );
1406     return ret;
1407
1408 update_format:
1409     info->bmiHeader.biPlanes   = 1;
1410     info->bmiHeader.biBitCount = format->bits_per_pixel;
1411     if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
1412     set_color_info( vis, info );
1413     return ERROR_BAD_FORMAT;
1414 }
1415
1416
1417 /***********************************************************************
1418  *           create_pixmap_from_image
1419  */
1420 Pixmap create_pixmap_from_image( HDC hdc, const XVisualInfo *vis, const BITMAPINFO *info,
1421                                  const struct gdi_image_bits *bits, UINT coloruse )
1422 {
1423     static const RGBQUAD default_colortable[2] = { { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff } };
1424     char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1425     char src_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1426     BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
1427     BITMAPINFO *src_info = (BITMAPINFO *)src_buffer;
1428     struct gdi_image_bits dst_bits;
1429     Pixmap pixmap;
1430     DWORD err;
1431     HBITMAP dib;
1432
1433     pixmap = XCreatePixmap( gdi_display, root_window,
1434                             info->bmiHeader.biWidth, abs(info->bmiHeader.biHeight), vis->depth );
1435     if (!pixmap) return 0;
1436
1437     memcpy( src_info, info, get_dib_info_size( info, coloruse ));
1438     memcpy( dst_info, info, get_dib_info_size( info, coloruse ));
1439
1440     if (coloruse == DIB_PAL_COLORS ||
1441         (err = put_pixmap_image( pixmap, vis, dst_info, bits )) == ERROR_BAD_FORMAT)
1442     {
1443         if (dst_info->bmiHeader.biBitCount == 1)  /* set a default color table for 1-bpp */
1444             memcpy( dst_info->bmiColors, default_colortable, sizeof(default_colortable) );
1445         dib = CreateDIBSection( hdc, dst_info, coloruse, &dst_bits.ptr, 0, 0 );
1446         if (dib)
1447         {
1448             if (src_info->bmiHeader.biBitCount == 1 && !src_info->bmiHeader.biClrUsed)
1449                 memcpy( src_info->bmiColors, default_colortable, sizeof(default_colortable) );
1450             SetDIBits( hdc, dib, 0, abs(info->bmiHeader.biHeight), bits->ptr, src_info, coloruse );
1451             dst_bits.free = NULL;
1452             dst_bits.is_copy = TRUE;
1453             err = put_pixmap_image( pixmap, vis, dst_info, &dst_bits );
1454             DeleteObject( dib );
1455         }
1456         else err = ERROR_OUTOFMEMORY;
1457     }
1458
1459     if (!err) return pixmap;
1460
1461     XFreePixmap( gdi_display, pixmap );
1462     return 0;
1463
1464 }
1465
1466
1467 /***********************************************************************
1468  *           get_pixmap_image
1469  *
1470  * Equivalent of X11DRV_GetImage that reads directly from a pixmap.
1471  */
1472 DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo *vis,
1473                         BITMAPINFO *info, struct gdi_image_bits *bits )
1474 {
1475     DWORD ret = ERROR_SUCCESS;
1476     XImage *image;
1477     struct gdi_image_bits src_bits;
1478     struct bitblt_coords coords;
1479     const XPixmapFormatValues *format = pixmap_formats[vis->depth];
1480     const int *mapping = NULL;
1481
1482     if (!format) return ERROR_INVALID_PARAMETER;
1483
1484     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
1485     info->bmiHeader.biWidth         = width;
1486     info->bmiHeader.biHeight        = -height;
1487     info->bmiHeader.biPlanes        = 1;
1488     info->bmiHeader.biBitCount      = format->bits_per_pixel;
1489     info->bmiHeader.biXPelsPerMeter = 0;
1490     info->bmiHeader.biYPelsPerMeter = 0;
1491     info->bmiHeader.biClrImportant  = 0;
1492     set_color_info( vis, info );
1493
1494     if (!bits) return ERROR_SUCCESS;  /* just querying the color information */
1495
1496     coords.x = 0;
1497     coords.y = 0;
1498     coords.width = width;
1499     coords.height = height;
1500     SetRect( &coords.visrect, 0, 0, width, height );
1501
1502     image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
1503     if (!image) return ERROR_OUTOFMEMORY;
1504
1505     info->bmiHeader.biSizeImage = height * image->bytes_per_line;
1506
1507     src_bits.ptr     = image->data;
1508     src_bits.is_copy = TRUE;
1509     ret = copy_image_bits( info, is_r8g8b8(vis), image, &src_bits, bits, &coords, mapping,
1510                            zeropad_masks[(width * image->bits_per_pixel) & 31] );
1511
1512     if (!ret && bits->ptr == image->data)
1513     {
1514         bits->free = free_ximage_bits;
1515         image->data = NULL;
1516     }
1517     XDestroyImage( image );
1518     return ret;
1519 }