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 GlPixelFormatDesc *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 GlPixelFormatDesc *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 GlPixelFormatDesc *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 | struct d3dfmt_convertor_desc {
|
---|
755 | WINED3DFORMAT from, to;
|
---|
756 | void (*convert)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h);
|
---|
757 | };
|
---|
758 |
|
---|
759 | static const struct d3dfmt_convertor_desc convertors[] =
|
---|
760 | {
|
---|
761 | {WINED3DFMT_R32_FLOAT, WINED3DFMT_R16_FLOAT, convert_r32_float_r16_float},
|
---|
762 | {WINED3DFMT_B5G6R5_UNORM, WINED3DFMT_B8G8R8X8_UNORM, convert_r5g6b5_x8r8g8b8},
|
---|
763 | {WINED3DFMT_B8G8R8A8_UNORM, WINED3DFMT_B8G8R8X8_UNORM, convert_a8r8g8b8_x8r8g8b8},
|
---|
764 | };
|
---|
765 |
|
---|
766 | static inline const struct d3dfmt_convertor_desc *find_convertor(WINED3DFORMAT from, WINED3DFORMAT to)
|
---|
767 | {
|
---|
768 | unsigned int i;
|
---|
769 | for(i = 0; i < (sizeof(convertors) / sizeof(convertors[0])); i++) {
|
---|
770 | if(convertors[i].from == from && convertors[i].to == to) {
|
---|
771 | return &convertors[i];
|
---|
772 | }
|
---|
773 | }
|
---|
774 | return NULL;
|
---|
775 | }
|
---|
776 |
|
---|
777 | /*****************************************************************************
|
---|
778 | * surface_convert_format
|
---|
779 | *
|
---|
780 | * Creates a duplicate of a surface in a different format. Is used by Blt to
|
---|
781 | * blit between surfaces with different formats
|
---|
782 | *
|
---|
783 | * Parameters
|
---|
784 | * source: Source surface
|
---|
785 | * fmt: Requested destination format
|
---|
786 | *
|
---|
787 | *****************************************************************************/
|
---|
788 | static IWineD3DSurfaceImpl *surface_convert_format(IWineD3DSurfaceImpl *source, WINED3DFORMAT to_fmt) {
|
---|
789 | IWineD3DSurface *ret = NULL;
|
---|
790 | const struct d3dfmt_convertor_desc *conv;
|
---|
791 | WINED3DLOCKED_RECT lock_src, lock_dst;
|
---|
792 | HRESULT hr;
|
---|
793 |
|
---|
794 | conv = find_convertor(source->resource.format_desc->format, to_fmt);
|
---|
795 | if(!conv) {
|
---|
796 | FIXME("Cannot find a conversion function from format %s to %s\n",
|
---|
797 | debug_d3dformat(source->resource.format_desc->format), debug_d3dformat(to_fmt));
|
---|
798 | return NULL;
|
---|
799 | }
|
---|
800 |
|
---|
801 | IWineD3DDevice_CreateSurface((IWineD3DDevice *)source->resource.device, source->currentDesc.Width,
|
---|
802 | source->currentDesc.Height, to_fmt, TRUE /* lockable */, TRUE /* discard */, 0 /* level */, &ret,
|
---|
803 | 0 /* usage */, WINED3DPOOL_SCRATCH, WINED3DMULTISAMPLE_NONE /* TODO: Multisampled conversion */,
|
---|
804 | 0 /* MultiSampleQuality */, IWineD3DSurface_GetImplType((IWineD3DSurface *) source),
|
---|
805 | NULL /* parent */, &wined3d_null_parent_ops);
|
---|
806 | if(!ret) {
|
---|
807 | ERR("Failed to create a destination surface for conversion\n");
|
---|
808 | return NULL;
|
---|
809 | }
|
---|
810 |
|
---|
811 | memset(&lock_src, 0, sizeof(lock_src));
|
---|
812 | memset(&lock_dst, 0, sizeof(lock_dst));
|
---|
813 |
|
---|
814 | hr = IWineD3DSurface_LockRect((IWineD3DSurface *) source, &lock_src, NULL, WINED3DLOCK_READONLY);
|
---|
815 | if(FAILED(hr)) {
|
---|
816 | ERR("Failed to lock the source surface\n");
|
---|
817 | IWineD3DSurface_Release(ret);
|
---|
818 | return NULL;
|
---|
819 | }
|
---|
820 | hr = IWineD3DSurface_LockRect(ret, &lock_dst, NULL, WINED3DLOCK_READONLY);
|
---|
821 | if(FAILED(hr)) {
|
---|
822 | ERR("Failed to lock the dest surface\n");
|
---|
823 | IWineD3DSurface_UnlockRect((IWineD3DSurface *) source);
|
---|
824 | IWineD3DSurface_Release(ret);
|
---|
825 | return NULL;
|
---|
826 | }
|
---|
827 |
|
---|
828 | conv->convert(lock_src.pBits, lock_dst.pBits, lock_src.Pitch, lock_dst.Pitch,
|
---|
829 | source->currentDesc.Width, source->currentDesc.Height);
|
---|
830 |
|
---|
831 | IWineD3DSurface_UnlockRect(ret);
|
---|
832 | IWineD3DSurface_UnlockRect((IWineD3DSurface *) source);
|
---|
833 |
|
---|
834 | return (IWineD3DSurfaceImpl *) ret;
|
---|
835 | }
|
---|
836 |
|
---|
837 | /*****************************************************************************
|
---|
838 | * _Blt_ColorFill
|
---|
839 | *
|
---|
840 | * Helper function that fills a memory area with a specific color
|
---|
841 | *
|
---|
842 | * Params:
|
---|
843 | * buf: memory address to start filling at
|
---|
844 | * width, height: Dimensions of the area to fill
|
---|
845 | * bpp: Bit depth of the surface
|
---|
846 | * lPitch: pitch of the surface
|
---|
847 | * color: Color to fill with
|
---|
848 | *
|
---|
849 | *****************************************************************************/
|
---|
850 | static HRESULT
|
---|
851 | _Blt_ColorFill(BYTE *buf,
|
---|
852 | int width, int height,
|
---|
853 | int bpp, LONG lPitch,
|
---|
854 | DWORD color)
|
---|
855 | {
|
---|
856 | int x, y;
|
---|
857 | LPBYTE first;
|
---|
858 |
|
---|
859 | /* Do first row */
|
---|
860 |
|
---|
861 | #define COLORFILL_ROW(type) \
|
---|
862 | { \
|
---|
863 | type *d = (type *) buf; \
|
---|
864 | for (x = 0; x < width; x++) \
|
---|
865 | d[x] = (type) color; \
|
---|
866 | break; \
|
---|
867 | }
|
---|
868 | switch(bpp)
|
---|
869 | {
|
---|
870 | case 1: COLORFILL_ROW(BYTE)
|
---|
871 | case 2: COLORFILL_ROW(WORD)
|
---|
872 | case 3:
|
---|
873 | {
|
---|
874 | BYTE *d = buf;
|
---|
875 | for (x = 0; x < width; x++,d+=3)
|
---|
876 | {
|
---|
877 | d[0] = (color ) & 0xFF;
|
---|
878 | d[1] = (color>> 8) & 0xFF;
|
---|
879 | d[2] = (color>>16) & 0xFF;
|
---|
880 | }
|
---|
881 | break;
|
---|
882 | }
|
---|
883 | case 4: COLORFILL_ROW(DWORD)
|
---|
884 | default:
|
---|
885 | FIXME("Color fill not implemented for bpp %d!\n", bpp*8);
|
---|
886 | return WINED3DERR_NOTAVAILABLE;
|
---|
887 | }
|
---|
888 |
|
---|
889 | #undef COLORFILL_ROW
|
---|
890 |
|
---|
891 | /* Now copy first row */
|
---|
892 | first = buf;
|
---|
893 | for (y = 1; y < height; y++)
|
---|
894 | {
|
---|
895 | buf += lPitch;
|
---|
896 | memcpy(buf, first, width * bpp);
|
---|
897 | }
|
---|
898 | return WINED3D_OK;
|
---|
899 | }
|
---|
900 |
|
---|
901 | /*****************************************************************************
|
---|
902 | * IWineD3DSurface::Blt, SW emulation version
|
---|
903 | *
|
---|
904 | * Performs blits to a surface, eigher from a source of source-less blts
|
---|
905 | * This is the main functionality of DirectDraw
|
---|
906 | *
|
---|
907 | * Params:
|
---|
908 | * DestRect: Destination rectangle to write to
|
---|
909 | * SrcSurface: Source surface, can be NULL
|
---|
910 | * SrcRect: Source rectangle
|
---|
911 | *****************************************************************************/
|
---|
912 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT *DestRect, IWineD3DSurface *SrcSurface,
|
---|
913 | const RECT *SrcRect, DWORD Flags, const WINEDDBLTFX *DDBltFx, WINED3DTEXTUREFILTERTYPE Filter)
|
---|
914 | {
|
---|
915 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
916 | IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
|
---|
917 | RECT xdst,xsrc;
|
---|
918 | HRESULT ret = WINED3D_OK;
|
---|
919 | WINED3DLOCKED_RECT dlock, slock;
|
---|
920 | int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
|
---|
921 | const struct GlPixelFormatDesc *sEntry, *dEntry;
|
---|
922 | int x, y;
|
---|
923 | const BYTE *sbuf;
|
---|
924 | BYTE *dbuf;
|
---|
925 | TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, Src, SrcRect, Flags, DDBltFx);
|
---|
926 |
|
---|
927 | if (TRACE_ON(d3d_surface))
|
---|
928 | {
|
---|
929 | if (DestRect) TRACE("\tdestrect :%dx%d-%dx%d\n",
|
---|
930 | DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
|
---|
931 | if (SrcRect) TRACE("\tsrcrect :%dx%d-%dx%d\n",
|
---|
932 | SrcRect->left, SrcRect->top, SrcRect->right, SrcRect->bottom);
|
---|
933 | #if 0
|
---|
934 | TRACE("\tflags: ");
|
---|
935 | DDRAW_dump_DDBLT(Flags);
|
---|
936 | if (Flags & WINEDDBLT_DDFX)
|
---|
937 | {
|
---|
938 | TRACE("\tblitfx: ");
|
---|
939 | DDRAW_dump_DDBLTFX(DDBltFx->dwDDFX);
|
---|
940 | }
|
---|
941 | #endif
|
---|
942 | }
|
---|
943 |
|
---|
944 | if ( (This->Flags & SFLAG_LOCKED) || ((Src != NULL) && (Src->Flags & SFLAG_LOCKED)))
|
---|
945 | {
|
---|
946 | WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
|
---|
947 | return WINEDDERR_SURFACEBUSY;
|
---|
948 | }
|
---|
949 |
|
---|
950 | if(Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT) {
|
---|
951 | /* Can happen when d3d9 apps do a StretchRect call which isn't handled in gl */
|
---|
952 | FIXME("Filters not supported in software blit\n");
|
---|
953 | }
|
---|
954 |
|
---|
955 | /* First check for the validity of source / destination rectangles. This was
|
---|
956 | * verified using a test application + by MSDN.
|
---|
957 | */
|
---|
958 | if ((Src != NULL) && (SrcRect != NULL) &&
|
---|
959 | ((SrcRect->bottom > Src->currentDesc.Height)||(SrcRect->bottom < 0) ||
|
---|
960 | (SrcRect->top > Src->currentDesc.Height)||(SrcRect->top < 0) ||
|
---|
961 | (SrcRect->left > Src->currentDesc.Width) ||(SrcRect->left < 0) ||
|
---|
962 | (SrcRect->right > Src->currentDesc.Width) ||(SrcRect->right < 0) ||
|
---|
963 | (SrcRect->right < SrcRect->left) ||(SrcRect->bottom < SrcRect->top)))
|
---|
964 | {
|
---|
965 | WARN("Application gave us bad source rectangle for Blt.\n");
|
---|
966 | return WINEDDERR_INVALIDRECT;
|
---|
967 | }
|
---|
968 | /* For the Destination rect, it can be out of bounds on the condition that a clipper
|
---|
969 | * is set for the given surface.
|
---|
970 | */
|
---|
971 | if ((/*This->clipper == NULL*/ TRUE) && (DestRect) &&
|
---|
972 | ((DestRect->bottom > This->currentDesc.Height)||(DestRect->bottom < 0) ||
|
---|
973 | (DestRect->top > This->currentDesc.Height)||(DestRect->top < 0) ||
|
---|
974 | (DestRect->left > This->currentDesc.Width) ||(DestRect->left < 0) ||
|
---|
975 | (DestRect->right > This->currentDesc.Width) ||(DestRect->right < 0) ||
|
---|
976 | (DestRect->right < DestRect->left) ||(DestRect->bottom < DestRect->top)))
|
---|
977 | {
|
---|
978 | WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n");
|
---|
979 | return WINEDDERR_INVALIDRECT;
|
---|
980 | }
|
---|
981 |
|
---|
982 | /* Now handle negative values in the rectangles. Warning: only supported for now
|
---|
983 | in the 'simple' cases (ie not in any stretching / rotation cases).
|
---|
984 |
|
---|
985 | First, the case where nothing is to be done.
|
---|
986 | */
|
---|
987 | if ((DestRect && ((DestRect->bottom <= 0) || (DestRect->right <= 0) ||
|
---|
988 | (DestRect->top >= (int) This->currentDesc.Height) ||
|
---|
989 | (DestRect->left >= (int) This->currentDesc.Width))) ||
|
---|
990 | ((Src != NULL) && (SrcRect != NULL) &&
|
---|
991 | ((SrcRect->bottom <= 0) || (SrcRect->right <= 0) ||
|
---|
992 | (SrcRect->top >= (int) Src->currentDesc.Height) ||
|
---|
993 | (SrcRect->left >= (int) Src->currentDesc.Width)) ))
|
---|
994 | {
|
---|
995 | TRACE("Nothing to be done !\n");
|
---|
996 | return WINED3D_OK;
|
---|
997 | }
|
---|
998 |
|
---|
999 | if (DestRect)
|
---|
1000 | {
|
---|
1001 | xdst = *DestRect;
|
---|
1002 | }
|
---|
1003 | else
|
---|
1004 | {
|
---|
1005 | xdst.top = 0;
|
---|
1006 | xdst.bottom = This->currentDesc.Height;
|
---|
1007 | xdst.left = 0;
|
---|
1008 | xdst.right = This->currentDesc.Width;
|
---|
1009 | }
|
---|
1010 |
|
---|
1011 | if (SrcRect)
|
---|
1012 | {
|
---|
1013 | xsrc = *SrcRect;
|
---|
1014 | }
|
---|
1015 | else
|
---|
1016 | {
|
---|
1017 | if (Src)
|
---|
1018 | {
|
---|
1019 | xsrc.top = 0;
|
---|
1020 | xsrc.bottom = Src->currentDesc.Height;
|
---|
1021 | xsrc.left = 0;
|
---|
1022 | xsrc.right = Src->currentDesc.Width;
|
---|
1023 | }
|
---|
1024 | else
|
---|
1025 | {
|
---|
1026 | memset(&xsrc,0,sizeof(xsrc));
|
---|
1027 | }
|
---|
1028 | }
|
---|
1029 |
|
---|
1030 | /* The easy case : the source-less blits.... */
|
---|
1031 | if (Src == NULL && DestRect)
|
---|
1032 | {
|
---|
1033 | RECT full_rect;
|
---|
1034 | RECT temp_rect; /* No idea if intersect rect can be the same as one of the source rect */
|
---|
1035 |
|
---|
1036 | full_rect.left = 0;
|
---|
1037 | full_rect.top = 0;
|
---|
1038 | full_rect.right = This->currentDesc.Width;
|
---|
1039 | full_rect.bottom = This->currentDesc.Height;
|
---|
1040 | IntersectRect(&temp_rect, &full_rect, DestRect);
|
---|
1041 | xdst = temp_rect;
|
---|
1042 | }
|
---|
1043 | else if (DestRect)
|
---|
1044 | {
|
---|
1045 | /* Only handle clipping on the destination rectangle */
|
---|
1046 | int clip_horiz = (DestRect->left < 0) || (DestRect->right > (int) This->currentDesc.Width );
|
---|
1047 | int clip_vert = (DestRect->top < 0) || (DestRect->bottom > (int) This->currentDesc.Height);
|
---|
1048 | if (clip_vert || clip_horiz)
|
---|
1049 | {
|
---|
1050 | /* Now check if this is a special case or not... */
|
---|
1051 | if ((((DestRect->bottom - DestRect->top ) != (xsrc.bottom - xsrc.top )) && clip_vert ) ||
|
---|
1052 | (((DestRect->right - DestRect->left) != (xsrc.right - xsrc.left)) && clip_horiz) ||
|
---|
1053 | (Flags & WINEDDBLT_DDFX))
|
---|
1054 | {
|
---|
1055 | WARN("Out of screen rectangle in special case. Not handled right now.\n");
|
---|
1056 | return WINED3D_OK;
|
---|
1057 | }
|
---|
1058 |
|
---|
1059 | if (clip_horiz)
|
---|
1060 | {
|
---|
1061 | if (DestRect->left < 0) { xsrc.left -= DestRect->left; xdst.left = 0; }
|
---|
1062 | if (DestRect->right > This->currentDesc.Width)
|
---|
1063 | {
|
---|
1064 | xsrc.right -= (DestRect->right - (int) This->currentDesc.Width);
|
---|
1065 | xdst.right = (int) This->currentDesc.Width;
|
---|
1066 | }
|
---|
1067 | }
|
---|
1068 | if (clip_vert)
|
---|
1069 | {
|
---|
1070 | if (DestRect->top < 0)
|
---|
1071 | {
|
---|
1072 | xsrc.top -= DestRect->top;
|
---|
1073 | xdst.top = 0;
|
---|
1074 | }
|
---|
1075 | if (DestRect->bottom > This->currentDesc.Height)
|
---|
1076 | {
|
---|
1077 | xsrc.bottom -= (DestRect->bottom - (int) This->currentDesc.Height);
|
---|
1078 | xdst.bottom = (int) This->currentDesc.Height;
|
---|
1079 | }
|
---|
1080 | }
|
---|
1081 | /* And check if after clipping something is still to be done... */
|
---|
1082 | if ((xdst.bottom <= 0) || (xdst.right <= 0) ||
|
---|
1083 | (xdst.top >= (int) This->currentDesc.Height) ||
|
---|
1084 | (xdst.left >= (int) This->currentDesc.Width) ||
|
---|
1085 | (xsrc.bottom <= 0) || (xsrc.right <= 0) ||
|
---|
1086 | (xsrc.top >= (int) Src->currentDesc.Height) ||
|
---|
1087 | (xsrc.left >= (int) Src->currentDesc.Width))
|
---|
1088 | {
|
---|
1089 | TRACE("Nothing to be done after clipping !\n");
|
---|
1090 | return WINED3D_OK;
|
---|
1091 | }
|
---|
1092 | }
|
---|
1093 | }
|
---|
1094 |
|
---|
1095 | if (Src == This)
|
---|
1096 | {
|
---|
1097 | IWineD3DSurface_LockRect(iface, &dlock, NULL, 0);
|
---|
1098 | slock = dlock;
|
---|
1099 | sEntry = This->resource.format_desc;
|
---|
1100 | dEntry = sEntry;
|
---|
1101 | }
|
---|
1102 | else
|
---|
1103 | {
|
---|
1104 | dEntry = This->resource.format_desc;
|
---|
1105 | if (Src)
|
---|
1106 | {
|
---|
1107 | if (This->resource.format_desc->format != Src->resource.format_desc->format)
|
---|
1108 | {
|
---|
1109 | Src = surface_convert_format(Src, dEntry->format);
|
---|
1110 | if(!Src) {
|
---|
1111 | /* The conv function writes a FIXME */
|
---|
1112 | WARN("Cannot convert source surface format to dest format\n");
|
---|
1113 | goto release;
|
---|
1114 | }
|
---|
1115 | }
|
---|
1116 | IWineD3DSurface_LockRect((IWineD3DSurface *) Src, &slock, NULL, WINED3DLOCK_READONLY);
|
---|
1117 | sEntry = Src->resource.format_desc;
|
---|
1118 | }
|
---|
1119 | else
|
---|
1120 | {
|
---|
1121 | sEntry = dEntry;
|
---|
1122 | }
|
---|
1123 | if (DestRect)
|
---|
1124 | IWineD3DSurface_LockRect(iface, &dlock, &xdst, 0);
|
---|
1125 | else
|
---|
1126 | IWineD3DSurface_LockRect(iface, &dlock, NULL, 0);
|
---|
1127 | }
|
---|
1128 |
|
---|
1129 | if (!DDBltFx || !(DDBltFx->dwDDFX)) Flags &= ~WINEDDBLT_DDFX;
|
---|
1130 |
|
---|
1131 | if (sEntry->Flags & dEntry->Flags & WINED3DFMT_FLAG_FOURCC)
|
---|
1132 | {
|
---|
1133 | if (!DestRect || Src == This)
|
---|
1134 | {
|
---|
1135 | memcpy(dlock.pBits, slock.pBits, This->resource.size);
|
---|
1136 | goto release;
|
---|
1137 | }
|
---|
1138 | }
|
---|
1139 |
|
---|
1140 | bpp = This->resource.format_desc->byte_count;
|
---|
1141 | srcheight = xsrc.bottom - xsrc.top;
|
---|
1142 | srcwidth = xsrc.right - xsrc.left;
|
---|
1143 | dstheight = xdst.bottom - xdst.top;
|
---|
1144 | dstwidth = xdst.right - xdst.left;
|
---|
1145 | width = (xdst.right - xdst.left) * bpp;
|
---|
1146 |
|
---|
1147 | if (DestRect && Src != This)
|
---|
1148 | dbuf = dlock.pBits;
|
---|
1149 | else
|
---|
1150 | dbuf = (BYTE*)dlock.pBits+(xdst.top*dlock.Pitch)+(xdst.left*bpp);
|
---|
1151 |
|
---|
1152 | if (Flags & WINEDDBLT_WAIT)
|
---|
1153 | {
|
---|
1154 | Flags &= ~WINEDDBLT_WAIT;
|
---|
1155 | }
|
---|
1156 | if (Flags & WINEDDBLT_ASYNC)
|
---|
1157 | {
|
---|
1158 | static BOOL displayed = FALSE;
|
---|
1159 | if (!displayed)
|
---|
1160 | FIXME("Can't handle WINEDDBLT_ASYNC flag right now.\n");
|
---|
1161 | displayed = TRUE;
|
---|
1162 | Flags &= ~WINEDDBLT_ASYNC;
|
---|
1163 | }
|
---|
1164 | if (Flags & WINEDDBLT_DONOTWAIT)
|
---|
1165 | {
|
---|
1166 | /* WINEDDBLT_DONOTWAIT appeared in DX7 */
|
---|
1167 | static BOOL displayed = FALSE;
|
---|
1168 | if (!displayed)
|
---|
1169 | FIXME("Can't handle WINEDDBLT_DONOTWAIT flag right now.\n");
|
---|
1170 | displayed = TRUE;
|
---|
1171 | Flags &= ~WINEDDBLT_DONOTWAIT;
|
---|
1172 | }
|
---|
1173 |
|
---|
1174 | /* First, all the 'source-less' blits */
|
---|
1175 | if (Flags & WINEDDBLT_COLORFILL)
|
---|
1176 | {
|
---|
1177 | ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp,
|
---|
1178 | dlock.Pitch, DDBltFx->u5.dwFillColor);
|
---|
1179 | Flags &= ~WINEDDBLT_COLORFILL;
|
---|
1180 | }
|
---|
1181 |
|
---|
1182 | if (Flags & WINEDDBLT_DEPTHFILL)
|
---|
1183 | {
|
---|
1184 | FIXME("DDBLT_DEPTHFILL needs to be implemented!\n");
|
---|
1185 | }
|
---|
1186 | if (Flags & WINEDDBLT_ROP)
|
---|
1187 | {
|
---|
1188 | /* Catch some degenerate cases here */
|
---|
1189 | switch(DDBltFx->dwROP)
|
---|
1190 | {
|
---|
1191 | case BLACKNESS:
|
---|
1192 | ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,dlock.Pitch,0);
|
---|
1193 | break;
|
---|
1194 | case 0xAA0029: /* No-op */
|
---|
1195 | break;
|
---|
1196 | case WHITENESS:
|
---|
1197 | ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,dlock.Pitch,~0);
|
---|
1198 | break;
|
---|
1199 | case SRCCOPY: /* well, we do that below ? */
|
---|
1200 | break;
|
---|
1201 | default:
|
---|
1202 | FIXME("Unsupported raster op: %08x Pattern: %p\n", DDBltFx->dwROP, DDBltFx->u5.lpDDSPattern);
|
---|
1203 | goto error;
|
---|
1204 | }
|
---|
1205 | Flags &= ~WINEDDBLT_ROP;
|
---|
1206 | }
|
---|
1207 | if (Flags & WINEDDBLT_DDROPS)
|
---|
1208 | {
|
---|
1209 | FIXME("\tDdraw Raster Ops: %08x Pattern: %p\n", DDBltFx->dwDDROP, DDBltFx->u5.lpDDSPattern);
|
---|
1210 | }
|
---|
1211 | /* Now the 'with source' blits */
|
---|
1212 | if (Src)
|
---|
1213 | {
|
---|
1214 | const BYTE *sbase;
|
---|
1215 | int sx, xinc, sy, yinc;
|
---|
1216 |
|
---|
1217 | if (!dstwidth || !dstheight) /* hmm... stupid program ? */
|
---|
1218 | goto release;
|
---|
1219 | sbase = (BYTE*)slock.pBits+(xsrc.top*slock.Pitch)+xsrc.left*bpp;
|
---|
1220 | xinc = (srcwidth << 16) / dstwidth;
|
---|
1221 | yinc = (srcheight << 16) / dstheight;
|
---|
1222 |
|
---|
1223 | if (!Flags)
|
---|
1224 | {
|
---|
1225 | /* No effects, we can cheat here */
|
---|
1226 | if (dstwidth == srcwidth)
|
---|
1227 | {
|
---|
1228 | if (dstheight == srcheight)
|
---|
1229 | {
|
---|
1230 | /* No stretching in either direction. This needs to be as
|
---|
1231 | * fast as possible */
|
---|
1232 | sbuf = sbase;
|
---|
1233 |
|
---|
1234 | /* check for overlapping surfaces */
|
---|
1235 | if (Src != This || xdst.top < xsrc.top ||
|
---|
1236 | xdst.right <= xsrc.left || xsrc.right <= xdst.left)
|
---|
1237 | {
|
---|
1238 | /* no overlap, or dst above src, so copy from top downwards */
|
---|
1239 | for (y = 0; y < dstheight; y++)
|
---|
1240 | {
|
---|
1241 | memcpy(dbuf, sbuf, width);
|
---|
1242 | sbuf += slock.Pitch;
|
---|
1243 | dbuf += dlock.Pitch;
|
---|
1244 | }
|
---|
1245 | }
|
---|
1246 | else if (xdst.top > xsrc.top) /* copy from bottom upwards */
|
---|
1247 | {
|
---|
1248 | sbuf += (slock.Pitch*dstheight);
|
---|
1249 | dbuf += (dlock.Pitch*dstheight);
|
---|
1250 | for (y = 0; y < dstheight; y++)
|
---|
1251 | {
|
---|
1252 | sbuf -= slock.Pitch;
|
---|
1253 | dbuf -= dlock.Pitch;
|
---|
1254 | memcpy(dbuf, sbuf, width);
|
---|
1255 | }
|
---|
1256 | }
|
---|
1257 | else /* src and dst overlapping on the same line, use memmove */
|
---|
1258 | {
|
---|
1259 | for (y = 0; y < dstheight; y++)
|
---|
1260 | {
|
---|
1261 | memmove(dbuf, sbuf, width);
|
---|
1262 | sbuf += slock.Pitch;
|
---|
1263 | dbuf += dlock.Pitch;
|
---|
1264 | }
|
---|
1265 | }
|
---|
1266 | } else {
|
---|
1267 | /* Stretching in Y direction only */
|
---|
1268 | for (y = sy = 0; y < dstheight; y++, sy += yinc) {
|
---|
1269 | sbuf = sbase + (sy >> 16) * slock.Pitch;
|
---|
1270 | memcpy(dbuf, sbuf, width);
|
---|
1271 | dbuf += dlock.Pitch;
|
---|
1272 | }
|
---|
1273 | }
|
---|
1274 | }
|
---|
1275 | else
|
---|
1276 | {
|
---|
1277 | /* Stretching in X direction */
|
---|
1278 | int last_sy = -1;
|
---|
1279 | for (y = sy = 0; y < dstheight; y++, sy += yinc)
|
---|
1280 | {
|
---|
1281 | sbuf = sbase + (sy >> 16) * slock.Pitch;
|
---|
1282 |
|
---|
1283 | if ((sy >> 16) == (last_sy >> 16))
|
---|
1284 | {
|
---|
1285 | /* this sourcerow is the same as last sourcerow -
|
---|
1286 | * copy already stretched row
|
---|
1287 | */
|
---|
1288 | memcpy(dbuf, dbuf - dlock.Pitch, width);
|
---|
1289 | }
|
---|
1290 | else
|
---|
1291 | {
|
---|
1292 | #define STRETCH_ROW(type) { \
|
---|
1293 | const type *s = (const type *)sbuf; \
|
---|
1294 | type *d = (type *)dbuf; \
|
---|
1295 | for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
|
---|
1296 | d[x] = s[sx >> 16]; \
|
---|
1297 | break; }
|
---|
1298 |
|
---|
1299 | switch(bpp)
|
---|
1300 | {
|
---|
1301 | case 1: STRETCH_ROW(BYTE)
|
---|
1302 | case 2: STRETCH_ROW(WORD)
|
---|
1303 | case 4: STRETCH_ROW(DWORD)
|
---|
1304 | case 3:
|
---|
1305 | {
|
---|
1306 | const BYTE *s;
|
---|
1307 | BYTE *d = dbuf;
|
---|
1308 | for (x = sx = 0; x < dstwidth; x++, sx+= xinc)
|
---|
1309 | {
|
---|
1310 | DWORD pixel;
|
---|
1311 |
|
---|
1312 | s = sbuf+3*(sx>>16);
|
---|
1313 | pixel = s[0]|(s[1]<<8)|(s[2]<<16);
|
---|
1314 | d[0] = (pixel )&0xff;
|
---|
1315 | d[1] = (pixel>> 8)&0xff;
|
---|
1316 | d[2] = (pixel>>16)&0xff;
|
---|
1317 | d+=3;
|
---|
1318 | }
|
---|
1319 | break;
|
---|
1320 | }
|
---|
1321 | default:
|
---|
1322 | FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8);
|
---|
1323 | ret = WINED3DERR_NOTAVAILABLE;
|
---|
1324 | goto error;
|
---|
1325 | }
|
---|
1326 | #undef STRETCH_ROW
|
---|
1327 | }
|
---|
1328 | dbuf += dlock.Pitch;
|
---|
1329 | last_sy = sy;
|
---|
1330 | }
|
---|
1331 | }
|
---|
1332 | }
|
---|
1333 | else
|
---|
1334 | {
|
---|
1335 | LONG dstyinc = dlock.Pitch, dstxinc = bpp;
|
---|
1336 | DWORD keylow = 0xFFFFFFFF, keyhigh = 0, keymask = 0xFFFFFFFF;
|
---|
1337 | DWORD destkeylow = 0x0, destkeyhigh = 0xFFFFFFFF, destkeymask = 0xFFFFFFFF;
|
---|
1338 | if (Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE))
|
---|
1339 | {
|
---|
1340 | /* The color keying flags are checked for correctness in ddraw */
|
---|
1341 | if (Flags & WINEDDBLT_KEYSRC)
|
---|
1342 | {
|
---|
1343 | keylow = Src->SrcBltCKey.dwColorSpaceLowValue;
|
---|
1344 | keyhigh = Src->SrcBltCKey.dwColorSpaceHighValue;
|
---|
1345 | }
|
---|
1346 | else if (Flags & WINEDDBLT_KEYSRCOVERRIDE)
|
---|
1347 | {
|
---|
1348 | keylow = DDBltFx->ddckSrcColorkey.dwColorSpaceLowValue;
|
---|
1349 | keyhigh = DDBltFx->ddckSrcColorkey.dwColorSpaceHighValue;
|
---|
1350 | }
|
---|
1351 |
|
---|
1352 | if (Flags & WINEDDBLT_KEYDEST)
|
---|
1353 | {
|
---|
1354 | /* Destination color keys are taken from the source surface ! */
|
---|
1355 | destkeylow = Src->DestBltCKey.dwColorSpaceLowValue;
|
---|
1356 | destkeyhigh = Src->DestBltCKey.dwColorSpaceHighValue;
|
---|
1357 | }
|
---|
1358 | else if (Flags & WINEDDBLT_KEYDESTOVERRIDE)
|
---|
1359 | {
|
---|
1360 | destkeylow = DDBltFx->ddckDestColorkey.dwColorSpaceLowValue;
|
---|
1361 | destkeyhigh = DDBltFx->ddckDestColorkey.dwColorSpaceHighValue;
|
---|
1362 | }
|
---|
1363 |
|
---|
1364 | if(bpp == 1)
|
---|
1365 | {
|
---|
1366 | keymask = 0xff;
|
---|
1367 | }
|
---|
1368 | else
|
---|
1369 | {
|
---|
1370 | keymask = sEntry->red_mask
|
---|
1371 | | sEntry->green_mask
|
---|
1372 | | sEntry->blue_mask;
|
---|
1373 | }
|
---|
1374 | Flags &= ~(WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE);
|
---|
1375 | }
|
---|
1376 |
|
---|
1377 | if (Flags & WINEDDBLT_DDFX)
|
---|
1378 | {
|
---|
1379 | LPBYTE dTopLeft, dTopRight, dBottomLeft, dBottomRight, tmp;
|
---|
1380 | LONG tmpxy;
|
---|
1381 | dTopLeft = dbuf;
|
---|
1382 | dTopRight = dbuf+((dstwidth-1)*bpp);
|
---|
1383 | dBottomLeft = dTopLeft+((dstheight-1)*dlock.Pitch);
|
---|
1384 | dBottomRight = dBottomLeft+((dstwidth-1)*bpp);
|
---|
1385 |
|
---|
1386 | if (DDBltFx->dwDDFX & WINEDDBLTFX_ARITHSTRETCHY)
|
---|
1387 | {
|
---|
1388 | /* I don't think we need to do anything about this flag */
|
---|
1389 | WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_ARITHSTRETCHY\n");
|
---|
1390 | }
|
---|
1391 | if (DDBltFx->dwDDFX & WINEDDBLTFX_MIRRORLEFTRIGHT)
|
---|
1392 | {
|
---|
1393 | tmp = dTopRight;
|
---|
1394 | dTopRight = dTopLeft;
|
---|
1395 | dTopLeft = tmp;
|
---|
1396 | tmp = dBottomRight;
|
---|
1397 | dBottomRight = dBottomLeft;
|
---|
1398 | dBottomLeft = tmp;
|
---|
1399 | dstxinc = dstxinc *-1;
|
---|
1400 | }
|
---|
1401 | if (DDBltFx->dwDDFX & WINEDDBLTFX_MIRRORUPDOWN)
|
---|
1402 | {
|
---|
1403 | tmp = dTopLeft;
|
---|
1404 | dTopLeft = dBottomLeft;
|
---|
1405 | dBottomLeft = tmp;
|
---|
1406 | tmp = dTopRight;
|
---|
1407 | dTopRight = dBottomRight;
|
---|
1408 | dBottomRight = tmp;
|
---|
1409 | dstyinc = dstyinc *-1;
|
---|
1410 | }
|
---|
1411 | if (DDBltFx->dwDDFX & WINEDDBLTFX_NOTEARING)
|
---|
1412 | {
|
---|
1413 | /* I don't think we need to do anything about this flag */
|
---|
1414 | WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_NOTEARING\n");
|
---|
1415 | }
|
---|
1416 | if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE180)
|
---|
1417 | {
|
---|
1418 | tmp = dBottomRight;
|
---|
1419 | dBottomRight = dTopLeft;
|
---|
1420 | dTopLeft = tmp;
|
---|
1421 | tmp = dBottomLeft;
|
---|
1422 | dBottomLeft = dTopRight;
|
---|
1423 | dTopRight = tmp;
|
---|
1424 | dstxinc = dstxinc * -1;
|
---|
1425 | dstyinc = dstyinc * -1;
|
---|
1426 | }
|
---|
1427 | if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE270)
|
---|
1428 | {
|
---|
1429 | tmp = dTopLeft;
|
---|
1430 | dTopLeft = dBottomLeft;
|
---|
1431 | dBottomLeft = dBottomRight;
|
---|
1432 | dBottomRight = dTopRight;
|
---|
1433 | dTopRight = tmp;
|
---|
1434 | tmpxy = dstxinc;
|
---|
1435 | dstxinc = dstyinc;
|
---|
1436 | dstyinc = tmpxy;
|
---|
1437 | dstxinc = dstxinc * -1;
|
---|
1438 | }
|
---|
1439 | if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE90)
|
---|
1440 | {
|
---|
1441 | tmp = dTopLeft;
|
---|
1442 | dTopLeft = dTopRight;
|
---|
1443 | dTopRight = dBottomRight;
|
---|
1444 | dBottomRight = dBottomLeft;
|
---|
1445 | dBottomLeft = tmp;
|
---|
1446 | tmpxy = dstxinc;
|
---|
1447 | dstxinc = dstyinc;
|
---|
1448 | dstyinc = tmpxy;
|
---|
1449 | dstyinc = dstyinc * -1;
|
---|
1450 | }
|
---|
1451 | if (DDBltFx->dwDDFX & WINEDDBLTFX_ZBUFFERBASEDEST)
|
---|
1452 | {
|
---|
1453 | /* I don't think we need to do anything about this flag */
|
---|
1454 | WARN("Flags=WINEDDBLT_DDFX nothing done for WINEDDBLTFX_ZBUFFERBASEDEST\n");
|
---|
1455 | }
|
---|
1456 | dbuf = dTopLeft;
|
---|
1457 | Flags &= ~(WINEDDBLT_DDFX);
|
---|
1458 | }
|
---|
1459 |
|
---|
1460 | #define COPY_COLORKEY_FX(type) { \
|
---|
1461 | const type *s; \
|
---|
1462 | type *d = (type *)dbuf, *dx, tmp; \
|
---|
1463 | for (y = sy = 0; y < dstheight; y++, sy += yinc) { \
|
---|
1464 | s = (const type*)(sbase + (sy >> 16) * slock.Pitch); \
|
---|
1465 | dx = d; \
|
---|
1466 | for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
|
---|
1467 | tmp = s[sx >> 16]; \
|
---|
1468 | if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) && \
|
---|
1469 | ((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) { \
|
---|
1470 | dx[0] = tmp; \
|
---|
1471 | } \
|
---|
1472 | dx = (type*)(((LPBYTE)dx)+dstxinc); \
|
---|
1473 | } \
|
---|
1474 | d = (type*)(((LPBYTE)d)+dstyinc); \
|
---|
1475 | } \
|
---|
1476 | break; }
|
---|
1477 |
|
---|
1478 | switch (bpp) {
|
---|
1479 | case 1: COPY_COLORKEY_FX(BYTE)
|
---|
1480 | case 2: COPY_COLORKEY_FX(WORD)
|
---|
1481 | case 4: COPY_COLORKEY_FX(DWORD)
|
---|
1482 | case 3:
|
---|
1483 | {
|
---|
1484 | const BYTE *s;
|
---|
1485 | BYTE *d = dbuf, *dx;
|
---|
1486 | for (y = sy = 0; y < dstheight; y++, sy += yinc)
|
---|
1487 | {
|
---|
1488 | sbuf = sbase + (sy >> 16) * slock.Pitch;
|
---|
1489 | dx = d;
|
---|
1490 | for (x = sx = 0; x < dstwidth; x++, sx+= xinc)
|
---|
1491 | {
|
---|
1492 | DWORD pixel, dpixel = 0;
|
---|
1493 | s = sbuf+3*(sx>>16);
|
---|
1494 | pixel = s[0]|(s[1]<<8)|(s[2]<<16);
|
---|
1495 | dpixel = dx[0]|(dx[1]<<8)|(dx[2]<<16);
|
---|
1496 | if (((pixel & keymask) < keylow || (pixel & keymask) > keyhigh) &&
|
---|
1497 | ((dpixel & keymask) >= destkeylow || (dpixel & keymask) <= keyhigh))
|
---|
1498 | {
|
---|
1499 | dx[0] = (pixel )&0xff;
|
---|
1500 | dx[1] = (pixel>> 8)&0xff;
|
---|
1501 | dx[2] = (pixel>>16)&0xff;
|
---|
1502 | }
|
---|
1503 | dx+= dstxinc;
|
---|
1504 | }
|
---|
1505 | d += dstyinc;
|
---|
1506 | }
|
---|
1507 | break;
|
---|
1508 | }
|
---|
1509 | default:
|
---|
1510 | FIXME("%s color-keyed blit not implemented for bpp %d!\n",
|
---|
1511 | (Flags & WINEDDBLT_KEYSRC) ? "Source" : "Destination", bpp*8);
|
---|
1512 | ret = WINED3DERR_NOTAVAILABLE;
|
---|
1513 | goto error;
|
---|
1514 | #undef COPY_COLORKEY_FX
|
---|
1515 | }
|
---|
1516 | }
|
---|
1517 | }
|
---|
1518 |
|
---|
1519 | error:
|
---|
1520 | if (Flags && FIXME_ON(d3d_surface))
|
---|
1521 | {
|
---|
1522 | FIXME("\tUnsupported flags: %08x\n", Flags);
|
---|
1523 | }
|
---|
1524 |
|
---|
1525 | release:
|
---|
1526 | IWineD3DSurface_UnlockRect(iface);
|
---|
1527 | if (Src && Src != This) IWineD3DSurface_UnlockRect((IWineD3DSurface *) Src);
|
---|
1528 | /* Release the converted surface if any */
|
---|
1529 | if (Src && SrcSurface != (IWineD3DSurface *) Src) IWineD3DSurface_Release((IWineD3DSurface *) Src);
|
---|
1530 | return ret;
|
---|
1531 | }
|
---|
1532 |
|
---|
1533 | /*****************************************************************************
|
---|
1534 | * IWineD3DSurface::BltFast, SW emulation version
|
---|
1535 | *
|
---|
1536 | * This is the software implementation of BltFast, as used by GDI surfaces
|
---|
1537 | * and as a fallback for OpenGL surfaces. This code is taken from the old
|
---|
1538 | * DirectDraw code, and was originally written by TransGaming.
|
---|
1539 | *
|
---|
1540 | * Params:
|
---|
1541 | * dstx:
|
---|
1542 | * dsty:
|
---|
1543 | * Source: Source surface to copy from
|
---|
1544 | * rsrc: Source rectangle
|
---|
1545 | * trans: Some Flags
|
---|
1546 | *
|
---|
1547 | * Returns:
|
---|
1548 | * WINED3D_OK on success
|
---|
1549 | *
|
---|
1550 | *****************************************************************************/
|
---|
1551 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty,
|
---|
1552 | IWineD3DSurface *Source, const RECT *rsrc, DWORD trans)
|
---|
1553 | {
|
---|
1554 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
|
---|
1555 | IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) Source;
|
---|
1556 |
|
---|
1557 | int bpp, w, h, x, y;
|
---|
1558 | WINED3DLOCKED_RECT dlock,slock;
|
---|
1559 | HRESULT ret = WINED3D_OK;
|
---|
1560 | RECT rsrc2;
|
---|
1561 | RECT lock_src, lock_dst, lock_union;
|
---|
1562 | const BYTE *sbuf;
|
---|
1563 | BYTE *dbuf;
|
---|
1564 | const struct GlPixelFormatDesc *sEntry, *dEntry;
|
---|
1565 |
|
---|
1566 | if (TRACE_ON(d3d_surface))
|
---|
1567 | {
|
---|
1568 | TRACE("(%p)->(%d,%d,%p,%p,%08x)\n", This,dstx,dsty,Src,rsrc,trans);
|
---|
1569 |
|
---|
1570 | if (rsrc)
|
---|
1571 | {
|
---|
1572 | TRACE("\tsrcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,
|
---|
1573 | rsrc->right,rsrc->bottom);
|
---|
1574 | }
|
---|
1575 | else
|
---|
1576 | {
|
---|
1577 | TRACE(" srcrect: NULL\n");
|
---|
1578 | }
|
---|
1579 | }
|
---|
1580 |
|
---|
1581 | if ((This->Flags & SFLAG_LOCKED) ||
|
---|
1582 | (Src->Flags & SFLAG_LOCKED))
|
---|
1583 | {
|
---|
1584 | WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
|
---|
1585 | return WINEDDERR_SURFACEBUSY;
|
---|
1586 | }
|
---|
1587 |
|
---|
1588 | if (!rsrc)
|
---|
1589 | {
|
---|
1590 | WARN("rsrc is NULL!\n");
|
---|
1591 | rsrc2.left = 0;
|
---|
1592 | rsrc2.top = 0;
|
---|
1593 | rsrc2.right = Src->currentDesc.Width;
|
---|
1594 | rsrc2.bottom = Src->currentDesc.Height;
|
---|
1595 | rsrc = &rsrc2;
|
---|
1596 | }
|
---|
1597 |
|
---|
1598 | /* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate.*/
|
---|
1599 | if ((rsrc->bottom > Src->currentDesc.Height) || (rsrc->bottom < 0) ||
|
---|
1600 | (rsrc->top > Src->currentDesc.Height) || (rsrc->top < 0) ||
|
---|
1601 | (rsrc->left > Src->currentDesc.Width) || (rsrc->left < 0) ||
|
---|
1602 | (rsrc->right > Src->currentDesc.Width) || (rsrc->right < 0) ||
|
---|
1603 | (rsrc->right < rsrc->left) || (rsrc->bottom < rsrc->top))
|
---|
1604 | {
|
---|
1605 | WARN("Application gave us bad source rectangle for BltFast.\n");
|
---|
1606 | return WINEDDERR_INVALIDRECT;
|
---|
1607 | }
|
---|
1608 |
|
---|
1609 | h = rsrc->bottom - rsrc->top;
|
---|
1610 | if (h > This->currentDesc.Height-dsty) h = This->currentDesc.Height-dsty;
|
---|
1611 | if (h > Src->currentDesc.Height-rsrc->top) h=Src->currentDesc.Height-rsrc->top;
|
---|
1612 | if (h <= 0) return WINEDDERR_INVALIDRECT;
|
---|
1613 |
|
---|
1614 | w = rsrc->right - rsrc->left;
|
---|
1615 | if (w > This->currentDesc.Width-dstx) w = This->currentDesc.Width-dstx;
|
---|
1616 | if (w > Src->currentDesc.Width-rsrc->left) w = Src->currentDesc.Width-rsrc->left;
|
---|
1617 | if (w <= 0) return WINEDDERR_INVALIDRECT;
|
---|
1618 |
|
---|
1619 | /* Now compute the locking rectangle... */
|
---|
1620 | lock_src.left = rsrc->left;
|
---|
1621 | lock_src.top = rsrc->top;
|
---|
1622 | lock_src.right = lock_src.left + w;
|
---|
1623 | lock_src.bottom = lock_src.top + h;
|
---|
1624 |
|
---|
1625 | lock_dst.left = dstx;
|
---|
1626 | lock_dst.top = dsty;
|
---|
1627 | lock_dst.right = dstx + w;
|
---|
1628 | lock_dst.bottom = dsty + h;
|
---|
1629 |
|
---|
1630 | bpp = This->resource.format_desc->byte_count;
|
---|
1631 |
|
---|
1632 | /* We need to lock the surfaces, or we won't get refreshes when done. */
|
---|
1633 | if (Src == This)
|
---|
1634 | {
|
---|
1635 | int pitch;
|
---|
1636 |
|
---|
1637 | UnionRect(&lock_union, &lock_src, &lock_dst);
|
---|
1638 |
|
---|
1639 | /* Lock the union of the two rectangles */
|
---|
1640 | ret = IWineD3DSurface_LockRect(iface, &dlock, &lock_union, 0);
|
---|
1641 | if(ret != WINED3D_OK) goto error;
|
---|
1642 |
|
---|
1643 | pitch = dlock.Pitch;
|
---|
1644 | slock.Pitch = dlock.Pitch;
|
---|
1645 |
|
---|
1646 | /* Since slock was originally copied from this surface's description, we can just reuse it */
|
---|
1647 | sbuf = This->resource.allocatedMemory + lock_src.top * pitch + lock_src.left * bpp;
|
---|
1648 | dbuf = This->resource.allocatedMemory + lock_dst.top * pitch + lock_dst.left * bpp;
|
---|
1649 | sEntry = Src->resource.format_desc;
|
---|
1650 | dEntry = sEntry;
|
---|
1651 | }
|
---|
1652 | else
|
---|
1653 | {
|
---|
1654 | ret = IWineD3DSurface_LockRect(Source, &slock, &lock_src, WINED3DLOCK_READONLY);
|
---|
1655 | if(ret != WINED3D_OK) goto error;
|
---|
1656 | ret = IWineD3DSurface_LockRect(iface, &dlock, &lock_dst, 0);
|
---|
1657 | if(ret != WINED3D_OK) goto error;
|
---|
1658 |
|
---|
1659 | sbuf = slock.pBits;
|
---|
1660 | dbuf = dlock.pBits;
|
---|
1661 | TRACE("Dst is at %p, Src is at %p\n", dbuf, sbuf);
|
---|
1662 |
|
---|
1663 | sEntry = Src->resource.format_desc;
|
---|
1664 | dEntry = This->resource.format_desc;
|
---|
1665 | }
|
---|
1666 |
|
---|
1667 | /* Handle compressed surfaces first... */
|
---|
1668 | if (sEntry->Flags & dEntry->Flags & WINED3DFMT_FLAG_COMPRESSED)
|
---|
1669 | {
|
---|
1670 | UINT row_block_count;
|
---|
1671 |
|
---|
1672 | TRACE("compressed -> compressed copy\n");
|
---|
1673 | if (trans)
|
---|
1674 | FIXME("trans arg not supported when a compressed surface is involved\n");
|
---|
1675 | if (dstx || dsty)
|
---|
1676 | FIXME("offset for destination surface is not supported\n");
|
---|
1677 | if (Src->resource.format_desc->format != This->resource.format_desc->format)
|
---|
1678 | {
|
---|
1679 | FIXME("compressed -> compressed copy only supported for the same type of surface\n");
|
---|
1680 | ret = WINED3DERR_WRONGTEXTUREFORMAT;
|
---|
1681 | goto error;
|
---|
1682 | }
|
---|
1683 |
|
---|
1684 | row_block_count = (w + dEntry->block_width - 1) / dEntry->block_width;
|
---|
1685 | for (y = 0; y < h; y += dEntry->block_height)
|
---|
1686 | {
|
---|
1687 | memcpy(dbuf, sbuf, row_block_count * dEntry->block_byte_count);
|
---|
1688 | dbuf += dlock.Pitch;
|
---|
1689 | sbuf += slock.Pitch;
|
---|
1690 | }
|
---|
1691 |
|
---|
1692 | goto error;
|
---|
1693 | }
|
---|
1694 | if ((sEntry->Flags & WINED3DFMT_FLAG_COMPRESSED) && !(dEntry->Flags & WINED3DFMT_FLAG_COMPRESSED))
|
---|
1695 | {
|
---|
1696 | /* TODO: Use the libtxc_dxtn.so shared library to do
|
---|
1697 | * software decompression
|
---|
1698 | */
|
---|
1699 | ERR("Software decompression not supported.\n");
|
---|
1700 | goto error;
|
---|
1701 | }
|
---|
1702 |
|
---|
1703 | if (trans & (WINEDDBLTFAST_SRCCOLORKEY | WINEDDBLTFAST_DESTCOLORKEY))
|
---|
1704 | {
|
---|
1705 | DWORD keylow, keyhigh;
|
---|
1706 | DWORD mask = Src->resource.format_desc->red_mask |
|
---|
1707 | Src->resource.format_desc->green_mask |
|
---|
1708 | Src->resource.format_desc->blue_mask;
|
---|
1709 |
|
---|
1710 | /* For some 8-bit formats like L8 and P8 color masks don't make sense */
|
---|
1711 | if(!mask && bpp==1)
|
---|
1712 | mask = 0xff;
|
---|
1713 |
|
---|
1714 | TRACE("Color keyed copy\n");
|
---|
1715 | if (trans & WINEDDBLTFAST_SRCCOLORKEY)
|
---|
1716 | {
|
---|
1717 | keylow = Src->SrcBltCKey.dwColorSpaceLowValue;
|
---|
1718 | keyhigh = Src->SrcBltCKey.dwColorSpaceHighValue;
|
---|
1719 | }
|
---|
1720 | else
|
---|
1721 | {
|
---|
1722 | /* I'm not sure if this is correct */
|
---|
1723 | FIXME("WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
|
---|
1724 | keylow = This->DestBltCKey.dwColorSpaceLowValue;
|
---|
1725 | keyhigh = This->DestBltCKey.dwColorSpaceHighValue;
|
---|
1726 | }
|
---|
1727 |
|
---|
1728 | #define COPYBOX_COLORKEY(type) { \
|
---|
1729 | const type *s = (const type *)sbuf; \
|
---|
1730 | type *d = (type *)dbuf; \
|
---|
1731 | type tmp; \
|
---|
1732 | for (y = 0; y < h; y++) { \
|
---|
1733 | for (x = 0; x < w; x++) { \
|
---|
1734 | tmp = s[x]; \
|
---|
1735 | if ((tmp & mask) < keylow || (tmp & mask) > keyhigh) d[x] = tmp; \
|
---|
1736 | } \
|
---|
1737 | s = (const type *)((const BYTE *)s + slock.Pitch); \
|
---|
1738 | d = (type *)((BYTE *)d + dlock.Pitch); \
|
---|
1739 | } \
|
---|
1740 | break; \
|
---|
1741 | }
|
---|
1742 |
|
---|
1743 | switch (bpp) {
|
---|
1744 | case 1: COPYBOX_COLORKEY(BYTE)
|
---|
1745 | case 2: COPYBOX_COLORKEY(WORD)
|
---|
1746 | case 4: COPYBOX_COLORKEY(DWORD)
|
---|
1747 | case 3:
|
---|
1748 | {
|
---|
1749 | const BYTE *s;
|
---|
1750 | BYTE *d;
|
---|
1751 | DWORD tmp;
|
---|
1752 | s = sbuf;
|
---|
1753 | d = dbuf;
|
---|
1754 | for (y = 0; y < h; y++)
|
---|
1755 | {
|
---|
1756 | for (x = 0; x < w * 3; x += 3)
|
---|
1757 | {
|
---|
1758 | tmp = (DWORD)s[x] + ((DWORD)s[x + 1] << 8) + ((DWORD)s[x + 2] << 16);
|
---|
1759 | if (tmp < keylow || tmp > keyhigh)
|
---|
1760 | {
|
---|
1761 | d[x + 0] = s[x + 0];
|
---|
1762 | d[x + 1] = s[x + 1];
|
---|
1763 | d[x + 2] = s[x + 2];
|
---|
1764 | }
|
---|
1765 | }
|
---|
1766 | s += slock.Pitch;
|
---|
1767 | d += dlock.Pitch;
|
---|
1768 | }
|
---|
1769 | break;
|
---|
1770 | }
|
---|
1771 | default:
|
---|
1772 | FIXME("Source color key blitting not supported for bpp %d\n",bpp*8);
|
---|
1773 | ret = WINED3DERR_NOTAVAILABLE;
|
---|
1774 | goto error;
|
---|
1775 | }
|
---|
1776 | #undef COPYBOX_COLORKEY
|
---|
1777 | TRACE("Copy Done\n");
|
---|
1778 | }
|
---|
1779 | else
|
---|
1780 | {
|
---|
1781 | int width = w * bpp;
|
---|
1782 | INT sbufpitch, dbufpitch;
|
---|
1783 |
|
---|
1784 | TRACE("NO color key copy\n");
|
---|
1785 | /* Handle overlapping surfaces */
|
---|
1786 | if (sbuf < dbuf)
|
---|
1787 | {
|
---|
1788 | sbuf += (h - 1) * slock.Pitch;
|
---|
1789 | dbuf += (h - 1) * dlock.Pitch;
|
---|
1790 | sbufpitch = -slock.Pitch;
|
---|
1791 | dbufpitch = -dlock.Pitch;
|
---|
1792 | }
|
---|
1793 | else
|
---|
1794 | {
|
---|
1795 | sbufpitch = slock.Pitch;
|
---|
1796 | dbufpitch = dlock.Pitch;
|
---|
1797 | }
|
---|
1798 | for (y = 0; y < h; y++)
|
---|
1799 | {
|
---|
1800 | /* This is pretty easy, a line for line memcpy */
|
---|
1801 | memmove(dbuf, sbuf, width);
|
---|
1802 | sbuf += sbufpitch;
|
---|
1803 | dbuf += dbufpitch;
|
---|
1804 | }
|
---|
1805 | TRACE("Copy done\n");
|
---|
1806 | }
|
---|
1807 |
|
---|
1808 | error:
|
---|
1809 | if (Src == This)
|
---|
1810 | {
|
---|
1811 | IWineD3DSurface_UnlockRect(iface);
|
---|
1812 | }
|
---|
1813 | else
|
---|
1814 | {
|
---|
1815 | IWineD3DSurface_UnlockRect(iface);
|
---|
1816 | IWineD3DSurface_UnlockRect(Source);
|
---|
1817 | }
|
---|
1818 |
|
---|
1819 | return ret;
|
---|
1820 | }
|
---|
1821 |
|
---|
1822 | HRESULT WINAPI IWineD3DBaseSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags)
|
---|
1823 | {
|
---|
1824 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
|
---|
1825 |
|
---|
1826 | TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n",
|
---|
1827 | This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
|
---|
1828 |
|
---|
1829 | pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
|
---|
1830 |
|
---|
1831 | if (NULL == pRect)
|
---|
1832 | {
|
---|
1833 | pLockedRect->pBits = This->resource.allocatedMemory;
|
---|
1834 | This->lockedRect.left = 0;
|
---|
1835 | This->lockedRect.top = 0;
|
---|
1836 | This->lockedRect.right = This->currentDesc.Width;
|
---|
1837 | This->lockedRect.bottom = This->currentDesc.Height;
|
---|
1838 |
|
---|
1839 | TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n",
|
---|
1840 | &This->lockedRect, This->lockedRect.left, This->lockedRect.top,
|
---|
1841 | This->lockedRect.right, This->lockedRect.bottom);
|
---|
1842 | }
|
---|
1843 | else
|
---|
1844 | {
|
---|
1845 | const struct GlPixelFormatDesc *format_desc = This->resource.format_desc;
|
---|
1846 |
|
---|
1847 | TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n",
|
---|
1848 | pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
|
---|
1849 |
|
---|
1850 | if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED)
|
---|
1851 | {
|
---|
1852 | /* Compressed textures are block based, so calculate the offset of
|
---|
1853 | * the block that contains the top-left pixel of the locked rectangle. */
|
---|
1854 | pLockedRect->pBits = This->resource.allocatedMemory
|
---|
1855 | + ((pRect->top / format_desc->block_height) * pLockedRect->Pitch)
|
---|
1856 | + ((pRect->left / format_desc->block_width) * format_desc->block_byte_count);
|
---|
1857 | }
|
---|
1858 | else
|
---|
1859 | {
|
---|
1860 | pLockedRect->pBits = This->resource.allocatedMemory +
|
---|
1861 | (pLockedRect->Pitch * pRect->top) +
|
---|
1862 | (pRect->left * format_desc->byte_count);
|
---|
1863 | }
|
---|
1864 | This->lockedRect.left = pRect->left;
|
---|
1865 | This->lockedRect.top = pRect->top;
|
---|
1866 | This->lockedRect.right = pRect->right;
|
---|
1867 | This->lockedRect.bottom = pRect->bottom;
|
---|
1868 | }
|
---|
1869 |
|
---|
1870 | /* No dirtifying is needed for this surface implementation */
|
---|
1871 | TRACE("returning memory@%p, pitch(%d)\n", pLockedRect->pBits, pLockedRect->Pitch);
|
---|
1872 |
|
---|
1873 | return WINED3D_OK;
|
---|
1874 | }
|
---|
1875 |
|
---|
1876 | void WINAPI IWineD3DBaseSurfaceImpl_BindTexture(IWineD3DSurface *iface, BOOL srgb) {
|
---|
1877 | ERR("Should not be called on base texture\n");
|
---|
1878 | }
|
---|
1879 |
|
---|
1880 | /* TODO: think about moving this down to resource? */
|
---|
1881 | const void *WINAPI IWineD3DBaseSurfaceImpl_GetData(IWineD3DSurface *iface)
|
---|
1882 | {
|
---|
1883 | IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
|
---|
1884 |
|
---|
1885 | /* This should only be called for sysmem textures, it may be a good idea
|
---|
1886 | * to extend this to all pools at some point in the future */
|
---|
1887 | if (This->resource.pool != WINED3DPOOL_SYSTEMMEM)
|
---|
1888 | {
|
---|
1889 | FIXME("(%p) Attempting to get system memory for a non-system memory texture\n", iface);
|
---|
1890 | }
|
---|
1891 | return This->resource.allocatedMemory;
|
---|
1892 | }
|
---|