blob: e2ebb74924bc8a2d74dcd88167f6fe6f0a9f8583 [file] [log] [blame]
Alexandre Julliard401710d1993-09-04 10:09:32 +00001/*
2 * GDI bit-blit operations
3 *
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00004 * Copyright 1993, 1994 Alexandre Julliard
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Alexandre Julliard3a5816f1994-12-27 14:11:53 +000019 */
20
Patrik Stridvallab121e71999-02-04 11:11:01 +000021#include "config.h"
22
Patrik Stridvall151170c1998-12-26 12:00:43 +000023#include <X11/Intrinsic.h>
Patrik Stridvall3d511612000-04-25 19:55:35 +000024
Patrik Stridvallab121e71999-02-04 11:11:01 +000025#include "ts_xlib.h"
Patrik Stridvall151170c1998-12-26 12:00:43 +000026
Alexandre Julliardb1bac321996-12-15 19:45:59 +000027#include <assert.h>
Alexandre Julliard401710d1993-09-04 10:09:32 +000028#include <stdio.h>
29#include <stdlib.h>
Alexandre Julliard8efd4542001-01-15 22:30:50 +000030#include "winbase.h"
31#include "wingdi.h"
Dmitry Timoshkovde70d2b2001-06-19 03:32:44 +000032#include "winreg.h"
Alexandre Julliard8efd4542001-01-15 22:30:50 +000033#include "winuser.h"
Alexandre Julliard3a5816f1994-12-27 14:11:53 +000034#include "bitmap.h"
Alexandre Julliard2239abb2000-11-05 02:05:07 +000035#include "gdi.h"
Alexandre Julliard75d86e11996-11-17 18:59:11 +000036#include "x11drv.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000037#include "wine/debug.h"
Alexandre Julliard401710d1993-09-04 10:09:32 +000038
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000039WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000040
Alexandre Julliard3a5816f1994-12-27 14:11:53 +000041
Alexandre Julliard7cbe6571995-01-09 18:21:16 +000042#define DST 0 /* Destination drawable */
43#define SRC 1 /* Source drawable */
44#define TMP 2 /* Temporary drawable */
Alexandre Julliard3a5816f1994-12-27 14:11:53 +000045#define PAT 3 /* Pattern (brush) in destination DC */
46
Alexandre Julliard7cbe6571995-01-09 18:21:16 +000047#define OP(src,dst,rop) (OP_ARGS(src,dst) << 4 | (rop))
Alexandre Julliard3a5816f1994-12-27 14:11:53 +000048#define OP_ARGS(src,dst) (((src) << 2) | (dst))
49
Alexandre Julliard7cbe6571995-01-09 18:21:16 +000050#define OP_SRC(opcode) ((opcode) >> 6)
51#define OP_DST(opcode) (((opcode) >> 4) & 3)
52#define OP_SRCDST(opcode) ((opcode) >> 4)
53#define OP_ROP(opcode) ((opcode) & 0x0f)
Alexandre Julliard3a5816f1994-12-27 14:11:53 +000054
Alexandre Julliard7cbe6571995-01-09 18:21:16 +000055#define MAX_OP_LEN 6 /* Longest opcode + 1 for the terminating 0 */
Alexandre Julliard3a5816f1994-12-27 14:11:53 +000056
Alexandre Julliardb1bac321996-12-15 19:45:59 +000057#define SWAP_INT32(i1,i2) \
Alexandre Julliarda3960291999-02-26 11:11:13 +000058 do { INT __t = *(i1); *(i1) = *(i2); *(i2) = __t; } while(0)
Alexandre Julliardb1bac321996-12-15 19:45:59 +000059
Alexandre Julliard3a5816f1994-12-27 14:11:53 +000060static const unsigned char BITBLT_Opcodes[256][MAX_OP_LEN] =
61{
62 { OP(PAT,DST,GXclear) }, /* 0x00 0 */
63 { OP(PAT,SRC,GXor), OP(SRC,DST,GXnor) }, /* 0x01 ~(D|(P|S)) */
64 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXand) }, /* 0x02 D&~(P|S) */
65 { OP(PAT,SRC,GXnor) }, /* 0x03 ~(P|S) */
66 { OP(PAT,DST,GXnor), OP(SRC,DST,GXand) }, /* 0x04 S&~(D|P) */
67 { OP(PAT,DST,GXnor) }, /* 0x05 ~(D|P) */
68 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnor), }, /* 0x06 ~(P|~(D^S)) */
69 { OP(SRC,DST,GXand), OP(PAT,DST,GXnor) }, /* 0x07 ~(P|(D&S)) */
70 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXand) },/* 0x08 S&D&~P */
71 { OP(SRC,DST,GXxor), OP(PAT,DST,GXnor) }, /* 0x09 ~(P|(D^S)) */
72 { OP(PAT,DST,GXandInverted) }, /* 0x0a D&~P */
73 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXnor) }, /* 0x0b ~(P|(S&~D)) */
74 { OP(PAT,SRC,GXandInverted) }, /* 0x0c S&~P */
75 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXnor) },/* 0x0d ~(P|(D&~S)) */
76 { OP(SRC,DST,GXnor), OP(PAT,DST,GXnor) }, /* 0x0e ~(P|~(D|S)) */
77 { OP(PAT,DST,GXcopyInverted) }, /* 0x0f ~P */
78 { OP(SRC,DST,GXnor), OP(PAT,DST,GXand) }, /* 0x10 P&~(S|D) */
79 { OP(SRC,DST,GXnor) }, /* 0x11 ~(D|S) */
80 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnor) }, /* 0x12 ~(S|~(D^P)) */
81 { OP(PAT,DST,GXand), OP(SRC,DST,GXnor) }, /* 0x13 ~(S|(D&P)) */
82 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnor) }, /* 0x14 ~(D|~(P^S)) */
83 { OP(PAT,SRC,GXand), OP(SRC,DST,GXnor) }, /* 0x15 ~(D|(P&S)) */
84 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXnand),
85 OP(TMP,DST,GXand), OP(SRC,DST,GXxor),
86 OP(PAT,DST,GXxor) }, /* 0x16 P^S^(D&~(P&S) */
87 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
88 OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
89 OP(TMP,DST,GXequiv) }, /* 0x17 ~S^((S^P)&(S^D))*/
90 { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
91 OP(SRC,DST,GXand) }, /* 0x18 (S^P)&(D^P) */
92 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXnand),
93 OP(TMP,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x19 ~S^(D&~(P&S)) */
94 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
95 OP(PAT,DST,GXxor) }, /* 0x1a P^(D|(S&P)) */
96 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXxor),
97 OP(TMP,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x1b ~S^(D&(P^S)) */
98 { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
99 OP(PAT,DST,GXxor) }, /* 0x1c P^(S|(D&P)) */
100 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
101 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x1d ~D^(S&(D^P)) */
102 { OP(SRC,DST,GXor), OP(PAT,DST,GXxor) }, /* 0x1e P^(D|S) */
103 { OP(SRC,DST,GXor), OP(PAT,DST,GXnand) }, /* 0x1f ~(P&(D|S)) */
104 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXand) }, /* 0x20 D&(P&~S) */
105 { OP(PAT,DST,GXxor), OP(SRC,DST,GXnor) }, /* 0x21 ~(S|(D^P)) */
106 { OP(SRC,DST,GXandInverted) }, /* 0x22 ~S&D */
107 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x23 ~(S|(P&~D)) */
108 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
109 OP(SRC,DST,GXand) }, /* 0x24 (S^P)&(S^D) */
110 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand),
111 OP(PAT,DST,GXequiv) }, /* 0x25 ~P^(D&~(S&P)) */
112 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXand),
113 OP(TMP,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x26 S^(D|(S&P)) */
114 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXequiv),
115 OP(TMP,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x27 S^(D|~(P^S)) */
116 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand) }, /* 0x28 D&(P^S) */
117 { OP(SRC,TMP,GXcopy), OP(PAT,TMP,GXand),
118 OP(TMP,DST,GXor), OP(SRC,DST,GXxor),
119 OP(PAT,DST,GXequiv) }, /* 0x29 ~P^S^(D|(P&S)) */
120 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXand) }, /* 0x2a D&~(P&S) */
121 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
122 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
123 OP(TMP,DST,GXequiv) }, /* 0x2b ~S^((P^S)&(P^D))*/
124 { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
125 OP(SRC,DST,GXxor) }, /* 0x2c S^(P&(S|D)) */
126 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXxor) }, /* 0x2d P^(S|~D) */
127 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
128 OP(PAT,DST,GXxor) }, /* 0x2e P^(S|(D^P)) */
129 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXnand) }, /* 0x2f ~(P&(S|~D)) */
130 { OP(PAT,SRC,GXandReverse) }, /* 0x30 P&~S */
131 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXnor) },/* 0x31 ~(S|(D&~P)) */
132 { OP(SRC,DST,GXor), OP(PAT,DST,GXor),
133 OP(SRC,DST,GXxor) }, /* 0x32 S^(D|P|S) */
134 { OP(SRC,DST,GXcopyInverted) }, /* 0x33 ~S */
135 { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
136 OP(SRC,DST,GXxor) }, /* 0x34 S^(P|(D&S)) */
137 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor),
138 OP(SRC,DST,GXxor) }, /* 0x35 S^(P|~(D^S)) */
139 { OP(PAT,DST,GXor), OP(SRC,DST,GXxor) }, /* 0x36 S^(D|P) */
140 { OP(PAT,DST,GXor), OP(SRC,DST,GXnand) }, /* 0x37 ~(S&(D|P)) */
141 { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
142 OP(PAT,DST,GXxor) }, /* 0x38 P^(S&(D|P)) */
143 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXxor) }, /* 0x39 S^(P|~D) */
144 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
145 OP(SRC,DST,GXxor) }, /* 0x3a S^(P|(D^S)) */
146 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x3b ~(S&(P|~D)) */
147 { OP(PAT,SRC,GXxor) }, /* 0x3c P^S */
148 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
149 OP(SRC,DST,GXxor) }, /* 0x3d S^(P|~(D|S)) */
150 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
151 OP(SRC,DST,GXxor) }, /* 0x3e S^(P|(D&~S)) */
152 { OP(PAT,SRC,GXnand) }, /* 0x3f ~(P&S) */
153 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXand) }, /* 0x40 P&S&~D */
154 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnor) }, /* 0x41 ~(D|(P^S)) */
155 { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
156 OP(SRC,DST,GXand) }, /* 0x42 (S^D)&(P^D) */
157 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
158 OP(SRC,DST,GXequiv) }, /* 0x43 ~S^(P&~(D&S)) */
159 { OP(SRC,DST,GXandReverse) }, /* 0x44 S&~D */
160 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXnor) }, /* 0x45 ~(D|(P&~S)) */
161 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
162 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x46 D^(S|(P&D)) */
163 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
164 OP(PAT,DST,GXequiv) }, /* 0x47 ~P^(S&(D^P)) */
165 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand) }, /* 0x48 S&(P^D) */
166 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
167 OP(SRC,DST,GXor), OP(TMP,DST,GXxor),
168 OP(PAT,DST,GXequiv) }, /* 0x49 ~P^D^(S|(P&D)) */
169 { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
170 OP(SRC,DST,GXxor) }, /* 0x4a D^(P&(S|D)) */
171 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXxor) }, /* 0x4b P^(D|~S) */
172 { OP(PAT,DST,GXnand), OP(SRC,DST,GXand) }, /* 0x4c S&~(D&P) */
173 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
174 OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
175 OP(TMP,DST,GXequiv) }, /* 0x4d ~S^((S^P)|(S^D))*/
176 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
177 OP(PAT,DST,GXxor) }, /* 0x4e P^(D|(S^P)) */
178 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXnand) },/* 0x4f ~(P&(D|~S)) */
179 { OP(PAT,DST,GXandReverse) }, /* 0x50 P&~D */
180 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXnor) },/* 0x51 ~(D|(S&~P)) */
181 { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
182 OP(SRC,DST,GXxor) }, /* 0x52 D^(P|(S&D)) */
183 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
184 OP(SRC,DST,GXequiv) }, /* 0x53 ~S^(P&(D^S)) */
185 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXnor) }, /* 0x54 ~(D|~(P|S)) */
186 { OP(PAT,DST,GXinvert) }, /* 0x55 ~D */
187 { OP(PAT,SRC,GXor), OP(SRC,DST,GXxor) }, /* 0x56 D^(P|S) */
188 { OP(PAT,SRC,GXor), OP(SRC,DST,GXnand) }, /* 0x57 ~(D&(P|S)) */
189 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
190 OP(PAT,DST,GXxor) }, /* 0x58 P^(D&(P|S)) */
191 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXxor) }, /* 0x59 D^(P|~S) */
192 { OP(PAT,DST,GXxor) }, /* 0x5a D^P */
193 { OP(DST,SRC,GXnor), OP(PAT,SRC,GXor),
194 OP(SRC,DST,GXxor) }, /* 0x5b D^(P|~(S|D)) */
195 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
196 OP(SRC,DST,GXxor) }, /* 0x5c D^(P|(S^D)) */
197 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXnand) }, /* 0x5d ~(D&(P|~S)) */
198 { OP(DST,SRC,GXandInverted), OP(PAT,SRC,GXor),
199 OP(SRC,DST,GXxor) }, /* 0x5e D^(P|(S&~D)) */
200 { OP(PAT,DST,GXnand) }, /* 0x5f ~(D&P) */
201 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand) }, /* 0x60 P&(D^S) */
202 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
203 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
204 OP(TMP,DST,GXequiv) }, /* 0x61 ~D^S^(P|(D&S)) */
205 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
206 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x62 D^(S&(P|D)) */
207 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x63 S^(D|~P) */
208 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
209 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x64 S^(D&(P|S)) */
210 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXxor) }, /* 0x65 D^(S|~P) */
211 { OP(SRC,DST,GXxor) }, /* 0x66 S^D */
212 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
213 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x67 S^(D|~(S|P) */
214 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnor),
215 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
216 OP(TMP,DST,GXequiv) }, /* 0x68 ~D^S^(P|~(D|S))*/
217 { OP(SRC,DST,GXxor), OP(PAT,DST,GXequiv) }, /* 0x69 ~P^(D^S) */
218 { OP(PAT,SRC,GXand), OP(SRC,DST,GXxor) }, /* 0x6a D^(P&S) */
219 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
220 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
221 OP(PAT,DST,GXequiv) }, /* 0x6b ~P^S^(D&(P|S)) */
222 { OP(PAT,DST,GXand), OP(SRC,DST,GXxor) }, /* 0x6c S^(D&P) */
223 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
224 OP(SRC,DST,GXand), OP(TMP,DST,GXxor),
225 OP(PAT,DST,GXequiv) }, /* 0x6d ~P^D^(S&(P|D)) */
226 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
227 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0x6e S^(D&(P|~S)) */
228 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXnand) }, /* 0x6f ~(P&~(S^D)) */
229 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand) }, /* 0x70 P&~(D&S) */
230 { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
231 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
232 OP(TMP,DST,GXequiv) }, /* 0x71 ~S^((S^D)&(P^D))*/
233 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
234 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x72 S^(D|(P^S)) */
235 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXnand) },/* 0x73 ~(S&(D|~P)) */
236 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
237 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x74 D^(S|(P^D)) */
238 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXnand) },/* 0x75 ~(D&(S|~P)) */
239 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
240 OP(SRC,DST,GXor), OP(TMP,DST,GXxor) }, /* 0x76 S^(D|(P&~S)) */
241 { OP(SRC,DST,GXnand) }, /* 0x77 ~(S&D) */
242 { OP(SRC,DST,GXand), OP(PAT,DST,GXxor) }, /* 0x78 P^(D&S) */
243 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
244 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
245 OP(TMP,DST,GXequiv) }, /* 0x79 ~D^S^(P&(D|S)) */
246 { OP(DST,SRC,GXorInverted), OP(PAT,SRC,GXand),
247 OP(SRC,DST,GXxor) }, /* 0x7a D^(P&(S|~D)) */
248 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXnand) }, /* 0x7b ~(S&~(D^P)) */
249 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
250 OP(SRC,DST,GXxor) }, /* 0x7c S^(P&(D|~S)) */
251 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXnand) }, /* 0x7d ~(D&~(P^S)) */
252 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
253 OP(SRC,DST,GXor) }, /* 0x7e (S^P)|(S^D) */
254 { OP(PAT,SRC,GXand), OP(SRC,DST,GXnand) }, /* 0x7f ~(D&P&S) */
255 { OP(PAT,SRC,GXand), OP(SRC,DST,GXand) }, /* 0x80 D&P&S */
256 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
257 OP(SRC,DST,GXnor) }, /* 0x81 ~((S^P)|(S^D)) */
258 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXand) }, /* 0x82 D&~(P^S) */
259 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand),
260 OP(SRC,DST,GXequiv) }, /* 0x83 ~S^(P&(D|~S)) */
261 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXand) }, /* 0x84 S&~(D^P) */
262 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand),
263 OP(PAT,DST,GXequiv) }, /* 0x85 ~P^(D&(S|~P)) */
264 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXor),
265 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
266 OP(TMP,DST,GXxor) }, /* 0x86 D^S^(P&(D|S)) */
267 { OP(SRC,DST,GXand), OP(PAT,DST,GXequiv) }, /* 0x87 ~P^(D&S) */
268 { OP(SRC,DST,GXand) }, /* 0x88 S&D */
269 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXandReverse),
270 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x89 ~S^(D|(P&~S)) */
271 { OP(PAT,SRC,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8a D&(S|~P) */
272 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
273 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x8b ~D^(S|(P^D)) */
274 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXand) }, /* 0x8c S&(D|~P) */
275 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
276 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x8d ~S^(D|(P^S)) */
277 { OP(SRC,TMP,GXcopy), OP(DST,SRC,GXxor),
278 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
279 OP(TMP,DST,GXxor) }, /* 0x8e S^((S^D)&(P^D))*/
280 { OP(SRC,DST,GXnand), OP(PAT,DST,GXnand) }, /* 0x8f ~(P&~(D&S)) */
281 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXand) }, /* 0x90 P&~(D^S) */
282 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXorReverse),
283 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x91 ~S^(D&(P|~S)) */
284 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
285 OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
286 OP(TMP,DST,GXxor) }, /* 0x92 D^P^(S&(D|P)) */
287 { OP(PAT,DST,GXand), OP(SRC,DST,GXequiv) }, /* 0x93 ~S^(P&D) */
288 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
289 OP(SRC,DST,GXand), OP(PAT,DST,GXxor),
290 OP(TMP,DST,GXxor) }, /* 0x94 S^P^(D&(P|S)) */
291 { OP(PAT,SRC,GXand), OP(SRC,DST,GXequiv) }, /* 0x95 ~D^(P&S) */
292 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXxor) }, /* 0x96 D^P^S */
293 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
294 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
295 OP(TMP,DST,GXxor) }, /* 0x97 S^P^(D|~(P|S)) */
296 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnor),
297 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0x98 ~S^(D|~(P|S)) */
298 { OP(SRC,DST,GXequiv) }, /* 0x99 ~S^D */
299 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9a D^(P&~S) */
300 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXor),
301 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x9b ~S^(D&(P|S)) */
302 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXxor) }, /* 0x9c S^(P&~D) */
303 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXor),
304 OP(SRC,DST,GXand), OP(TMP,DST,GXequiv) }, /* 0x9d ~D^(S&(P|D)) */
305 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXand),
306 OP(PAT,DST,GXor), OP(SRC,DST,GXxor),
307 OP(TMP,DST,GXxor) }, /* 0x9e D^S^(P|(D&S)) */
308 { OP(SRC,DST,GXxor), OP(PAT,DST,GXnand) }, /* 0x9f ~(P&(D^S)) */
309 { OP(PAT,DST,GXand) }, /* 0xa0 D&P */
310 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor),
311 OP(PAT,DST,GXequiv) }, /* 0xa1 ~P^(D|(S&~P)) */
312 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXand) }, /* 0xa2 D&(P|~S) */
313 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXor),
314 OP(SRC,DST,GXequiv) }, /* 0xa3 ~D^(P|(S^D)) */
315 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor),
316 OP(PAT,DST,GXequiv) }, /* 0xa4 ~P^(D|~(S|P)) */
317 { OP(PAT,DST,GXequiv) }, /* 0xa5 ~P^D */
318 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXxor) },/* 0xa6 D^(S&~P) */
319 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand),
320 OP(PAT,DST,GXequiv) }, /* 0xa7 ~P^(D&(S|P)) */
321 { OP(PAT,SRC,GXor), OP(SRC,DST,GXand) }, /* 0xa8 D&(P|S) */
322 { OP(PAT,SRC,GXor), OP(SRC,DST,GXequiv) }, /* 0xa9 ~D^(P|S) */
323 { OP(SRC,DST,GXnoop) }, /* 0xaa D */
324 { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor) }, /* 0xab D|~(P|S) */
325 { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
326 OP(SRC,DST,GXxor) }, /* 0xac S^(P&(D^S)) */
327 { OP(DST,SRC,GXand), OP(PAT,SRC,GXor),
328 OP(SRC,DST,GXequiv) }, /* 0xad ~D^(P|(S&D)) */
329 { OP(PAT,SRC,GXandInverted), OP(SRC,DST,GXor) }, /* 0xae D|(S&~P) */
330 { OP(PAT,DST,GXorInverted) }, /* 0xaf D|~P */
331 { OP(SRC,DST,GXorInverted), OP(PAT,DST,GXand) }, /* 0xb0 P&(D|~S) */
332 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
333 OP(PAT,DST,GXequiv) }, /* 0xb1 ~P^(D|(S^P)) */
334 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
335 OP(PAT,SRC,GXxor), OP(SRC,DST,GXor),
336 OP(TMP,DST,GXxor) }, /* 0xb2 S^((S^P)|(S^D))*/
337 { OP(PAT,DST,GXnand), OP(SRC,DST,GXnand) }, /* 0xb3 ~(S&~(D&P)) */
338 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXxor) }, /* 0xb4 P^(S&~D) */
339 { OP(DST,SRC,GXor), OP(PAT,SRC,GXand),
340 OP(SRC,DST,GXequiv) }, /* 0xb5 ~D^(P&(S|D)) */
341 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
342 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
343 OP(TMP,DST,GXxor) }, /* 0xb6 D^P^(S|(D&P)) */
344 { OP(PAT,DST,GXxor), OP(SRC,DST,GXnand) }, /* 0xb7 ~(S&(D^P)) */
345 { OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
346 OP(PAT,DST,GXxor) }, /* 0xb8 P^(S&(D^P)) */
347 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXand),
348 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0xb9 ~D^(S|(P&D)) */
349 { OP(PAT,SRC,GXandReverse), OP(SRC,DST,GXor) }, /* 0xba D|(P&~S) */
350 { OP(SRC,DST,GXorInverted) }, /* 0xbb ~S|D */
351 { OP(SRC,DST,GXnand), OP(PAT,DST,GXand),
352 OP(SRC,DST,GXxor) }, /* 0xbc S^(P&~(D&S)) */
353 { OP(DST,SRC,GXxor), OP(PAT,DST,GXxor),
354 OP(SRC,DST,GXnand) }, /* 0xbd ~((S^D)&(P^D)) */
355 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXor) }, /* 0xbe D|(P^S) */
356 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXor) }, /* 0xbf D|~(P&S) */
357 { OP(PAT,SRC,GXand) }, /* 0xc0 P&S */
358 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor),
359 OP(SRC,DST,GXequiv) }, /* 0xc1 ~S^(P|(D&~S)) */
360 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor),
361 OP(SRC,DST,GXequiv) }, /* 0xc2 ~S^(P|~(D|S)) */
362 { OP(PAT,SRC,GXequiv) }, /* 0xc3 ~P^S */
363 { OP(PAT,DST,GXorReverse), OP(SRC,DST,GXand) }, /* 0xc4 S&(P|~D) */
364 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor),
365 OP(SRC,DST,GXequiv) }, /* 0xc5 ~S^(P|(D^S)) */
366 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXxor) },/* 0xc6 S^(D&~P) */
367 { OP(PAT,DST,GXor), OP(SRC,DST,GXand),
368 OP(PAT,DST,GXequiv) }, /* 0xc7 ~P^(S&(D|P)) */
369 { OP(PAT,DST,GXor), OP(SRC,DST,GXand) }, /* 0xc8 S&(D|P) */
370 { OP(PAT,DST,GXor), OP(SRC,DST,GXequiv) }, /* 0xc9 ~S^(P|D) */
371 { OP(DST,SRC,GXxor), OP(PAT,SRC,GXand),
372 OP(SRC,DST,GXxor) }, /* 0xca D^(P&(S^D)) */
373 { OP(SRC,DST,GXand), OP(PAT,DST,GXor),
374 OP(SRC,DST,GXequiv) }, /* 0xcb ~S^(P|(D&S)) */
375 { OP(SRC,DST,GXcopy) }, /* 0xcc S */
376 { OP(PAT,DST,GXnor), OP(SRC,DST,GXor) }, /* 0xcd S|~(D|P) */
377 { OP(PAT,DST,GXandInverted), OP(SRC,DST,GXor) }, /* 0xce S|(D&~P) */
378 { OP(PAT,SRC,GXorInverted) }, /* 0xcf S|~P */
379 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXand) }, /* 0xd0 P&(S|~D) */
380 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor),
381 OP(PAT,DST,GXequiv) }, /* 0xd1 ~P^(S|(D^P)) */
382 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXxor) },/* 0xd2 P^(D&~S) */
383 { OP(SRC,DST,GXor), OP(PAT,DST,GXand),
384 OP(SRC,DST,GXequiv) }, /* 0xd3 ~S^(P&(D|S)) */
385 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
386 OP(PAT,DST,GXxor), OP(SRC,DST,GXand),
387 OP(TMP,DST,GXxor) }, /* 0xd4 S^((S^P)&(D^P))*/
388 { OP(PAT,SRC,GXnand), OP(SRC,DST,GXnand) }, /* 0xd5 ~(D&~(P&S)) */
389 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
390 OP(SRC,DST,GXor), OP(PAT,DST,GXxor),
391 OP(TMP,DST,GXxor) }, /* 0xd6 S^P^(D|(P&S)) */
392 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXnand) }, /* 0xd7 ~(D&(P^S)) */
393 { OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
394 OP(PAT,DST,GXxor) }, /* 0xd8 P^(D&(S^P)) */
395 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXand),
396 OP(SRC,DST,GXor), OP(TMP,DST,GXequiv) }, /* 0xd9 ~S^(D|(P&S)) */
397 { OP(DST,SRC,GXnand), OP(PAT,SRC,GXand),
398 OP(SRC,DST,GXxor) }, /* 0xda D^(P&~(S&D)) */
399 { OP(SRC,DST,GXxor), OP(PAT,SRC,GXxor),
400 OP(SRC,DST,GXnand) }, /* 0xdb ~((S^P)&(S^D)) */
401 { OP(PAT,DST,GXandReverse), OP(SRC,DST,GXor) }, /* 0xdc S|(P&~D) */
402 { OP(SRC,DST,GXorReverse) }, /* 0xdd S|~D */
403 { OP(PAT,DST,GXxor), OP(SRC,DST,GXor) }, /* 0xde S|(D^P) */
404 { OP(PAT,DST,GXnand), OP(SRC,DST,GXor) }, /* 0xdf S|~(D&P) */
405 { OP(SRC,DST,GXor), OP(PAT,DST,GXand) }, /* 0xe0 P&(D|S) */
406 { OP(SRC,DST,GXor), OP(PAT,DST,GXequiv) }, /* 0xe1 ~P^(D|S) */
407 { OP(DST,TMP,GXcopy), OP(PAT,DST,GXxor),
408 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe2 D^(S&(P^D)) */
409 { OP(PAT,DST,GXand), OP(SRC,DST,GXor),
410 OP(PAT,DST,GXequiv) }, /* 0xe3 ~P^(S|(D&P)) */
411 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXxor),
412 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe4 S^(D&(P^S)) */
413 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor),
414 OP(PAT,DST,GXequiv) }, /* 0xe5 ~P^(D|(S&P)) */
415 { OP(SRC,TMP,GXcopy), OP(PAT,SRC,GXnand),
416 OP(SRC,DST,GXand), OP(TMP,DST,GXxor) }, /* 0xe6 S^(D&~(P&S)) */
417 { OP(PAT,SRC,GXxor), OP(PAT,DST,GXxor),
418 OP(SRC,DST,GXnand) }, /* 0xe7 ~((S^P)&(D^P)) */
419 { OP(SRC,TMP,GXcopy), OP(SRC,DST,GXxor),
420 OP(PAT,SRC,GXxor), OP(SRC,DST,GXand),
421 OP(TMP,DST,GXxor) }, /* 0xe8 S^((S^P)&(S^D))*/
422 { OP(DST,TMP,GXcopy), OP(SRC,DST,GXnand),
423 OP(PAT,DST,GXand), OP(SRC,DST,GXxor),
424 OP(TMP,DST,GXequiv) }, /* 0xe9 ~D^S^(P&~(S&D))*/
425 { OP(PAT,SRC,GXand), OP(SRC,DST,GXor) }, /* 0xea D|(P&S) */
426 { OP(PAT,SRC,GXequiv), OP(SRC,DST,GXor) }, /* 0xeb D|~(P^S) */
427 { OP(PAT,DST,GXand), OP(SRC,DST,GXor) }, /* 0xec S|(D&P) */
428 { OP(PAT,DST,GXequiv), OP(SRC,DST,GXor) }, /* 0xed S|~(D^P) */
429 { OP(SRC,DST,GXor) }, /* 0xee S|D */
430 { OP(PAT,DST,GXorInverted), OP(SRC,DST,GXor) }, /* 0xef S|D|~P */
431 { OP(PAT,DST,GXcopy) }, /* 0xf0 P */
432 { OP(SRC,DST,GXnor), OP(PAT,DST,GXor) }, /* 0xf1 P|~(D|S) */
433 { OP(SRC,DST,GXandInverted), OP(PAT,DST,GXor) }, /* 0xf2 P|(D&~S) */
434 { OP(PAT,SRC,GXorReverse) }, /* 0xf3 P|~S */
435 { OP(SRC,DST,GXandReverse), OP(PAT,DST,GXor) }, /* 0xf4 P|(S&~D) */
436 { OP(PAT,DST,GXorReverse) }, /* 0xf5 P|~D */
437 { OP(SRC,DST,GXxor), OP(PAT,DST,GXor) }, /* 0xf6 P|(D^S) */
438 { OP(SRC,DST,GXnand), OP(PAT,DST,GXor) }, /* 0xf7 P|~(S&D) */
439 { OP(SRC,DST,GXand), OP(PAT,DST,GXor) }, /* 0xf8 P|(D&S) */
440 { OP(SRC,DST,GXequiv), OP(PAT,DST,GXor) }, /* 0xf9 P|~(D^S) */
441 { OP(PAT,DST,GXor) }, /* 0xfa D|P */
442 { OP(PAT,SRC,GXorReverse), OP(SRC,DST,GXor) }, /* 0xfb D|P|~S */
443 { OP(PAT,SRC,GXor) }, /* 0xfc P|S */
444 { OP(SRC,DST,GXorReverse), OP(PAT,DST,GXor) }, /* 0xfd P|S|~D */
445 { OP(SRC,DST,GXor), OP(PAT,DST,GXor) }, /* 0xfe P|D|S */
446 { OP(PAT,DST,GXset) } /* 0xff 1 */
447};
448
449
450#ifdef BITBLT_TEST /* Opcodes test */
451
452static int do_bitop( int s, int d, int rop )
453{
454 int res;
455 switch(rop)
456 {
457 case GXclear: res = 0; break;
458 case GXand: res = s & d; break;
459 case GXandReverse: res = s & ~d; break;
460 case GXcopy: res = s; break;
461 case GXandInverted: res = ~s & d; break;
462 case GXnoop: res = d; break;
463 case GXxor: res = s ^ d; break;
464 case GXor: res = s | d; break;
465 case GXnor: res = ~(s | d); break;
466 case GXequiv: res = ~s ^ d; break;
467 case GXinvert: res = ~d; break;
468 case GXorReverse: res = s | ~d; break;
469 case GXcopyInverted: res = ~s; break;
470 case GXorInverted: res = ~s | d; break;
471 case GXnand: res = ~(s & d); break;
472 case GXset: res = 1; break;
473 }
474 return res & 1;
475}
476
Patrik Stridvall3c0211f2001-09-11 00:32:32 +0000477int main()
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000478{
479 int rop, i, res, src, dst, pat, tmp, dstUsed;
480 const BYTE *opcode;
481
482 for (rop = 0; rop < 256; rop++)
483 {
484 res = dstUsed = 0;
485 for (i = 0; i < 8; i++)
486 {
487 pat = (i >> 2) & 1;
488 src = (i >> 1) & 1;
489 dst = i & 1;
490 for (opcode = BITBLT_Opcodes[rop]; *opcode; opcode++)
491 {
492 switch(*opcode >> 4)
493 {
494 case OP_ARGS(DST,TMP):
495 tmp = do_bitop( dst, tmp, *opcode & 0xf );
496 break;
497 case OP_ARGS(DST,SRC):
498 src = do_bitop( dst, src, *opcode & 0xf );
499 break;
500 case OP_ARGS(SRC,TMP):
501 tmp = do_bitop( src, tmp, *opcode & 0xf );
502 break;
503 case OP_ARGS(SRC,DST):
504 dst = do_bitop( src, dst, *opcode & 0xf );
505 dstUsed = 1;
506 break;
507 case OP_ARGS(PAT,TMP):
508 tmp = do_bitop( pat, tmp, *opcode & 0xf );
509 break;
510 case OP_ARGS(PAT,DST):
511 dst = do_bitop( pat, dst, *opcode & 0xf );
512 dstUsed = 1;
513 break;
514 case OP_ARGS(PAT,SRC):
515 src = do_bitop( pat, src, *opcode & 0xf );
516 break;
517 case OP_ARGS(TMP,DST):
518 dst = do_bitop( tmp, dst, *opcode & 0xf );
519 dstUsed = 1;
520 break;
521 case OP_ARGS(TMP,SRC):
522 src = do_bitop( tmp, src, *opcode & 0xf );
523 break;
524 default:
525 printf( "Invalid opcode %x\n", *opcode );
526 }
527 }
528 if (!dstUsed) dst = src;
529 if (dst) res |= 1 << i;
530 }
531 if (res != rop) printf( "%02x: ERROR, res=%02x\n", rop, res );
532 }
Patrik Stridvall3c0211f2001-09-11 00:32:32 +0000533
534 return 0;
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000535}
536
537#endif /* BITBLT_TEST */
538
Alexandre Julliard401710d1993-09-04 10:09:32 +0000539
Alexandre Julliard401710d1993-09-04 10:09:32 +0000540/***********************************************************************
Alexandre Julliardfe085682000-03-18 21:56:10 +0000541 * perfect_graphics
542 *
543 * Favor correctness or speed?
544 */
Bill Medland25e44db2001-07-26 20:13:47 +0000545static int perfect_graphics(void)
Alexandre Julliardfe085682000-03-18 21:56:10 +0000546{
547 static int perfect = -1;
Dmitry Timoshkovde70d2b2001-06-19 03:32:44 +0000548 if (perfect == -1)
549 {
550 HKEY hkey;
551 char buffer[20];
552 /* default value */
553 perfect = 0;
554 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
555 {
556 DWORD type, count = sizeof(buffer);
557 if(!RegQueryValueExA(hkey, "PerfectGraphics", 0, &type, buffer, &count))
Alexandre Julliardf899ef02001-07-23 00:04:00 +0000558 {
559 char ch = buffer[0];
560 perfect = (ch == 'y' || ch == 'Y' || ch == 't' || ch == 'T' || ch == '1');
561 }
Dmitry Timoshkovde70d2b2001-06-19 03:32:44 +0000562 RegCloseKey(hkey);
563 }
564 }
Alexandre Julliardfe085682000-03-18 21:56:10 +0000565 return perfect;
566}
567
568/***********************************************************************
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000569 * BITBLT_StretchRow
570 *
571 * Stretch a row of pixels. Helper function for BITBLT_StretchImage.
Alexandre Julliardecc37121994-11-22 16:31:29 +0000572 */
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000573static void BITBLT_StretchRow( int *rowSrc, int *rowDst,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000574 INT startDst, INT widthDst,
575 INT xinc, INT xoff, WORD mode )
Alexandre Julliardecc37121994-11-22 16:31:29 +0000576{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000577 register INT xsrc = xinc * startDst + xoff;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000578 rowDst += startDst;
579 switch(mode)
Alexandre Julliardecc37121994-11-22 16:31:29 +0000580 {
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000581 case STRETCH_ANDSCANS:
582 for(; widthDst > 0; widthDst--, xsrc += xinc)
583 *rowDst++ &= rowSrc[xsrc >> 16];
584 break;
585 case STRETCH_ORSCANS:
586 for(; widthDst > 0; widthDst--, xsrc += xinc)
587 *rowDst++ |= rowSrc[xsrc >> 16];
588 break;
589 case STRETCH_DELETESCANS:
590 for(; widthDst > 0; widthDst--, xsrc += xinc)
591 *rowDst++ = rowSrc[xsrc >> 16];
592 break;
Alexandre Julliardecc37121994-11-22 16:31:29 +0000593 }
Alexandre Julliardecc37121994-11-22 16:31:29 +0000594}
595
596
597/***********************************************************************
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000598 * BITBLT_ShrinkRow
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000599 *
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000600 * Shrink a row of pixels. Helper function for BITBLT_StretchImage.
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000601 */
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000602static void BITBLT_ShrinkRow( int *rowSrc, int *rowDst,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000603 INT startSrc, INT widthSrc,
604 INT xinc, INT xoff, WORD mode )
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000605{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000606 register INT xdst = xinc * startSrc + xoff;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000607 rowSrc += startSrc;
608 switch(mode)
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000609 {
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000610 case STRETCH_ORSCANS:
611 for(; widthSrc > 0; widthSrc--, xdst += xinc)
612 rowDst[xdst >> 16] |= *rowSrc++;
613 break;
614 case STRETCH_ANDSCANS:
615 for(; widthSrc > 0; widthSrc--, xdst += xinc)
616 rowDst[xdst >> 16] &= *rowSrc++;
617 break;
618 case STRETCH_DELETESCANS:
619 for(; widthSrc > 0; widthSrc--, xdst += xinc)
620 rowDst[xdst >> 16] = *rowSrc++;
621 break;
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000622 }
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000623}
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000624
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000625
626/***********************************************************************
627 * BITBLT_GetRow
628 *
629 * Retrieve a row from an image. Helper function for BITBLT_StretchImage.
630 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000631static void BITBLT_GetRow( XImage *image, int *pdata, INT row,
632 INT start, INT width, INT depthDst,
633 int fg, int bg, BOOL swap)
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000634{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000635 register INT i;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000636
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000637 assert( (row >= 0) && (row < image->height) );
638 assert( (start >= 0) && (width <= image->width) );
639
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000640 pdata += swap ? start+width-1 : start;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000641 if (image->depth == depthDst) /* color -> color */
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000642 {
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000643 if (X11DRV_PALETTE_XPixelToPalette && (depthDst != 1))
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000644 if (swap) for (i = 0; i < width; i++)
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000645 *pdata-- = X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, i, row )];
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000646 else for (i = 0; i < width; i++)
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000647 *pdata++ = X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, i, row )];
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000648 else
649 if (swap) for (i = 0; i < width; i++)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000650 *pdata-- = XGetPixel( image, i, row );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000651 else for (i = 0; i < width; i++)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000652 *pdata++ = XGetPixel( image, i, row );
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000653 }
654 else
655 {
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000656 if (image->depth == 1) /* monochrome -> color */
657 {
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000658 if (X11DRV_PALETTE_XPixelToPalette)
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000659 {
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000660 fg = X11DRV_PALETTE_XPixelToPalette[fg];
661 bg = X11DRV_PALETTE_XPixelToPalette[bg];
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000662 }
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000663 if (swap) for (i = 0; i < width; i++)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000664 *pdata-- = XGetPixel( image, i, row ) ? bg : fg;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000665 else for (i = 0; i < width; i++)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000666 *pdata++ = XGetPixel( image, i, row ) ? bg : fg;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000667 }
668 else /* color -> monochrome */
669 {
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000670 if (swap) for (i = 0; i < width; i++)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000671 *pdata-- = (XGetPixel( image, i, row ) == bg) ? 1 : 0;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000672 else for (i = 0; i < width; i++)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000673 *pdata++ = (XGetPixel( image, i, row ) == bg) ? 1 : 0;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000674 }
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000675 }
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000676}
677
678
679/***********************************************************************
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000680 * BITBLT_StretchImage
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000681 *
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000682 * Stretch an X image.
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000683 * FIXME: does not work for full 32-bit coordinates.
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000684 */
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000685static void BITBLT_StretchImage( XImage *srcImage, XImage *dstImage,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000686 INT widthSrc, INT heightSrc,
687 INT widthDst, INT heightDst,
688 RECT *visRectSrc, RECT *visRectDst,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000689 int foreground, int background, WORD mode )
Alexandre Julliard3a5816f1994-12-27 14:11:53 +0000690{
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000691 int *rowSrc, *rowDst, *pixel;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000692 char *pdata;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000693 INT xinc, xoff, yinc, ysrc, ydst;
694 register INT x, y;
695 BOOL hstretch, vstretch, hswap, vswap;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000696
697 hswap = ((int)widthSrc * widthDst) < 0;
698 vswap = ((int)heightSrc * heightDst) < 0;
699 widthSrc = abs(widthSrc);
700 heightSrc = abs(heightSrc);
701 widthDst = abs(widthDst);
702 heightDst = abs(heightDst);
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000703
Alexandre Julliard491502b1997-11-01 19:08:16 +0000704 if (!(rowSrc = (int *)HeapAlloc( GetProcessHeap(), 0,
705 (widthSrc+widthDst)*sizeof(int) ))) return;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000706 rowDst = rowSrc + widthSrc;
707
708 /* When stretching, all modes are the same, and DELETESCANS is faster */
709 if ((widthSrc < widthDst) && (heightSrc < heightDst))
710 mode = STRETCH_DELETESCANS;
711
Alexandre Julliard18506551995-01-24 16:21:01 +0000712 if (mode != STRETCH_DELETESCANS)
713 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
714 widthDst*sizeof(int) );
715
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000716 hstretch = (widthSrc < widthDst);
717 vstretch = (heightSrc < heightDst);
718
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000719 if (hstretch)
720 {
721 xinc = ((int)widthSrc << 16) / widthDst;
722 xoff = ((widthSrc << 16) - (xinc * widthDst)) / 2;
723 }
724 else
725 {
726 xinc = ((int)widthDst << 16) / widthSrc;
727 xoff = ((widthDst << 16) - (xinc * widthSrc)) / 2;
728 }
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000729
730 if (vstretch)
731 {
732 yinc = ((int)heightSrc << 16) / heightDst;
733 ydst = visRectDst->top;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000734 if (vswap)
735 {
736 ysrc = yinc * (heightDst - ydst - 1);
737 yinc = -yinc;
738 }
739 else
740 ysrc = yinc * ydst;
741
742 for ( ; (ydst < visRectDst->bottom); ysrc += yinc, ydst++)
743 {
744 if (((ysrc >> 16) < visRectSrc->top) ||
745 ((ysrc >> 16) >= visRectSrc->bottom)) continue;
746
747 /* Retrieve a source row */
748 BITBLT_GetRow( srcImage, rowSrc, (ysrc >> 16) - visRectSrc->top,
749 hswap ? widthSrc - visRectSrc->right
750 : visRectSrc->left,
751 visRectSrc->right - visRectSrc->left,
752 dstImage->depth, foreground, background, hswap );
753
754 /* Stretch or shrink it */
755 if (hstretch)
756 BITBLT_StretchRow( rowSrc, rowDst, visRectDst->left,
757 visRectDst->right - visRectDst->left,
758 xinc, xoff, mode );
759 else BITBLT_ShrinkRow( rowSrc, rowDst,
760 hswap ? widthSrc - visRectSrc->right
761 : visRectSrc->left,
762 visRectSrc->right - visRectSrc->left,
763 xinc, xoff, mode );
764
765 /* Store the destination row */
766 pixel = rowDst + visRectDst->right - 1;
767 y = ydst - visRectDst->top;
768 for (x = visRectDst->right-visRectDst->left-1; x >= 0; x--)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000769 XPutPixel( dstImage, x, y, *pixel-- );
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000770 if (mode != STRETCH_DELETESCANS)
771 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
772 widthDst*sizeof(int) );
773
774 /* Make copies of the destination row */
775
776 pdata = dstImage->data + dstImage->bytes_per_line * y;
777 while (((ysrc + yinc) >> 16 == ysrc >> 16) &&
778 (ydst < visRectDst->bottom-1))
779 {
780 memcpy( pdata + dstImage->bytes_per_line, pdata,
781 dstImage->bytes_per_line );
782 pdata += dstImage->bytes_per_line;
783 ysrc += yinc;
784 ydst++;
785 }
786 }
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000787 }
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000788 else /* Shrinking */
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000789 {
790 yinc = ((int)heightDst << 16) / heightSrc;
791 ysrc = visRectSrc->top;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000792 ydst = ((heightDst << 16) - (yinc * heightSrc)) / 2;
793 if (vswap)
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000794 {
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000795 ydst += yinc * (heightSrc - ysrc - 1);
796 yinc = -yinc;
797 }
798 else
799 ydst += yinc * ysrc;
800
801 for( ; (ysrc < visRectSrc->bottom); ydst += yinc, ysrc++)
802 {
803 if (((ydst >> 16) < visRectDst->top) ||
804 ((ydst >> 16) >= visRectDst->bottom)) continue;
805
806 /* Retrieve a source row */
807 BITBLT_GetRow( srcImage, rowSrc, ysrc - visRectSrc->top,
808 hswap ? widthSrc - visRectSrc->right
809 : visRectSrc->left,
810 visRectSrc->right - visRectSrc->left,
811 dstImage->depth, foreground, background, hswap );
812
813 /* Stretch or shrink it */
814 if (hstretch)
815 BITBLT_StretchRow( rowSrc, rowDst, visRectDst->left,
816 visRectDst->right - visRectDst->left,
817 xinc, xoff, mode );
818 else BITBLT_ShrinkRow( rowSrc, rowDst,
819 hswap ? widthSrc - visRectSrc->right
820 : visRectSrc->left,
821 visRectSrc->right - visRectSrc->left,
822 xinc, xoff, mode );
823
824 /* Merge several source rows into the destination */
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000825 if (mode == STRETCH_DELETESCANS)
826 {
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000827 /* Simply skip the overlapping rows */
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000828 while (((ydst + yinc) >> 16 == ydst >> 16) &&
829 (ysrc < visRectSrc->bottom-1))
830 {
831 ydst += yinc;
832 ysrc++;
833 }
834 }
835 else if (((ydst + yinc) >> 16 == ydst >> 16) &&
836 (ysrc < visRectSrc->bottom-1))
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000837 continue; /* Restart loop for next overlapping row */
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000838
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000839 /* Store the destination row */
840 pixel = rowDst + visRectDst->right - 1;
841 y = (ydst >> 16) - visRectDst->top;
842 for (x = visRectDst->right-visRectDst->left-1; x >= 0; x--)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000843 XPutPixel( dstImage, x, y, *pixel-- );
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000844 if (mode != STRETCH_DELETESCANS)
845 memset( rowDst, (mode == STRETCH_ANDSCANS) ? 0xff : 0x00,
846 widthDst*sizeof(int) );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000847 }
848 }
Alexandre Julliard491502b1997-11-01 19:08:16 +0000849 HeapFree( GetProcessHeap(), 0, rowSrc );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000850}
851
852
853/***********************************************************************
854 * BITBLT_GetSrcAreaStretch
855 *
856 * Retrieve an area from the source DC, stretching and mapping all the
857 * pixels to Windows colors.
858 */
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000859static int BITBLT_GetSrcAreaStretch( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000860 Pixmap pixmap, GC gc,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000861 INT xSrc, INT ySrc,
862 INT widthSrc, INT heightSrc,
863 INT xDst, INT yDst,
864 INT widthDst, INT heightDst,
865 RECT *visRectSrc, RECT *visRectDst )
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000866{
867 XImage *imageSrc, *imageDst;
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000868 DC *dcDst = physDevDst->dc;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000869
Alexandre Julliarda3960291999-02-26 11:11:13 +0000870 RECT rectSrc = *visRectSrc;
871 RECT rectDst = *visRectDst;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000872
873 if (widthSrc < 0) xSrc += widthSrc;
874 if (widthDst < 0) xDst += widthDst;
875 if (heightSrc < 0) ySrc += heightSrc;
876 if (heightDst < 0) yDst += heightDst;
Alexandre Julliard62f824f2000-03-18 22:12:33 +0000877 rectSrc.left -= xSrc;
878 rectSrc.right -= xSrc;
879 rectSrc.top -= ySrc;
880 rectSrc.bottom -= ySrc;
881 rectDst.left -= xDst;
882 rectDst.right -= xDst;
883 rectDst.top -= yDst;
884 rectDst.bottom -= yDst;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000885
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000886 /* FIXME: avoid BadMatch errors */
Alexandre Julliardc5597352001-05-11 00:17:47 +0000887 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000888 visRectSrc->left, visRectSrc->top,
889 visRectSrc->right - visRectSrc->left,
890 visRectSrc->bottom - visRectSrc->top,
891 AllPlanes, ZPixmap );
Alexandre Julliardc5597352001-05-11 00:17:47 +0000892 imageDst = X11DRV_DIB_CreateXImage( rectDst.right - rectDst.left,
893 rectDst.bottom - rectDst.top, dcDst->bitsPerPixel );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000894 BITBLT_StretchImage( imageSrc, imageDst, widthSrc, heightSrc,
895 widthDst, heightDst, &rectSrc, &rectDst,
Alexandre Julliard2239abb2000-11-05 02:05:07 +0000896 physDevDst->textPixel, dcDst->bitsPerPixel != 1 ?
Huw D M Davies9c68faa1998-11-25 12:36:03 +0000897 physDevDst->backgroundPixel :
898 physDevSrc->backgroundPixel,
Alexandre Julliard2239abb2000-11-05 02:05:07 +0000899 dcDst->stretchBltMode );
Alexandre Julliardc5597352001-05-11 00:17:47 +0000900 XPutImage( gdi_display, pixmap, gc, imageDst, 0, 0, 0, 0,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000901 rectDst.right - rectDst.left, rectDst.bottom - rectDst.top );
Alexandre Julliard03468f71998-02-15 19:40:49 +0000902 XDestroyImage( imageSrc );
903 XDestroyImage( imageDst );
Alexandre Julliard6d027e12001-06-11 20:24:57 +0000904 return 0; /* no exposure events generated */
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000905}
906
907
908/***********************************************************************
909 * BITBLT_GetSrcArea
910 *
911 * Retrieve an area from the source DC, mapping all the
912 * pixels to Windows colors.
913 */
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000914static int BITBLT_GetSrcArea( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
915 Pixmap pixmap, GC gc, INT xSrc, INT ySrc, RECT *visRectSrc )
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000916{
917 XImage *imageSrc, *imageDst;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000918 register INT x, y;
Alexandre Julliard6d027e12001-06-11 20:24:57 +0000919 int exposures = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000920 INT width = visRectSrc->right - visRectSrc->left;
921 INT height = visRectSrc->bottom - visRectSrc->top;
Alexandre Julliarde21c15e2002-03-28 22:22:05 +0000922 DC *dcSrc = physDevSrc->dc;
923 DC *dcDst = physDevDst->dc;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000924
Alexandre Julliard2239abb2000-11-05 02:05:07 +0000925 if (dcSrc->bitsPerPixel == dcDst->bitsPerPixel)
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000926 {
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000927 if (!X11DRV_PALETTE_XPixelToPalette ||
Alexandre Julliard2239abb2000-11-05 02:05:07 +0000928 (dcDst->bitsPerPixel == 1)) /* monochrome -> monochrome */
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000929 {
Alexandre Julliard2239abb2000-11-05 02:05:07 +0000930 if (dcDst->bitsPerPixel == 1)
Alexandre Julliard960dc902000-06-08 19:23:12 +0000931 {
932 /* MSDN says if StretchBlt must convert a bitmap from monochrome
933 to color or vice versa, the forground and background color of
934 the device context are used. In fact, it also applies to the
935 case when it is converted from mono to mono. */
Alexandre Julliardc5597352001-05-11 00:17:47 +0000936 XSetBackground( gdi_display, gc, physDevDst->textPixel );
937 XSetForeground( gdi_display, gc, physDevDst->backgroundPixel );
938 XCopyPlane( gdi_display, physDevSrc->drawable, pixmap, gc,
Alexandre Julliard960dc902000-06-08 19:23:12 +0000939 visRectSrc->left, visRectSrc->top,
940 width, height, 0, 0, 1);
941 }
942 else
Alexandre Julliardc5597352001-05-11 00:17:47 +0000943 XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc,
944 visRectSrc->left, visRectSrc->top, width, height, 0, 0);
Alexandre Julliard6d027e12001-06-11 20:24:57 +0000945 exposures++;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000946 }
947 else /* color -> color */
948 {
Alexandre Julliard2239abb2000-11-05 02:05:07 +0000949 if (dcSrc->flags & DC_MEMORY)
Alexandre Julliardc5597352001-05-11 00:17:47 +0000950 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000951 visRectSrc->left, visRectSrc->top,
952 width, height, AllPlanes, ZPixmap );
953 else
954 {
955 /* Make sure we don't get a BadMatch error */
Alexandre Julliardc5597352001-05-11 00:17:47 +0000956 XCopyArea( gdi_display, physDevSrc->drawable, pixmap, gc,
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000957 visRectSrc->left, visRectSrc->top,
958 width, height, 0, 0);
Alexandre Julliard6d027e12001-06-11 20:24:57 +0000959 exposures++;
Alexandre Julliardc5597352001-05-11 00:17:47 +0000960 imageSrc = XGetImage( gdi_display, pixmap, 0, 0, width, height,
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000961 AllPlanes, ZPixmap );
962 }
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000963 for (y = 0; y < height; y++)
964 for (x = 0; x < width; x++)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000965 XPutPixel(imageSrc, x, y,
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000966 X11DRV_PALETTE_XPixelToPalette[XGetPixel(imageSrc, x, y)]);
Alexandre Julliardc5597352001-05-11 00:17:47 +0000967 XPutImage( gdi_display, pixmap, gc, imageSrc,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000968 0, 0, 0, 0, width, height );
Alexandre Julliard03468f71998-02-15 19:40:49 +0000969 XDestroyImage( imageSrc );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000970 }
971 }
972 else
973 {
Alexandre Julliard2239abb2000-11-05 02:05:07 +0000974 if (dcSrc->bitsPerPixel == 1) /* monochrome -> color */
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000975 {
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000976 if (X11DRV_PALETTE_XPixelToPalette)
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000977 {
Alexandre Julliardc5597352001-05-11 00:17:47 +0000978 XSetBackground( gdi_display, gc,
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000979 X11DRV_PALETTE_XPixelToPalette[physDevDst->textPixel] );
Alexandre Julliardc5597352001-05-11 00:17:47 +0000980 XSetForeground( gdi_display, gc,
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +0000981 X11DRV_PALETTE_XPixelToPalette[physDevDst->backgroundPixel]);
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000982 }
983 else
984 {
Alexandre Julliardc5597352001-05-11 00:17:47 +0000985 XSetBackground( gdi_display, gc, physDevDst->textPixel );
986 XSetForeground( gdi_display, gc, physDevDst->backgroundPixel );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000987 }
Alexandre Julliardc5597352001-05-11 00:17:47 +0000988 XCopyPlane( gdi_display, physDevSrc->drawable, pixmap, gc,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000989 visRectSrc->left, visRectSrc->top,
990 width, height, 0, 0, 1 );
Alexandre Julliard6d027e12001-06-11 20:24:57 +0000991 exposures++;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000992 }
993 else /* color -> monochrome */
994 {
Alexandre Julliard1e37a181996-08-18 16:21:52 +0000995 /* FIXME: avoid BadMatch error */
Alexandre Julliardc5597352001-05-11 00:17:47 +0000996 imageSrc = XGetImage( gdi_display, physDevSrc->drawable,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +0000997 visRectSrc->left, visRectSrc->top,
998 width, height, AllPlanes, ZPixmap );
Alexandre Julliardc5597352001-05-11 00:17:47 +0000999 imageDst = X11DRV_DIB_CreateXImage( width, height, dcDst->bitsPerPixel );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001000 for (y = 0; y < height; y++)
1001 for (x = 0; x < width; x++)
Alexandre Julliard03468f71998-02-15 19:40:49 +00001002 XPutPixel(imageDst, x, y, (XGetPixel(imageSrc,x,y) ==
Huw D M Davies9c68faa1998-11-25 12:36:03 +00001003 physDevSrc->backgroundPixel) );
Alexandre Julliardc5597352001-05-11 00:17:47 +00001004 XPutImage( gdi_display, pixmap, gc, imageDst,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001005 0, 0, 0, 0, width, height );
Alexandre Julliard03468f71998-02-15 19:40:49 +00001006 XDestroyImage( imageSrc );
1007 XDestroyImage( imageDst );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001008 }
1009 }
Alexandre Julliard6d027e12001-06-11 20:24:57 +00001010 return exposures;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001011}
1012
1013
1014/***********************************************************************
1015 * BITBLT_GetDstArea
1016 *
1017 * Retrieve an area from the destination DC, mapping all the
1018 * pixels to Windows colors.
1019 */
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001020static int BITBLT_GetDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, GC gc, RECT *visRectDst)
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001021{
Alexandre Julliard6d027e12001-06-11 20:24:57 +00001022 int exposures = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001023 INT width = visRectDst->right - visRectDst->left;
1024 INT height = visRectDst->bottom - visRectDst->top;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001025
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001026 if (!X11DRV_PALETTE_XPixelToPalette || (physDev->dc->bitsPerPixel == 1) ||
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001027 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001028 {
Alexandre Julliardc5597352001-05-11 00:17:47 +00001029 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001030 visRectDst->left, visRectDst->top, width, height, 0, 0 );
Alexandre Julliard6d027e12001-06-11 20:24:57 +00001031 exposures++;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001032 }
1033 else
1034 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001035 register INT x, y;
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001036 XImage *image;
1037
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001038 if (physDev->dc->flags & DC_MEMORY)
Alexandre Julliardc5597352001-05-11 00:17:47 +00001039 image = XGetImage( gdi_display, physDev->drawable,
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001040 visRectDst->left, visRectDst->top,
1041 width, height, AllPlanes, ZPixmap );
1042 else
1043 {
1044 /* Make sure we don't get a BadMatch error */
Alexandre Julliardc5597352001-05-11 00:17:47 +00001045 XCopyArea( gdi_display, physDev->drawable, pixmap, gc,
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001046 visRectDst->left, visRectDst->top, width, height, 0, 0);
Alexandre Julliard6d027e12001-06-11 20:24:57 +00001047 exposures++;
Alexandre Julliardc5597352001-05-11 00:17:47 +00001048 image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
Alexandre Julliard1e37a181996-08-18 16:21:52 +00001049 AllPlanes, ZPixmap );
1050 }
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001051 for (y = 0; y < height; y++)
1052 for (x = 0; x < width; x++)
Alexandre Julliard03468f71998-02-15 19:40:49 +00001053 XPutPixel( image, x, y,
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001054 X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]);
Alexandre Julliardc5597352001-05-11 00:17:47 +00001055 XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height );
Alexandre Julliard03468f71998-02-15 19:40:49 +00001056 XDestroyImage( image );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001057 }
Alexandre Julliard6d027e12001-06-11 20:24:57 +00001058 return exposures;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001059}
1060
1061
1062/***********************************************************************
1063 * BITBLT_PutDstArea
1064 *
1065 * Put an area back into the destination DC, mapping the pixel
1066 * colors to X pixels.
1067 */
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001068static int BITBLT_PutDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, RECT *visRectDst)
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001069{
Alexandre Julliard6d027e12001-06-11 20:24:57 +00001070 int exposures = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001071 INT width = visRectDst->right - visRectDst->left;
1072 INT height = visRectDst->bottom - visRectDst->top;
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001073
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001074 /* !X11DRV_PALETTE_PaletteToXPixel is _NOT_ enough */
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001075
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001076 if (!X11DRV_PALETTE_PaletteToXPixel || (physDev->dc->bitsPerPixel == 1) ||
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001077 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) )
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001078 {
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001079 XCopyArea( gdi_display, pixmap, physDev->drawable, physDev->gc, 0, 0,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001080 width, height, visRectDst->left, visRectDst->top );
Alexandre Julliard6d027e12001-06-11 20:24:57 +00001081 exposures++;
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001082 }
1083 else
1084 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001085 register INT x, y;
Alexandre Julliardc5597352001-05-11 00:17:47 +00001086 XImage *image = XGetImage( gdi_display, pixmap, 0, 0, width, height,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001087 AllPlanes, ZPixmap );
1088 for (y = 0; y < height; y++)
1089 for (x = 0; x < width; x++)
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001090 {
Alexandre Julliard03468f71998-02-15 19:40:49 +00001091 XPutPixel( image, x, y,
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001092 X11DRV_PALETTE_PaletteToXPixel[XGetPixel( image, x, y )]);
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001093 }
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001094 XPutImage( gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001095 visRectDst->left, visRectDst->top, width, height );
Alexandre Julliard03468f71998-02-15 19:40:49 +00001096 XDestroyImage( image );
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001097 }
Alexandre Julliard6d027e12001-06-11 20:24:57 +00001098 return exposures;
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001099}
1100
1101
1102/***********************************************************************
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001103 * BITBLT_GetVisRectangles
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001104 *
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001105 * Get the source and destination visible rectangles for StretchBlt().
1106 * Return FALSE if one of the rectangles is empty.
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001107 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001108static BOOL BITBLT_GetVisRectangles( DC *dcDst, INT xDst, INT yDst,
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001109 INT widthDst, INT heightDst,
1110 DC *dcSrc, INT xSrc, INT ySrc,
1111 INT widthSrc, INT heightSrc,
1112 RECT *visRectSrc, RECT *visRectDst )
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001113{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001114 RECT rect, clipRect;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001115
1116 /* Get the destination visible rectangle */
1117
Alexandre Julliard62f824f2000-03-18 22:12:33 +00001118 rect.left = xDst;
1119 rect.top = yDst;
1120 rect.right = xDst + widthDst;
1121 rect.bottom = yDst + heightDst;
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001122 if (widthDst < 0) SWAP_INT32( &rect.left, &rect.right );
1123 if (heightDst < 0) SWAP_INT32( &rect.top, &rect.bottom );
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001124 GetRgnBox( dcDst->hGCClipRgn, &clipRect );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001125 if (!IntersectRect( visRectDst, &rect, &clipRect )) return FALSE;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001126
1127 /* Get the source visible rectangle */
1128
1129 if (!dcSrc) return TRUE;
Alexandre Julliard62f824f2000-03-18 22:12:33 +00001130 rect.left = xSrc;
1131 rect.top = ySrc;
1132 rect.right = xSrc + widthSrc;
1133 rect.bottom = ySrc + heightSrc;
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001134 if (widthSrc < 0) SWAP_INT32( &rect.left, &rect.right );
1135 if (heightSrc < 0) SWAP_INT32( &rect.top, &rect.bottom );
Ulrich Weigand27bb3621998-10-14 18:06:44 +00001136 /* Apparently the clipping and visible regions are only for output,
1137 so just check against totalExtent here to avoid BadMatch errors */
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001138 if (!IntersectRect( visRectSrc, &rect, &dcSrc->totalExtent ))
Ulrich Weigand27bb3621998-10-14 18:06:44 +00001139 return FALSE;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001140
1141 /* Intersect the rectangles */
1142
1143 if ((widthSrc == widthDst) && (heightSrc == heightDst)) /* no stretching */
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001144 {
Alexandre Julliard62f824f2000-03-18 22:12:33 +00001145 visRectSrc->left += xDst - xSrc;
1146 visRectSrc->right += xDst - xSrc;
1147 visRectSrc->top += yDst - ySrc;
1148 visRectSrc->bottom += yDst - ySrc;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001149 if (!IntersectRect( &rect, visRectSrc, visRectDst )) return FALSE;
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001150 *visRectSrc = *visRectDst = rect;
Alexandre Julliard62f824f2000-03-18 22:12:33 +00001151 visRectSrc->left += xSrc - xDst;
1152 visRectSrc->right += xSrc - xDst;
1153 visRectSrc->top += ySrc - yDst;
1154 visRectSrc->bottom += ySrc - yDst;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001155 }
1156 else /* stretching */
1157 {
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001158 /* Map source rectangle into destination coordinates */
1159 rect.left = xDst + (visRectSrc->left - xSrc)*widthDst/widthSrc;
1160 rect.top = yDst + (visRectSrc->top - ySrc)*heightDst/heightSrc;
1161 rect.right = xDst + ((visRectSrc->right - xSrc)*widthDst)/widthSrc;
1162 rect.bottom = yDst + ((visRectSrc->bottom - ySrc)*heightDst)/heightSrc;
1163 if (rect.left > rect.right) SWAP_INT32( &rect.left, &rect.right );
1164 if (rect.top > rect.bottom) SWAP_INT32( &rect.top, &rect.bottom );
Alexandre Julliard62f824f2000-03-18 22:12:33 +00001165
1166 /* Avoid rounding errors */
1167 rect.left--;
1168 rect.top--;
1169 rect.right++;
1170 rect.bottom++;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001171 if (!IntersectRect( visRectDst, &rect, visRectDst )) return FALSE;
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001172
1173 /* Map destination rectangle back to source coordinates */
1174 rect = *visRectDst;
1175 rect.left = xSrc + (visRectDst->left - xDst)*widthSrc/widthDst;
1176 rect.top = ySrc + (visRectDst->top - yDst)*heightSrc/heightDst;
1177 rect.right = xSrc + ((visRectDst->right - xDst)*widthSrc)/widthDst;
1178 rect.bottom = ySrc + ((visRectDst->bottom - yDst)*heightSrc)/heightDst;
1179 if (rect.left > rect.right) SWAP_INT32( &rect.left, &rect.right );
1180 if (rect.top > rect.bottom) SWAP_INT32( &rect.top, &rect.bottom );
Alexandre Julliard62f824f2000-03-18 22:12:33 +00001181
1182 /* Avoid rounding errors */
1183 rect.left--;
1184 rect.top--;
1185 rect.right++;
1186 rect.bottom++;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001187 if (!IntersectRect( visRectSrc, &rect, visRectSrc )) return FALSE;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001188 }
1189 return TRUE;
1190}
1191
1192
1193/***********************************************************************
1194 * BITBLT_InternalStretchBlt
1195 *
1196 * Implementation of PatBlt(), BitBlt() and StretchBlt().
1197 */
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001198static BOOL BITBLT_InternalStretchBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst,
1199 INT widthDst, INT heightDst,
1200 X11DRV_PDEVICE *physDevSrc, INT xSrc, INT ySrc,
1201 INT widthSrc, INT heightSrc,
1202 DWORD rop )
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001203{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001204 BOOL usePat, useSrc, useDst, destUsed, fStretch, fNullBrush;
1205 RECT visRectDst, visRectSrc;
1206 INT width, height;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001207 const BYTE *opcode;
1208 Pixmap pixmaps[3] = { 0, 0, 0 }; /* pixmaps for DST, SRC, TMP */
1209 GC tmpGC = 0;
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001210 DC *dcSrc = physDevSrc ? physDevSrc->dc : NULL;
1211 DC *dcDst = physDevDst->dc;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001212
Randy Weems0bc73c71999-03-25 15:49:11 +00001213 /* compensate for off-by-one shifting for negative widths and heights */
1214 if (widthDst < 0)
1215 ++xDst;
1216 if (heightDst < 0)
1217 ++yDst;
1218 if (widthSrc < 0)
1219 ++xSrc;
1220 if (heightSrc < 0)
1221 ++ySrc;
1222
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001223 usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
1224 useSrc = (((rop >> 2) & 0x330000) != (rop & 0x330000));
1225 useDst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
1226 if (!dcSrc && useSrc) return FALSE;
1227
1228 /* Map the coordinates to device coords */
1229
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001230 xDst = dcDst->DCOrgX + XLPTODP( dcDst, xDst );
1231 yDst = dcDst->DCOrgY + YLPTODP( dcDst, yDst );
Pascal Lessarddff30ac1999-08-15 14:18:59 +00001232
1233 /* Here we have to round to integers, not truncate */
1234 widthDst = MulDiv(widthDst, dcDst->vportExtX, dcDst->wndExtX);
1235 heightDst = MulDiv(heightDst, dcDst->vportExtY, dcDst->wndExtY);
Alexandre Julliardded30381995-07-06 17:18:27 +00001236
Alexandre Julliard61fece01999-06-26 19:09:08 +00001237 TRACE(" vportdst=%d,%d-%d,%d wnddst=%d,%d-%d,%d\n",
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001238 dcDst->vportOrgX, dcDst->vportOrgY,
1239 dcDst->vportExtX, dcDst->vportExtY,
1240 dcDst->wndOrgX, dcDst->wndOrgY,
1241 dcDst->wndExtX, dcDst->wndExtY );
Alexandre Julliard61fece01999-06-26 19:09:08 +00001242 TRACE(" rectdst=%d,%d-%d,%d orgdst=%d,%d\n",
Alexandre Julliardded30381995-07-06 17:18:27 +00001243 xDst, yDst, widthDst, heightDst,
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001244 dcDst->DCOrgX, dcDst->DCOrgY );
Alexandre Julliardded30381995-07-06 17:18:27 +00001245
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001246 if (useSrc)
1247 {
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001248 xSrc = dcSrc->DCOrgX + XLPTODP( dcSrc, xSrc );
1249 ySrc = dcSrc->DCOrgY + YLPTODP( dcSrc, ySrc );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001250 widthSrc = widthSrc * dcSrc->vportExtX / dcSrc->wndExtX;
1251 heightSrc = heightSrc * dcSrc->vportExtY / dcSrc->wndExtY;
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001252 fStretch = (widthSrc != widthDst) || (heightSrc != heightDst);
Alexandre Julliard61fece01999-06-26 19:09:08 +00001253 TRACE(" vportsrc=%d,%d-%d,%d wndsrc=%d,%d-%d,%d\n",
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001254 dcSrc->vportOrgX, dcSrc->vportOrgY,
1255 dcSrc->vportExtX, dcSrc->vportExtY,
1256 dcSrc->wndOrgX, dcSrc->wndOrgY,
1257 dcSrc->wndExtX, dcSrc->wndExtY );
Alexandre Julliard61fece01999-06-26 19:09:08 +00001258 TRACE(" rectsrc=%d,%d-%d,%d orgsrc=%d,%d\n",
Alexandre Julliardded30381995-07-06 17:18:27 +00001259 xSrc, ySrc, widthSrc, heightSrc,
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001260 dcSrc->DCOrgX, dcSrc->DCOrgY );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001261 if (!BITBLT_GetVisRectangles( dcDst, xDst, yDst, widthDst, heightDst,
1262 dcSrc, xSrc, ySrc, widthSrc, heightSrc,
1263 &visRectSrc, &visRectDst ))
1264 return TRUE;
Alexandre Julliard61fece01999-06-26 19:09:08 +00001265 TRACE(" vissrc=%d,%d-%d,%d visdst=%d,%d-%d,%d\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001266 visRectSrc.left, visRectSrc.top,
1267 visRectSrc.right, visRectSrc.bottom,
1268 visRectDst.left, visRectDst.top,
1269 visRectDst.right, visRectDst.bottom );
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001270 }
1271 else
1272 {
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001273 fStretch = FALSE;
1274 if (!BITBLT_GetVisRectangles( dcDst, xDst, yDst, widthDst, heightDst,
1275 NULL, 0, 0, 0, 0, NULL, &visRectDst ))
1276 return TRUE;
Alexandre Julliard61fece01999-06-26 19:09:08 +00001277 TRACE(" vissrc=none visdst=%d,%d-%d,%d\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001278 visRectDst.left, visRectDst.top,
1279 visRectDst.right, visRectDst.bottom );
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001280 }
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001281
1282 width = visRectDst.right - visRectDst.left;
1283 height = visRectDst.bottom - visRectDst.top;
1284
1285 if (!fStretch) switch(rop) /* A few optimisations */
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001286 {
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001287 case BLACKNESS: /* 0x00 */
Alexandre Julliard704d0352001-07-12 02:49:31 +00001288 wine_tsx11_lock();
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001289 if ((dcDst->bitsPerPixel == 1) || !X11DRV_PALETTE_PaletteToXPixel)
Alexandre Julliardc5597352001-05-11 00:17:47 +00001290 XSetFunction( gdi_display, physDevDst->gc, GXclear );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001291 else
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001292 {
Alexandre Julliardc5597352001-05-11 00:17:47 +00001293 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1294 XSetForeground( gdi_display, physDevDst->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
1295 XSetFillStyle( gdi_display, physDevDst->gc, FillSolid );
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001296 }
Alexandre Julliardc5597352001-05-11 00:17:47 +00001297 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001298 visRectDst.left, visRectDst.top, width, height );
Alexandre Julliard704d0352001-07-12 02:49:31 +00001299 wine_tsx11_unlock();
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001300 return TRUE;
1301
Alexandre Julliard18f92e71996-07-17 20:02:21 +00001302 case DSTINVERT: /* 0x55 */
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001303 if ((dcDst->bitsPerPixel == 1) || !X11DRV_PALETTE_PaletteToXPixel ||
Alexandre Julliardfe085682000-03-18 21:56:10 +00001304 !perfect_graphics())
Alexandre Julliard18f92e71996-07-17 20:02:21 +00001305 {
Alexandre Julliard704d0352001-07-12 02:49:31 +00001306 wine_tsx11_lock();
Alexandre Julliardc5597352001-05-11 00:17:47 +00001307 XSetFunction( gdi_display, physDevDst->gc, GXinvert );
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001308
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001309 if( X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL) )
Alexandre Julliardc5597352001-05-11 00:17:47 +00001310 XSetFunction( gdi_display, physDevDst->gc, GXinvert);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001311 else
1312 {
1313 /* Xor is much better when we do not have full colormap. */
1314 /* Using white^black ensures that we invert at least black */
1315 /* and white. */
Alexandre Julliardc5597352001-05-11 00:17:47 +00001316 Pixel xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
1317 BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
1318 XSetFunction( gdi_display, physDevDst->gc, GXxor );
1319 XSetForeground( gdi_display, physDevDst->gc, xor_pix);
1320 XSetFillStyle( gdi_display, physDevDst->gc, FillSolid );
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001321 }
Alexandre Julliardc5597352001-05-11 00:17:47 +00001322 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
Alexandre Julliard18f92e71996-07-17 20:02:21 +00001323 visRectDst.left, visRectDst.top, width, height );
Alexandre Julliard704d0352001-07-12 02:49:31 +00001324 wine_tsx11_unlock();
Alexandre Julliard18f92e71996-07-17 20:02:21 +00001325 return TRUE;
1326 }
1327 break;
1328
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001329 case PATINVERT: /* 0x5a */
Alexandre Julliardfe085682000-03-18 21:56:10 +00001330 if (perfect_graphics()) break;
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001331 if (X11DRV_SetupGCForBrush( physDevDst ))
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001332 {
Alexandre Julliard704d0352001-07-12 02:49:31 +00001333 wine_tsx11_lock();
Alexandre Julliardc5597352001-05-11 00:17:47 +00001334 XSetFunction( gdi_display, physDevDst->gc, GXxor );
1335 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001336 visRectDst.left, visRectDst.top, width, height );
Alexandre Julliard704d0352001-07-12 02:49:31 +00001337 wine_tsx11_unlock();
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001338 }
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001339 return TRUE;
Alexandre Julliard18f92e71996-07-17 20:02:21 +00001340
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001341 case 0xa50065:
Alexandre Julliardfe085682000-03-18 21:56:10 +00001342 if (perfect_graphics()) break;
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001343 if (X11DRV_SetupGCForBrush( physDevDst ))
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001344 {
Alexandre Julliard704d0352001-07-12 02:49:31 +00001345 wine_tsx11_lock();
Alexandre Julliardc5597352001-05-11 00:17:47 +00001346 XSetFunction( gdi_display, physDevDst->gc, GXequiv );
1347 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001348 visRectDst.left, visRectDst.top, width, height );
Alexandre Julliard704d0352001-07-12 02:49:31 +00001349 wine_tsx11_unlock();
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001350 }
1351 return TRUE;
1352
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001353 case SRCCOPY: /* 0xcc */
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001354 if (dcSrc->bitsPerPixel == dcDst->bitsPerPixel)
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001355 {
Alexandre Julliard704d0352001-07-12 02:49:31 +00001356 wine_tsx11_lock();
Alexandre Julliardc5597352001-05-11 00:17:47 +00001357 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1358 XCopyArea( gdi_display, physDevSrc->drawable,
Huw D M Davies9c68faa1998-11-25 12:36:03 +00001359 physDevDst->drawable, physDevDst->gc,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001360 visRectSrc.left, visRectSrc.top,
1361 width, height, visRectDst.left, visRectDst.top );
Alexandre Julliard6d027e12001-06-11 20:24:57 +00001362 physDevDst->exposures++;
Alexandre Julliard704d0352001-07-12 02:49:31 +00001363 wine_tsx11_unlock();
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001364 return TRUE;
1365 }
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001366 if (dcSrc->bitsPerPixel == 1)
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001367 {
Alexandre Julliard704d0352001-07-12 02:49:31 +00001368 wine_tsx11_lock();
Alexandre Julliardc5597352001-05-11 00:17:47 +00001369 XSetBackground( gdi_display, physDevDst->gc, physDevDst->textPixel );
1370 XSetForeground( gdi_display, physDevDst->gc, physDevDst->backgroundPixel );
1371 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
Alexandre Julliardc5597352001-05-11 00:17:47 +00001372 XCopyPlane( gdi_display, physDevSrc->drawable,
Huw D M Davies9c68faa1998-11-25 12:36:03 +00001373 physDevDst->drawable, physDevDst->gc,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001374 visRectSrc.left, visRectSrc.top,
1375 width, height, visRectDst.left, visRectDst.top, 1 );
Alexandre Julliard6d027e12001-06-11 20:24:57 +00001376 physDevDst->exposures++;
Alexandre Julliard704d0352001-07-12 02:49:31 +00001377 wine_tsx11_unlock();
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001378 return TRUE;
1379 }
1380 break;
1381
1382 case PATCOPY: /* 0xf0 */
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001383 if (!X11DRV_SetupGCForBrush( physDevDst )) return TRUE;
Alexandre Julliard704d0352001-07-12 02:49:31 +00001384 wine_tsx11_lock();
Alexandre Julliardc5597352001-05-11 00:17:47 +00001385 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1386 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001387 visRectDst.left, visRectDst.top, width, height );
Alexandre Julliard704d0352001-07-12 02:49:31 +00001388 wine_tsx11_unlock();
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001389 return TRUE;
1390
1391 case WHITENESS: /* 0xff */
Alexandre Julliard704d0352001-07-12 02:49:31 +00001392 wine_tsx11_lock();
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001393 if ((dcDst->bitsPerPixel == 1) || !X11DRV_PALETTE_PaletteToXPixel)
Alexandre Julliardc5597352001-05-11 00:17:47 +00001394 XSetFunction( gdi_display, physDevDst->gc, GXset );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001395 else
1396 {
Alexandre Julliardc5597352001-05-11 00:17:47 +00001397 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
1398 XSetForeground( gdi_display, physDevDst->gc,
1399 WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
1400 XSetFillStyle( gdi_display, physDevDst->gc, FillSolid );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001401 }
Alexandre Julliardc5597352001-05-11 00:17:47 +00001402 XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001403 visRectDst.left, visRectDst.top, width, height );
Alexandre Julliard704d0352001-07-12 02:49:31 +00001404 wine_tsx11_unlock();
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001405 return TRUE;
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001406 }
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001407
Alexandre Julliard704d0352001-07-12 02:49:31 +00001408 wine_tsx11_lock();
1409
Alexandre Julliardc5597352001-05-11 00:17:47 +00001410 tmpGC = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001411 XSetSubwindowMode( gdi_display, tmpGC, IncludeInferiors );
Alexandre Julliardc5597352001-05-11 00:17:47 +00001412 XSetGraphicsExposures( gdi_display, tmpGC, False );
1413 pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height,
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001414 dcDst->bitsPerPixel );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001415 if (useSrc)
1416 {
Alexandre Julliardc5597352001-05-11 00:17:47 +00001417 pixmaps[SRC] = XCreatePixmap( gdi_display, root_window, width, height,
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001418 dcDst->bitsPerPixel );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001419 if (fStretch)
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001420 BITBLT_GetSrcAreaStretch( physDevSrc, physDevDst, pixmaps[SRC], tmpGC,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001421 xSrc, ySrc, widthSrc, heightSrc,
1422 xDst, yDst, widthDst, heightDst,
1423 &visRectSrc, &visRectDst );
1424 else
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001425 BITBLT_GetSrcArea( physDevSrc, physDevDst, pixmaps[SRC], tmpGC,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001426 xSrc, ySrc, &visRectSrc );
1427 }
Alexandre Julliard704d0352001-07-12 02:49:31 +00001428
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001429 if (useDst) BITBLT_GetDstArea( physDevDst, pixmaps[DST], tmpGC, &visRectDst );
1430 if (usePat) fNullBrush = !X11DRV_SetupGCForPatBlt( physDevDst, tmpGC, TRUE );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001431 else fNullBrush = FALSE;
1432 destUsed = FALSE;
1433
1434 for (opcode = BITBLT_Opcodes[(rop >> 16) & 0xff]; *opcode; opcode++)
1435 {
1436 if (OP_DST(*opcode) == DST) destUsed = TRUE;
Alexandre Julliardc5597352001-05-11 00:17:47 +00001437 XSetFunction( gdi_display, tmpGC, OP_ROP(*opcode) );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001438 switch(OP_SRCDST(*opcode))
1439 {
1440 case OP_ARGS(DST,TMP):
1441 case OP_ARGS(SRC,TMP):
1442 if (!pixmaps[TMP])
Alexandre Julliardc5597352001-05-11 00:17:47 +00001443 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001444 width, height,
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001445 dcDst->bitsPerPixel );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001446 /* fall through */
1447 case OP_ARGS(DST,SRC):
1448 case OP_ARGS(SRC,DST):
1449 case OP_ARGS(TMP,SRC):
1450 case OP_ARGS(TMP,DST):
Alexandre Julliardc5597352001-05-11 00:17:47 +00001451 XCopyArea( gdi_display, pixmaps[OP_SRC(*opcode)],
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001452 pixmaps[OP_DST(*opcode)], tmpGC,
1453 0, 0, width, height, 0, 0 );
1454 break;
1455
1456 case OP_ARGS(PAT,TMP):
1457 if (!pixmaps[TMP] && !fNullBrush)
Alexandre Julliardc5597352001-05-11 00:17:47 +00001458 pixmaps[TMP] = XCreatePixmap( gdi_display, root_window,
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001459 width, height,
Alexandre Julliard2239abb2000-11-05 02:05:07 +00001460 dcDst->bitsPerPixel );
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001461 /* fall through */
1462 case OP_ARGS(PAT,DST):
1463 case OP_ARGS(PAT,SRC):
1464 if (!fNullBrush)
Alexandre Julliardc5597352001-05-11 00:17:47 +00001465 XFillRectangle( gdi_display, pixmaps[OP_DST(*opcode)],
Alexandre Julliard7cbe6571995-01-09 18:21:16 +00001466 tmpGC, 0, 0, width, height );
1467 break;
1468 }
1469 }
Alexandre Julliardc5597352001-05-11 00:17:47 +00001470 XSetFunction( gdi_display, physDevDst->gc, GXcopy );
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001471 physDevDst->exposures += BITBLT_PutDstArea( physDevDst, pixmaps[destUsed ? DST : SRC],
1472 &visRectDst );
Alexandre Julliardc5597352001-05-11 00:17:47 +00001473 XFreePixmap( gdi_display, pixmaps[DST] );
1474 if (pixmaps[SRC]) XFreePixmap( gdi_display, pixmaps[SRC] );
1475 if (pixmaps[TMP]) XFreePixmap( gdi_display, pixmaps[TMP] );
1476 XFreeGC( gdi_display, tmpGC );
Alexandre Julliard704d0352001-07-12 02:49:31 +00001477 wine_tsx11_unlock();
Alexandre Julliard3a5816f1994-12-27 14:11:53 +00001478 return TRUE;
1479}
1480
1481
1482/***********************************************************************
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001483 * X11DRV_PatBlt
Alexandre Julliard401710d1993-09-04 10:09:32 +00001484 */
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001485BOOL X11DRV_PatBlt( X11DRV_PDEVICE *physDev, INT left, INT top, INT width, INT height, DWORD rop )
Alexandre Julliard401710d1993-09-04 10:09:32 +00001486{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001487 BOOL result;
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +00001488
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001489 X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod, FALSE );
1490 result = BITBLT_InternalStretchBlt( physDev, left, top, width, height, NULL, 0, 0, 0, 0, rop );
1491 X11DRV_UnlockDIBSection( physDev, TRUE );
Alexandre Julliard03468f71998-02-15 19:40:49 +00001492 return result;
Alexandre Julliard401710d1993-09-04 10:09:32 +00001493}
1494
1495
1496/***********************************************************************
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001497 * X11DRV_BitBlt
Alexandre Julliard401710d1993-09-04 10:09:32 +00001498 */
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001499BOOL X11DRV_BitBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst,
1500 INT width, INT height, X11DRV_PDEVICE *physDevSrc,
1501 INT xSrc, INT ySrc, DWORD rop )
Alexandre Julliard401710d1993-09-04 10:09:32 +00001502{
Alexandre Julliard447ddfd2000-12-06 20:15:43 +00001503 BOOL result = FALSE;
1504 INT sSrc, sDst;
Alexandre Julliard3f75eaa2000-12-22 01:07:57 +00001505 RECT visRectDst, visRectSrc;
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001506 DC *dcSrc = physDevSrc->dc;
1507 DC *dcDst = physDevDst->dc;
Alexandre Julliard447ddfd2000-12-06 20:15:43 +00001508
1509 if (((rop >> 16) & 0x55) == ((rop >> 17) & 0x55)) {
1510 /* FIXME: seems the ROP doesn't include destination;
1511 * now if the destination area include the entire dcDst,
1512 * we can pass TRUE instead of FALSE to CoerceDIBSection(dcDst...),
1513 * which may avoid a copy in some situations */
1514 }
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001515 sDst = X11DRV_LockDIBSection( physDevDst, DIB_Status_None, FALSE );
1516 sSrc = X11DRV_LockDIBSection( physDevSrc, DIB_Status_None, FALSE );
Alexandre Julliard3f75eaa2000-12-22 01:07:57 +00001517
Alexandre Julliard3c76b142001-10-03 18:45:41 +00001518 if ((sSrc == DIB_Status_AppMod) && (rop == SRCCOPY) &&
1519 (dcSrc->bitsPerPixel == dcDst->bitsPerPixel))
1520 {
Alexandre Julliard3f75eaa2000-12-22 01:07:57 +00001521 /* do everything ourselves; map coordinates */
1522 xSrc = dcSrc->DCOrgX + XLPTODP( dcSrc, xSrc );
1523 ySrc = dcSrc->DCOrgY + YLPTODP( dcSrc, ySrc );
1524 xDst = dcDst->DCOrgX + XLPTODP( dcDst, xDst );
1525 yDst = dcDst->DCOrgY + YLPTODP( dcDst, yDst );
1526 width = MulDiv(width, dcDst->vportExtX, dcDst->wndExtX);
1527 height = MulDiv(height, dcDst->vportExtY, dcDst->wndExtY);
1528
1529 /* Perform basic clipping */
1530 if (!BITBLT_GetVisRectangles( dcDst, xDst, yDst, width, height,
1531 dcSrc, xSrc, ySrc, width, height,
1532 &visRectSrc, &visRectDst ))
1533 goto END;
Alexandre Julliard8efd4542001-01-15 22:30:50 +00001534
Alexandre Julliard3f75eaa2000-12-22 01:07:57 +00001535 xSrc = visRectSrc.left;
1536 ySrc = visRectSrc.top;
1537 xDst = visRectDst.left;
1538 yDst = visRectDst.top;
1539 width = visRectDst.right - visRectDst.left;
1540 height = visRectDst.bottom - visRectDst.top;
1541
Alexandre Julliard447ddfd2000-12-06 20:15:43 +00001542 if (sDst == DIB_Status_AppMod) {
1543 FIXME("potential optimization - client-side DIB copy\n");
1544 }
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001545 X11DRV_CoerceDIBSection( physDevDst, DIB_Status_GdiMod, FALSE );
Alexandre Julliard447ddfd2000-12-06 20:15:43 +00001546
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001547 X11DRV_DIB_CopyDIBSection( physDevSrc, physDevDst, xSrc, ySrc, xDst, yDst, width, height );
Andreas Mohr7f6c84b2001-01-04 19:28:33 +00001548 result = TRUE;
Alexandre Julliard3f75eaa2000-12-22 01:07:57 +00001549 goto END;
Alexandre Julliard447ddfd2000-12-06 20:15:43 +00001550 }
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +00001551
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001552 X11DRV_CoerceDIBSection( physDevDst, DIB_Status_GdiMod, FALSE );
1553 X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod, FALSE );
James Abbatiellob96c6e22000-02-13 16:08:19 +00001554
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001555 result = BITBLT_InternalStretchBlt( physDevDst, xDst, yDst, width, height,
1556 physDevSrc, xSrc, ySrc, width, height, rop );
Alexandre Julliard447ddfd2000-12-06 20:15:43 +00001557
1558END:
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001559 X11DRV_UnlockDIBSection( physDevSrc, FALSE );
1560 X11DRV_UnlockDIBSection( physDevDst, TRUE );
Alexandre Julliard447ddfd2000-12-06 20:15:43 +00001561
Alexandre Julliard03468f71998-02-15 19:40:49 +00001562 return result;
Alexandre Julliard401710d1993-09-04 10:09:32 +00001563}
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001564
1565
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001566/***********************************************************************
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001567 * X11DRV_StretchBlt
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001568 */
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001569BOOL X11DRV_StretchBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst,
1570 INT widthDst, INT heightDst,
1571 X11DRV_PDEVICE *physDevSrc, INT xSrc, INT ySrc,
1572 INT widthSrc, INT heightSrc, DWORD rop )
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001573{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001574 BOOL result;
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +00001575
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001576 X11DRV_LockDIBSection( physDevDst, DIB_Status_GdiMod, FALSE );
1577 X11DRV_LockDIBSection( physDevSrc, DIB_Status_GdiMod, FALSE );
James Abbatiellob96c6e22000-02-13 16:08:19 +00001578
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001579 result = BITBLT_InternalStretchBlt( physDevDst, xDst, yDst, widthDst, heightDst,
1580 physDevSrc, xSrc, ySrc, widthSrc, heightSrc, rop );
Alexandre Julliard447ddfd2000-12-06 20:15:43 +00001581
Alexandre Julliarde21c15e2002-03-28 22:22:05 +00001582 X11DRV_UnlockDIBSection( physDevSrc, FALSE );
1583 X11DRV_UnlockDIBSection( physDevDst, TRUE );
Alexandre Julliard03468f71998-02-15 19:40:49 +00001584 return result;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001585}
Patrik Stridvallab121e71999-02-04 11:11:01 +00001586