d3d9: Use D3DQUERYTYPE instead of HRESULT in IDirect3DQuery9Impl_GetType().
[wine] / dlls / winex11.drv / bitblt.c
CommitLineData
401710d7
AJ
1/*
2 * GDI bit-blit operations
3 *
3a5816f8 4 * Copyright 1993, 1994 Alexandre Julliard
54fd8b3d 5 * Copyright 2006 Damjan Jovanovic
0799c1a7
AJ
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
360a3f91 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
3a5816f8
AJ
20 */
21
ab121e78
PS
22#include "config.h"
23
b1bac320 24#include <assert.h>
e37c6e18 25#include <stdarg.h>
401710d7
AJ
26#include <stdio.h>
27#include <stdlib.h>
15c64e70 28
e37c6e18 29#include "windef.h"
8efd4540
AJ
30#include "winbase.h"
31#include "wingdi.h"
32#include "winuser.h"
75d86e1f 33#include "x11drv.h"
0799c1a7 34#include "wine/debug.h"
401710d7 35
0799c1a7 36WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
b4b9fae6 37
3a5816f8 38
7cbe6572
AJ
39#define DST 0 /* Destination drawable */
40#define SRC 1 /* Source drawable */
41#define TMP 2 /* Temporary drawable */
3a5816f8
AJ
42#define PAT 3 /* Pattern (brush) in destination DC */
43
7cbe6572 44#define OP(src,dst,rop) (OP_ARGS(src,dst) << 4 | (rop))
3a5816f8
AJ
45#define OP_ARGS(src,dst) (((src) << 2) | (dst))
46
7cbe6572 47#define OP_SRC(opcode) ((opcode) >> 6)
9a624916 48#define OP_DST(opcode) (((opcode) >> 4) & 3)
7cbe6572
AJ
49#define OP_SRCDST(opcode) ((opcode) >> 4)
50#define OP_ROP(opcode) ((opcode) & 0x0f)
3a5816f8 51
7cbe6572 52#define MAX_OP_LEN 6 /* Longest opcode + 1 for the terminating 0 */
3a5816f8 53
b1bac320 54#define SWAP_INT32(i1,i2) \
a3960292 55 do { INT __t = *(i1); *(i1) = *(i2); *(i2) = __t; } while(0)
b1bac320 56
3a5816f8
AJ
57static const unsigned char BITBLT_Opcodes[256][MAX_OP_LEN] =
58{
59 { OP(PAT,DST,GXclear) }, /* 0x00 0 */
60 { OP(PAT,SRC,GXor), OP(SRC,DST,GXnor) }, /* 0x01 ~(D|(P|S)) */
61 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXand) }, /* 0x02 D&~(P|S) */
62 { OP(PAT,SRC,GXnor) }, /* 0x03 ~(P|S) */
63 { OP(PAT,DST,GXnor), OP(SRC,DST,GXand) }, /* 0x04 S&~(D|P) */
64 { OP(PAT,DST,GXnor) }, /* 0x05 ~(D|P) */
65 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnor), }, /* 0x06 ~(P|~(D^S)) */
66 { OP(SRC,DST,GXand), OP(PAT,DST,GXnor) }, /* 0x07 ~(P|(D&S)) */
67 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXand) },/* 0x08 S&D&~P */
68 { OP(SRC,DST,GXxor), OP(PAT,DST,GXnor) }, /* 0x09 ~(P|(D^S)) */
69 { OP(PAT,DST,GXandInverted) }, /* 0x0a D&~P */
70 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXnor) }, /* 0x0b ~(P|(S&~D)) */
71 { OP(PAT,SRC,GXandInverted) }, /* 0x0c S&~P */
72 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXnor) },/* 0x0d ~(P|(D&~S)) */
73 { OP(SRC,DST,GXnor), OP(PAT,DST,GXnor) }, /* 0x0e ~(P|~(D|S)) */
74 { OP(PAT,DST,GXcopyInverted) }, /* 0x0f ~P */
75 { OP(SRC,DST,GXnor), OP(PAT,DST,GXand) }, /* 0x10 P&~(S|D) */
76 { OP(SRC,DST,GXnor) }, /* 0x11 ~(D|S) */
77 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnor) }, /* 0x12 ~(S|~(D^P)) */
78 { OP(PAT,DST,GXand), OP(SRC,DST,GXnor) }, /* 0x13 ~(S|(D&P)) */
79 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnor) }, /* 0x14 ~(D|~(P^S)) */
80 { OP(PAT,SRC,GXand), OP(SRC,DST,GXnor) }, /* 0x15 ~(D|(P&S)) */
81 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXnand),
82 OP(TMP,DST,GXand), OP(SRC,DST,GXxor),
83 OP(PAT,DST,GXxor) }, /* 0x16 P^S^(D&~(P&S) */
84 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
85 OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
86 OP(TMP,DST,GXequiv) }, /* 0x17 ~S^((S^P)&(S^D))*/
87 { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
88 OP(SRC,DST,GXand) }, /* 0x18 (S^P)&(D^P) */
89 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXnand),
90 OP(TMP,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x19 ~S^(D&~(P&S)) */
91 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
92 OP(PAT,DST,GXxor) }, /* 0x1a P^(D|(S&P)) */
93 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXxor),
94 OP(TMP,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x1b ~S^(D&(P^S)) */
95 { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
96 OP(PAT,DST,GXxor) }, /* 0x1c P^(S|(D&P)) */
97 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
98 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x1d ~D^(S&(D^P)) */
99 { OP(SRC,DST,GXor), OP(PAT,DST,GXxor) }, /* 0x1e P^(D|S) */
100 { OP(SRC,DST,GXor), OP(PAT,DST,GXnand) }, /* 0x1f ~(P&(D|S)) */
101 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXand) }, /* 0x20 D&(P&~S) */
102 { OP(PAT,DST,GXxor), OP(SRC,DST,GXnor) }, /* 0x21 ~(S|(D^P)) */
103 { OP(SRC,DST,GXandInverted) }, /* 0x22 ~S&D */
104 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x23 ~(S|(P&~D)) */
105 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
106 OP(SRC,DST,GXand) }, /* 0x24 (S^P)&(S^D) */
107 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand),
108 OP(PAT,DST,GXequiv) }, /* 0x25 ~P^(D&~(S&P)) */
109 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXand),
110 OP(TMP,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x26 S^(D|(S&P)) */
111 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXequiv),
112 OP(TMP,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x27 S^(D|~(P^S)) */
113 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand) }, /* 0x28 D&(P^S) */
114 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXand),
115 OP(TMP,DST,GXor), OP(SRC,DST,GXxor),
116 OP(PAT,DST,GXequiv) }, /* 0x29 ~P^S^(D|(P&S)) */
117 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand) }, /* 0x2a D&~(P&S) */
118 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
119 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
120 OP(TMP,DST,GXequiv) }, /* 0x2b ~S^((P^S)&(P^D))*/
121 { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
122 OP(SRC,DST,GXxor) }, /* 0x2c S^(P&(S|D)) */
123 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXxor) }, /* 0x2d P^(S|~D) */
124 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
125 OP(PAT,DST,GXxor) }, /* 0x2e P^(S|(D^P)) */
126 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXnand) }, /* 0x2f ~(P&(S|~D)) */
127 { OP(PAT,SRC,GXandReverse) }, /* 0x30 P&~S */
128 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXnor) },/* 0x31 ~(S|(D&~P)) */
129 { OP(SRC,DST,GXor), OP(PAT,DST,GXor),
130 OP(SRC,DST,GXxor) }, /* 0x32 S^(D|P|S) */
131 { OP(SRC,DST,GXcopyInverted) }, /* 0x33 ~S */
132 { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
133 OP(SRC,DST,GXxor) }, /* 0x34 S^(P|(D&S)) */
134 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor),
135 OP(SRC,DST,GXxor) }, /* 0x35 S^(P|~(D^S)) */
136 { OP(PAT,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x36 S^(D|P) */
137 { OP(PAT,DST,GXor), OP(SRC,DST,GXnand) }, /* 0x37 ~(S&(D|P)) */
138 { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
139 OP(PAT,DST,GXxor) }, /* 0x38 P^(S&(D|P)) */
140 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXxor) }, /* 0x39 S^(P|~D) */
141 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
142 OP(SRC,DST,GXxor) }, /* 0x3a S^(P|(D^S)) */
143 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x3b ~(S&(P|~D)) */
144 { OP(PAT,SRC,GXxor) }, /* 0x3c P^S */
145 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
146 OP(SRC,DST,GXxor) }, /* 0x3d S^(P|~(D|S)) */
147 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
148 OP(SRC,DST,GXxor) }, /* 0x3e S^(P|(D&~S)) */
149 { OP(PAT,SRC,GXnand) }, /* 0x3f ~(P&S) */
150 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXand) }, /* 0x40 P&S&~D */
151 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnor) }, /* 0x41 ~(D|(P^S)) */
152 { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
153 OP(SRC,DST,GXand) }, /* 0x42 (S^D)&(P^D) */
154 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
155 OP(SRC,DST,GXequiv) }, /* 0x43 ~S^(P&~(D&S)) */
156 { OP(SRC,DST,GXandReverse) }, /* 0x44 S&~D */
157 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x45 ~(D|(P&~S)) */
158 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
159 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x46 D^(S|(P&D)) */
160 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
161 OP(PAT,DST,GXequiv) }, /* 0x47 ~P^(S&(D^P)) */
162 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand) }, /* 0x48 S&(P^D) */
163 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
164 OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
165 OP(PAT,DST,GXequiv) }, /* 0x49 ~P^D^(S|(P&D)) */
166 { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
167 OP(SRC,DST,GXxor) }, /* 0x4a D^(P&(S|D)) */
168 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXxor) }, /* 0x4b P^(D|~S) */
169 { OP(PAT,DST,GXnand), OP(SRC,DST,GXand) }, /* 0x4c S&~(D&P) */
170 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
171 OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
172 OP(TMP,DST,GXequiv) }, /* 0x4d ~S^((S^P)|(S^D))*/
173 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
174 OP(PAT,DST,GXxor) }, /* 0x4e P^(D|(S^P)) */
175 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXnand) },/* 0x4f ~(P&(D|~S)) */
176 { OP(PAT,DST,GXandReverse) }, /* 0x50 P&~D */
177 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXnor) },/* 0x51 ~(D|(S&~P)) */
178 { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
179 OP(SRC,DST,GXxor) }, /* 0x52 D^(P|(S&D)) */
180 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
181 OP(SRC,DST,GXequiv) }, /* 0x53 ~S^(P&(D^S)) */
182 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXnor) }, /* 0x54 ~(D|~(P|S)) */
183 { OP(PAT,DST,GXinvert) }, /* 0x55 ~D */
184 { OP(PAT,SRC,GXor), OP(SRC,DST,GXxor) }, /* 0x56 D^(P|S) */
185 { OP(PAT,SRC,GXor), OP(SRC,DST,GXnand) }, /* 0x57 ~(D&(P|S)) */
186 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
187 OP(PAT,DST,GXxor) }, /* 0x58 P^(D&(P|S)) */
188 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXxor) }, /* 0x59 D^(P|~S) */
189 { OP(PAT,DST,GXxor) }, /* 0x5a D^P */
190 { OP(DST,SRC,GXnor), OP(PAT,SRC,GXor),
191 OP(SRC,DST,GXxor) }, /* 0x5b D^(P|~(S|D)) */
192 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
193 OP(SRC,DST,GXxor) }, /* 0x5c D^(P|(S^D)) */
194 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x5d ~(D&(P|~S)) */
195 { OP(DST,SRC,GXandInverted), OP(PAT,SRC,GXor),
196 OP(SRC,DST,GXxor) }, /* 0x5e D^(P|(S&~D)) */
197 { OP(PAT,DST,GXnand) }, /* 0x5f ~(D&P) */
198 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand) }, /* 0x60 P&(D^S) */
199 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
200 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
201 OP(TMP,DST,GXequiv) }, /* 0x61 ~D^S^(P|(D&S)) */
202 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
203 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x62 D^(S&(P|D)) */
204 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x63 S^(D|~P) */
205 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
206 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x64 S^(D&(P|S)) */
207 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x65 D^(S|~P) */
208 { OP(SRC,DST,GXxor) }, /* 0x66 S^D */
209 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
210 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x67 S^(D|~(S|P) */
211 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnor),
212 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
213 OP(TMP,DST,GXequiv) }, /* 0x68 ~D^S^(P|~(D|S))*/
214 { OP(SRC,DST,GXxor), OP(PAT,DST,GXequiv) }, /* 0x69 ~P^(D^S) */
215 { OP(PAT,SRC,GXand), OP(SRC,DST,GXxor) }, /* 0x6a D^(P&S) */
216 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
217 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
218 OP(PAT,DST,GXequiv) }, /* 0x6b ~P^S^(D&(P|S)) */
219 { OP(PAT,DST,GXand), OP(SRC,DST,GXxor) }, /* 0x6c S^(D&P) */
220 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
221 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
222 OP(PAT,DST,GXequiv) }, /* 0x6d ~P^D^(S&(P|D)) */
223 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
224 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x6e S^(D&(P|~S)) */
225 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnand) }, /* 0x6f ~(P&~(S^D)) */
226 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand) }, /* 0x70 P&~(D&S) */
227 { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
228 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
229 OP(TMP,DST,GXequiv) }, /* 0x71 ~S^((S^D)&(P^D))*/
230 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
231 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x72 S^(D|(P^S)) */
232 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXnand) },/* 0x73 ~(S&(D|~P)) */
233 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
234 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x74 D^(S|(P^D)) */
235 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXnand) },/* 0x75 ~(D&(S|~P)) */
236 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
237 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x76 S^(D|(P&~S)) */
238 { OP(SRC,DST,GXnand) }, /* 0x77 ~(S&D) */
239 { OP(SRC,DST,GXand), OP(PAT,DST,GXxor) }, /* 0x78 P^(D&S) */
240 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
241 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
242 OP(TMP,DST,GXequiv) }, /* 0x79 ~D^S^(P&(D|S)) */
243 { OP(DST,SRC,GXorInverted), OP(PAT,SRC,GXand),
244 OP(SRC,DST,GXxor) }, /* 0x7a D^(P&(S|~D)) */
245 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnand) }, /* 0x7b ~(S&~(D^P)) */
246 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
247 OP(SRC,DST,GXxor) }, /* 0x7c S^(P&(D|~S)) */
248 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnand) }, /* 0x7d ~(D&~(P^S)) */
249 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
250 OP(SRC,DST,GXor) }, /* 0x7e (S^P)|(S^D) */
251 { OP(PAT,SRC,GXand), OP(SRC,DST,GXnand) }, /* 0x7f ~(D&P&S) */
252 { OP(PAT,SRC,GXand), OP(SRC,DST,GXand) }, /* 0x80 D&P&S */
253 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
254 OP(SRC,DST,GXnor) }, /* 0x81 ~((S^P)|(S^D)) */
255 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXand) }, /* 0x82 D&~(P^S) */
256 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
257 OP(SRC,DST,GXequiv) }, /* 0x83 ~S^(P&(D|~S)) */
258 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXand) }, /* 0x84 S&~(D^P) */
259 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand),
260 OP(PAT,DST,GXequiv) }, /* 0x85 ~P^(D&(S|~P)) */
261 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
262 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
263 OP(TMP,DST,GXxor) }, /* 0x86 D^S^(P&(D|S)) */
264 { OP(SRC,DST,GXand), OP(PAT,DST,GXequiv) }, /* 0x87 ~P^(D&S) */
265 { OP(SRC,DST,GXand) }, /* 0x88 S&D */
266 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
267 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x89 ~S^(D|(P&~S)) */
268 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8a D&(S|~P) */
269 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
270 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x8b ~D^(S|(P^D)) */
271 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8c S&(D|~P) */
272 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
273 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x8d ~S^(D|(P^S)) */
274 { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
275 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
276 OP(TMP,DST,GXxor) }, /* 0x8e S^((S^D)&(P^D))*/
277 { OP(SRC,DST,GXnand), OP(PAT,DST,GXnand) }, /* 0x8f ~(P&~(D&S)) */
278 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXand) }, /* 0x90 P&~(D^S) */
279 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
280 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x91 ~S^(D&(P|~S)) */
281 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
282 OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
283 OP(TMP,DST,GXxor) }, /* 0x92 D^P^(S&(D|P)) */
284 { OP(PAT,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x93 ~S^(P&D) */
285 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
286 OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
287 OP(TMP,DST,GXxor) }, /* 0x94 S^P^(D&(P|S)) */
288 { OP(PAT,SRC,GXand), OP(SRC,DST,GXequiv) }, /* 0x95 ~D^(P&S) */
289 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXxor) }, /* 0x96 D^P^S */
290 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
291 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
292 OP(TMP,DST,GXxor) }, /* 0x97 S^P^(D|~(P|S)) */
293 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
294 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x98 ~S^(D|~(P|S)) */
295 { OP(SRC,DST,GXequiv) }, /* 0x99 ~S^D */
296 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9a D^(P&~S) */
297 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
298 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x9b ~S^(D&(P|S)) */
299 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9c S^(P&~D) */
300 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
301 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x9d ~D^(S&(P|D)) */
302 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
303 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
304 OP(TMP,DST,GXxor) }, /* 0x9e D^S^(P|(D&S)) */
305 { OP(SRC,DST,GXxor), OP(PAT,DST,GXnand) }, /* 0x9f ~(P&(D^S)) */
306 { OP(PAT,DST,GXand) }, /* 0xa0 D&P */
307 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor),
308 OP(PAT,DST,GXequiv) }, /* 0xa1 ~P^(D|(S&~P)) */
309 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXand) }, /* 0xa2 D&(P|~S) */
310 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
311 OP(SRC,DST,GXequiv) }, /* 0xa3 ~D^(P|(S^D)) */
312 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor),
313 OP(PAT,DST,GXequiv) }, /* 0xa4 ~P^(D|~(S|P)) */
314 { OP(PAT,DST,GXequiv) }, /* 0xa5 ~P^D */
315 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXxor) },/* 0xa6 D^(S&~P) */
316 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
317 OP(PAT,DST,GXequiv) }, /* 0xa7 ~P^(D&(S|P)) */
318 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand) }, /* 0xa8 D&(P|S) */
319 { OP(PAT,SRC,GXor), OP(SRC,DST,GXequiv) }, /* 0xa9 ~D^(P|S) */
23afe2e9 320 { OP(PAT,DST,GXnoop) }, /* 0xaa D */
3a5816f8
AJ
321 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor) }, /* 0xab D|~(P|S) */
322 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
323 OP(SRC,DST,GXxor) }, /* 0xac S^(P&(D^S)) */
324 { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
325 OP(SRC,DST,GXequiv) }, /* 0xad ~D^(P|(S&D)) */
326 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor) }, /* 0xae D|(S&~P) */
327 { OP(PAT,DST,GXorInverted) }, /* 0xaf D|~P */
328 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand) }, /* 0xb0 P&(D|~S) */
329 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
330 OP(PAT,DST,GXequiv) }, /* 0xb1 ~P^(D|(S^P)) */
331 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
332 OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
333 OP(TMP,DST,GXxor) }, /* 0xb2 S^((S^P)|(S^D))*/
334 { OP(PAT,DST,GXnand), OP(SRC,DST,GXnand) }, /* 0xb3 ~(S&~(D&P)) */
335 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXxor) }, /* 0xb4 P^(S&~D) */
336 { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
337 OP(SRC,DST,GXequiv) }, /* 0xb5 ~D^(P&(S|D)) */
338 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
339 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
340 OP(TMP,DST,GXxor) }, /* 0xb6 D^P^(S|(D&P)) */
341 { OP(PAT,DST,GXxor), OP(SRC,DST,GXnand) }, /* 0xb7 ~(S&(D^P)) */
342 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
343 OP(PAT,DST,GXxor) }, /* 0xb8 P^(S&(D^P)) */
344 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
345 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0xb9 ~D^(S|(P&D)) */
346 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXor) }, /* 0xba D|(P&~S) */
347 { OP(SRC,DST,GXorInverted) }, /* 0xbb ~S|D */
348 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
349 OP(SRC,DST,GXxor) }, /* 0xbc S^(P&~(D&S)) */
350 { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
351 OP(SRC,DST,GXnand) }, /* 0xbd ~((S^D)&(P^D)) */
352 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor) }, /* 0xbe D|(P^S) */
353 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXor) }, /* 0xbf D|~(P&S) */
354 { OP(PAT,SRC,GXand) }, /* 0xc0 P&S */
355 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
356 OP(SRC,DST,GXequiv) }, /* 0xc1 ~S^(P|(D&~S)) */
357 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
358 OP(SRC,DST,GXequiv) }, /* 0xc2 ~S^(P|~(D|S)) */
359 { OP(PAT,SRC,GXequiv) }, /* 0xc3 ~P^S */
360 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXand) }, /* 0xc4 S&(P|~D) */
361 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
362 OP(SRC,DST,GXequiv) }, /* 0xc5 ~S^(P|(D^S)) */
363 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXxor) },/* 0xc6 S^(D&~P) */
364 { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
365 OP(PAT,DST,GXequiv) }, /* 0xc7 ~P^(S&(D|P)) */
366 { OP(PAT,DST,GXor), OP(SRC,DST,GXand) }, /* 0xc8 S&(D|P) */
367 { OP(PAT,DST,GXor), OP(SRC,DST,GXequiv) }, /* 0xc9 ~S^(P|D) */
368 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXand),
369 OP(SRC,DST,GXxor) }, /* 0xca D^(P&(S^D)) */
370 { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
371 OP(SRC,DST,GXequiv) }, /* 0xcb ~S^(P|(D&S)) */
372 { OP(SRC,DST,GXcopy) }, /* 0xcc S */
373 { OP(PAT,DST,GXnor), OP(SRC,DST,GXor) }, /* 0xcd S|~(D|P) */
374 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXor) }, /* 0xce S|(D&~P) */
375 { OP(PAT,SRC,GXorInverted) }, /* 0xcf S|~P */
376 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXand) }, /* 0xd0 P&(S|~D) */
377 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
378 OP(PAT,DST,GXequiv) }, /* 0xd1 ~P^(S|(D^P)) */
379 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXxor) },/* 0xd2 P^(D&~S) */
380 { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
381 OP(SRC,DST,GXequiv) }, /* 0xd3 ~S^(P&(D|S)) */
382 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
383 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
384 OP(TMP,DST,GXxor) }, /* 0xd4 S^((S^P)&(D^P))*/
385 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXnand) }, /* 0xd5 ~(D&~(P&S)) */
386 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
387 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
388 OP(TMP,DST,GXxor) }, /* 0xd6 S^P^(D|(P&S)) */
389 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnand) }, /* 0xd7 ~(D&(P^S)) */
390 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
391 OP(PAT,DST,GXxor) }, /* 0xd8 P^(D&(S^P)) */
392 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
393 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0xd9 ~S^(D|(P&S)) */
394 { OP(DST,SRC,GXnand), OP(PAT,SRC,GXand),
395 OP(SRC,DST,GXxor) }, /* 0xda D^(P&~(S&D)) */
396 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
397 OP(SRC,DST,GXnand) }, /* 0xdb ~((S^P)&(S^D)) */
398 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXor) }, /* 0xdc S|(P&~D) */
399 { OP(SRC,DST,GXorReverse) }, /* 0xdd S|~D */
400 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor) }, /* 0xde S|(D^P) */
401 { OP(PAT,DST,GXnand), OP(SRC,DST,GXor) }, /* 0xdf S|~(D&P) */
402 { OP(SRC,DST,GXor), OP(PAT,DST,GXand) }, /* 0xe0 P&(D|S) */
403 { OP(SRC,DST,GXor), OP(PAT,DST,GXequiv) }, /* 0xe1 ~P^(D|S) */
404 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
405 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe2 D^(S&(P^D)) */
406 { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
407 OP(PAT,DST,GXequiv) }, /* 0xe3 ~P^(S|(D&P)) */
408 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
409 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe4 S^(D&(P^S)) */
410 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
411 OP(PAT,DST,GXequiv) }, /* 0xe5 ~P^(D|(S&P)) */
412 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
413 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe6 S^(D&~(P&S)) */
414 { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
415 OP(SRC,DST,GXnand) }, /* 0xe7 ~((S^P)&(D^P)) */
416 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
417 OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
418 OP(TMP,DST,GXxor) }, /* 0xe8 S^((S^P)&(S^D))*/
419 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnand),
420 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
421 OP(TMP,DST,GXequiv) }, /* 0xe9 ~D^S^(P&~(S&D))*/
422 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor) }, /* 0xea D|(P&S) */
423 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXor) }, /* 0xeb D|~(P^S) */
424 { OP(PAT,DST,GXand), OP(SRC,DST,GXor) }, /* 0xec S|(D&P) */
425 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXor) }, /* 0xed S|~(D^P) */
426 { OP(SRC,DST,GXor) }, /* 0xee S|D */
427 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXor) }, /* 0xef S|D|~P */
428 { OP(PAT,DST,GXcopy) }, /* 0xf0 P */
429 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor) }, /* 0xf1 P|~(D|S) */
430 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor) }, /* 0xf2 P|(D&~S) */
431 { OP(PAT,SRC,GXorReverse) }, /* 0xf3 P|~S */
432 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXor) }, /* 0xf4 P|(S&~D) */
433 { OP(PAT,DST,GXorReverse) }, /* 0xf5 P|~D */
434 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor) }, /* 0xf6 P|(D^S) */
435 { OP(SRC,DST,GXnand), OP(PAT,DST,GXor) }, /* 0xf7 P|~(S&D) */
436 { OP(SRC,DST,GXand), OP(PAT,DST,GXor) }, /* 0xf8 P|(D&S) */
437 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor) }, /* 0xf9 P|~(D^S) */
438 { OP(PAT,DST,GXor) }, /* 0xfa D|P */
439 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXor) }, /* 0xfb D|P|~S */
440 { OP(PAT,SRC,GXor) }, /* 0xfc P|S */
441 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXor) }, /* 0xfd P|S|~D */
442 { OP(SRC,DST,GXor), OP(PAT,DST,GXor) }, /* 0xfe P|D|S */
443 { OP(PAT,DST,GXset) } /* 0xff 1 */
444};
445
446
447#ifdef BITBLT_TEST /* Opcodes test */
448
449static int do_bitop( int s, int d, int rop )
450{
451 int res;
452 switch(rop)
453 {
454 case GXclear: res = 0; break;
455 case GXand: res = s & d; break;
456 case GXandReverse: res = s & ~d; break;
457 case GXcopy: res = s; break;
458 case GXandInverted: res = ~s & d; break;
459 case GXnoop: res = d; break;
460 case GXxor: res = s ^ d; break;
461 case GXor: res = s | d; break;
462 case GXnor: res = ~(s | d); break;
463 case GXequiv: res = ~s ^ d; break;
464 case GXinvert: res = ~d; break;
465 case GXorReverse: res = s | ~d; break;
466 case GXcopyInverted: res = ~s; break;
467 case GXorInverted: res = ~s | d; break;
468 case GXnand: res = ~(s & d); break;
469 case GXset: res = 1; break;
470 }
471 return res & 1;
472}
473
3c0211f9 474int main()
3a5816f8
AJ
475{
476 int rop, i, res, src, dst, pat, tmp, dstUsed;
477 const BYTE *opcode;
478
479 for (rop = 0; rop < 256; rop++)
480 {
481 res = dstUsed = 0;
482 for (i = 0; i < 8; i++)
483 {
484 pat = (i >> 2) & 1;
485 src = (i >> 1) & 1;
486 dst = i & 1;
487 for (opcode = BITBLT_Opcodes[rop]; *opcode; opcode++)
488 {
489 switch(*opcode >> 4)
490 {
491 case OP_ARGS(DST,TMP):
492 tmp = do_bitop( dst, tmp, *opcode & 0xf );
493 break;
494 case OP_ARGS(DST,SRC):
495 src = do_bitop( dst, src, *opcode & 0xf );
496 break;
497 case OP_ARGS(SRC,TMP):
498 tmp = do_bitop( src, tmp, *opcode & 0xf );
499 break;
500 case OP_ARGS(SRC,DST):
501 dst = do_bitop( src, dst, *opcode & 0xf );
502 dstUsed = 1;
503 break;
504 case OP_ARGS(PAT,TMP):
505 tmp = do_bitop( pat, tmp, *opcode & 0xf );
506 break;
507 case OP_ARGS(PAT,DST):
508 dst = do_bitop( pat, dst, *opcode & 0xf );
509 dstUsed = 1;
510 break;
511 case OP_ARGS(PAT,SRC):
512 src = do_bitop( pat, src, *opcode & 0xf );
513 break;
514 case OP_ARGS(TMP,DST):
515 dst = do_bitop( tmp, dst, *opcode & 0xf );
516 dstUsed = 1;
517 break;
518 case OP_ARGS(TMP,SRC):
519 src = do_bitop( tmp, src, *opcode & 0xf );
520 break;
521 default:
522 printf( "Invalid opcode %x\n", *opcode );
523 }
524 }
525 if (!dstUsed) dst = src;
526 if (dst) res |= 1 << i;
527 }
528 if (res != rop) printf( "%02x: ERROR, res=%02x\n", rop, res );
529 }
3c0211f9
PS
530
531 return 0;
3a5816f8
AJ
532}
533
534#endif /* BITBLT_TEST */
535
401710d7 536
daf776fd
HD
537static void get_colors(X11DRV_PDEVICE *physDevDst, X11DRV_PDEVICE *physDevSrc,
538 int *fg, int *bg)
539{
540 RGBQUAD rgb[2];
541
542 *fg = physDevDst->textPixel;
543 *bg = physDevDst->backgroundPixel;
544 if(physDevSrc->depth == 1) {
545 if(GetDIBColorTable(physDevSrc->hdc, 0, 2, rgb) == 2) {
546 DWORD logcolor;
547 logcolor = RGB(rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue);
548 *fg = X11DRV_PALETTE_ToPhysical( physDevDst, logcolor );
549 logcolor = RGB(rgb[1].rgbRed, rgb[1].rgbGreen,rgb[1].rgbBlue);
550 *bg = X11DRV_PALETTE_ToPhysical( physDevDst, logcolor );
551 }
552 }
553}
554
da57adf2
AJ
555/* return a mask for meaningful bits when doing an XGetPixel on an image */
556static unsigned long image_pixel_mask( X11DRV_PDEVICE *physDev )
557{
558 unsigned long ret;
559 ColorShifts *shifts = physDev->color_shifts;
560
561 if (!shifts) shifts = &X11DRV_PALETTE_default_shifts;
562 ret = (shifts->physicalRed.max << shifts->physicalRed.shift) |
563 (shifts->physicalGreen.max << shifts->physicalGreen.shift) |
564 (shifts->physicalBlue.max << shifts->physicalBlue.shift);
565 if (!ret) ret = (1 << physDev->depth) - 1;
566 return ret;
567}
568
569
ecc3712d 570/***********************************************************************
7cbe6572
AJ
571 * BITBLT_StretchRow
572 *
573 * Stretch a row of pixels. Helper function for BITBLT_StretchImage.
ecc3712d 574 */
7cbe6572 575static void BITBLT_StretchRow( int *rowSrc, int *rowDst,
a3960292
AJ
576 INT startDst, INT widthDst,
577 INT xinc, INT xoff, WORD mode )
ecc3712d 578{
a3960292 579 register INT xsrc = xinc * startDst + xoff;
7cbe6572
AJ
580 rowDst += startDst;
581 switch(mode)
ecc3712d 582 {
7cbe6572
AJ
583 case STRETCH_ANDSCANS:
584 for(; widthDst > 0; widthDst--, xsrc += xinc)
585 *rowDst++ &= rowSrc[xsrc >> 16];
586 break;
587 case STRETCH_ORSCANS:
588 for(; widthDst > 0; widthDst--, xsrc += xinc)
589 *rowDst++ |= rowSrc[xsrc >> 16];
590 break;
591 case STRETCH_DELETESCANS:
592 for(; widthDst > 0; widthDst--, xsrc += xinc)
593 *rowDst++ = rowSrc[xsrc >> 16];
594 break;
ecc3712d 595 }
7cbe6572
AJ
596}
597
598
599/***********************************************************************
600 * BITBLT_ShrinkRow
601 *
602 * Shrink a row of pixels. Helper function for BITBLT_StretchImage.
603 */
604static void BITBLT_ShrinkRow( int *rowSrc, int *rowDst,
a3960292
AJ
605 INT startSrc, INT widthSrc,
606 INT xinc, INT xoff, WORD mode )
7cbe6572 607{
a3960292 608 register INT xdst = xinc * startSrc + xoff;
7cbe6572
AJ
609 rowSrc += startSrc;
610 switch(mode)
ecc3712d 611 {
7cbe6572
AJ
612 case STRETCH_ORSCANS:
613 for(; widthSrc > 0; widthSrc--, xdst += xinc)
614 rowDst[xdst >> 16] |= *rowSrc++;
615 break;
616 case STRETCH_ANDSCANS:
617 for(; widthSrc > 0; widthSrc--, xdst += xinc)
618 rowDst[xdst >> 16] &= *rowSrc++;
619 break;
620 case STRETCH_DELETESCANS:
621 for(; widthSrc > 0; widthSrc--, xdst += xinc)
622 rowDst[xdst >> 16] = *rowSrc++;
623 break;
ecc3712d 624 }
ecc3712d
AJ
625}
626
627
3a5816f8 628/***********************************************************************
7cbe6572 629 * BITBLT_GetRow
3a5816f8 630 *
7cbe6572 631 * Retrieve a row from an image. Helper function for BITBLT_StretchImage.
3a5816f8 632 */
a3960292
AJ
633static void BITBLT_GetRow( XImage *image, int *pdata, INT row,
634 INT start, INT width, INT depthDst,
da57adf2 635 int fg, int bg, unsigned long pixel_mask, BOOL swap)
3a5816f8 636{
a3960292 637 register INT i;
3a5816f8 638
b1bac320
AJ
639 assert( (row >= 0) && (row < image->height) );
640 assert( (start >= 0) && (width <= image->width) );
641
7cbe6572 642 pdata += swap ? start+width-1 : start;
a2f2e019 643 if (image->depth == depthDst) /* color -> color */
3a5816f8 644 {
b87fe2e9 645 if (X11DRV_PALETTE_XPixelToPalette && (depthDst != 1))
7cbe6572 646 if (swap) for (i = 0; i < width; i++)
b87fe2e9 647 *pdata-- = X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, i, row )];
7cbe6572 648 else for (i = 0; i < width; i++)
b87fe2e9 649 *pdata++ = X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, i, row )];
7cbe6572
AJ
650 else
651 if (swap) for (i = 0; i < width; i++)
03468f7d 652 *pdata-- = XGetPixel( image, i, row );
7cbe6572 653 else for (i = 0; i < width; i++)
03468f7d 654 *pdata++ = XGetPixel( image, i, row );
3a5816f8 655 }
7cbe6572 656 else
3a5816f8 657 {
a2f2e019
AJ
658 if (image->depth == 1) /* monochrome -> color */
659 {
b87fe2e9 660 if (X11DRV_PALETTE_XPixelToPalette)
a2f2e019 661 {
b87fe2e9
PS
662 fg = X11DRV_PALETTE_XPixelToPalette[fg];
663 bg = X11DRV_PALETTE_XPixelToPalette[bg];
a2f2e019 664 }
7cbe6572 665 if (swap) for (i = 0; i < width; i++)
03468f7d 666 *pdata-- = XGetPixel( image, i, row ) ? bg : fg;
7cbe6572 667 else for (i = 0; i < width; i++)
03468f7d 668 *pdata++ = XGetPixel( image, i, row ) ? bg : fg;
a2f2e019
AJ
669 }
670 else /* color -> monochrome */
671 {
7cbe6572 672 if (swap) for (i = 0; i < width; i++)
da57adf2 673 *pdata-- = ((XGetPixel( image, i, row ) & pixel_mask) == bg) ? 1 : 0;
7cbe6572 674 else for (i = 0; i < width; i++)
da57adf2 675 *pdata++ = ((XGetPixel( image, i, row ) & pixel_mask) == bg) ? 1 : 0;
a2f2e019 676 }
3a5816f8 677 }
7cbe6572
AJ
678}
679
680
681/***********************************************************************
682 * BITBLT_StretchImage
683 *
684 * Stretch an X image.
75d86e1f 685 * FIXME: does not work for full 32-bit coordinates.
7cbe6572
AJ
686 */
687static void BITBLT_StretchImage( XImage *srcImage, XImage *dstImage,
a3960292
AJ
688 INT widthSrc, INT heightSrc,
689 INT widthDst, INT heightDst,
690 RECT *visRectSrc, RECT *visRectDst,
da57adf2
AJ
691 int foreground, int background,
692 unsigned long pixel_mask, WORD mode )
7cbe6572
AJ
693{
694 int *rowSrc, *rowDst, *pixel;
b1bac320 695 char *pdata;
a3960292
AJ
696 INT xinc, xoff, yinc, ysrc, ydst;
697 register INT x, y;
698 BOOL hstretch, vstretch, hswap, vswap;
7cbe6572 699
68feed7e
AT
700 hswap = widthSrc * widthDst < 0;
701 vswap = heightSrc * heightDst < 0;
7cbe6572
AJ
702 widthSrc = abs(widthSrc);
703 heightSrc = abs(heightSrc);
704 widthDst = abs(widthDst);
705 heightDst = abs(heightDst);
7cbe6572 706
9ed61de9
JE
707 if (!(rowSrc = HeapAlloc( GetProcessHeap(), 0,
708 (widthSrc+widthDst)*sizeof(int) ))) return;
7cbe6572 709 rowDst = rowSrc + widthSrc;
3a5816f8 710
7cbe6572
AJ
711 /* When stretching, all modes are the same, and DELETESCANS is faster */
712 if ((widthSrc < widthDst) && (heightSrc < heightDst))
713 mode = STRETCH_DELETESCANS;
714
0f55bdd4
HD
715 if (mode == STRETCH_HALFTONE) /* FIXME */
716 mode = STRETCH_DELETESCANS;
717
18506558
AJ
718 if (mode != STRETCH_DELETESCANS)
719 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
720 widthDst*sizeof(int) );
721
8cc3a5e4
AJ
722 hstretch = (widthSrc < widthDst);
723 vstretch = (heightSrc < heightDst);
724
b1bac320
AJ
725 if (hstretch)
726 {
68feed7e 727 xinc = (widthSrc << 16) / widthDst;
b1bac320
AJ
728 xoff = ((widthSrc << 16) - (xinc * widthDst)) / 2;
729 }
730 else
731 {
732 xinc = ((int)widthDst << 16) / widthSrc;
733 xoff = ((widthDst << 16) - (xinc * widthSrc)) / 2;
734 }
7cbe6572 735
809af590 736 wine_tsx11_lock();
7cbe6572 737 if (vstretch)
3a5816f8 738 {
68feed7e 739 yinc = (heightSrc << 16) / heightDst;
7cbe6572 740 ydst = visRectDst->top;
b1bac320
AJ
741 if (vswap)
742 {
743 ysrc = yinc * (heightDst - ydst - 1);
744 yinc = -yinc;
745 }
746 else
747 ysrc = yinc * ydst;
748
749 for ( ; (ydst < visRectDst->bottom); ysrc += yinc, ydst++)
750 {
751 if (((ysrc >> 16) < visRectSrc->top) ||
752 ((ysrc >> 16) >= visRectSrc->bottom)) continue;
753
754 /* Retrieve a source row */
755 BITBLT_GetRow( srcImage, rowSrc, (ysrc >> 16) - visRectSrc->top,
756 hswap ? widthSrc - visRectSrc->right
757 : visRectSrc->left,
758 visRectSrc->right - visRectSrc->left,
da57adf2 759 dstImage->depth, foreground, background, pixel_mask, hswap );
b1bac320
AJ
760
761 /* Stretch or shrink it */
762 if (hstretch)
763 BITBLT_StretchRow( rowSrc, rowDst, visRectDst->left,
764 visRectDst->right - visRectDst->left,
765 xinc, xoff, mode );
766 else BITBLT_ShrinkRow( rowSrc, rowDst,
767 hswap ? widthSrc - visRectSrc->right
768 : visRectSrc->left,
769 visRectSrc->right - visRectSrc->left,
770 xinc, xoff, mode );
771
772 /* Store the destination row */
773 pixel = rowDst + visRectDst->right - 1;
774 y = ydst - visRectDst->top;
775 for (x = visRectDst->right-visRectDst->left-1; x >= 0; x--)
03468f7d 776 XPutPixel( dstImage, x, y, *pixel-- );
b1bac320
AJ
777 if (mode != STRETCH_DELETESCANS)
778 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
779 widthDst*sizeof(int) );
780
781 /* Make copies of the destination row */
782
783 pdata = dstImage->data + dstImage->bytes_per_line * y;
784 while (((ysrc + yinc) >> 16 == ysrc >> 16) &&
785 (ydst < visRectDst->bottom-1))
786 {
787 memcpy( pdata + dstImage->bytes_per_line, pdata,
788 dstImage->bytes_per_line );
789 pdata += dstImage->bytes_per_line;
790 ysrc += yinc;
791 ydst++;
792 }
9a624916 793 }
3a5816f8 794 }
b1bac320 795 else /* Shrinking */
3a5816f8 796 {
68feed7e 797 yinc = (heightDst << 16) / heightSrc;
7cbe6572 798 ysrc = visRectSrc->top;
b1bac320
AJ
799 ydst = ((heightDst << 16) - (yinc * heightSrc)) / 2;
800 if (vswap)
801 {
802 ydst += yinc * (heightSrc - ysrc - 1);
803 yinc = -yinc;
804 }
805 else
806 ydst += yinc * ysrc;
7cbe6572 807
b1bac320 808 for( ; (ysrc < visRectSrc->bottom); ydst += yinc, ysrc++)
7cbe6572 809 {
b1bac320
AJ
810 if (((ydst >> 16) < visRectDst->top) ||
811 ((ydst >> 16) >= visRectDst->bottom)) continue;
812
813 /* Retrieve a source row */
814 BITBLT_GetRow( srcImage, rowSrc, ysrc - visRectSrc->top,
815 hswap ? widthSrc - visRectSrc->right
816 : visRectSrc->left,
817 visRectSrc->right - visRectSrc->left,
da57adf2 818 dstImage->depth, foreground, background, pixel_mask, hswap );
b1bac320
AJ
819
820 /* Stretch or shrink it */
821 if (hstretch)
822 BITBLT_StretchRow( rowSrc, rowDst, visRectDst->left,
823 visRectDst->right - visRectDst->left,
824 xinc, xoff, mode );
825 else BITBLT_ShrinkRow( rowSrc, rowDst,
826 hswap ? widthSrc - visRectSrc->right
827 : visRectSrc->left,
828 visRectSrc->right - visRectSrc->left,
829 xinc, xoff, mode );
830
831 /* Merge several source rows into the destination */
7cbe6572 832 if (mode == STRETCH_DELETESCANS)
3a5816f8 833 {
b1bac320 834 /* Simply skip the overlapping rows */
7cbe6572
AJ
835 while (((ydst + yinc) >> 16 == ydst >> 16) &&
836 (ysrc < visRectSrc->bottom-1))
837 {
838 ydst += yinc;
839 ysrc++;
840 }
3a5816f8 841 }
7cbe6572
AJ
842 else if (((ydst + yinc) >> 16 == ydst >> 16) &&
843 (ysrc < visRectSrc->bottom-1))
7cbe6572 844 continue; /* Restart loop for next overlapping row */
9a624916 845
b1bac320
AJ
846 /* Store the destination row */
847 pixel = rowDst + visRectDst->right - 1;
848 y = (ydst >> 16) - visRectDst->top;
849 for (x = visRectDst->right-visRectDst->left-1; x >= 0; x--)
03468f7d 850 XPutPixel( dstImage, x, y, *pixel-- );
b1bac320
AJ
851 if (mode != STRETCH_DELETESCANS)
852 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
853 widthDst*sizeof(int) );
7cbe6572 854 }
9a624916 855 }
809af590 856 wine_tsx11_unlock();
491502b9 857 HeapFree( GetProcessHeap(), 0, rowSrc );
3a5816f8
AJ
858}
859
860
861/***********************************************************************
7cbe6572 862 * BITBLT_GetSrcAreaStretch
3a5816f8 863 *
7cbe6572
AJ
864 * Retrieve an area from the source DC, stretching and mapping all the
865 * pixels to Windows colors.
3a5816f8 866 */
e21c15e3 867static int BITBLT_GetSrcAreaStretch( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
39493b06
AJ
868 Pixmap pixmap, GC gc,
869 const struct bitblt_coords *src, const struct bitblt_coords *dst )
3a5816f8 870{
7cbe6572 871 XImage *imageSrc, *imageDst;
39493b06
AJ
872 RECT rectSrc = src->visrect;
873 RECT rectDst = dst->visrect;
daf776fd 874 int fg, bg;
b1bac320 875
39493b06
AJ
876 rectSrc.left -= src->x;
877 rectSrc.right -= src->x;
878 rectSrc.top -= src->y;
879 rectSrc.bottom -= src->y;
880 rectDst.left -= dst->x;
881 rectDst.right -= dst->x;
882 rectDst.top -= dst->y;
883 rectDst.bottom -= dst->y;
884 if (src->width < 0)
885 {
886 rectSrc.left -= src->width;
887 rectSrc.right -= src->width;
888 }
889 if (dst->width < 0)
890 {
891 rectDst.left -= dst->width;
892 rectDst.right -= dst->width;
893 }
894 if (src->height < 0)
895 {
896 rectSrc.top -= src->height;
897 rectSrc.bottom -= src->height;
898 }
899 if (dst->height < 0)
900 {
901 rectDst.top -= dst->height;
902 rectDst.bottom -= dst->height;
903 }
b1bac320 904
daf776fd 905 get_colors(physDevDst, physDevSrc, &fg, &bg);
809af590 906 wine_tsx11_lock();
1e37a181 907 /* FIXME: avoid BadMatch errors */
c559735b 908 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
39493b06
AJ
909 physDevSrc->dc_rect.left + src->visrect.left,
910 physDevSrc->dc_rect.top + src->visrect.top,
911 src->visrect.right - src->visrect.left,
912 src->visrect.bottom - src->visrect.top,
7cbe6572 913 AllPlanes, ZPixmap );
809af590
AJ
914 wine_tsx11_unlock();
915
c559735b 916 imageDst = X11DRV_DIB_CreateXImage( rectDst.right - rectDst.left,
b89525fb 917 rectDst.bottom - rectDst.top, physDevDst->depth );
39493b06
AJ
918 BITBLT_StretchImage( imageSrc, imageDst, src->width, src->height,
919 dst->width, dst->height, &rectSrc, &rectDst,
da57adf2
AJ
920 fg, physDevDst->depth != 1 ? bg : physDevSrc->backgroundPixel,
921 image_pixel_mask( physDevSrc ), GetStretchBltMode(physDevDst->hdc) );
809af590 922 wine_tsx11_lock();
c559735b 923 XPutImage( gdi_display, pixmap, gc, imageDst, 0, 0, 0, 0,
7cbe6572 924 rectDst.right - rectDst.left, rectDst.bottom - rectDst.top );
03468f7d 925 XDestroyImage( imageSrc );
90ef43ab 926 X11DRV_DIB_DestroyXImage( imageDst );
809af590 927 wine_tsx11_unlock();
6d027e1f 928 return 0; /* no exposure events generated */
7cbe6572 929}
3a5816f8 930
7cbe6572
AJ
931
932/***********************************************************************
933 * BITBLT_GetSrcArea
934 *
935 * Retrieve an area from the source DC, mapping all the
936 * pixels to Windows colors.
937 */
e21c15e3 938static int BITBLT_GetSrcArea( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
773d53d8 939 Pixmap pixmap, GC gc, RECT *visRectSrc )
7cbe6572
AJ
940{
941 XImage *imageSrc, *imageDst;
a3960292 942 register INT x, y;
6d027e1f 943 int exposures = 0;
a3960292
AJ
944 INT width = visRectSrc->right - visRectSrc->left;
945 INT height = visRectSrc->bottom - visRectSrc->top;
daf776fd 946 int fg, bg;
809af590 947 BOOL memdc = (GetObjectType(physDevSrc->hdc) == OBJ_MEMDC);
7cbe6572 948
b89525fb 949 if (physDevSrc->depth == physDevDst->depth)
3a5816f8 950 {
809af590 951 wine_tsx11_lock();
b87fe2e9 952 if (!X11DRV_PALETTE_XPixelToPalette ||
b89525fb 953 (physDevDst->depth == 1)) /* monochrome -> monochrome */
7cbe6572 954 {
b89525fb 955 if (physDevDst->depth == 1)
960dc908
AJ
956 {
957 /* MSDN says if StretchBlt must convert a bitmap from monochrome
0e4adae9 958 to color or vice versa, the foreground and background color of
960dc908 959 the device context are used. In fact, it also applies to the
9a624916 960 case when it is converted from mono to mono. */
c559735b
AJ
961 XSetBackground( gdi_display, gc, physDevDst->textPixel );
962 XSetForeground( gdi_display, gc, physDevDst->backgroundPixel );
963 XCopyPlane( gdi_display, physDevSrc->drawable, pixmap, gc,
4bdf4345
UC
964 physDevSrc->dc_rect.left + visRectSrc->left,
965 physDevSrc->dc_rect.top + visRectSrc->top,
960dc908
AJ
966 width, height, 0, 0, 1);
967 }
968 else
c559735b 969 XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc,
4bdf4345
UC
970 physDevSrc->dc_rect.left + visRectSrc->left,
971 physDevSrc->dc_rect.top + visRectSrc->top,
d3cab185 972 width, height, 0, 0);
6d027e1f 973 exposures++;
7cbe6572
AJ
974 }
975 else /* color -> color */
976 {
809af590 977 if (memdc)
c559735b 978 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
4bdf4345
UC
979 physDevSrc->dc_rect.left + visRectSrc->left,
980 physDevSrc->dc_rect.top + visRectSrc->top,
1e37a181
AJ
981 width, height, AllPlanes, ZPixmap );
982 else
983 {
984 /* Make sure we don't get a BadMatch error */
c559735b 985 XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc,
4bdf4345
UC
986 physDevSrc->dc_rect.left + visRectSrc->left,
987 physDevSrc->dc_rect.top + visRectSrc->top,
1e37a181 988 width, height, 0, 0);
6d027e1f 989 exposures++;
c559735b 990 imageSrc = XGetImage( gdi_display, pixmap, 0, 0, width, height,
1e37a181
AJ
991 AllPlanes, ZPixmap );
992 }
7cbe6572
AJ
993 for (y = 0; y < height; y++)
994 for (x = 0; x < width; x++)
03468f7d 995 XPutPixel(imageSrc, x, y,
b87fe2e9 996 X11DRV_PALETTE_XPixelToPalette[XGetPixel(imageSrc, x, y)]);
c559735b 997 XPutImage( gdi_display, pixmap, gc, imageSrc,
7cbe6572 998 0, 0, 0, 0, width, height );
03468f7d 999 XDestroyImage( imageSrc );
7cbe6572 1000 }
809af590 1001 wine_tsx11_unlock();
3a5816f8
AJ
1002 }
1003 else
1004 {
b89525fb 1005 if (physDevSrc->depth == 1) /* monochrome -> color */
7cbe6572 1006 {
daf776fd
HD
1007 get_colors(physDevDst, physDevSrc, &fg, &bg);
1008
809af590 1009 wine_tsx11_lock();
b87fe2e9 1010 if (X11DRV_PALETTE_XPixelToPalette)
3a5816f8 1011 {
c559735b 1012 XSetBackground( gdi_display, gc,
daf776fd 1013 X11DRV_PALETTE_XPixelToPalette[fg] );
c559735b 1014 XSetForeground( gdi_display, gc,
daf776fd 1015 X11DRV_PALETTE_XPixelToPalette[bg]);
3a5816f8 1016 }
7cbe6572
AJ
1017 else
1018 {
daf776fd
HD
1019 XSetBackground( gdi_display, gc, fg );
1020 XSetForeground( gdi_display, gc, bg );
7cbe6572 1021 }
c559735b 1022 XCopyPlane( gdi_display, physDevSrc->drawable, pixmap, gc,
4bdf4345
UC
1023 physDevSrc->dc_rect.left + visRectSrc->left,
1024 physDevSrc->dc_rect.top + visRectSrc->top,
7cbe6572 1025 width, height, 0, 0, 1 );
6d027e1f 1026 exposures++;
809af590 1027 wine_tsx11_unlock();
7cbe6572
AJ
1028 }
1029 else /* color -> monochrome */
1030 {
da57adf2 1031 unsigned long pixel_mask;
809af590 1032 wine_tsx11_lock();
1e37a181 1033 /* FIXME: avoid BadMatch error */
c559735b 1034 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
4bdf4345
UC
1035 physDevSrc->dc_rect.left + visRectSrc->left,
1036 physDevSrc->dc_rect.top + visRectSrc->top,
7cbe6572 1037 width, height, AllPlanes, ZPixmap );
e845fd9c
WB
1038 if (!imageSrc)
1039 {
809af590 1040 wine_tsx11_unlock();
e845fd9c
WB
1041 return exposures;
1042 }
b89525fb 1043 imageDst = X11DRV_DIB_CreateXImage( width, height, physDevDst->depth );
809af590 1044 if (!imageDst)
e845fd9c
WB
1045 {
1046 XDestroyImage(imageSrc);
809af590 1047 wine_tsx11_unlock();
e845fd9c
WB
1048 return exposures;
1049 }
da57adf2 1050 pixel_mask = image_pixel_mask( physDevSrc );
7cbe6572
AJ
1051 for (y = 0; y < height; y++)
1052 for (x = 0; x < width; x++)
da57adf2
AJ
1053 XPutPixel(imageDst, x, y,
1054 !((XGetPixel(imageSrc,x,y) ^ physDevSrc->backgroundPixel) & pixel_mask));
c559735b 1055 XPutImage( gdi_display, pixmap, gc, imageDst,
7cbe6572 1056 0, 0, 0, 0, width, height );
03468f7d 1057 XDestroyImage( imageSrc );
90ef43ab 1058 X11DRV_DIB_DestroyXImage( imageDst );
809af590 1059 wine_tsx11_unlock();
7cbe6572 1060 }
3a5816f8 1061 }
6d027e1f 1062 return exposures;
3a5816f8
AJ
1063}
1064
1065
1066/***********************************************************************
7cbe6572 1067 * BITBLT_GetDstArea
3a5816f8 1068 *
7cbe6572
AJ
1069 * Retrieve an area from the destination DC, mapping all the
1070 * pixels to Windows colors.
3a5816f8 1071 */
e21c15e3 1072static int BITBLT_GetDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, GC gc, RECT *visRectDst)
3a5816f8 1073{
6d027e1f 1074 int exposures = 0;
a3960292
AJ
1075 INT width = visRectDst->right - visRectDst->left;
1076 INT height = visRectDst->bottom - visRectDst->top;
809af590
AJ
1077 BOOL memdc = (GetObjectType( physDev->hdc ) == OBJ_MEMDC);
1078
1079 wine_tsx11_lock();
7cbe6572 1080
b89525fb 1081 if (!X11DRV_PALETTE_XPixelToPalette || (physDev->depth == 1) ||
b87fe2e9 1082 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
3a5816f8 1083 {
c559735b 1084 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
4bdf4345 1085 physDev->dc_rect.left + visRectDst->left, physDev->dc_rect.top + visRectDst->top,
d3cab185 1086 width, height, 0, 0 );
6d027e1f 1087 exposures++;
3a5816f8
AJ
1088 }
1089 else
1090 {
a3960292 1091 register INT x, y;
1e37a181
AJ
1092 XImage *image;
1093
809af590 1094 if (memdc)
c559735b 1095 image = XGetImage( gdi_display, physDev->drawable,
4bdf4345
UC
1096 physDev->dc_rect.left + visRectDst->left,
1097 physDev->dc_rect.top + visRectDst->top,
1e37a181
AJ
1098 width, height, AllPlanes, ZPixmap );
1099 else
1100 {
1101 /* Make sure we don't get a BadMatch error */
c559735b 1102 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
4bdf4345
UC
1103 physDev->dc_rect.left + visRectDst->left,
1104 physDev->dc_rect.top + visRectDst->top,
d3cab185 1105 width, height, 0, 0);
6d027e1f 1106 exposures++;
c559735b 1107 image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
1e37a181
AJ
1108 AllPlanes, ZPixmap );
1109 }
809af590
AJ
1110 if (image)
1111 {
1112 for (y = 0; y < height; y++)
1113 for (x = 0; x < width; x++)
1114 XPutPixel( image, x, y,
1115 X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]);
1116 XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height );
1117 XDestroyImage( image );
1118 }
3a5816f8 1119 }
809af590
AJ
1120
1121 wine_tsx11_unlock();
6d027e1f 1122 return exposures;
7cbe6572
AJ
1123}
1124
1125
1126/***********************************************************************
1127 * BITBLT_PutDstArea
1128 *
1129 * Put an area back into the destination DC, mapping the pixel
1130 * colors to X pixels.
1131 */
e21c15e3 1132static int BITBLT_PutDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, RECT *visRectDst)
7cbe6572 1133{
6d027e1f 1134 int exposures = 0;
a3960292
AJ
1135 INT width = visRectDst->right - visRectDst->left;
1136 INT height = visRectDst->bottom - visRectDst->top;
7cbe6572 1137
b87fe2e9 1138 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
ac9c9b07 1139
b89525fb 1140 if (!X11DRV_PALETTE_PaletteToXPixel || (physDev->depth == 1) ||
b87fe2e9 1141 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
3a5816f8 1142 {
d3cab185 1143 XCopyArea( gdi_display, pixmap, physDev->drawable, physDev->gc, 0, 0, width, height,
4bdf4345
UC
1144 physDev->dc_rect.left + visRectDst->left,
1145 physDev->dc_rect.top + visRectDst->top );
6d027e1f 1146 exposures++;
3a5816f8 1147 }
7cbe6572 1148 else
3a5816f8 1149 {
a3960292 1150 register INT x, y;
c559735b 1151 XImage *image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
7cbe6572
AJ
1152 AllPlanes, ZPixmap );
1153 for (y = 0; y < height; y++)
1154 for (x = 0; x < width; x++)
1155 {
03468f7d 1156 XPutPixel( image, x, y,
b87fe2e9 1157 X11DRV_PALETTE_PaletteToXPixel[XGetPixel( image, x, y )]);
7cbe6572 1158 }
e21c15e3 1159 XPutImage( gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
4bdf4345
UC
1160 physDev->dc_rect.left + visRectDst->left,
1161 physDev->dc_rect.top + visRectDst->top, width, height );
03468f7d 1162 XDestroyImage( image );
3a5816f8 1163 }
6d027e1f 1164 return exposures;
3a5816f8
AJ
1165}
1166
1167
401710d7 1168/***********************************************************************
7cbe6572
AJ
1169 * BITBLT_GetVisRectangles
1170 *
1171 * Get the source and destination visible rectangles for StretchBlt().
1172 * Return FALSE if one of the rectangles is empty.
401710d7 1173 */
39493b06
AJ
1174static BOOL BITBLT_GetVisRectangles( X11DRV_PDEVICE *physDevDst, X11DRV_PDEVICE *physDevSrc,
1175 struct bitblt_coords *dst, struct bitblt_coords *src )
401710d7 1176{
a3960292 1177 RECT rect, clipRect;
401710d7 1178
7cbe6572 1179 /* Get the destination visible rectangle */
aca05783 1180
39493b06
AJ
1181 rect.left = dst->x;
1182 rect.top = dst->y;
1183 rect.right = dst->x + dst->width;
1184 rect.bottom = dst->y + dst->height;
439223d4
AJ
1185 LPtoDP( physDevDst->hdc, (POINT *)&rect, 2 );
1186 dst->x = rect.left;
1187 dst->y = rect.top;
1188 dst->width = rect.right - rect.left;
1189 dst->height = rect.bottom - rect.top;
ebcd07a9
AJ
1190 if (dst->layout & LAYOUT_RTL && dst->layout & LAYOUT_BITMAPORIENTATIONPRESERVED)
1191 {
1192 SWAP_INT32( &rect.left, &rect.right );
1193 dst->x = rect.left;
1194 dst->width = rect.right - rect.left;
1195 }
1196 if (rect.left > rect.right) { SWAP_INT32( &rect.left, &rect.right ); rect.left++; rect.right++; }
1197 if (rect.top > rect.bottom) { SWAP_INT32( &rect.top, &rect.bottom ); rect.top++; rect.bottom++; }
439223d4 1198
e04fe7da 1199 GetRgnBox( physDevDst->region, &clipRect );
39493b06 1200 if (!IntersectRect( &dst->visrect, &rect, &clipRect )) return FALSE;
7cbe6572
AJ
1201
1202 /* Get the source visible rectangle */
aca05783 1203
50a783f7 1204 if (!physDevSrc) return TRUE;
439223d4 1205
39493b06
AJ
1206 rect.left = src->x;
1207 rect.top = src->y;
1208 rect.right = src->x + src->width;
1209 rect.bottom = src->y + src->height;
439223d4
AJ
1210 LPtoDP( physDevSrc->hdc, (POINT *)&rect, 2 );
1211 src->x = rect.left;
1212 src->y = rect.top;
1213 src->width = rect.right - rect.left;
1214 src->height = rect.bottom - rect.top;
ebcd07a9
AJ
1215 if (src->layout & LAYOUT_RTL && src->layout & LAYOUT_BITMAPORIENTATIONPRESERVED)
1216 {
1217 SWAP_INT32( &rect.left, &rect.right );
1218 src->x = rect.left;
1219 src->width = rect.right - rect.left;
1220 }
1221 if (rect.left > rect.right) { SWAP_INT32( &rect.left, &rect.right ); rect.left++; rect.right++; }
1222 if (rect.top > rect.bottom) { SWAP_INT32( &rect.top, &rect.bottom ); rect.top++; rect.bottom++; }
439223d4 1223
9a624916 1224 /* Apparently the clipping and visible regions are only for output,
da6214a3 1225 so just check against dc extent here to avoid BadMatch errors */
d302db41
AJ
1226 clipRect = physDevSrc->drawable_rect;
1227 OffsetRect( &clipRect, -(physDevSrc->drawable_rect.left + physDevSrc->dc_rect.left),
1228 -(physDevSrc->drawable_rect.top + physDevSrc->dc_rect.top) );
39493b06 1229 if (!IntersectRect( &src->visrect, &rect, &clipRect ))
27bb362f 1230 return FALSE;
aca05783 1231
7cbe6572 1232 /* Intersect the rectangles */
aca05783 1233
39493b06 1234 if ((src->width == dst->width) && (src->height == dst->height)) /* no stretching */
aca05783 1235 {
39493b06
AJ
1236 OffsetRect( &src->visrect, dst->x - src->x, dst->y - src->y );
1237 if (!IntersectRect( &rect, &src->visrect, &dst->visrect )) return FALSE;
1238 src->visrect = dst->visrect = rect;
1239 OffsetRect( &src->visrect, src->x - dst->x, src->y - dst->y );
aca05783 1240 }
7cbe6572 1241 else /* stretching */
aca05783 1242 {
b1bac320 1243 /* Map source rectangle into destination coordinates */
39493b06
AJ
1244 rect.left = dst->x + (src->visrect.left - src->x)*dst->width/src->width;
1245 rect.top = dst->y + (src->visrect.top - src->y)*dst->height/src->height;
1246 rect.right = dst->x + (src->visrect.right - src->x)*dst->width/src->width;
1247 rect.bottom = dst->y + (src->visrect.bottom - src->y)*dst->height/src->height;
b1bac320
AJ
1248 if (rect.left > rect.right) SWAP_INT32( &rect.left, &rect.right );
1249 if (rect.top > rect.bottom) SWAP_INT32( &rect.top, &rect.bottom );
62f824f7
AJ
1250
1251 /* Avoid rounding errors */
1252 rect.left--;
1253 rect.top--;
1254 rect.right++;
1255 rect.bottom++;
39493b06 1256 if (!IntersectRect( &dst->visrect, &rect, &dst->visrect )) return FALSE;
b1bac320
AJ
1257
1258 /* Map destination rectangle back to source coordinates */
39493b06
AJ
1259 rect = dst->visrect;
1260 rect.left = src->x + (dst->visrect.left - dst->x)*src->width/dst->width;
1261 rect.top = src->y + (dst->visrect.top - dst->y)*src->height/dst->height;
1262 rect.right = src->x + (dst->visrect.right - dst->x)*src->width/dst->width;
1263 rect.bottom = src->y + (dst->visrect.bottom - dst->y)*src->height/dst->height;
b1bac320
AJ
1264 if (rect.left > rect.right) SWAP_INT32( &rect.left, &rect.right );
1265 if (rect.top > rect.bottom) SWAP_INT32( &rect.top, &rect.bottom );
62f824f7
AJ
1266
1267 /* Avoid rounding errors */
1268 rect.left--;
1269 rect.top--;
1270 rect.right++;
1271 rect.bottom++;
39493b06 1272 if (!IntersectRect( &src->visrect, &rect, &src->visrect )) return FALSE;
aca05783 1273 }
401710d7
AJ
1274 return TRUE;
1275}
1276
1277
7bc4b074
AJ
1278/***********************************************************************
1279 * client_side_dib_copy
1280 */
1281static BOOL client_side_dib_copy( X11DRV_PDEVICE *physDevSrc, INT xSrc, INT ySrc,
1282 X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst,
1283 INT width, INT height )
1284{
1285 DIBSECTION srcDib, dstDib;
1286 BYTE *srcPtr, *dstPtr;
1287 INT srcRowOffset, dstRowOffset;
1288 INT bytesPerPixel;
1289 INT bytesToCopy;
1290 INT y;
1291 static RECT unusedRect;
1292
1293 if (GetObjectW(physDevSrc->bitmap->hbitmap, sizeof(srcDib), &srcDib) != sizeof(srcDib))
1294 return FALSE;
1295 if (GetObjectW(physDevDst->bitmap->hbitmap, sizeof(dstDib), &dstDib) != sizeof(dstDib))
1296 return FALSE;
1297
1298 /* check for oversized values, just like X11DRV_DIB_CopyDIBSection() */
1299 if (xSrc > srcDib.dsBm.bmWidth || ySrc > srcDib.dsBm.bmHeight)
1300 return FALSE;
1301 if (xSrc + width > srcDib.dsBm.bmWidth)
1302 width = srcDib.dsBm.bmWidth - xSrc;
1303 if (ySrc + height > srcDib.dsBm.bmHeight)
1304 height = srcDib.dsBm.bmHeight - ySrc;
1305
1306 if (GetRgnBox(physDevDst->region, &unusedRect) == COMPLEXREGION)
1307 {
1308 /* for simple regions, the clipping was already done by BITBLT_GetVisRectangles */
1309 FIXME("potential optimization: client-side complex region clipping\n");
1310 return FALSE;
1311 }
1312 if (dstDib.dsBm.bmBitsPixel <= 8)
1313 {
c7089361
AH
1314 static BOOL fixme_once;
1315 if(!fixme_once++) FIXME("potential optimization: client-side color-index mode DIB copy\n");
7bc4b074
AJ
1316 return FALSE;
1317 }
1318 if (!(srcDib.dsBmih.biCompression == BI_BITFIELDS &&
1319 dstDib.dsBmih.biCompression == BI_BITFIELDS &&
1320 !memcmp(srcDib.dsBitfields, dstDib.dsBitfields, 3*sizeof(DWORD)))
1321 && !(srcDib.dsBmih.biCompression == BI_RGB &&
1322 dstDib.dsBmih.biCompression == BI_RGB))
1323 {
1324 FIXME("potential optimization: client-side compressed DIB copy\n");
1325 return FALSE;
1326 }
1327 if (srcDib.dsBm.bmBitsPixel != dstDib.dsBm.bmBitsPixel)
1328 {
1329 FIXME("potential optimization: pixel format conversion\n");
1330 return FALSE;
1331 }
1332 if (srcDib.dsBmih.biWidth < 0 || dstDib.dsBmih.biWidth < 0)
1333 {
1334 FIXME("negative widths not yet implemented\n");
1335 return FALSE;
1336 }
1337
1338 switch (dstDib.dsBm.bmBitsPixel)
1339 {
1340 case 15:
1341 case 16:
1342 bytesPerPixel = 2;
1343 break;
1344 case 24:
1345 bytesPerPixel = 3;
1346 break;
1347 case 32:
1348 bytesPerPixel = 4;
1349 break;
1350 default:
1351 FIXME("don't know how to work with a depth of %d\n", physDevSrc->depth);
1352 return FALSE;
1353 }
1354
1355 bytesToCopy = width * bytesPerPixel;
1356
f331fe4c 1357 if (physDevSrc->bitmap->topdown)
7bc4b074
AJ
1358 {
1359 srcPtr = &physDevSrc->bitmap->base[ySrc*srcDib.dsBm.bmWidthBytes + xSrc*bytesPerPixel];
1360 srcRowOffset = srcDib.dsBm.bmWidthBytes;
1361 }
1362 else
1363 {
1364 srcPtr = &physDevSrc->bitmap->base[(srcDib.dsBm.bmHeight-ySrc-1)*srcDib.dsBm.bmWidthBytes
1365 + xSrc*bytesPerPixel];
1366 srcRowOffset = -srcDib.dsBm.bmWidthBytes;
1367 }
f331fe4c 1368 if (physDevDst->bitmap->topdown)
7bc4b074
AJ
1369 {
1370 dstPtr = &physDevDst->bitmap->base[yDst*dstDib.dsBm.bmWidthBytes + xDst*bytesPerPixel];
1371 dstRowOffset = dstDib.dsBm.bmWidthBytes;
1372 }
1373 else
1374 {
1375 dstPtr = &physDevDst->bitmap->base[(dstDib.dsBm.bmHeight-yDst-1)*dstDib.dsBm.bmWidthBytes
1376 + xDst*bytesPerPixel];
1377 dstRowOffset = -dstDib.dsBm.bmWidthBytes;
1378 }
1379
1380 /* Handle overlapping regions on the same DIB */
1381 if (physDevSrc == physDevDst && ySrc < yDst)
1382 {
1383 srcPtr += srcRowOffset * (height - 1);
1384 srcRowOffset = -srcRowOffset;
1385 dstPtr += dstRowOffset * (height - 1);
1386 dstRowOffset = -dstRowOffset;
1387 }
1388
1389 for (y = yDst; y < yDst + height; ++y)
1390 {
1391 memmove(dstPtr, srcPtr, bytesToCopy);
1392 srcPtr += srcRowOffset;
1393 dstPtr += dstRowOffset;
1394 }
1395
1396 return TRUE;
1397}
1398
61633b62
RC
1399static BOOL same_format(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst)
1400{
1401 if (physDevSrc->depth != physDevDst->depth) return FALSE;
1402 if (!physDevSrc->color_shifts && !physDevDst->color_shifts) return TRUE;
1403 if (physDevSrc->color_shifts && physDevDst->color_shifts)
1404 return !memcmp(physDevSrc->color_shifts, physDevDst->color_shifts, sizeof(ColorShifts));
1405 return FALSE;
1406}
7bc4b074 1407
8e396a94
AJ
1408/***********************************************************************
1409 * X11DRV_PatBlt
1410 */
1411BOOL CDECL X11DRV_PatBlt( X11DRV_PDEVICE *physDev, INT x, INT y, INT width, INT height, DWORD rop )
1412{
1413 BOOL usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
1414 const BYTE *opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
1415 struct bitblt_coords dst;
1416
1417 dst.x = x;
1418 dst.y = y;
1419 dst.width = width;
1420 dst.height = height;
1421 dst.layout = GetLayout( physDev->hdc );
1422
1423 if (rop & NOMIRRORBITMAP)
1424 {
1425 dst.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
1426 rop &= ~NOMIRRORBITMAP;
1427 }
1428
1429 if (!BITBLT_GetVisRectangles( physDev, NULL, &dst, NULL )) return TRUE;
1430 if (usePat && !X11DRV_SetupGCForBrush( physDev )) return TRUE;
1431
1432 TRACE( "rect=%d,%d %dx%d org=%d,%d vis=%s\n",
1433 dst.x, dst.y, dst.width, dst.height,
1434 physDev->dc_rect.left, physDev->dc_rect.top, wine_dbgstr_rect( &dst.visrect ) );
1435
1436 width = dst.visrect.right - dst.visrect.left;
1437 height = dst.visrect.bottom - dst.visrect.top;
1438
1439 X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod );
1440
1441 wine_tsx11_lock();
1442 XSetFunction( gdi_display, physDev->gc, OP_ROP(*opcode) );
1443
1444 switch(rop) /* a few special cases */
1445 {
1446 case BLACKNESS: /* 0x00 */
1447 case WHITENESS: /* 0xff */
1448 if ((physDev->depth != 1) && X11DRV_PALETTE_PaletteToXPixel)
1449 {
1450 XSetFunction( gdi_display, physDev->gc, GXcopy );
1451 if (rop == BLACKNESS)
1452 XSetForeground( gdi_display, physDev->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
1453 else
1454 XSetForeground( gdi_display, physDev->gc,
1455 WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
1456 XSetFillStyle( gdi_display, physDev->gc, FillSolid );
1457 }
1458 break;
1459 case DSTINVERT: /* 0x55 */
1460 if (!(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL)))
1461 {
1462 /* Xor is much better when we do not have full colormap. */
1463 /* Using white^black ensures that we invert at least black */
1464 /* and white. */
1465 unsigned long xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
1466 BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
1467 XSetFunction( gdi_display, physDev->gc, GXxor );
1468 XSetForeground( gdi_display, physDev->gc, xor_pix);
1469 XSetFillStyle( gdi_display, physDev->gc, FillSolid );
1470 }
1471 break;
1472 }
1473 XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
1474 physDev->dc_rect.left + dst.visrect.left,
1475 physDev->dc_rect.top + dst.visrect.top,
1476 dst.visrect.right - dst.visrect.left,
1477 dst.visrect.bottom - dst.visrect.top );
1478 wine_tsx11_unlock();
1479
1480 X11DRV_UnlockDIBSection( physDev, TRUE );
1481 return TRUE;
1482}
1483
1484
401710d7 1485/***********************************************************************
89c91ac0 1486 * X11DRV_StretchBlt
401710d7 1487 */
89c91ac0 1488BOOL CDECL X11DRV_StretchBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
3d34f01f 1489 PHYSDEV src_dev, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc,
89c91ac0 1490 DWORD rop )
401710d7 1491{
3d34f01f 1492 X11DRV_PDEVICE *physDevSrc = (X11DRV_PDEVICE *)src_dev; /* FIXME: check that it's really an x11 dev */
8e396a94 1493 BOOL usePat, useDst, destUsed, fStretch, fNullBrush;
39493b06 1494 struct bitblt_coords src, dst;
a3960292 1495 INT width, height;
77b9b8a3 1496 INT sDst, sSrc = DIB_Status_None;
3a5816f8 1497 const BYTE *opcode;
7cbe6572 1498 Pixmap pixmaps[3] = { 0, 0, 0 }; /* pixmaps for DST, SRC, TMP */
3a5816f8 1499 GC tmpGC = 0;
401710d7 1500
3a5816f8 1501 usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
3a5816f8 1502 useDst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
aca05783 1503
439223d4
AJ
1504 src.x = xSrc;
1505 src.y = ySrc;
1506 src.width = widthSrc;
1507 src.height = heightSrc;
3d34f01f 1508 src.layout = GetLayout( physDevSrc->hdc );
439223d4
AJ
1509 dst.x = xDst;
1510 dst.y = yDst;
1511 dst.width = widthDst;
1512 dst.height = heightDst;
ebcd07a9
AJ
1513 dst.layout = GetLayout( physDevDst->hdc );
1514
1515 if (rop & NOMIRRORBITMAP)
1516 {
1517 src.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
1518 dst.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
1519 rop &= ~NOMIRRORBITMAP;
1520 }
ded3038c 1521
8e396a94
AJ
1522 if (!BITBLT_GetVisRectangles( physDevDst, physDevSrc, &dst, &src ))
1523 return TRUE;
1524 fStretch = (src.width != dst.width) || (src.height != dst.height);
439223d4 1525
8e396a94
AJ
1526 if (physDevDst != physDevSrc)
1527 sSrc = X11DRV_LockDIBSection( physDevSrc, DIB_Status_None );
3a5816f8 1528
439223d4
AJ
1529 TRACE(" rectdst=%d,%d %dx%d orgdst=%d,%d visdst=%s\n",
1530 dst.x, dst.y, dst.width, dst.height,
1531 physDevDst->dc_rect.left, physDevDst->dc_rect.top, wine_dbgstr_rect( &dst.visrect ) );
8e396a94
AJ
1532 TRACE(" rectsrc=%d,%d %dx%d orgsrc=%d,%d vissrc=%s\n",
1533 src.x, src.y, src.width, src.height,
1534 physDevSrc->dc_rect.left, physDevSrc->dc_rect.top, wine_dbgstr_rect( &src.visrect ) );
439223d4 1535
39493b06
AJ
1536 width = dst.visrect.right - dst.visrect.left;
1537 height = dst.visrect.bottom - dst.visrect.top;
3a5816f8 1538
77b9b8a3
AJ
1539 sDst = X11DRV_LockDIBSection( physDevDst, DIB_Status_None );
1540 if (physDevDst == physDevSrc) sSrc = sDst;
1541
1542 /* try client-side DIB copy */
1543 if (!fStretch && rop == SRCCOPY &&
1544 sSrc == DIB_Status_AppMod && sDst == DIB_Status_AppMod &&
61633b62 1545 same_format(physDevSrc, physDevDst))
77b9b8a3 1546 {
39493b06
AJ
1547 if (client_side_dib_copy( physDevSrc, src.visrect.left, src.visrect.top,
1548 physDevDst, dst.visrect.left, dst.visrect.top, width, height ))
77b9b8a3
AJ
1549 goto done;
1550 }
1551
1552 X11DRV_CoerceDIBSection( physDevDst, DIB_Status_GdiMod );
1553
23afe2e9 1554 opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
daf776fd 1555
6e59cd2c 1556 /* a few optimizations for single-op ROPs */
8e396a94 1557 if (!fStretch && !opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
23afe2e9 1558 {
8e396a94 1559 if (same_format(physDevSrc, physDevDst))
3a5816f8 1560 {
8e396a94
AJ
1561 wine_tsx11_lock();
1562 XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
1563 wine_tsx11_unlock();
1564
1565 if (physDevSrc != physDevDst)
23afe2e9 1566 {
8e396a94 1567 if (sSrc == DIB_Status_AppMod)
23afe2e9 1568 {
8e396a94
AJ
1569 X11DRV_DIB_CopyDIBSection( physDevSrc, physDevDst, src.visrect.left, src.visrect.top,
1570 dst.visrect.left, dst.visrect.top, width, height );
77b9b8a3 1571 goto done;
23afe2e9 1572 }
8e396a94 1573 X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod );
23afe2e9 1574 }
8e396a94
AJ
1575 wine_tsx11_lock();
1576 XCopyArea( gdi_display, physDevSrc->drawable,
1577 physDevDst->drawable, physDevDst->gc,
1578 physDevSrc->dc_rect.left + src.visrect.left,
1579 physDevSrc->dc_rect.top + src.visrect.top,
1580 width, height,
1581 physDevDst->dc_rect.left + dst.visrect.left,
1582 physDevDst->dc_rect.top + dst.visrect.top );
1583 physDevDst->exposures++;
1584 wine_tsx11_unlock();
77b9b8a3 1585 goto done;
3a5816f8 1586 }
8e396a94 1587 if (physDevSrc->depth == 1)
7cbe6572 1588 {
8e396a94 1589 int fg, bg;
77b9b8a3 1590
8e396a94
AJ
1591 X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod );
1592 get_colors(physDevDst, physDevSrc, &fg, &bg);
1593 wine_tsx11_lock();
1594 XSetBackground( gdi_display, physDevDst->gc, fg );
1595 XSetForeground( gdi_display, physDevDst->gc, bg );
1596 XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
1597 XCopyPlane( gdi_display, physDevSrc->drawable,
1598 physDevDst->drawable, physDevDst->gc,
1599 physDevSrc->dc_rect.left + src.visrect.left,
1600 physDevSrc->dc_rect.top + src.visrect.top,
1601 width, height,
1602 physDevDst->dc_rect.left + dst.visrect.left,
1603 physDevDst->dc_rect.top + dst.visrect.top, 1 );
1604 physDevDst->exposures++;
1605 wine_tsx11_unlock();
1606 goto done;
7cbe6572 1607 }
988ca977 1608 }
401710d7 1609
704d0353 1610 wine_tsx11_lock();
c559735b 1611 tmpGC = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
dc4fe773 1612 XSetSubwindowMode( gdi_display, tmpGC, IncludeInferiors );
c559735b
AJ
1613 XSetGraphicsExposures( gdi_display, tmpGC, False );
1614 pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height,
b89525fb 1615 physDevDst->depth );
8e396a94
AJ
1616 pixmaps[SRC] = XCreatePixmap( gdi_display, root_window, width, height,
1617 physDevDst->depth );
809af590
AJ
1618 wine_tsx11_unlock();
1619
8e396a94 1620 if (physDevDst != physDevSrc) X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod );
004eabfb 1621
8e396a94
AJ
1622 if(!X11DRV_XRender_GetSrcAreaStretch( physDevSrc, physDevDst, pixmaps[SRC], tmpGC, &src, &dst ))
1623 {
1624 if (fStretch)
1625 BITBLT_GetSrcAreaStretch( physDevSrc, physDevDst, pixmaps[SRC], tmpGC, &src, &dst );
1626 else
1627 BITBLT_GetSrcArea( physDevSrc, physDevDst, pixmaps[SRC], tmpGC, &src.visrect );
7cbe6572 1628 }
704d0353 1629
39493b06 1630 if (useDst) BITBLT_GetDstArea( physDevDst, pixmaps[DST], tmpGC, &dst.visrect );
e21c15e3 1631 if (usePat) fNullBrush = !X11DRV_SetupGCForPatBlt( physDevDst, tmpGC, TRUE );
7cbe6572 1632 else fNullBrush = FALSE;
3a5816f8
AJ
1633 destUsed = FALSE;
1634
809af590 1635 wine_tsx11_lock();
23afe2e9 1636 for ( ; *opcode; opcode++)
3a5816f8 1637 {
7cbe6572 1638 if (OP_DST(*opcode) == DST) destUsed = TRUE;
c559735b 1639 XSetFunction( gdi_display, tmpGC, OP_ROP(*opcode) );
7cbe6572 1640 switch(OP_SRCDST(*opcode))
3a5816f8
AJ
1641 {
1642 case OP_ARGS(DST,TMP):
3a5816f8 1643 case OP_ARGS(SRC,TMP):
7cbe6572 1644 if (!pixmaps[TMP])
c559735b 1645 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window,
b89525fb 1646 width, height, physDevDst->depth );
7cbe6572
AJ
1647 /* fall through */
1648 case OP_ARGS(DST,SRC):
3a5816f8 1649 case OP_ARGS(SRC,DST):
7cbe6572
AJ
1650 case OP_ARGS(TMP,SRC):
1651 case OP_ARGS(TMP,DST):
8e396a94
AJ
1652 XCopyArea( gdi_display, pixmaps[OP_SRC(*opcode)],
1653 pixmaps[OP_DST(*opcode)], tmpGC,
1654 0, 0, width, height, 0, 0 );
3a5816f8
AJ
1655 break;
1656
1657 case OP_ARGS(PAT,TMP):
7cbe6572 1658 if (!pixmaps[TMP] && !fNullBrush)
c559735b 1659 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window,
b89525fb 1660 width, height, physDevDst->depth );
7cbe6572 1661 /* fall through */
3a5816f8 1662 case OP_ARGS(PAT,DST):
3a5816f8 1663 case OP_ARGS(PAT,SRC):
7cbe6572 1664 if (!fNullBrush)
c559735b 1665 XFillRectangle( gdi_display, pixmaps[OP_DST(*opcode)],
7cbe6572 1666 tmpGC, 0, 0, width, height );
3a5816f8
AJ
1667 break;
1668 }
1669 }
c559735b 1670 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
39493b06 1671 physDevDst->exposures += BITBLT_PutDstArea( physDevDst, pixmaps[destUsed ? DST : SRC], &dst.visrect );
c559735b
AJ
1672 XFreePixmap( gdi_display, pixmaps[DST] );
1673 if (pixmaps[SRC]) XFreePixmap( gdi_display, pixmaps[SRC] );
1674 if (pixmaps[TMP]) XFreePixmap( gdi_display, pixmaps[TMP] );
1675 XFreeGC( gdi_display, tmpGC );
704d0353 1676 wine_tsx11_unlock();
77b9b8a3
AJ
1677
1678done:
8e396a94 1679 if (physDevDst != physDevSrc) X11DRV_UnlockDIBSection( physDevSrc, FALSE );
77b9b8a3 1680 X11DRV_UnlockDIBSection( physDevDst, TRUE );
3a5816f8 1681 return TRUE;
401710d7 1682}
246e3732
AJ
1683
1684
1685/***********************************************************************
1686 * X11DRV_AlphaBlend
1687 */
1688BOOL CDECL X11DRV_AlphaBlend( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
3d34f01f 1689 PHYSDEV src_dev, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc,
246e3732
AJ
1690 BLENDFUNCTION blendfn )
1691{
3d34f01f 1692 X11DRV_PDEVICE *physDevSrc = (X11DRV_PDEVICE *)src_dev; /* FIXME: check that it's really an x11 dev */
246e3732
AJ
1693 struct bitblt_coords src, dst;
1694
1695 src.x = xSrc;
1696 src.y = ySrc;
1697 src.width = widthSrc;
1698 src.height = heightSrc;
ebcd07a9 1699 src.layout = GetLayout( physDevSrc->hdc );
246e3732
AJ
1700 dst.x = xDst;
1701 dst.y = yDst;
1702 dst.width = widthDst;
1703 dst.height = heightDst;
ebcd07a9 1704 dst.layout = GetLayout( physDevDst->hdc );
246e3732
AJ
1705
1706 if (!BITBLT_GetVisRectangles( physDevDst, physDevSrc, &dst, &src )) return TRUE;
1707
f0460e3c
AJ
1708 TRACE( "format %x alpha %u rectdst=%d,%d %dx%d orgdst=%d,%d visdst=%s rectsrc=%d,%d %dx%d orgsrc=%d,%d vissrc=%s\n",
1709 blendfn.AlphaFormat, blendfn.SourceConstantAlpha, dst.x, dst.y, dst.width, dst.height,
1710 physDevDst->dc_rect.left, physDevDst->dc_rect.top, wine_dbgstr_rect( &dst.visrect ),
1711 src.x, src.y, src.width, src.height,
1712 physDevSrc->dc_rect.left, physDevSrc->dc_rect.top, wine_dbgstr_rect( &src.visrect ) );
1713
246e3732
AJ
1714 if (src.x < 0 || src.y < 0 || src.width < 0 || src.height < 0 ||
1715 src.width > physDevSrc->drawable_rect.right - physDevSrc->drawable_rect.left - src.x ||
1716 src.height > physDevSrc->drawable_rect.bottom - physDevSrc->drawable_rect.top - src.y)
1717 {
1718 WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src.x, src.y, src.width, src.height );
1719 SetLastError( ERROR_INVALID_PARAMETER );
1720 return FALSE;
1721 }
1722
1723 return XRender_AlphaBlend( physDevDst, physDevSrc, &dst, &src, blendfn );
1724}