1 | /*
|
---|
2 | * IWineD3DSurface Implementation of management(non-rendering) functions
|
---|
3 | *
|
---|
4 | * Copyright 1998 Lionel Ulmer
|
---|
5 | * Copyright 2000-2001 TransGaming Technologies Inc.
|
---|
6 | * Copyright 2002-2005 Jason Edmeades
|
---|
7 | * Copyright 2002-2003 Raphael Junqueira
|
---|
8 | * Copyright 2004 Christian Costa
|
---|
9 | * Copyright 2005 Oliver Stieber
|
---|
10 | * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
|
---|
11 | * Copyright 2007 Henri Verbeet
|
---|
12 | * Copyright 2006-2007 Roderick Colenbrander
|
---|
13 | * Copyright 2009 Henri Verbeet for CodeWeavers
|
---|
14 | *
|
---|
15 | * This library is free software; you can redistribute it and/or
|
---|
16 | * modify it under the terms of the GNU Lesser General Public
|
---|
17 | * License as published by the Free Software Foundation; either
|
---|
18 | * version 2.1 of the License, or (at your option) any later version.
|
---|
19 | *
|
---|
20 | * This library is distributed in the hope that it will be useful,
|
---|
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
23 | * Lesser General Public License for more details.
|
---|
24 | *
|
---|
25 | * You should have received a copy of the GNU Lesser General Public
|
---|
26 | * License along with this library; if not, write to the Free Software
|
---|
27 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
---|
28 | */
|
---|
29 |
|
---|
30 | /*
|
---|
31 | * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
|
---|
32 | * other than GPL or LGPL is available it will apply instead, Sun elects to use only
|
---|
33 | * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
|
---|
34 | * a choice of LGPL license versions is made available with the language indicating
|
---|
35 | * that LGPLv2 or any later version may be used, or where a choice of which version
|
---|
36 | * of the LGPL is applied is otherwise unspecified.
|
---|
37 | */
|
---|
38 |
|
---|
39 | #include "config.h"
|
---|
40 | #include "wine/port.h"
|
---|
41 | #include "wined3d_private.h"
|
---|
42 |
|
---|
43 | WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
|
---|
44 |
|
---|
45 | /* See also float_16_to_32() in wined3d_private.h */
|
---|
46 | static inline unsigned short float_32_to_16(const float *in)
|
---|
47 | {
|
---|
48 | int exp = 0;
|
---|
49 | float tmp = fabs(*in);
|
---|
50 | unsigned int mantissa;
|
---|
51 | unsigned short ret;
|
---|
52 |
|
---|
53 | /* Deal with special numbers */
|
---|
54 | if (*in == 0.0f) return 0x0000;
|
---|
55 | if(_isnan(*in)) return 0x7C01;
|
---|
56 | if(!_finite(*in)) return (*in < 0.0f ? 0xFC00 : 0x7c00);
|
---|
57 |
|
---|
58 | if(tmp < pow(2, 10)) {
|
---|
59 | do
|
---|
60 | {
|
---|
61 | tmp = tmp * 2.0f;
|
---|
62 | exp--;
|
---|
63 | }while(tmp < pow(2, 10));
|
---|
64 | } else if(tmp >= pow(2, 11)) {
|
---|
65 | do
|
---|
66 | {
|
---|
67 | tmp /= 2.0f;
|
---|
68 | exp++;
|
---|
69 | }while(tmp >= pow(2, 11));
|
---|
70 | }
|
---|
71 |
|
---|
72 | mantissa = (unsigned int) tmp;
|
---|
73 | if(tmp - mantissa >= 0.5f) mantissa++; /* round to nearest, away from zero */
|
---|
74 |
|
---|
75 | exp += 10; /* Normalize the mantissa */
|
---|
76 | exp += 15; /* Exponent is encoded with excess 15 */
|
---|
77 |
|
---|
78 | if(exp > 30) { /* too big */
|
---|
79 | ret = 0x7c00; /* INF */
|
---|
80 | } else if(exp <= 0) {
|
---|
81 | /* exp == 0: Non-normalized mantissa. Returns 0x0000 (=0.0) for too small numbers */
|
---|
82 | while(exp <= 0) {
|
---|
83 | mantissa = mantissa >> 1;
|
---|
84 | exp++;
|
---|
85 | }
|
---|
86 | ret = mantissa & 0x3ff;
|
---|
87 | } else {
|
---|
88 | ret = (exp << 10) | (mantissa & 0x3ff);
|
---|
89 | }
|
---|
90 |
|
---|
91 | ret |= ((*in < 0.0f ? 1 : 0) << 15); /* Add the sign */
|
---|
92 | return ret;
|
---|
93 | }
|
---|
94 |
|
---|
95 |
|
---|
96 | /* Do NOT define GLINFO_LOCATION in this file. THIS CODE MUST NOT USE IT */
|
---|
97 |
|
---|
98 | /* *******************************************
|
---|
99 | IWineD3DSurface IUnknown parts follow
|
---|
100 | ******************************************* */
|
---|
101 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
|
---|
102 | {
|
---|
103 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
|
---|
104 | /* Warn ,but be nice about things */
|
---|
105 | TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);
|
---|
106 |
|
---|
107 | if (IsEqualGUID(riid, &IID_IUnknown)
|
---|
108 | || IsEqualGUID(riid, &IID_IWineD3DBase)
|
---|
109 | || IsEqualGUID(riid, &IID_IWineD3DResource)
|
---|
110 | || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
|
---|
111 | IUnknown_AddRef((IUnknown*)iface);
|
---|
112 | *ppobj = This;
|
---|
113 | return S_OK;
|
---|
114 | }
|
---|
115 | *ppobj = NULL;
|
---|
116 | return E_NOINTERFACE;
|
---|
117 | }
|
---|
118 |
|
---|
119 | ULONG WINAPI IWineD3DBaseSurfaceImpl_AddRef(IWineD3DSurface *iface) {
|
---|
120 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
|
---|
121 | ULONG ref = InterlockedIncrement(&This->resource.ref);
|
---|
122 | TRACE("(%p) : AddRef increasing from %d\n", This,ref - 1);
|
---|
123 | return ref;
|
---|
124 | }
|
---|
125 |
|
---|
126 | /* ****************************************************
|
---|
127 | IWineD3DSurface IWineD3DResource parts follow
|
---|
128 | **************************************************** */
|
---|
129 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
|
---|
130 | return resource_set_private_data((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
|
---|
131 | }
|
---|
132 |
|
---|
133 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
|
---|
134 | return resource_get_private_data((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
|
---|
135 | }
|
---|
136 |
|
---|
137 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
|
---|
138 | return resource_free_private_data((IWineD3DResource *)iface, refguid);
|
---|
139 | }
|
---|
140 |
|
---|
141 | DWORD WINAPI IWineD3DBaseSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
|
---|
142 | return resource_set_priority((IWineD3DResource *)iface, PriorityNew);
|
---|
143 | }
|
---|
144 |
|
---|
145 | DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
|
---|
146 | return resource_get_priority((IWineD3DResource *)iface);
|
---|
147 | }
|
---|
148 |
|
---|
149 | WINED3DRESOURCETYPE WINAPI IWineD3DBaseSurfaceImpl_GetType(IWineD3DSurface *iface) {
|
---|
150 | TRACE("(%p) : calling resourceimpl_GetType\n", iface);
|
---|
151 | return resource_get_type((IWineD3DResource *)iface);
|
---|
152 | }
|
---|
153 |
|
---|
154 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
|
---|
155 | TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
|
---|
156 | return resource_get_parent((IWineD3DResource *)iface, pParent);
|
---|
157 | }
|
---|
158 |
|
---|
159 | /* ******************************************************
|
---|
160 | IWineD3DSurface IWineD3DSurface parts follow
|
---|
161 | ****************************************************** */
|
---|
162 |
|
---|
163 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
|
---|
164 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
|
---|
165 | IWineD3DBase *container = 0;
|
---|
166 |
|
---|
167 | TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
|
---|
168 |
|
---|
169 | if (!ppContainer) {
|
---|
170 | ERR("Called without a valid ppContainer.\n");
|
---|
171 | }
|
---|
172 |
|
---|
173 | /* Standalone surfaces return the device as container. */
|
---|
174 | if (This->container) container = This->container;
|
---|
175 | else container = (IWineD3DBase *)This->resource.device;
|
---|
176 |
|
---|
177 | TRACE("Relaying to QueryInterface\n");
|
---|
178 | return IUnknown_QueryInterface(container, riid, ppContainer);
|
---|
179 | }
|
---|
180 |
|
---|
181 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
|
---|
182 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
|
---|
183 |
|
---|
184 | TRACE("(%p) : copying into %p\n", This, pDesc);
|
---|
185 |
|
---|
186 | pDesc->format = This->resource.format_desc->format;
|
---|
187 | pDesc->resource_type = This->resource.resourceType;
|
---|
188 | pDesc->usage = This->resource.usage;
|
---|
189 | pDesc->pool = This->resource.pool;
|
---|
190 | pDesc->size = This->resource.size; /* dx8 only */
|
---|
191 | pDesc->multisample_type = This->currentDesc.MultiSampleType;
|
---|
192 | pDesc->multisample_quality = This->currentDesc.MultiSampleQuality;
|
---|
193 | pDesc->width = This->currentDesc.Width;
|
---|
194 | pDesc->height = This->currentDesc.Height;
|
---|
195 |
|
---|
196 | return WINED3D_OK;
|
---|
197 | }
|
---|
198 |
|
---|
199 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags)
|
---|
200 | {
|
---|
201 | TRACE("iface %p, flags %#x.\n", iface, Flags);
|
---|
202 |
|
---|
203 | switch (Flags)
|
---|
204 | {
|
---|
205 | case WINEDDGBS_CANBLT:
|
---|
206 | case WINEDDGBS_ISBLTDONE:
|
---|
207 | return WINED3D_OK;
|
---|
208 |
|
---|
209 | default:
|
---|
210 | return WINED3DERR_INVALIDCALL;
|
---|
211 | }
|
---|
212 | }
|
---|
213 |
|
---|
214 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
|
---|
215 | /* XXX: DDERR_INVALIDSURFACETYPE */
|
---|
216 |
|
---|
217 | TRACE("(%p)->(%08x)\n",iface,Flags);
|
---|
218 | switch (Flags) {
|
---|
219 | case WINEDDGFS_CANFLIP:
|
---|
220 | case WINEDDGFS_ISFLIPDONE:
|
---|
221 | return WINED3D_OK;
|
---|
222 |
|
---|
223 | default:
|
---|
224 | return WINED3DERR_INVALIDCALL;
|
---|
225 | }
|
---|
226 | }
|
---|
227 |
|
---|
228 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_IsLost(IWineD3DSurface *iface) {
|
---|
229 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
230 | TRACE("(%p)\n", This);
|
---|
231 |
|
---|
232 | /* D3D8 and 9 loose full devices, ddraw only surfaces */
|
---|
233 | return This->Flags & SFLAG_LOST ? WINED3DERR_DEVICELOST : WINED3D_OK;
|
---|
234 | }
|
---|
235 |
|
---|
236 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_Restore(IWineD3DSurface *iface) {
|
---|
237 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
238 | TRACE("(%p)\n", This);
|
---|
239 |
|
---|
240 | /* So far we don't lose anything :) */
|
---|
241 | This->Flags &= ~SFLAG_LOST;
|
---|
242 | return WINED3D_OK;
|
---|
243 | }
|
---|
244 |
|
---|
245 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
|
---|
246 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
247 | IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal;
|
---|
248 | TRACE("(%p)->(%p)\n", This, Pal);
|
---|
249 |
|
---|
250 | if(This->palette == PalImpl) {
|
---|
251 | TRACE("Nop palette change\n");
|
---|
252 | return WINED3D_OK;
|
---|
253 | }
|
---|
254 |
|
---|
255 | if(This->palette != NULL)
|
---|
256 | if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
|
---|
257 | This->palette->Flags &= ~WINEDDPCAPS_PRIMARYSURFACE;
|
---|
258 |
|
---|
259 | This->palette = PalImpl;
|
---|
260 |
|
---|
261 | if(PalImpl != NULL) {
|
---|
262 | if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
|
---|
263 | (PalImpl)->Flags |= WINEDDPCAPS_PRIMARYSURFACE;
|
---|
264 | }
|
---|
265 |
|
---|
266 | return IWineD3DSurface_RealizePalette(iface);
|
---|
267 | }
|
---|
268 | else return WINED3D_OK;
|
---|
269 | }
|
---|
270 |
|
---|
271 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, const WINEDDCOLORKEY *CKey)
|
---|
272 | {
|
---|
273 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
274 | TRACE("(%p)->(%08x,%p)\n", This, Flags, CKey);
|
---|
275 |
|
---|
276 | if ((Flags & WINEDDCKEY_COLORSPACE) != 0) {
|
---|
277 | FIXME(" colorkey value not supported (%08x) !\n", Flags);
|
---|
278 | return WINED3DERR_INVALIDCALL;
|
---|
279 | }
|
---|
280 |
|
---|
281 | /* Dirtify the surface, but only if a key was changed */
|
---|
282 | if(CKey) {
|
---|
283 | switch (Flags & ~WINEDDCKEY_COLORSPACE) {
|
---|
284 | case WINEDDCKEY_DESTBLT:
|
---|
285 | This->DestBltCKey = *CKey;
|
---|
286 | This->CKeyFlags |= WINEDDSD_CKDESTBLT;
|
---|
287 | break;
|
---|
288 |
|
---|
289 | case WINEDDCKEY_DESTOVERLAY:
|
---|
290 | This->DestOverlayCKey = *CKey;
|
---|
291 | This->CKeyFlags |= WINEDDSD_CKDESTOVERLAY;
|
---|
292 | break;
|
---|
293 |
|
---|
294 | case WINEDDCKEY_SRCOVERLAY:
|
---|
295 | This->SrcOverlayCKey = *CKey;
|
---|
296 | This->CKeyFlags |= WINEDDSD_CKSRCOVERLAY;
|
---|
297 | break;
|
---|
298 |
|
---|
299 | case WINEDDCKEY_SRCBLT:
|
---|
300 | This->SrcBltCKey = *CKey;
|
---|
301 | This->CKeyFlags |= WINEDDSD_CKSRCBLT;
|
---|
302 | break;
|
---|
303 | }
|
---|
304 | }
|
---|
305 | else {
|
---|
306 | switch (Flags & ~WINEDDCKEY_COLORSPACE) {
|
---|
307 | case WINEDDCKEY_DESTBLT:
|
---|
308 | This->CKeyFlags &= ~WINEDDSD_CKDESTBLT;
|
---|
309 | break;
|
---|
310 |
|
---|
311 | case WINEDDCKEY_DESTOVERLAY:
|
---|
312 | This->CKeyFlags &= ~WINEDDSD_CKDESTOVERLAY;
|
---|
313 | break;
|
---|
314 |
|
---|
315 | case WINEDDCKEY_SRCOVERLAY:
|
---|
316 | This->CKeyFlags &= ~WINEDDSD_CKSRCOVERLAY;
|
---|
317 | break;
|
---|
318 |
|
---|
319 | case WINEDDCKEY_SRCBLT:
|
---|
320 | This->CKeyFlags &= ~WINEDDSD_CKSRCBLT;
|
---|
321 | break;
|
---|
322 | }
|
---|
323 | }
|
---|
324 |
|
---|
325 | return WINED3D_OK;
|
---|
326 | }
|
---|
327 |
|
---|
328 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
|
---|
329 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
330 | TRACE("(%p)->(%p)\n", This, Pal);
|
---|
331 |
|
---|
332 | *Pal = (IWineD3DPalette *) This->palette;
|
---|
333 | return WINED3D_OK;
|
---|
334 | }
|
---|
335 |
|
---|
336 | DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
|
---|
337 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
338 | const struct wined3d_format_desc *format_desc = This->resource.format_desc;
|
---|
339 | DWORD ret;
|
---|
340 | TRACE("(%p)\n", This);
|
---|
341 |
|
---|
342 | if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED)
|
---|
343 | {
|
---|
344 | /* Since compressed formats are block based, pitch means the amount of
|
---|
345 | * bytes to the next row of block rather than the next row of pixels. */
|
---|
346 | UINT row_block_count = (This->currentDesc.Width + format_desc->block_width - 1) / format_desc->block_width;
|
---|
347 | ret = row_block_count * format_desc->block_byte_count;
|
---|
348 | }
|
---|
349 | else
|
---|
350 | {
|
---|
351 | unsigned char alignment = This->resource.device->surface_alignment;
|
---|
352 | ret = This->resource.format_desc->byte_count * This->currentDesc.Width; /* Bytes / row */
|
---|
353 | ret = (ret + alignment - 1) & ~(alignment - 1);
|
---|
354 | }
|
---|
355 | TRACE("(%p) Returning %d\n", This, ret);
|
---|
356 | return ret;
|
---|
357 | }
|
---|
358 |
|
---|
359 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG X, LONG Y) {
|
---|
360 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
361 | LONG w, h;
|
---|
362 |
|
---|
363 | TRACE("(%p)->(%d,%d) Stub!\n", This, X, Y);
|
---|
364 |
|
---|
365 | if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
|
---|
366 | {
|
---|
367 | TRACE("(%p): Not an overlay surface\n", This);
|
---|
368 | return WINEDDERR_NOTAOVERLAYSURFACE;
|
---|
369 | }
|
---|
370 |
|
---|
371 | w = This->overlay_destrect.right - This->overlay_destrect.left;
|
---|
372 | h = This->overlay_destrect.bottom - This->overlay_destrect.top;
|
---|
373 | This->overlay_destrect.left = X;
|
---|
374 | This->overlay_destrect.top = Y;
|
---|
375 | This->overlay_destrect.right = X + w;
|
---|
376 | This->overlay_destrect.bottom = Y + h;
|
---|
377 |
|
---|
378 | IWineD3DSurface_DrawOverlay(iface);
|
---|
379 |
|
---|
380 | return WINED3D_OK;
|
---|
381 | }
|
---|
382 |
|
---|
383 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y) {
|
---|
384 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
385 | HRESULT hr;
|
---|
386 |
|
---|
387 | TRACE("(%p)->(%p,%p)\n", This, X, Y);
|
---|
388 |
|
---|
389 | if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
|
---|
390 | {
|
---|
391 | TRACE("(%p): Not an overlay surface\n", This);
|
---|
392 | return WINEDDERR_NOTAOVERLAYSURFACE;
|
---|
393 | }
|
---|
394 | if(This->overlay_dest == NULL) {
|
---|
395 | *X = 0; *Y = 0;
|
---|
396 | hr = WINEDDERR_OVERLAYNOTVISIBLE;
|
---|
397 | } else {
|
---|
398 | *X = This->overlay_destrect.left;
|
---|
399 | *Y = This->overlay_destrect.top;
|
---|
400 | hr = WINED3D_OK;
|
---|
401 | }
|
---|
402 |
|
---|
403 | TRACE("Returning 0x%08x, position %d, %d\n", hr, *X, *Y);
|
---|
404 | return hr;
|
---|
405 | }
|
---|
406 |
|
---|
407 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, DWORD Flags, IWineD3DSurface *Ref) {
|
---|
408 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
409 |
|
---|
410 | FIXME("iface %p, flags %#x, ref %p stub!\n", iface, Flags, Ref);
|
---|
411 |
|
---|
412 | if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
|
---|
413 | {
|
---|
414 | TRACE("(%p): Not an overlay surface\n", This);
|
---|
415 | return WINEDDERR_NOTAOVERLAYSURFACE;
|
---|
416 | }
|
---|
417 |
|
---|
418 | return WINED3D_OK;
|
---|
419 | }
|
---|
420 |
|
---|
421 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, const RECT *SrcRect,
|
---|
422 | IWineD3DSurface *DstSurface, const RECT *DstRect, DWORD Flags, const WINEDDOVERLAYFX *FX)
|
---|
423 | {
|
---|
424 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
425 | IWineD3DSurfaceImpl *Dst = (IWineD3DSurfaceImpl *) DstSurface;
|
---|
426 | TRACE("(%p)->(%p, %p, %p, %08x, %p)\n", This, SrcRect, Dst, DstRect, Flags, FX);
|
---|
427 |
|
---|
428 | if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
|
---|
429 | {
|
---|
430 | WARN("(%p): Not an overlay surface\n", This);
|
---|
431 | return WINEDDERR_NOTAOVERLAYSURFACE;
|
---|
432 | } else if(!DstSurface) {
|
---|
433 | WARN("(%p): Dest surface is NULL\n", This);
|
---|
434 | return WINED3DERR_INVALIDCALL;
|
---|
435 | }
|
---|
436 |
|
---|
437 | if(SrcRect) {
|
---|
438 | This->overlay_srcrect = *SrcRect;
|
---|
439 | } else {
|
---|
440 | This->overlay_srcrect.left = 0;
|
---|
441 | This->overlay_srcrect.top = 0;
|
---|
442 | This->overlay_srcrect.right = This->currentDesc.Width;
|
---|
443 | This->overlay_srcrect.bottom = This->currentDesc.Height;
|
---|
444 | }
|
---|
445 |
|
---|
446 | if(DstRect) {
|
---|
447 | This->overlay_destrect = *DstRect;
|
---|
448 | } else {
|
---|
449 | This->overlay_destrect.left = 0;
|
---|
450 | This->overlay_destrect.top = 0;
|
---|
451 | This->overlay_destrect.right = Dst ? Dst->currentDesc.Width : 0;
|
---|
452 | This->overlay_destrect.bottom = Dst ? Dst->currentDesc.Height : 0;
|
---|
453 | }
|
---|
454 |
|
---|
455 | if(This->overlay_dest && (This->overlay_dest != Dst || Flags & WINEDDOVER_HIDE)) {
|
---|
456 | list_remove(&This->overlay_entry);
|
---|
457 | }
|
---|
458 |
|
---|
459 | if(Flags & WINEDDOVER_SHOW) {
|
---|
460 | if(This->overlay_dest != Dst) {
|
---|
461 | This->overlay_dest = Dst;
|
---|
462 | list_add_tail(&Dst->overlays, &This->overlay_entry);
|
---|
463 | }
|
---|
464 | } else if(Flags & WINEDDOVER_HIDE) {
|
---|
465 | /* tests show that the rectangles are erased on hide */
|
---|
466 | This->overlay_srcrect.left = 0; This->overlay_srcrect.top = 0;
|
---|
467 | This->overlay_srcrect.right = 0; This->overlay_srcrect.bottom = 0;
|
---|
468 | This->overlay_destrect.left = 0; This->overlay_destrect.top = 0;
|
---|
469 | This->overlay_destrect.right = 0; This->overlay_destrect.bottom = 0;
|
---|
470 | This->overlay_dest = NULL;
|
---|
471 | }
|
---|
472 |
|
---|
473 | IWineD3DSurface_DrawOverlay(iface);
|
---|
474 |
|
---|
475 | return WINED3D_OK;
|
---|
476 | }
|
---|
477 |
|
---|
478 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetClipper(IWineD3DSurface *iface, IWineD3DClipper *clipper)
|
---|
479 | {
|
---|
480 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
481 | TRACE("(%p)->(%p)\n", This, clipper);
|
---|
482 |
|
---|
483 | This->clipper = clipper;
|
---|
484 | return WINED3D_OK;
|
---|
485 | }
|
---|
486 |
|
---|
487 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetClipper(IWineD3DSurface *iface, IWineD3DClipper **clipper)
|
---|
488 | {
|
---|
489 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
490 | TRACE("(%p)->(%p)\n", This, clipper);
|
---|
491 |
|
---|
492 | *clipper = This->clipper;
|
---|
493 | if(*clipper) {
|
---|
494 | IWineD3DClipper_AddRef(*clipper);
|
---|
495 | }
|
---|
496 | return WINED3D_OK;
|
---|
497 | }
|
---|
498 |
|
---|
499 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
|
---|
500 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
|
---|
501 |
|
---|
502 | TRACE("This %p, container %p\n", This, container);
|
---|
503 |
|
---|
504 | /* We can't keep a reference to the container, since the container already keeps a reference to us. */
|
---|
505 |
|
---|
506 | TRACE("Setting container to %p from %p\n", container, This->container);
|
---|
507 | This->container = container;
|
---|
508 |
|
---|
509 | return WINED3D_OK;
|
---|
510 | }
|
---|
511 |
|
---|
512 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
|
---|
513 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
|
---|
514 | const struct wined3d_format_desc *format_desc = getFormatDescEntry(format,
|
---|
515 | &This->resource.device->adapter->gl_info);
|
---|
516 |
|
---|
517 | if (This->resource.format_desc->format != WINED3DFMT_UNKNOWN)
|
---|
518 | {
|
---|
519 | FIXME("(%p) : The format of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
|
---|
520 | return WINED3DERR_INVALIDCALL;
|
---|
521 | }
|
---|
522 |
|
---|
523 | TRACE("(%p) : Setting texture format to (%d,%s)\n", This, format, debug_d3dformat(format));
|
---|
524 |
|
---|
525 | This->resource.size = surface_calculate_size(format_desc, This->resource.device->surface_alignment,
|
---|
526 | This->pow2Width, This->pow2Height);
|
---|
527 |
|
---|
528 | This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0;
|
---|
529 |
|
---|
530 | This->resource.format_desc = format_desc;
|
---|
531 |
|
---|
532 | TRACE("(%p) : Size %d, bytesPerPixel %d\n", This, This->resource.size, format_desc->byte_count);
|
---|
533 |
|
---|
534 | return WINED3D_OK;
|
---|
535 | }
|
---|
536 |
|
---|
537 | HRESULT IWineD3DBaseSurfaceImpl_CreateDIBSection(IWineD3DSurface *iface) {
|
---|
538 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
|
---|
539 | const struct wined3d_format_desc *format_desc = This->resource.format_desc;
|
---|
540 | int extraline = 0;
|
---|
541 | SYSTEM_INFO sysInfo;
|
---|
542 | BITMAPINFO* b_info;
|
---|
543 | HDC ddc;
|
---|
544 | DWORD *masks;
|
---|
545 | UINT usage;
|
---|
546 |
|
---|
547 | if(!(format_desc->Flags & WINED3DFMT_FLAG_GETDC))
|
---|
548 | {
|
---|
549 | WARN("Cannot use GetDC on a %s surface\n", debug_d3dformat(format_desc->format));
|
---|
550 | return WINED3DERR_INVALIDCALL;
|
---|
551 | }
|
---|
552 |
|
---|
553 | switch (format_desc->byte_count)
|
---|
554 | {
|
---|
555 | case 2:
|
---|
556 | case 4:
|
---|
557 | /* Allocate extra space to store the RGB bit masks. */
|
---|
558 | b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
|
---|
559 | break;
|
---|
560 |
|
---|
561 | case 3:
|
---|
562 | b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
|
---|
563 | break;
|
---|
564 |
|
---|
565 | default:
|
---|
566 | /* Allocate extra space for a palette. */
|
---|
567 | b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
---|
568 | sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << (format_desc->byte_count * 8)));
|
---|
569 | break;
|
---|
570 | }
|
---|
571 |
|
---|
572 | if (!b_info)
|
---|
573 | return E_OUTOFMEMORY;
|
---|
574 |
|
---|
575 | /* Some apps access the surface in via DWORDs, and do not take the necessary care at the end of the
|
---|
576 | * surface. So we need at least extra 4 bytes at the end of the surface. Check against the page size,
|
---|
577 | * if the last page used for the surface has at least 4 spare bytes we're safe, otherwise
|
---|
578 | * add an extra line to the dib section
|
---|
579 | */
|
---|
580 | GetSystemInfo(&sysInfo);
|
---|
581 | if( ((This->resource.size + 3) % sysInfo.dwPageSize) < 4) {
|
---|
582 | extraline = 1;
|
---|
583 | TRACE("Adding an extra line to the dib section\n");
|
---|
584 | }
|
---|
585 |
|
---|
586 | b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
---|
587 | /* TODO: Is there a nicer way to force a specific alignment? (8 byte for ddraw) */
|
---|
588 | b_info->bmiHeader.biWidth = IWineD3DSurface_GetPitch(iface) / format_desc->byte_count;
|
---|
589 | b_info->bmiHeader.biHeight = -This->currentDesc.Height -extraline;
|
---|
590 | b_info->bmiHeader.biSizeImage = ( This->currentDesc.Height + extraline) * IWineD3DSurface_GetPitch(iface);
|
---|
591 | b_info->bmiHeader.biPlanes = 1;
|
---|
592 | b_info->bmiHeader.biBitCount = format_desc->byte_count * 8;
|
---|
593 |
|
---|
594 | b_info->bmiHeader.biXPelsPerMeter = 0;
|
---|
595 | b_info->bmiHeader.biYPelsPerMeter = 0;
|
---|
596 | b_info->bmiHeader.biClrUsed = 0;
|
---|
597 | b_info->bmiHeader.biClrImportant = 0;
|
---|
598 |
|
---|
599 | /* Get the bit masks */
|
---|
600 | masks = (DWORD *)b_info->bmiColors;
|
---|
601 | switch (This->resource.format_desc->format)
|
---|
602 | {
|
---|
603 | case WINED3DFMT_B8G8R8_UNORM:
|
---|
604 | usage = DIB_RGB_COLORS;
|
---|
605 | b_info->bmiHeader.biCompression = BI_RGB;
|
---|
606 | break;
|
---|
607 |
|
---|
608 | case WINED3DFMT_B5G5R5X1_UNORM:
|
---|
609 | case WINED3DFMT_B5G5R5A1_UNORM:
|
---|
610 | case WINED3DFMT_B4G4R4A4_UNORM:
|
---|
611 | case WINED3DFMT_B4G4R4X4_UNORM:
|
---|
612 | case WINED3DFMT_B2G3R3_UNORM:
|
---|
613 | case WINED3DFMT_B2G3R3A8_UNORM:
|
---|
614 | case WINED3DFMT_R10G10B10A2_UNORM:
|
---|
615 | case WINED3DFMT_R8G8B8A8_UNORM:
|
---|
616 | case WINED3DFMT_R8G8B8X8_UNORM:
|
---|
617 | case WINED3DFMT_B10G10R10A2_UNORM:
|
---|
618 | case WINED3DFMT_B5G6R5_UNORM:
|
---|
619 | case WINED3DFMT_R16G16B16A16_UNORM:
|
---|
620 | usage = 0;
|
---|
621 | b_info->bmiHeader.biCompression = BI_BITFIELDS;
|
---|
622 | masks[0] = format_desc->red_mask;
|
---|
623 | masks[1] = format_desc->green_mask;
|
---|
624 | masks[2] = format_desc->blue_mask;
|
---|
625 | break;
|
---|
626 |
|
---|
627 | default:
|
---|
628 | /* Don't know palette */
|
---|
629 | b_info->bmiHeader.biCompression = BI_RGB;
|
---|
630 | usage = 0;
|
---|
631 | break;
|
---|
632 | }
|
---|
633 |
|
---|
634 | ddc = GetDC(0);
|
---|
635 | if (ddc == 0) {
|
---|
636 | HeapFree(GetProcessHeap(), 0, b_info);
|
---|
637 | return HRESULT_FROM_WIN32(GetLastError());
|
---|
638 | }
|
---|
639 |
|
---|
640 | TRACE("Creating a DIB section with size %dx%dx%d, size=%d\n", b_info->bmiHeader.biWidth, b_info->bmiHeader.biHeight, b_info->bmiHeader.biBitCount, b_info->bmiHeader.biSizeImage);
|
---|
641 | This->dib.DIBsection = CreateDIBSection(ddc, b_info, usage, &This->dib.bitmap_data, 0 /* Handle */, 0 /* Offset */);
|
---|
642 | ReleaseDC(0, ddc);
|
---|
643 |
|
---|
644 | if (!This->dib.DIBsection) {
|
---|
645 | ERR("CreateDIBSection failed!\n");
|
---|
646 | HeapFree(GetProcessHeap(), 0, b_info);
|
---|
647 | return HRESULT_FROM_WIN32(GetLastError());
|
---|
648 | }
|
---|
649 |
|
---|
650 | TRACE("DIBSection at : %p\n", This->dib.bitmap_data);
|
---|
651 | /* copy the existing surface to the dib section */
|
---|
652 | if(This->resource.allocatedMemory) {
|
---|
653 | memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, This->currentDesc.Height * IWineD3DSurface_GetPitch(iface));
|
---|
654 | } else {
|
---|
655 | /* This is to make LockRect read the gl Texture although memory is allocated */
|
---|
656 | This->Flags &= ~SFLAG_INSYSMEM;
|
---|
657 | }
|
---|
658 | This->dib.bitmap_size = b_info->bmiHeader.biSizeImage;
|
---|
659 |
|
---|
660 | HeapFree(GetProcessHeap(), 0, b_info);
|
---|
661 |
|
---|
662 | /* Now allocate a HDC */
|
---|
663 | This->hDC = CreateCompatibleDC(0);
|
---|
664 | This->dib.holdbitmap = SelectObject(This->hDC, This->dib.DIBsection);
|
---|
665 | TRACE("using wined3d palette %p\n", This->palette);
|
---|
666 | SelectPalette(This->hDC,
|
---|
667 | This->palette ? This->palette->hpal : 0,
|
---|
668 | FALSE);
|
---|
669 |
|
---|
670 | This->Flags |= SFLAG_DIBSECTION;
|
---|
671 |
|
---|
672 | HeapFree(GetProcessHeap(), 0, This->resource.heapMemory);
|
---|
673 | This->resource.heapMemory = NULL;
|
---|
674 |
|
---|
675 | return WINED3D_OK;
|
---|
676 | }
|
---|
677 |
|
---|
678 | static void convert_r32_float_r16_float(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out,
|
---|
679 | unsigned int w, unsigned int h)
|
---|
680 | {
|
---|
681 | unsigned int x, y;
|
---|
682 | const float *src_f;
|
---|
683 | unsigned short *dst_s;
|
---|
684 |
|
---|
685 | TRACE("Converting %dx%d pixels, pitches %d %d\n", w, h, pitch_in, pitch_out);
|
---|
686 | for(y = 0; y < h; y++) {
|
---|
687 | src_f = (const float *)(src + y * pitch_in);
|
---|
688 | dst_s = (unsigned short *) (dst + y * pitch_out);
|
---|
689 | for(x = 0; x < w; x++) {
|
---|
690 | dst_s[x] = float_32_to_16(src_f + x);
|
---|
691 | }
|
---|
692 | }
|
---|
693 | }
|
---|
694 |
|
---|
695 | static void convert_r5g6b5_x8r8g8b8(const BYTE *src, BYTE *dst,
|
---|
696 | DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
|
---|
697 | {
|
---|
698 | static const unsigned char convert_5to8[] =
|
---|
699 | {
|
---|
700 | 0x00, 0x08, 0x10, 0x19, 0x21, 0x29, 0x31, 0x3a,
|
---|
701 | 0x42, 0x4a, 0x52, 0x5a, 0x63, 0x6b, 0x73, 0x7b,
|
---|
702 | 0x84, 0x8c, 0x94, 0x9c, 0xa5, 0xad, 0xb5, 0xbd,
|
---|
703 | 0xc5, 0xce, 0xd6, 0xde, 0xe6, 0xef, 0xf7, 0xff,
|
---|
704 | };
|
---|
705 | static const unsigned char convert_6to8[] =
|
---|
706 | {
|
---|
707 | 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
|
---|
708 | 0x20, 0x24, 0x28, 0x2d, 0x31, 0x35, 0x39, 0x3d,
|
---|
709 | 0x41, 0x45, 0x49, 0x4d, 0x51, 0x55, 0x59, 0x5d,
|
---|
710 | 0x61, 0x65, 0x69, 0x6d, 0x71, 0x75, 0x79, 0x7d,
|
---|
711 | 0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
|
---|
712 | 0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
|
---|
713 | 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd7, 0xdb, 0xdf,
|
---|
714 | 0xe3, 0xe7, 0xeb, 0xef, 0xf3, 0xf7, 0xfb, 0xff,
|
---|
715 | };
|
---|
716 | unsigned int x, y;
|
---|
717 |
|
---|
718 | TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out);
|
---|
719 |
|
---|
720 | for (y = 0; y < h; ++y)
|
---|
721 | {
|
---|
722 | const WORD *src_line = (const WORD *)(src + y * pitch_in);
|
---|
723 | DWORD *dst_line = (DWORD *)(dst + y * pitch_out);
|
---|
724 | for (x = 0; x < w; ++x)
|
---|
725 | {
|
---|
726 | WORD pixel = src_line[x];
|
---|
727 | dst_line[x] = 0xff000000
|
---|
728 | | convert_5to8[(pixel & 0xf800) >> 11] << 16
|
---|
729 | | convert_6to8[(pixel & 0x07e0) >> 5] << 8
|
---|
730 | | convert_5to8[(pixel & 0x001f)];
|
---|
731 | }
|
---|
732 | }
|
---|
733 | }
|
---|
734 |
|
---|
735 | static void convert_a8r8g8b8_x8r8g8b8(const BYTE *src, BYTE *dst,
|
---|
736 | DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
|
---|
737 | {
|
---|
738 | unsigned int x, y;
|
---|
739 |
|
---|
740 | TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out);
|
---|
741 |
|
---|
742 | for (y = 0; y < h; ++y)
|
---|
743 | {
|
---|
744 | const DWORD *src_line = (const DWORD *)(src + y * pitch_in);
|
---|
745 | DWORD *dst_line = (DWORD *)(dst + y * pitch_out);
|
---|
746 |
|
---|
747 | for (x = 0; x < w; ++x)
|
---|
748 | {
|
---|
749 | dst_line[x] = 0xff000000 | (src_line[x] & 0xffffff);
|
---|
750 | }
|
---|
751 | }
|
---|
752 | }
|
---|
753 |
|
---|
754 | static inline BYTE cliptobyte(int x)
|
---|
755 | {
|
---|
756 | return (BYTE) ((x < 0) ? 0 : ((x > 255) ? 255 : x));
|
---|
757 | }
|
---|
758 |
|
---|
759 | static void convert_yuy2_x8r8g8b8(const BYTE *src, BYTE *dst,
|
---|
760 | DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
|
---|
761 | {
|
---|
762 | unsigned int x, y;
|
---|
763 | int c2, d, e, r2 = 0, g2 = 0, b2 = 0;
|
---|
764 |
|
---|
765 | TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out);
|
---|
766 |
|
---|
767 | for (y = 0; y < h; ++y)
|
---|
768 | {
|
---|
769 | const BYTE *src_line = src + y * pitch_in;
|
---|
770 | DWORD *dst_line = (DWORD *)(dst + y * pitch_out);
|
---|
771 | for (x = 0; x < w; ++x)
|
---|
772 | {
|
---|
773 | /* YUV to RGB conversion formulas from http://en.wikipedia.org/wiki/YUV:
|
---|
774 | * C = Y - 16; D = U - 128; E = V - 128;
|
---|
775 | * R = cliptobyte((298 * C + 409 * E + 128) >> 8);
|
---|
776 | * G = cliptobyte((298 * C - 100 * D - 208 * E + 128) >> 8);
|
---|
777 | * B = cliptobyte((298 * C + 516 * D + 128) >> 8);
|
---|
778 | * Two adjacent YUY2 pixels are stored as four bytes: Y0 U Y1 V .
|
---|
779 | * U and V are shared between the pixels.
|
---|
780 | */
|
---|
781 | if (!(x & 1)) /* for every even pixel, read new U and V */
|
---|
782 | {
|
---|
783 | d = (int) src_line[1] - 128;
|
---|
784 | e = (int) src_line[3] - 128;
|
---|
785 | r2 = 409 * e + 128;
|
---|
786 | g2 = - 100 * d - 208 * e + 128;
|
---|
787 | b2 = 516 * d + 128;
|
---|
788 | }
|
---|
789 | c2 = 298 * ((int) src_line[0] - 16);
|
---|
790 | dst_line[x] = 0xff000000
|
---|
791 | | cliptobyte((c2 + r2) >> 8) << 16 /* red */
|
---|
792 | | cliptobyte((c2 + g2) >> 8) << 8 /* green */
|
---|
793 | | cliptobyte((c2 + b2) >> 8); /* blue */
|
---|
794 | /* Scale RGB values to 0..255 range,
|
---|
795 | * then clip them if still not in range (may be negative),
|
---|
796 | * then shift them within DWORD if necessary.
|
---|
797 | */
|
---|
798 | src_line += 2;
|
---|
799 | }
|
---|
800 | }
|
---|
801 | }
|
---|
802 |
|
---|
803 | struct d3dfmt_convertor_desc {
|
---|
804 | WINED3DFORMAT from, to;
|
---|
805 | void (*convert)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h);
|
---|
806 | };
|
---|
807 |
|
---|
808 | static const struct d3dfmt_convertor_desc convertors[] =
|
---|
809 | {
|
---|
810 | {WINED3DFMT_R32_FLOAT, WINED3DFMT_R16_FLOAT, convert_r32_float_r16_float},
|
---|
811 | {WINED3DFMT_B5G6R5_UNORM, WINED3DFMT_B8G8R8X8_UNORM, convert_r5g6b5_x8r8g8b8},
|
---|
812 | {WINED3DFMT_B8G8R8A8_UNORM, WINED3DFMT_B8G8R8X8_UNORM, convert_a8r8g8b8_x8r8g8b8},
|
---|
813 | {WINED3DFMT_YUY2, WINED3DFMT_B8G8R8X8_UNORM, convert_yuy2_x8r8g8b8},
|
---|
814 | };
|
---|
815 |
|
---|
816 | static inline const struct d3dfmt_convertor_desc *find_convertor(WINED3DFORMAT from, WINED3DFORMAT to)
|
---|
817 | {
|
---|
818 | unsigned int i;
|
---|
819 | for(i = 0; i < (sizeof(convertors) / sizeof(convertors[0])); i++) {
|
---|
820 | if(convertors[i].from == from && convertors[i].to == to) {
|
---|
821 | return &convertors[i];
|
---|
822 | }
|
---|
823 | }
|
---|
824 | return NULL;
|
---|
825 | }
|
---|
826 |
|
---|
827 | /*****************************************************************************
|
---|
828 | * surface_convert_format
|
---|
829 | *
|
---|
830 | * Creates a duplicate of a surface in a different format. Is used by Blt to
|
---|
831 | * blit between surfaces with different formats
|
---|
832 | *
|
---|
833 | * Parameters
|
---|
834 | * source: Source surface
|
---|
835 | * fmt: Requested destination format
|
---|
836 | *
|
---|
837 | *****************************************************************************/
|
---|
838 | static IWineD3DSurfaceImpl *surface_convert_format(IWineD3DSurfaceImpl *source, WINED3DFORMAT to_fmt) {
|
---|
839 | IWineD3DSurface *ret = NULL;
|
---|
840 | const struct d3dfmt_convertor_desc *conv;
|
---|
841 | WINED3DLOCKED_RECT lock_src, lock_dst;
|
---|
842 | HRESULT hr;
|
---|
843 |
|
---|
844 | conv = find_convertor(source->resource.format_desc->format, to_fmt);
|
---|
845 | if(!conv) {
|
---|
846 | FIXME("Cannot find a conversion function from format %s to %s\n",
|
---|
847 | debug_d3dformat(source->resource.format_desc->format), debug_d3dformat(to_fmt));
|
---|
848 | return NULL;
|
---|
849 | }
|
---|
850 |
|
---|
851 | IWineD3DDevice_CreateSurface((IWineD3DDevice *)source->resource.device, source->currentDesc.Width,
|
---|
852 | source->currentDesc.Height, to_fmt, TRUE /* lockable */, TRUE /* discard */, 0 /* level */, &ret,
|
---|
853 | 0 /* usage */, WINED3DPOOL_SCRATCH, WINED3DMULTISAMPLE_NONE /* TODO: Multisampled conversion */,
|
---|
854 | 0 /* MultiSampleQuality */, IWineD3DSurface_GetImplType((IWineD3DSurface *) source),
|
---|
855 | NULL /* parent */, &wined3d_null_parent_ops);
|
---|
856 | if(!ret) {
|
---|
857 | ERR("Failed to create a destination surface for conversion\n");
|
---|
858 | return NULL;
|
---|
859 | }
|
---|
860 |
|
---|
861 | memset(&lock_src, 0, sizeof(lock_src));
|
---|
862 | memset(&lock_dst, 0, sizeof(lock_dst));
|
---|
863 |
|
---|
864 | hr = IWineD3DSurface_LockRect((IWineD3DSurface *) source, &lock_src, NULL, WINED3DLOCK_READONLY);
|
---|
865 | if(FAILED(hr)) {
|
---|
866 | ERR("Failed to lock the source surface\n");
|
---|
867 | IWineD3DSurface_Release(ret);
|
---|
868 | return NULL;
|
---|
869 | }
|
---|
870 | hr = IWineD3DSurface_LockRect(ret, &lock_dst, NULL, WINED3DLOCK_READONLY);
|
---|
871 | if(FAILED(hr)) {
|
---|
872 | ERR("Failed to lock the dest surface\n");
|
---|
873 | IWineD3DSurface_UnlockRect((IWineD3DSurface *) source);
|
---|
874 | IWineD3DSurface_Release(ret);
|
---|
875 | return NULL;
|
---|
876 | }
|
---|
877 |
|
---|
878 | conv->convert(lock_src.pBits, lock_dst.pBits, lock_src.Pitch, lock_dst.Pitch,
|
---|
879 | source->currentDesc.Width, source->currentDesc.Height);
|
---|
880 |
|
---|
881 | IWineD3DSurface_UnlockRect(ret);
|
---|
882 | IWineD3DSurface_UnlockRect((IWineD3DSurface *) source);
|
---|
883 |
|
---|
884 | return (IWineD3DSurfaceImpl *) ret;
|
---|
885 | }
|
---|
886 |
|
---|
887 | /*****************************************************************************
|
---|
888 | * _Blt_ColorFill
|
---|
889 | *
|
---|
890 | * Helper function that fills a memory area with a specific color
|
---|
891 | *
|
---|
892 | * Params:
|
---|
893 | * buf: memory address to start filling at
|
---|
894 | * width, height: Dimensions of the area to fill
|
---|
895 | * bpp: Bit depth of the surface
|
---|
896 | * lPitch: pitch of the surface
|
---|
897 | * color: Color to fill with
|
---|
898 | *
|
---|
899 | *****************************************************************************/
|
---|
900 | static HRESULT
|
---|
901 | _Blt_ColorFill(BYTE *buf,
|
---|
902 | int width, int height,
|
---|
903 | int bpp, LONG lPitch,
|
---|
904 | DWORD color)
|
---|
905 | {
|
---|
906 | int x, y;
|
---|
907 | LPBYTE first;
|
---|
908 |
|
---|
909 | /* Do first row */
|
---|
910 |
|
---|
911 | #define COLORFILL_ROW(type) \
|
---|
912 | { \
|
---|
913 | type *d = (type *) buf; \
|
---|
914 | for (x = 0; x < width; x++) \
|
---|
915 | d[x] = (type) color; \
|
---|
916 | break; \
|
---|
917 | }
|
---|
918 | switch(bpp)
|
---|
919 | {
|
---|
920 | case 1: COLORFILL_ROW(BYTE)
|
---|
921 | case 2: COLORFILL_ROW(WORD)
|
---|
922 | case 3:
|
---|
923 | {
|
---|
924 | BYTE *d = buf;
|
---|
925 | for (x = 0; x < width; x++,d+=3)
|
---|
926 | {
|
---|
927 | d[0] = (color ) & 0xFF;
|
---|
928 | d[1] = (color>> 8) & 0xFF;
|
---|
929 | d[2] = (color>>16) & 0xFF;
|
---|
930 | }
|
---|
931 | break;
|
---|
932 | }
|
---|
933 | case 4: COLORFILL_ROW(DWORD)
|
---|
934 | default:
|
---|
935 | FIXME("Color fill not implemented for bpp %d!\n", bpp*8);
|
---|
936 | return WINED3DERR_NOTAVAILABLE;
|
---|
937 | }
|
---|
938 |
|
---|
939 | #undef COLORFILL_ROW
|
---|
940 |
|
---|
941 | /* Now copy first row */
|
---|
942 | first = buf;
|
---|
943 | for (y = 1; y < height; y++)
|
---|
944 | {
|
---|
945 | buf += lPitch;
|
---|
946 | memcpy(buf, first, width * bpp);
|
---|
947 | }
|
---|
948 | return WINED3D_OK;
|
---|
949 | }
|
---|
950 |
|
---|
951 | /*****************************************************************************
|
---|
952 | * IWineD3DSurface::Blt, SW emulation version
|
---|
953 | *
|
---|
954 | * Performs blits to a surface, eigher from a source of source-less blts
|
---|
955 | * This is the main functionality of DirectDraw
|
---|
956 | *
|
---|
957 | * Params:
|
---|
958 | * DestRect: Destination rectangle to write to
|
---|
959 | * SrcSurface: Source surface, can be NULL
|
---|
960 | * SrcRect: Source rectangle
|
---|
961 | *****************************************************************************/
|
---|
962 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT *DestRect, IWineD3DSurface *SrcSurface,
|
---|
963 | const RECT *SrcRect, DWORD Flags, const WINEDDBLTFX *DDBltFx, WINED3DTEXTUREFILTERTYPE Filter)
|
---|
964 | {
|
---|
965 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
966 | IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
|
---|
967 | RECT xdst,xsrc;
|
---|
968 | HRESULT ret = WINED3D_OK;
|
---|
969 | WINED3DLOCKED_RECT dlock, slock;
|
---|
970 | int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
|
---|
971 | const struct wined3d_format_desc *sEntry, *dEntry;
|
---|
972 | int x, y;
|
---|
973 | const BYTE *sbuf;
|
---|
974 | BYTE *dbuf;
|
---|
975 | TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, Src, SrcRect, Flags, DDBltFx);
|
---|
976 |
|
---|
977 | if (TRACE_ON(d3d_surface))
|
---|
978 | {
|
---|
979 | if (DestRect) TRACE("\tdestrect :%dx%d-%dx%d\n",
|
---|
980 | DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
|
---|
981 | if (SrcRect) TRACE("\tsrcrect :%dx%d-%dx%d\n",
|
---|
982 | SrcRect->left, SrcRect->top, SrcRect->right, SrcRect->bottom);
|
---|
983 | #if 0
|
---|
984 | TRACE("\tflags: ");
|
---|
985 | DDRAW_dump_DDBLT(Flags);
|
---|
986 | if (Flags & WINEDDBLT_DDFX)
|
---|
987 | {
|
---|
988 | TRACE("\tblitfx: ");
|
---|
989 | DDRAW_dump_DDBLTFX(DDBltFx->dwDDFX);
|
---|
990 | }
|
---|
991 | #endif
|
---|
992 | }
|
---|
993 |
|
---|
994 | if ( (This->Flags & SFLAG_LOCKED) || ((Src != NULL) && (Src->Flags & SFLAG_LOCKED)))
|
---|
995 | {
|
---|
996 | WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
|
---|
997 | return WINEDDERR_SURFACEBUSY;
|
---|
998 | }
|
---|
999 |
|
---|
1000 | if(Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT) {
|
---|
1001 | /* Can happen when d3d9 apps do a StretchRect call which isn't handled in gl */
|
---|
1002 | FIXME("Filters not supported in software blit\n");
|
---|
1003 | }
|
---|
1004 |
|
---|
1005 | /* First check for the validity of source / destination rectangles. This was
|
---|
1006 | * verified using a test application + by MSDN.
|
---|
1007 | */
|
---|
1008 | if ((Src != NULL) && (SrcRect != NULL) &&
|
---|
1009 | ((SrcRect->bottom > Src->currentDesc.Height)||(SrcRect->bottom < 0) ||
|
---|
1010 | (SrcRect->top > Src->currentDesc.Height)||(SrcRect->top < 0) ||
|
---|
1011 | (SrcRect->left > Src->currentDesc.Width) ||(SrcRect->left < 0) ||
|
---|
1012 | (SrcRect->right > Src->currentDesc.Width) ||(SrcRect->right < 0) ||
|
---|
1013 | (SrcRect->right < SrcRect->left) ||(SrcRect->bottom < SrcRect->top)))
|
---|
1014 | {
|
---|
1015 | WARN("Application gave us bad source rectangle for Blt.\n");
|
---|
1016 | return WINEDDERR_INVALIDRECT;
|
---|
1017 | }
|
---|
1018 | /* For the Destination rect, it can be out of bounds on the condition that a clipper
|
---|
1019 | * is set for the given surface.
|
---|
1020 | */
|
---|
1021 | if ((/*This->clipper == NULL*/ TRUE) && (DestRect) &&
|
---|
1022 | ((DestRect->bottom > This->currentDesc.Height)||(DestRect->bottom < 0) ||
|
---|
1023 | (DestRect->top > This->currentDesc.Height)||(DestRect->top < 0) ||
|
---|
1024 | (DestRect->left > This->currentDesc.Width) ||(DestRect->left < 0) ||
|
---|
1025 | (DestRect->right > This->currentDesc.Width) ||(DestRect->right < 0) ||
|
---|
1026 | (DestRect->right < DestRect->left) ||(DestRect->bottom < DestRect->top)))
|
---|
1027 | {
|
---|
1028 | WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n");
|
---|
1029 | return WINEDDERR_INVALIDRECT;
|
---|
1030 | }
|
---|
1031 |
|
---|
1032 | /* Now handle negative values in the rectangles. Warning: only supported for now
|
---|
1033 | in the 'simple' cases (ie not in any stretching / rotation cases).
|
---|
1034 |
|
---|
1035 | First, the case where nothing is to be done.
|
---|
1036 | */
|
---|
1037 | if ((DestRect && ((DestRect->bottom <= 0) || (DestRect->right <= 0) ||
|
---|
1038 | (DestRect->top >= (int) This->currentDesc.Height) ||
|
---|
1039 | (DestRect->left >= (int) This->currentDesc.Width))) ||
|
---|
1040 | ((Src != NULL) && (SrcRect != NULL) &&
|
---|
1041 | ((SrcRect->bottom <= 0) || (SrcRect->right <= 0) ||
|
---|
1042 | (SrcRect->top >= (int) Src->currentDesc.Height) ||
|
---|
1043 | (SrcRect->left >= (int) Src->currentDesc.Width)) ))
|
---|
1044 | {
|
---|
1045 | TRACE("Nothing to be done !\n");
|
---|
1046 | return WINED3D_OK;
|
---|
1047 | }
|
---|
1048 |
|
---|
1049 | if (DestRect)
|
---|
1050 | {
|
---|
1051 | xdst = *DestRect;
|
---|
1052 | }
|
---|
1053 | else
|
---|
1054 | {
|
---|
1055 | xdst.top = 0;
|
---|
1056 | xdst.bottom = This->currentDesc.Height;
|
---|
1057 | xdst.left = 0;
|
---|
1058 | xdst.right = This->currentDesc.Width;
|
---|
1059 | }
|
---|
1060 |
|
---|
1061 | if (SrcRect)
|
---|
1062 | {
|
---|
1063 | xsrc = *SrcRect;
|
---|
1064 | }
|
---|
1065 | else
|
---|
1066 | {
|
---|
1067 | if (Src)
|
---|
1068 | {
|
---|
1069 | xsrc.top = 0;
|
---|
1070 | xsrc.bottom = Src->currentDesc.Height;
|
---|
1071 | xsrc.left = 0;
|
---|
1072 | xsrc.right = Src->currentDesc.Width;
|
---|
1073 | }
|
---|
1074 | else
|
---|
1075 | {
|
---|
1076 | memset(&xsrc,0,sizeof(xsrc));
|
---|
1077 | }
|
---|
1078 | }
|
---|
1079 |
|
---|
1080 | /* The easy case : the source-less blits.... */
|
---|
1081 | if (Src == NULL && DestRect)
|
---|
1082 | {
|
---|
1083 | RECT full_rect;
|
---|
1084 | RECT temp_rect; /* No idea if intersect rect can be the same as one of the source rect */
|
---|
1085 |
|
---|
1086 | full_rect.left = 0;
|
---|
1087 | full_rect.top = 0;
|
---|
1088 | full_rect.right = This->currentDesc.Width;
|
---|
1089 | full_rect.bottom = This->currentDesc.Height;
|
---|
1090 | IntersectRect(&temp_rect, &full_rect, DestRect);
|
---|
1091 | xdst = temp_rect;
|
---|
1092 | }
|
---|
1093 | else if (DestRect)
|
---|
1094 | {
|
---|
1095 | /* Only handle clipping on the destination rectangle */
|
---|
1096 | int clip_horiz = (DestRect->left < 0) || (DestRect->right > (int) This->currentDesc.Width );
|
---|
1097 | int clip_vert = (DestRect->top < 0) || (DestRect->bottom > (int) This->currentDesc.Height);
|
---|
1098 | if (clip_vert || clip_horiz)
|
---|
1099 | {
|
---|
1100 | /* Now check if this is a special case or not... */
|
---|
1101 | if ((((DestRect->bottom - DestRect->top ) != (xsrc.bottom - xsrc.top )) && clip_vert ) ||
|
---|
1102 | (((DestRect->right - DestRect->left) != (xsrc.right - xsrc.left)) && clip_horiz) ||
|
---|
1103 | (Flags & WINEDDBLT_DDFX))
|
---|
1104 | {
|
---|
1105 | WARN("Out of screen rectangle in special case. Not handled right now.\n");
|
---|
1106 | return WINED3D_OK;
|
---|
1107 | }
|
---|
1108 |
|
---|
1109 | if (clip_horiz)
|
---|
1110 | {
|
---|
1111 | if (DestRect->left < 0) { xsrc.left -= DestRect->left; xdst.left = 0; }
|
---|
1112 | if (DestRect->right > This->currentDesc.Width)
|
---|
1113 | {
|
---|
1114 | xsrc.right -= (DestRect->right - (int) This->currentDesc.Width);
|
---|
1115 | xdst.right = (int) This->currentDesc.Width;
|
---|
1116 | }
|
---|
1117 | }
|
---|
1118 | if (clip_vert)
|
---|
1119 | {
|
---|
1120 | if (DestRect->top < 0)
|
---|
1121 | {
|
---|
1122 | xsrc.top -= DestRect->top;
|
---|
1123 | xdst.top = 0;
|
---|
1124 | }
|
---|
1125 | if (DestRect->bottom > This->currentDesc.Height)
|
---|
1126 | {
|
---|
1127 | xsrc.bottom -= (DestRect->bottom - (int) This->currentDesc.Height);
|
---|
1128 | xdst.bottom = (int) This->currentDesc.Height;
|
---|
1129 | }
|
---|
1130 | }
|
---|
1131 | /* And check if after clipping something is still to be done... */
|
---|
1132 | if ((xdst.bottom <= 0) || (xdst.right <= 0) ||
|
---|
1133 | (xdst.top >= (int) This->currentDesc.Height) ||
|
---|
1134 | (xdst.left >= (int) This->currentDesc.Width) ||
|
---|
1135 | (xsrc.bottom <= 0) || (xsrc.right <= 0) ||
|
---|
1136 | (xsrc.top >= (int) Src->currentDesc.Height) ||
|
---|
1137 | (xsrc.left >= (int) Src->currentDesc.Width))
|
---|
1138 | {
|
---|
1139 | TRACE("Nothing to be done after clipping !\n");
|
---|
1140 | return WINED3D_OK;
|
---|
1141 | }
|
---|
1142 | }
|
---|
1143 | }
|
---|
1144 |
|
---|
1145 | if (Src == This)
|
---|
1146 | {
|
---|
1147 | IWineD3DSurface_LockRect(iface, &dlock, NULL, 0);
|
---|
1148 | slock = dlock;
|
---|
1149 | sEntry = This->resource.format_desc;
|
---|
1150 | dEntry = sEntry;
|
---|
1151 | }
|
---|
1152 | else
|
---|
1153 | {
|
---|
1154 | dEntry = This->resource.format_desc;
|
---|
1155 | if (Src)
|
---|
1156 | {
|
---|
1157 | if (This->resource.format_desc->format != Src->resource.format_desc->format)
|
---|
1158 | {
|
---|
1159 | Src = surface_convert_format(Src, dEntry->format);
|
---|
1160 | if(!Src) {
|
---|
1161 | /* The conv function writes a FIXME */
|
---|
1162 | WARN("Cannot convert source surface format to dest format\n");
|
---|
1163 | goto release;
|
---|
1164 | }
|
---|
1165 | }
|
---|
1166 | IWineD3DSurface_LockRect((IWineD3DSurface *) Src, &slock, NULL, WINED3DLOCK_READONLY);
|
---|
1167 | sEntry = Src->resource.format_desc;
|
---|
1168 | }
|
---|
1169 | else
|
---|
1170 | {
|
---|
1171 | sEntry = dEntry;
|
---|
1172 | }
|
---|
1173 | if (DestRect)
|
---|
1174 | IWineD3DSurface_LockRect(iface, &dlock, &xdst, 0);
|
---|
1175 | else
|
---|
1176 | IWineD3DSurface_LockRect(iface, &dlock, NULL, 0);
|
---|
1177 | }
|
---|
1178 |
|
---|
1179 | if (!DDBltFx || !(DDBltFx->dwDDFX)) Flags &= ~WINEDDBLT_DDFX;
|
---|
1180 |
|
---|
1181 | if (sEntry->Flags & dEntry->Flags & WINED3DFMT_FLAG_FOURCC)
|
---|
1182 | {
|
---|
1183 | if (!DestRect || Src == This)
|
---|
1184 | {
|
---|
1185 | memcpy(dlock.pBits, slock.pBits, This->resource.size);
|
---|
1186 | goto release;
|
---|
1187 | }
|
---|
1188 | }
|
---|
1189 |
|
---|
1190 | bpp = This->resource.format_desc->byte_count;
|
---|
1191 | srcheight = xsrc.bottom - xsrc.top;
|
---|
1192 | srcwidth = xsrc.right - xsrc.left;
|
---|
1193 | dstheight = xdst.bottom - xdst.top;
|
---|
1194 | dstwidth = xdst.right - xdst.left;
|
---|
1195 | width = (xdst.right - xdst.left) * bpp;
|
---|
1196 |
|
---|
1197 | if (DestRect && Src != This)
|
---|
1198 | dbuf = dlock.pBits;
|
---|
1199 | else
|
---|
1200 | dbuf = (BYTE*)dlock.pBits+(xdst.top*dlock.Pitch)+(xdst.left*bpp);
|
---|
1201 |
|
---|
1202 | if (Flags & WINEDDBLT_WAIT)
|
---|
1203 | {
|
---|
1204 | Flags &= ~WINEDDBLT_WAIT;
|
---|
1205 | }
|
---|
1206 | if (Flags & WINEDDBLT_ASYNC)
|
---|
1207 | {
|
---|
1208 | static BOOL displayed = FALSE;
|
---|
1209 | if (!displayed)
|
---|
1210 | FIXME("Can't handle WINEDDBLT_ASYNC flag right now.\n");
|
---|
1211 | displayed = TRUE;
|
---|
1212 | Flags &= ~WINEDDBLT_ASYNC;
|
---|
1213 | }
|
---|
1214 | if (Flags & WINEDDBLT_DONOTWAIT)
|
---|
1215 | {
|
---|
1216 | /* WINEDDBLT_DONOTWAIT appeared in DX7 */
|
---|
1217 | static BOOL displayed = FALSE;
|
---|
1218 | if (!displayed)
|
---|
1219 | FIXME("Can't handle WINEDDBLT_DONOTWAIT flag right now.\n");
|
---|
1220 | displayed = TRUE;
|
---|
1221 | Flags &= ~WINEDDBLT_DONOTWAIT;
|
---|
1222 | }
|
---|
1223 |
|
---|
1224 | /* First, all the 'source-less' blits */
|
---|
1225 | if (Flags & WINEDDBLT_COLORFILL)
|
---|
1226 | {
|
---|
1227 | ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp,
|
---|
1228 | dlock.Pitch, DDBltFx->u5.dwFillColor);
|
---|
1229 | Flags &= ~WINEDDBLT_COLORFILL;
|
---|
1230 | }
|
---|
1231 |
|
---|
1232 | if (Flags & WINEDDBLT_DEPTHFILL)
|
---|
1233 | {
|
---|
1234 | FIXME("DDBLT_DEPTHFILL needs to be implemented!\n");
|
---|
1235 | }
|
---|
1236 | if (Flags & WINEDDBLT_ROP)
|
---|
1237 | {
|
---|
1238 | /* Catch some degenerate cases here */
|
---|
1239 | switch(DDBltFx->dwROP)
|
---|
1240 | {
|
---|
1241 | case BLACKNESS:
|
---|
1242 | ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,dlock.Pitch,0);
|
---|
1243 | break;
|
---|
1244 | case 0xAA0029: /* No-op */
|
---|
1245 | break;
|
---|
1246 | case WHITENESS:
|
---|
1247 | ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,dlock.Pitch,~0);
|
---|
1248 | break;
|
---|
1249 | case SRCCOPY: /* well, we do that below ? */
|
---|
1250 | break;
|
---|
1251 | default:
|
---|
1252 | FIXME("Unsupported raster op: %08x Pattern: %p\n", DDBltFx->dwROP, DDBltFx->u5.lpDDSPattern);
|
---|
1253 | goto error;
|
---|
1254 | }
|
---|
1255 | Flags &= ~WINEDDBLT_ROP;
|
---|
1256 | }
|
---|
1257 | if (Flags & WINEDDBLT_DDROPS)
|
---|
1258 | {
|
---|
1259 | FIXME("\tDdraw Raster Ops: %08x Pattern: %p\n", DDBltFx->dwDDROP, DDBltFx->u5.lpDDSPattern);
|
---|
1260 | }
|
---|
1261 | /* Now the 'with source' blits */
|
---|
1262 | if (Src)
|
---|
1263 | {
|
---|
1264 | const BYTE *sbase;
|
---|
1265 | int sx, xinc, sy, yinc;
|
---|
1266 |
|
---|
1267 | if (!dstwidth || !dstheight) /* hmm... stupid program ? */
|
---|
1268 | goto release;
|
---|
1269 | sbase = (BYTE*)slock.pBits+(xsrc.top*slock.Pitch)+xsrc.left*bpp;
|
---|
1270 | xinc = (srcwidth << 16) / dstwidth;
|
---|
1271 | yinc = (srcheight << 16) / dstheight;
|
---|
1272 |
|
---|
1273 | if (!Flags)
|
---|
1274 | {
|
---|
1275 | /* No effects, we can cheat here */
|
---|
1276 | if (dstwidth == srcwidth)
|
---|
1277 | {
|
---|
1278 | if (dstheight == srcheight)
|
---|
1279 | {
|
---|
1280 | /* No stretching in either direction. This needs to be as
|
---|
1281 | * fast as possible */
|
---|
1282 | sbuf = sbase;
|
---|
1283 |
|
---|
1284 | /* check for overlapping surfaces */
|
---|
1285 | if (Src != This || xdst.top < xsrc.top ||
|
---|
1286 | xdst.right <= xsrc.left || xsrc.right <= xdst.left)
|
---|
1287 | {
|
---|
1288 | /* no overlap, or dst above src, so copy from top downwards */
|
---|
1289 | for (y = 0; y < dstheight; y++)
|
---|
1290 | {
|
---|
1291 | memcpy(dbuf, sbuf, width);
|
---|
1292 | sbuf += slock.Pitch;
|
---|
1293 | dbuf += dlock.Pitch;
|
---|
1294 | }
|
---|
1295 | }
|
---|
1296 | else if (xdst.top > xsrc.top) /* copy from bottom upwards */
|
---|
1297 | {
|
---|
1298 | sbuf += (slock.Pitch*dstheight);
|
---|
1299 | dbuf += (dlock.Pitch*dstheight);
|
---|
1300 | for (y = 0; y < dstheight; y++)
|
---|
1301 | {
|
---|
1302 | sbuf -= slock.Pitch;
|
---|
1303 | dbuf -= dlock.Pitch;
|
---|
1304 | memcpy(dbuf, sbuf, width);
|
---|
1305 | }
|
---|
1306 | }
|
---|
1307 | else /* src and dst overlapping on the same line, use memmove */
|
---|
1308 | {
|
---|
1309 | for (y = 0; y < dstheight; y++)
|
---|
1310 | {
|
---|
1311 | memmove(dbuf, sbuf, width);
|
---|
1312 | sbuf += slock.Pitch;
|
---|
1313 | dbuf += dlock.Pitch;
|
---|
1314 | }
|
---|
1315 | }
|
---|
1316 | } else {
|
---|
1317 | /* Stretching in Y direction only */
|
---|
1318 | for (y = sy = 0; y < dstheight; y++, sy += yinc) {
|
---|
1319 | sbuf = sbase + (sy >> 16) * slock.Pitch;
|
---|
1320 | memcpy(dbuf, sbuf, width);
|
---|
1321 | dbuf += dlock.Pitch;
|
---|
1322 | }
|
---|
1323 | }
|
---|
1324 | }
|
---|
1325 | else
|
---|
1326 | {
|
---|
1327 | /* Stretching in X direction */
|
---|
1328 | int last_sy = -1;
|
---|
1329 | for (y = sy = 0; y < dstheight; y++, sy += yinc)
|
---|
1330 | {
|
---|
1331 | sbuf = sbase + (sy >> 16) * slock.Pitch;
|
---|
1332 |
|
---|
1333 | if ((sy >> 16) == (last_sy >> 16))
|
---|
1334 | {
|
---|
1335 | /* this sourcerow is the same as last sourcerow -
|
---|
1336 | * copy already stretched row
|
---|
1337 | */
|
---|
1338 | memcpy(dbuf, dbuf - dlock.Pitch, width);
|
---|
1339 | }
|
---|
1340 | else
|
---|
1341 | {
|
---|
1342 | #define STRETCH_ROW(type) { \
|
---|
1343 | const type *s = (const type *)sbuf; \
|
---|
1344 | type *d = (type *)dbuf; \
|
---|
1345 | for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
|
---|
1346 | d[x] = s[sx >> 16]; \
|
---|
1347 | break; }
|
---|
1348 |
|
---|
1349 | switch(bpp)
|
---|
1350 | {
|
---|
1351 | case 1: STRETCH_ROW(BYTE)
|
---|
1352 | case 2: STRETCH_ROW(WORD)
|
---|
1353 | case 4: STRETCH_ROW(DWORD)
|
---|
1354 | case 3:
|
---|
1355 | {
|
---|
1356 | const BYTE *s;
|
---|
1357 | BYTE *d = dbuf;
|
---|
1358 | for (x = sx = 0; x < dstwidth; x++, sx+= xinc)
|
---|
1359 | {
|
---|
1360 | DWORD pixel;
|
---|
1361 |
|
---|
1362 | s = sbuf+3*(sx>>16);
|
---|
1363 | pixel = s[0]|(s[1]<<8)|(s[2]<<16);
|
---|
1364 | d[0] = (pixel )&0xff;
|
---|
1365 | d[1] = (pixel>> 8)&0xff;
|
---|
1366 | d[2] = (pixel>>16)&0xff;
|
---|
1367 | d+=3;
|
---|
1368 | }
|
---|
1369 | break;
|
---|
1370 | }
|
---|
1371 | default:
|
---|
1372 | FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8);
|
---|
1373 | ret = WINED3DERR_NOTAVAILABLE;
|
---|
1374 | goto error;
|
---|
1375 | }
|
---|
1376 | #undef STRETCH_ROW
|
---|
1377 | }
|
---|
1378 | dbuf += dlock.Pitch;
|
---|
1379 | last_sy = sy;
|
---|
1380 | }
|
---|
1381 | }
|
---|
1382 | }
|
---|
1383 | else
|
---|
1384 | {
|
---|
1385 | LONG dstyinc = dlock.Pitch, dstxinc = bpp;
|
---|
1386 | DWORD keylow = 0xFFFFFFFF, keyhigh = 0, keymask = 0xFFFFFFFF;
|
---|
1387 | DWORD destkeylow = 0x0, destkeyhigh = 0xFFFFFFFF, destkeymask = 0xFFFFFFFF;
|
---|
1388 | if (Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE))
|
---|
1389 | {
|
---|
1390 | /* The color keying flags are checked for correctness in ddraw */
|
---|
1391 | if (Flags & WINEDDBLT_KEYSRC)
|
---|
1392 | {
|
---|
1393 | keylow = Src->SrcBltCKey.dwColorSpaceLowValue;
|
---|
1394 | keyhigh = Src->SrcBltCKey.dwColorSpaceHighValue;
|
---|
1395 | }
|
---|
1396 | else if (Flags & WINEDDBLT_KEYSRCOVERRIDE)
|
---|
1397 | {
|
---|
1398 | keylow = DDBltFx->ddckSrcColorkey.dwColorSpaceLowValue;
|
---|
1399 | keyhigh = DDBltFx->ddckSrcColorkey.dwColorSpaceHighValue;
|
---|
1400 | }
|
---|
1401 |
|
---|
1402 | if (Flags & WINEDDBLT_KEYDEST)
|
---|
1403 | {
|
---|
1404 | /* Destination color keys are taken from the source surface ! */
|
---|
1405 | destkeylow = Src->DestBltCKey.dwColorSpaceLowValue;
|
---|
1406 | destkeyhigh = Src->DestBltCKey.dwColorSpaceHighValue;
|
---|
1407 | }
|
---|
1408 | else if (Flags & WINEDDBLT_KEYDESTOVERRIDE)
|
---|
1409 | {
|
---|
1410 | destkeylow = DDBltFx->ddckDestColorkey.dwColorSpaceLowValue;
|
---|
1411 | destkeyhigh = DDBltFx->ddckDestColorkey.dwColorSpaceHighValue;
|
---|
1412 | }
|
---|
1413 |
|
---|
1414 | if(bpp == 1)
|
---|
1415 | {
|
---|
1416 | keymask = 0xff;
|
---|
1417 | }
|
---|
1418 | else
|
---|
1419 | {
|
---|
1420 | keymask = sEntry->red_mask
|
---|
1421 | | sEntry->green_mask
|
---|
1422 | | sEntry->blue_mask;
|
---|
1423 | }
|
---|
1424 | Flags &= ~(WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE);
|
---|
1425 | }
|
---|
1426 |
|
---|
1427 | if (Flags & WINEDDBLT_DDFX)
|
---|
1428 | {
|
---|
1429 | LPBYTE dTopLeft, dTopRight, dBottomLeft, dBottomRight, tmp;
|
---|
1430 | LONG tmpxy;
|
---|
1431 | dTopLeft = dbuf;
|
---|
1432 | dTopRight = dbuf+((dstwidth-1)*bpp);
|
---|
1433 | dBottomLeft = dTopLeft+((dstheight-1)*dlock.Pitch);
|
---|
1434 | dBottomRight = dBottomLeft+((dstwidth-1)*bpp);
|
---|
1435 |
|
---|
1436 | if (DDBltFx->dwDDFX & WINEDDBLTFX_ARITHSTRETCHY)
|
---|
1437 | {
|
---|
1438 | /* I don't think we need to do anything about this flag */
|
---|
1439 | WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_ARITHSTRETCHY\n");
|
---|
1440 | }
|
---|
1441 | if (DDBltFx->dwDDFX & WINEDDBLTFX_MIRRORLEFTRIGHT)
|
---|
1442 | {
|
---|
1443 | tmp = dTopRight;
|
---|
1444 | dTopRight = dTopLeft;
|
---|
1445 | dTopLeft = tmp;
|
---|
1446 | tmp = dBottomRight;
|
---|
1447 | dBottomRight = dBottomLeft;
|
---|
1448 | dBottomLeft = tmp;
|
---|
1449 | dstxinc = dstxinc *-1;
|
---|
1450 | }
|
---|
1451 | if (DDBltFx->dwDDFX & WINEDDBLTFX_MIRRORUPDOWN)
|
---|
1452 | {
|
---|
1453 | tmp = dTopLeft;
|
---|
1454 | dTopLeft = dBottomLeft;
|
---|
1455 | dBottomLeft = tmp;
|
---|
1456 | tmp = dTopRight;
|
---|
1457 | dTopRight = dBottomRight;
|
---|
1458 | dBottomRight = tmp;
|
---|
1459 | dstyinc = dstyinc *-1;
|
---|
1460 | }
|
---|
1461 | if (DDBltFx->dwDDFX & WINEDDBLTFX_NOTEARING)
|
---|
1462 | {
|
---|
1463 | /* I don't think we need to do anything about this flag */
|
---|
1464 | WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_NOTEARING\n");
|
---|
1465 | }
|
---|
1466 | if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE180)
|
---|
1467 | {
|
---|
1468 | tmp = dBottomRight;
|
---|
1469 | dBottomRight = dTopLeft;
|
---|
1470 | dTopLeft = tmp;
|
---|
1471 | tmp = dBottomLeft;
|
---|
1472 | dBottomLeft = dTopRight;
|
---|
1473 | dTopRight = tmp;
|
---|
1474 | dstxinc = dstxinc * -1;
|
---|
1475 | dstyinc = dstyinc * -1;
|
---|
1476 | }
|
---|
1477 | if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE270)
|
---|
1478 | {
|
---|
1479 | tmp = dTopLeft;
|
---|
1480 | dTopLeft = dBottomLeft;
|
---|
1481 | dBottomLeft = dBottomRight;
|
---|
1482 | dBottomRight = dTopRight;
|
---|
1483 | dTopRight = tmp;
|
---|
1484 | tmpxy = dstxinc;
|
---|
1485 | dstxinc = dstyinc;
|
---|
1486 | dstyinc = tmpxy;
|
---|
1487 | dstxinc = dstxinc * -1;
|
---|
1488 | }
|
---|
1489 | if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE90)
|
---|
1490 | {
|
---|
1491 | tmp = dTopLeft;
|
---|
1492 | dTopLeft = dTopRight;
|
---|
1493 | dTopRight = dBottomRight;
|
---|
1494 | dBottomRight = dBottomLeft;
|
---|
1495 | dBottomLeft = tmp;
|
---|
1496 | tmpxy = dstxinc;
|
---|
1497 | dstxinc = dstyinc;
|
---|
1498 | dstyinc = tmpxy;
|
---|
1499 | dstyinc = dstyinc * -1;
|
---|
1500 | }
|
---|
1501 | if (DDBltFx->dwDDFX & WINEDDBLTFX_ZBUFFERBASEDEST)
|
---|
1502 | {
|
---|
1503 | /* I don't think we need to do anything about this flag */
|
---|
1504 | WARN("Flags=WINEDDBLT_DDFX nothing done for WINEDDBLTFX_ZBUFFERBASEDEST\n");
|
---|
1505 | }
|
---|
1506 | dbuf = dTopLeft;
|
---|
1507 | Flags &= ~(WINEDDBLT_DDFX);
|
---|
1508 | }
|
---|
1509 |
|
---|
1510 | #define COPY_COLORKEY_FX(type) { \
|
---|
1511 | const type *s; \
|
---|
1512 | type *d = (type *)dbuf, *dx, tmp; \
|
---|
1513 | for (y = sy = 0; y < dstheight; y++, sy += yinc) { \
|
---|
1514 | s = (const type*)(sbase + (sy >> 16) * slock.Pitch); \
|
---|
1515 | dx = d; \
|
---|
1516 | for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
|
---|
1517 | tmp = s[sx >> 16]; \
|
---|
1518 | if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) && \
|
---|
1519 | ((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) { \
|
---|
1520 | dx[0] = tmp; \
|
---|
1521 | } \
|
---|
1522 | dx = (type*)(((LPBYTE)dx)+dstxinc); \
|
---|
1523 | } \
|
---|
1524 | d = (type*)(((LPBYTE)d)+dstyinc); \
|
---|
1525 | } \
|
---|
1526 | break; }
|
---|
1527 |
|
---|
1528 | switch (bpp) {
|
---|
1529 | case 1: COPY_COLORKEY_FX(BYTE)
|
---|
1530 | case 2: COPY_COLORKEY_FX(WORD)
|
---|
1531 | case 4: COPY_COLORKEY_FX(DWORD)
|
---|
1532 | case 3:
|
---|
1533 | {
|
---|
1534 | const BYTE *s;
|
---|
1535 | BYTE *d = dbuf, *dx;
|
---|
1536 | for (y = sy = 0; y < dstheight; y++, sy += yinc)
|
---|
1537 | {
|
---|
1538 | sbuf = sbase + (sy >> 16) * slock.Pitch;
|
---|
1539 | dx = d;
|
---|
1540 | for (x = sx = 0; x < dstwidth; x++, sx+= xinc)
|
---|
1541 | {
|
---|
1542 | DWORD pixel, dpixel = 0;
|
---|
1543 | s = sbuf+3*(sx>>16);
|
---|
1544 | pixel = s[0]|(s[1]<<8)|(s[2]<<16);
|
---|
1545 | dpixel = dx[0]|(dx[1]<<8)|(dx[2]<<16);
|
---|
1546 | if (((pixel & keymask) < keylow || (pixel & keymask) > keyhigh) &&
|
---|
1547 | ((dpixel & keymask) >= destkeylow || (dpixel & keymask) <= keyhigh))
|
---|
1548 | {
|
---|
1549 | dx[0] = (pixel )&0xff;
|
---|
1550 | dx[1] = (pixel>> 8)&0xff;
|
---|
1551 | dx[2] = (pixel>>16)&0xff;
|
---|
1552 | }
|
---|
1553 | dx+= dstxinc;
|
---|
1554 | }
|
---|
1555 | d += dstyinc;
|
---|
1556 | }
|
---|
1557 | break;
|
---|
1558 | }
|
---|
1559 | default:
|
---|
1560 | FIXME("%s color-keyed blit not implemented for bpp %d!\n",
|
---|
1561 | (Flags & WINEDDBLT_KEYSRC) ? "Source" : "Destination", bpp*8);
|
---|
1562 | ret = WINED3DERR_NOTAVAILABLE;
|
---|
1563 | goto error;
|
---|
1564 | #undef COPY_COLORKEY_FX
|
---|
1565 | }
|
---|
1566 | }
|
---|
1567 | }
|
---|
1568 |
|
---|
1569 | error:
|
---|
1570 | if (Flags && FIXME_ON(d3d_surface))
|
---|
1571 | {
|
---|
1572 | FIXME("\tUnsupported flags: %08x\n", Flags);
|
---|
1573 | }
|
---|
1574 |
|
---|
1575 | release:
|
---|
1576 | IWineD3DSurface_UnlockRect(iface);
|
---|
1577 | if (Src && Src != This) IWineD3DSurface_UnlockRect((IWineD3DSurface *) Src);
|
---|
1578 | /* Release the converted surface if any */
|
---|
1579 | if (Src && SrcSurface != (IWineD3DSurface *) Src) IWineD3DSurface_Release((IWineD3DSurface *) Src);
|
---|
1580 | return ret;
|
---|
1581 | }
|
---|
1582 |
|
---|
1583 | /*****************************************************************************
|
---|
1584 | * IWineD3DSurface::BltFast, SW emulation version
|
---|
1585 | *
|
---|
1586 | * This is the software implementation of BltFast, as used by GDI surfaces
|
---|
1587 | * and as a fallback for OpenGL surfaces. This code is taken from the old
|
---|
1588 | * DirectDraw code, and was originally written by TransGaming.
|
---|
1589 | *
|
---|
1590 | * Params:
|
---|
1591 | * dstx:
|
---|
1592 | * dsty:
|
---|
1593 | * Source: Source surface to copy from
|
---|
1594 | * rsrc: Source rectangle
|
---|
1595 | * trans: Some Flags
|
---|
1596 | *
|
---|
1597 | * Returns:
|
---|
1598 | * WINED3D_OK on success
|
---|
1599 | *
|
---|
1600 | *****************************************************************************/
|
---|
1601 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty,
|
---|
1602 | IWineD3DSurface *Source, const RECT *rsrc, DWORD trans)
|
---|
1603 | {
|
---|
1604 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
1605 | IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) Source;
|
---|
1606 |
|
---|
1607 | int bpp, w, h, x, y;
|
---|
1608 | WINED3DLOCKED_RECT dlock,slock;
|
---|
1609 | HRESULT ret = WINED3D_OK;
|
---|
1610 | RECT rsrc2;
|
---|
1611 | RECT lock_src, lock_dst, lock_union;
|
---|
1612 | const BYTE *sbuf;
|
---|
1613 | BYTE *dbuf;
|
---|
1614 | const struct wined3d_format_desc *sEntry, *dEntry;
|
---|
1615 |
|
---|
1616 | if (TRACE_ON(d3d_surface))
|
---|
1617 | {
|
---|
1618 | TRACE("(%p)->(%d,%d,%p,%p,%08x)\n", This,dstx,dsty,Src,rsrc,trans);
|
---|
1619 |
|
---|
1620 | if (rsrc)
|
---|
1621 | {
|
---|
1622 | TRACE("\tsrcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,
|
---|
1623 | rsrc->right,rsrc->bottom);
|
---|
1624 | }
|
---|
1625 | else
|
---|
1626 | {
|
---|
1627 | TRACE(" srcrect: NULL\n");
|
---|
1628 | }
|
---|
1629 | }
|
---|
1630 |
|
---|
1631 | if ((This->Flags & SFLAG_LOCKED) ||
|
---|
1632 | (Src->Flags & SFLAG_LOCKED))
|
---|
1633 | {
|
---|
1634 | WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
|
---|
1635 | return WINEDDERR_SURFACEBUSY;
|
---|
1636 | }
|
---|
1637 |
|
---|
1638 | if (!rsrc)
|
---|
1639 | {
|
---|
1640 | WARN("rsrc is NULL!\n");
|
---|
1641 | rsrc2.left = 0;
|
---|
1642 | rsrc2.top = 0;
|
---|
1643 | rsrc2.right = Src->currentDesc.Width;
|
---|
1644 | rsrc2.bottom = Src->currentDesc.Height;
|
---|
1645 | rsrc = &rsrc2;
|
---|
1646 | }
|
---|
1647 |
|
---|
1648 | /* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate.*/
|
---|
1649 | if ((rsrc->bottom > Src->currentDesc.Height) || (rsrc->bottom < 0) ||
|
---|
1650 | (rsrc->top > Src->currentDesc.Height) || (rsrc->top < 0) ||
|
---|
1651 | (rsrc->left > Src->currentDesc.Width) || (rsrc->left < 0) ||
|
---|
1652 | (rsrc->right > Src->currentDesc.Width) || (rsrc->right < 0) ||
|
---|
1653 | (rsrc->right < rsrc->left) || (rsrc->bottom < rsrc->top))
|
---|
1654 | {
|
---|
1655 | WARN("Application gave us bad source rectangle for BltFast.\n");
|
---|
1656 | return WINEDDERR_INVALIDRECT;
|
---|
1657 | }
|
---|
1658 |
|
---|
1659 | h = rsrc->bottom - rsrc->top;
|
---|
1660 | if (h > This->currentDesc.Height-dsty) h = This->currentDesc.Height-dsty;
|
---|
1661 | if (h > Src->currentDesc.Height-rsrc->top) h=Src->currentDesc.Height-rsrc->top;
|
---|
1662 | if (h <= 0) return WINEDDERR_INVALIDRECT;
|
---|
1663 |
|
---|
1664 | w = rsrc->right - rsrc->left;
|
---|
1665 | if (w > This->currentDesc.Width-dstx) w = This->currentDesc.Width-dstx;
|
---|
1666 | if (w > Src->currentDesc.Width-rsrc->left) w = Src->currentDesc.Width-rsrc->left;
|
---|
1667 | if (w <= 0) return WINEDDERR_INVALIDRECT;
|
---|
1668 |
|
---|
1669 | /* Now compute the locking rectangle... */
|
---|
1670 | lock_src.left = rsrc->left;
|
---|
1671 | lock_src.top = rsrc->top;
|
---|
1672 | lock_src.right = lock_src.left + w;
|
---|
1673 | lock_src.bottom = lock_src.top + h;
|
---|
1674 |
|
---|
1675 | lock_dst.left = dstx;
|
---|
1676 | lock_dst.top = dsty;
|
---|
1677 | lock_dst.right = dstx + w;
|
---|
1678 | lock_dst.bottom = dsty + h;
|
---|
1679 |
|
---|
1680 | bpp = This->resource.format_desc->byte_count;
|
---|
1681 |
|
---|
1682 | /* We need to lock the surfaces, or we won't get refreshes when done. */
|
---|
1683 | if (Src == This)
|
---|
1684 | {
|
---|
1685 | int pitch;
|
---|
1686 |
|
---|
1687 | UnionRect(&lock_union, &lock_src, &lock_dst);
|
---|
1688 |
|
---|
1689 | /* Lock the union of the two rectangles */
|
---|
1690 | ret = IWineD3DSurface_LockRect(iface, &dlock, &lock_union, 0);
|
---|
1691 | if(ret != WINED3D_OK) goto error;
|
---|
1692 |
|
---|
1693 | pitch = dlock.Pitch;
|
---|
1694 | slock.Pitch = dlock.Pitch;
|
---|
1695 |
|
---|
1696 | /* Since slock was originally copied from this surface's description, we can just reuse it */
|
---|
1697 | sbuf = This->resource.allocatedMemory + lock_src.top * pitch + lock_src.left * bpp;
|
---|
1698 | dbuf = This->resource.allocatedMemory + lock_dst.top * pitch + lock_dst.left * bpp;
|
---|
1699 | sEntry = Src->resource.format_desc;
|
---|
1700 | dEntry = sEntry;
|
---|
1701 | }
|
---|
1702 | else
|
---|
1703 | {
|
---|
1704 | ret = IWineD3DSurface_LockRect(Source, &slock, &lock_src, WINED3DLOCK_READONLY);
|
---|
1705 | if(ret != WINED3D_OK) goto error;
|
---|
1706 | ret = IWineD3DSurface_LockRect(iface, &dlock, &lock_dst, 0);
|
---|
1707 | if(ret != WINED3D_OK) goto error;
|
---|
1708 |
|
---|
1709 | sbuf = slock.pBits;
|
---|
1710 | dbuf = dlock.pBits;
|
---|
1711 | TRACE("Dst is at %p, Src is at %p\n", dbuf, sbuf);
|
---|
1712 |
|
---|
1713 | sEntry = Src->resource.format_desc;
|
---|
1714 | dEntry = This->resource.format_desc;
|
---|
1715 | }
|
---|
1716 |
|
---|
1717 | /* Handle compressed surfaces first... */
|
---|
1718 | if (sEntry->Flags & dEntry->Flags & WINED3DFMT_FLAG_COMPRESSED)
|
---|
1719 | {
|
---|
1720 | UINT row_block_count;
|
---|
1721 |
|
---|
1722 | TRACE("compressed -> compressed copy\n");
|
---|
1723 | if (trans)
|
---|
1724 | FIXME("trans arg not supported when a compressed surface is involved\n");
|
---|
1725 | if (dstx || dsty)
|
---|
1726 | FIXME("offset for destination surface is not supported\n");
|
---|
1727 | if (Src->resource.format_desc->format != This->resource.format_desc->format)
|
---|
1728 | {
|
---|
1729 | FIXME("compressed -> compressed copy only supported for the same type of surface\n");
|
---|
1730 | ret = WINED3DERR_WRONGTEXTUREFORMAT;
|
---|
1731 | goto error;
|
---|
1732 | }
|
---|
1733 |
|
---|
1734 | row_block_count = (w + dEntry->block_width - 1) / dEntry->block_width;
|
---|
1735 | for (y = 0; y < h; y += dEntry->block_height)
|
---|
1736 | {
|
---|
1737 | memcpy(dbuf, sbuf, row_block_count * dEntry->block_byte_count);
|
---|
1738 | dbuf += dlock.Pitch;
|
---|
1739 | sbuf += slock.Pitch;
|
---|
1740 | }
|
---|
1741 |
|
---|
1742 | goto error;
|
---|
1743 | }
|
---|
1744 | if ((sEntry->Flags & WINED3DFMT_FLAG_COMPRESSED) && !(dEntry->Flags & WINED3DFMT_FLAG_COMPRESSED))
|
---|
1745 | {
|
---|
1746 | /* TODO: Use the libtxc_dxtn.so shared library to do
|
---|
1747 | * software decompression
|
---|
1748 | */
|
---|
1749 | ERR("Software decompression not supported.\n");
|
---|
1750 | goto error;
|
---|
1751 | }
|
---|
1752 |
|
---|
1753 | if (trans & (WINEDDBLTFAST_SRCCOLORKEY | WINEDDBLTFAST_DESTCOLORKEY))
|
---|
1754 | {
|
---|
1755 | DWORD keylow, keyhigh;
|
---|
1756 | DWORD mask = Src->resource.format_desc->red_mask |
|
---|
1757 | Src->resource.format_desc->green_mask |
|
---|
1758 | Src->resource.format_desc->blue_mask;
|
---|
1759 |
|
---|
1760 | /* For some 8-bit formats like L8 and P8 color masks don't make sense */
|
---|
1761 | if(!mask && bpp==1)
|
---|
1762 | mask = 0xff;
|
---|
1763 |
|
---|
1764 | TRACE("Color keyed copy\n");
|
---|
1765 | if (trans & WINEDDBLTFAST_SRCCOLORKEY)
|
---|
1766 | {
|
---|
1767 | keylow = Src->SrcBltCKey.dwColorSpaceLowValue;
|
---|
1768 | keyhigh = Src->SrcBltCKey.dwColorSpaceHighValue;
|
---|
1769 | }
|
---|
1770 | else
|
---|
1771 | {
|
---|
1772 | /* I'm not sure if this is correct */
|
---|
1773 | FIXME("WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
|
---|
1774 | keylow = This->DestBltCKey.dwColorSpaceLowValue;
|
---|
1775 | keyhigh = This->DestBltCKey.dwColorSpaceHighValue;
|
---|
1776 | }
|
---|
1777 |
|
---|
1778 | #define COPYBOX_COLORKEY(type) { \
|
---|
1779 | const type *s = (const type *)sbuf; \
|
---|
1780 | type *d = (type *)dbuf; \
|
---|
1781 | type tmp; \
|
---|
1782 | for (y = 0; y < h; y++) { \
|
---|
1783 | for (x = 0; x < w; x++) { \
|
---|
1784 | tmp = s[x]; \
|
---|
1785 | if ((tmp & mask) < keylow || (tmp & mask) > keyhigh) d[x] = tmp; \
|
---|
1786 | } \
|
---|
1787 | s = (const type *)((const BYTE *)s + slock.Pitch); \
|
---|
1788 | d = (type *)((BYTE *)d + dlock.Pitch); \
|
---|
1789 | } \
|
---|
1790 | break; \
|
---|
1791 | }
|
---|
1792 |
|
---|
1793 | switch (bpp) {
|
---|
1794 | case 1: COPYBOX_COLORKEY(BYTE)
|
---|
1795 | case 2: COPYBOX_COLORKEY(WORD)
|
---|
1796 | case 4: COPYBOX_COLORKEY(DWORD)
|
---|
1797 | case 3:
|
---|
1798 | {
|
---|
1799 | const BYTE *s;
|
---|
1800 | BYTE *d;
|
---|
1801 | DWORD tmp;
|
---|
1802 | s = sbuf;
|
---|
1803 | d = dbuf;
|
---|
1804 | for (y = 0; y < h; y++)
|
---|
1805 | {
|
---|
1806 | for (x = 0; x < w * 3; x += 3)
|
---|
1807 | {
|
---|
1808 | tmp = (DWORD)s[x] + ((DWORD)s[x + 1] << 8) + ((DWORD)s[x + 2] << 16);
|
---|
1809 | if (tmp < keylow || tmp > keyhigh)
|
---|
1810 | {
|
---|
1811 | d[x + 0] = s[x + 0];
|
---|
1812 | d[x + 1] = s[x + 1];
|
---|
1813 | d[x + 2] = s[x + 2];
|
---|
1814 | }
|
---|
1815 | }
|
---|
1816 | s += slock.Pitch;
|
---|
1817 | d += dlock.Pitch;
|
---|
1818 | }
|
---|
1819 | break;
|
---|
1820 | }
|
---|
1821 | default:
|
---|
1822 | FIXME("Source color key blitting not supported for bpp %d\n",bpp*8);
|
---|
1823 | ret = WINED3DERR_NOTAVAILABLE;
|
---|
1824 | goto error;
|
---|
1825 | }
|
---|
1826 | #undef COPYBOX_COLORKEY
|
---|
1827 | TRACE("Copy Done\n");
|
---|
1828 | }
|
---|
1829 | else
|
---|
1830 | {
|
---|
1831 | int width = w * bpp;
|
---|
1832 | INT sbufpitch, dbufpitch;
|
---|
1833 |
|
---|
1834 | TRACE("NO color key copy\n");
|
---|
1835 | /* Handle overlapping surfaces */
|
---|
1836 | if (sbuf < dbuf)
|
---|
1837 | {
|
---|
1838 | sbuf += (h - 1) * slock.Pitch;
|
---|
1839 | dbuf += (h - 1) * dlock.Pitch;
|
---|
1840 | sbufpitch = -slock.Pitch;
|
---|
1841 | dbufpitch = -dlock.Pitch;
|
---|
1842 | }
|
---|
1843 | else
|
---|
1844 | {
|
---|
1845 | sbufpitch = slock.Pitch;
|
---|
1846 | dbufpitch = dlock.Pitch;
|
---|
1847 | }
|
---|
1848 | for (y = 0; y < h; y++)
|
---|
1849 | {
|
---|
1850 | /* This is pretty easy, a line for line memcpy */
|
---|
1851 | memmove(dbuf, sbuf, width);
|
---|
1852 | sbuf += sbufpitch;
|
---|
1853 | dbuf += dbufpitch;
|
---|
1854 | }
|
---|
1855 | TRACE("Copy done\n");
|
---|
1856 | }
|
---|
1857 |
|
---|
1858 | error:
|
---|
1859 | if (Src == This)
|
---|
1860 | {
|
---|
1861 | IWineD3DSurface_UnlockRect(iface);
|
---|
1862 | }
|
---|
1863 | else
|
---|
1864 | {
|
---|
1865 | IWineD3DSurface_UnlockRect(iface);
|
---|
1866 | IWineD3DSurface_UnlockRect(Source);
|
---|
1867 | }
|
---|
1868 |
|
---|
1869 | return ret;
|
---|
1870 | }
|
---|
1871 |
|
---|
1872 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags)
|
---|
1873 | {
|
---|
1874 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
|
---|
1875 |
|
---|
1876 | TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n",
|
---|
1877 | This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
|
---|
1878 |
|
---|
1879 | pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
|
---|
1880 |
|
---|
1881 | if (NULL == pRect)
|
---|
1882 | {
|
---|
1883 | pLockedRect->pBits = This->resource.allocatedMemory;
|
---|
1884 | This->lockedRect.left = 0;
|
---|
1885 | This->lockedRect.top = 0;
|
---|
1886 | This->lockedRect.right = This->currentDesc.Width;
|
---|
1887 | This->lockedRect.bottom = This->currentDesc.Height;
|
---|
1888 |
|
---|
1889 | TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n",
|
---|
1890 | &This->lockedRect, This->lockedRect.left, This->lockedRect.top,
|
---|
1891 | This->lockedRect.right, This->lockedRect.bottom);
|
---|
1892 | }
|
---|
1893 | else
|
---|
1894 | {
|
---|
1895 | const struct wined3d_format_desc *format_desc = This->resource.format_desc;
|
---|
1896 |
|
---|
1897 | TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n",
|
---|
1898 | pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
|
---|
1899 |
|
---|
1900 | if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED)
|
---|
1901 | {
|
---|
1902 | /* Compressed textures are block based, so calculate the offset of
|
---|
1903 | * the block that contains the top-left pixel of the locked rectangle. */
|
---|
1904 | pLockedRect->pBits = This->resource.allocatedMemory
|
---|
1905 | + ((pRect->top / format_desc->block_height) * pLockedRect->Pitch)
|
---|
1906 | + ((pRect->left / format_desc->block_width) * format_desc->block_byte_count);
|
---|
1907 | }
|
---|
1908 | else
|
---|
1909 | {
|
---|
1910 | pLockedRect->pBits = This->resource.allocatedMemory +
|
---|
1911 | (pLockedRect->Pitch * pRect->top) +
|
---|
1912 | (pRect->left * format_desc->byte_count);
|
---|
1913 | }
|
---|
1914 | This->lockedRect.left = pRect->left;
|
---|
1915 | This->lockedRect.top = pRect->top;
|
---|
1916 | This->lockedRect.right = pRect->right;
|
---|
1917 | This->lockedRect.bottom = pRect->bottom;
|
---|
1918 | }
|
---|
1919 |
|
---|
1920 | /* No dirtifying is needed for this surface implementation */
|
---|
1921 | TRACE("returning memory@%p, pitch(%d)\n", pLockedRect->pBits, pLockedRect->Pitch);
|
---|
1922 |
|
---|
1923 | return WINED3D_OK;
|
---|
1924 | }
|
---|
1925 |
|
---|
1926 | void WINAPI IWineD3DBaseSurfaceImpl_BindTexture(IWineD3DSurface *iface, BOOL srgb) {
|
---|
1927 | ERR("Should not be called on base texture\n");
|
---|
1928 | }
|
---|
1929 |
|
---|
1930 | /* TODO: think about moving this down to resource? */
|
---|
1931 | const void *WINAPI IWineD3DBaseSurfaceImpl_GetData(IWineD3DSurface *iface)
|
---|
1932 | {
|
---|
1933 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
|
---|
1934 |
|
---|
1935 | /* This should only be called for sysmem textures, it may be a good idea
|
---|
1936 | * to extend this to all pools at some point in the future */
|
---|
1937 | if (This->resource.pool != WINED3DPOOL_SYSTEMMEM)
|
---|
1938 | {
|
---|
1939 | FIXME("(%p) Attempting to get system memory for a non-system memory texture\n", iface);
|
---|
1940 | }
|
---|
1941 | return This->resource.allocatedMemory;
|
---|
1942 | }
|
---|