ddraw: Use unsafe_impl_from_IDirectDrawSurface4.
[wine/wine-gecko.git] / dlls / ddraw / surface.c
blob5e57518e44aede725d7dff5b39d6481f3c75c034
1 /* DirectDraw Surface Implementation
3 * Copyright (c) 1997-2000 Marcus Meissner
4 * Copyright (c) 1998-2000 Lionel Ulmer
5 * Copyright (c) 2000-2001 TransGaming Technologies Inc.
6 * Copyright (c) 2006 Stefan Dösinger
8 * This file contains the (internal) driver registration functions,
9 * driver enumeration APIs and DirectDraw creation functions.
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "config.h"
27 #include "wine/port.h"
29 #include "ddraw_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
33 static inline IDirectDrawSurfaceImpl *surface_from_gamma_control(IDirectDrawGammaControl *iface)
35 return (IDirectDrawSurfaceImpl *)((char*)iface
36 - FIELD_OFFSET(IDirectDrawSurfaceImpl, IDirectDrawGammaControl_vtbl));
39 /*****************************************************************************
40 * IUnknown parts follow
41 *****************************************************************************/
43 /*****************************************************************************
44 * IDirectDrawSurface7::QueryInterface
46 * A normal QueryInterface implementation. For QueryInterface rules
47 * see ddraw.c, IDirectDraw7::QueryInterface. This method
48 * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
49 * in all versions, the IDirectDrawGammaControl interface and it can
50 * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
52 * Params:
53 * riid: The interface id queried for
54 * obj: Address to write the pointer to
56 * Returns:
57 * S_OK on success
58 * E_NOINTERFACE if the requested interface wasn't found
60 *****************************************************************************/
61 static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface, REFIID riid, void **obj)
63 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
65 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
67 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
68 *obj = NULL;
70 if(!riid)
71 return DDERR_INVALIDPARAMS;
73 if (IsEqualGUID(riid, &IID_IUnknown)
74 || IsEqualGUID(riid, &IID_IDirectDrawSurface7)
75 || IsEqualGUID(riid, &IID_IDirectDrawSurface4) )
77 IUnknown_AddRef(iface);
78 *obj = iface;
79 TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This, *obj);
80 return S_OK;
82 else if( IsEqualGUID(riid, &IID_IDirectDrawSurface3)
83 || IsEqualGUID(riid, &IID_IDirectDrawSurface2)
84 || IsEqualGUID(riid, &IID_IDirectDrawSurface) )
86 IUnknown_AddRef(iface);
87 *obj = &This->IDirectDrawSurface3_iface;
88 TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
89 return S_OK;
91 else if( IsEqualGUID(riid, &IID_IDirectDrawGammaControl) )
93 IUnknown_AddRef(iface);
94 *obj = &This->IDirectDrawGammaControl_vtbl;
95 TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This, *obj);
96 return S_OK;
98 else if( IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D) ||
99 IsEqualGUID(riid, &IID_IDirect3DHALDevice)||
100 IsEqualGUID(riid, &IID_IDirect3DRGBDevice) )
102 IDirect3DDevice7 *d3d;
104 /* Call into IDirect3D7 for creation */
105 IDirect3D7_CreateDevice(&This->ddraw->IDirect3D7_iface, riid, &This->IDirectDrawSurface7_iface,
106 &d3d);
108 if (d3d)
110 *obj = (IDirect3DDevice *)&((IDirect3DDeviceImpl *)d3d)->IDirect3DDevice_vtbl;
111 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
112 return S_OK;
115 WARN("Unable to create a IDirect3DDevice instance, returning E_NOINTERFACE\n");
116 return E_NOINTERFACE;
118 else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
119 IsEqualGUID( &IID_IDirect3DTexture2, riid ))
121 if (IsEqualGUID( &IID_IDirect3DTexture, riid ))
123 *obj = &This->IDirect3DTexture_vtbl;
124 TRACE(" returning Direct3DTexture interface at %p.\n", *obj);
126 else
128 *obj = &This->IDirect3DTexture2_vtbl;
129 TRACE(" returning Direct3DTexture2 interface at %p.\n", *obj);
131 IUnknown_AddRef( (IUnknown *) *obj);
132 return S_OK;
135 ERR("No interface\n");
136 return E_NOINTERFACE;
139 static HRESULT WINAPI ddraw_surface3_QueryInterface(IDirectDrawSurface3 *iface, REFIID riid, void **object)
141 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
142 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
144 return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
147 static HRESULT WINAPI ddraw_gamma_control_QueryInterface(IDirectDrawGammaControl *iface, REFIID riid, void **object)
149 IDirectDrawSurfaceImpl *This = surface_from_gamma_control(iface);
150 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
152 return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
155 static HRESULT WINAPI d3d_texture2_QueryInterface(IDirect3DTexture2 *iface, REFIID riid, void **object)
157 IDirectDrawSurfaceImpl *This = surface_from_texture2(iface);
158 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
160 return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
163 static HRESULT WINAPI d3d_texture1_QueryInterface(IDirect3DTexture *iface, REFIID riid, void **object)
165 IDirectDrawSurfaceImpl *This = surface_from_texture1(iface);
166 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
168 return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
171 /*****************************************************************************
172 * IDirectDrawSurface7::AddRef
174 * A normal addref implementation
176 * Returns:
177 * The new refcount
179 *****************************************************************************/
180 static ULONG WINAPI ddraw_surface7_AddRef(IDirectDrawSurface7 *iface)
182 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
183 ULONG refCount = InterlockedIncrement(&This->ref);
185 TRACE("%p increasing refcount to %u.\n", This, refCount);
187 if (refCount == 1)
189 EnterCriticalSection(&ddraw_cs);
190 if (This->wined3d_surface)
191 wined3d_surface_incref(This->wined3d_surface);
192 if (This->wined3d_texture)
193 wined3d_texture_incref(This->wined3d_texture);
194 LeaveCriticalSection(&ddraw_cs);
197 return refCount;
200 static ULONG WINAPI ddraw_surface3_AddRef(IDirectDrawSurface3 *iface)
202 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
203 TRACE("iface %p.\n", iface);
205 return ddraw_surface7_AddRef(&This->IDirectDrawSurface7_iface);
208 static ULONG WINAPI ddraw_gamma_control_AddRef(IDirectDrawGammaControl *iface)
210 IDirectDrawSurfaceImpl *This = surface_from_gamma_control(iface);
211 TRACE("iface %p.\n", iface);
213 return ddraw_surface7_AddRef(&This->IDirectDrawSurface7_iface);
216 static ULONG WINAPI d3d_texture2_AddRef(IDirect3DTexture2 *iface)
218 IDirectDrawSurfaceImpl *This = surface_from_texture2(iface);
219 TRACE("iface %p.\n", iface);
221 return ddraw_surface7_AddRef(&This->IDirectDrawSurface7_iface);
224 static ULONG WINAPI d3d_texture1_AddRef(IDirect3DTexture *iface)
226 IDirectDrawSurfaceImpl *This = surface_from_texture1(iface);
227 TRACE("iface %p.\n", iface);
229 return ddraw_surface7_AddRef(&This->IDirectDrawSurface7_iface);
232 /*****************************************************************************
233 * ddraw_surface_destroy
235 * A helper function for IDirectDrawSurface7::Release
237 * Frees the surface, regardless of its refcount.
238 * See IDirectDrawSurface7::Release for more information
240 * Params:
241 * This: Surface to free
243 *****************************************************************************/
244 void ddraw_surface_destroy(IDirectDrawSurfaceImpl *This)
246 TRACE("surface %p.\n", This);
248 /* Check the refcount and give a warning */
249 if(This->ref > 1)
251 /* This can happen when a complex surface is destroyed,
252 * because the 2nd surface was addref()ed when the app
253 * called GetAttachedSurface
255 WARN("(%p): Destroying surface with refount %d\n", This, This->ref);
258 if (This->wined3d_surface)
259 wined3d_surface_decref(This->wined3d_surface);
262 static void ddraw_surface_cleanup(IDirectDrawSurfaceImpl *surface)
264 IDirectDrawSurfaceImpl *surf;
265 IUnknown *ifaceToRelease;
266 UINT i;
268 TRACE("surface %p.\n", surface);
270 if (surface->wined3d_swapchain)
272 IDirectDrawImpl *ddraw = surface->ddraw;
274 /* If it's the render target, destroy the D3D device. */
275 if (ddraw->d3d_initialized && surface == ddraw->d3d_target)
277 TRACE("Destroying the render target, uninitializing D3D.\n");
279 for (i = 0; i < ddraw->numConvertedDecls; ++i)
281 wined3d_vertex_declaration_decref(ddraw->decls[i].decl);
283 HeapFree(GetProcessHeap(), 0, ddraw->decls);
284 ddraw->numConvertedDecls = 0;
286 if (FAILED(wined3d_device_uninit_3d(ddraw->wined3d_device)))
288 ERR("Failed to uninit 3D.\n");
290 else
292 /* Free the d3d window if one was created. */
293 if (ddraw->d3d_window && ddraw->d3d_window != ddraw->dest_window)
295 TRACE("Destroying the hidden render window %p.\n", ddraw->d3d_window);
296 DestroyWindow(ddraw->d3d_window);
297 ddraw->d3d_window = 0;
301 ddraw->d3d_initialized = FALSE;
302 ddraw->d3d_target = NULL;
304 else
306 wined3d_device_uninit_gdi(ddraw->wined3d_device);
309 surface->wined3d_swapchain = NULL;
311 /* Reset to the default surface implementation type. This is needed
312 * if applications use non render target surfaces and expect blits to
313 * work after destroying the render target.
315 * TODO: Recreate existing offscreen surfaces. */
316 ddraw->ImplType = DefaultSurfaceType;
318 TRACE("D3D unloaded.\n");
321 /* The refcount test shows that the palette is detached when the surface
322 * is destroyed. */
323 IDirectDrawSurface7_SetPalette(&surface->IDirectDrawSurface7_iface, NULL);
325 /* Loop through all complex attached surfaces and destroy them.
327 * Yet again, only the root can have more than one complexly attached
328 * surface, all the others have a total of one. */
329 for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i)
331 if (!surface->complex_array[i])
332 break;
334 surf = surface->complex_array[i];
335 surface->complex_array[i] = NULL;
336 while (surf)
338 IDirectDrawSurfaceImpl *destroy = surf;
339 surf = surf->complex_array[0]; /* Iterate through the "tree" */
340 ddraw_surface_destroy(destroy); /* Destroy it */
344 ifaceToRelease = surface->ifaceToRelease;
346 /* Destroy the root surface. */
347 ddraw_surface_destroy(surface);
349 /* Reduce the ddraw refcount */
350 if (ifaceToRelease)
351 IUnknown_Release(ifaceToRelease);
354 /*****************************************************************************
355 * IDirectDrawSurface7::Release
357 * Reduces the surface's refcount by 1. If the refcount falls to 0, the
358 * surface is destroyed.
360 * Destroying the surface is a bit tricky. For the connection between
361 * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
362 * It has a nice graph explaining the connection.
364 * What happens here is basically this:
365 * When a surface is destroyed, its WineD3DSurface is released,
366 * and the refcount of the DirectDraw interface is reduced by 1. If it has
367 * complex surfaces attached to it, then these surfaces are destroyed too,
368 * regardless of their refcount. If any surface being destroyed has another
369 * surface attached to it (with a "soft" attachment, not complex), then
370 * this surface is detached with DeleteAttachedSurface.
372 * When the surface is a texture, the WineD3DTexture is released.
373 * If the surface is the Direct3D render target, then the D3D
374 * capabilities of the WineD3DDevice are uninitialized, which causes the
375 * swapchain to be released.
377 * When a complex sublevel falls to ref zero, then this is ignored.
379 * Returns:
380 * The new refcount
382 *****************************************************************************/
383 static ULONG WINAPI ddraw_surface7_Release(IDirectDrawSurface7 *iface)
385 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
386 ULONG ref = InterlockedDecrement(&This->ref);
388 TRACE("%p decreasing refcount to %u.\n", This, ref);
390 if (ref == 0)
392 /* Complex attached surfaces are destroyed implicitly when the root is released */
393 EnterCriticalSection(&ddraw_cs);
394 if(!This->is_complex_root)
396 WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
397 LeaveCriticalSection(&ddraw_cs);
398 return ref;
400 if (This->wined3d_texture) /* If it's a texture, destroy the wined3d texture. */
401 wined3d_texture_decref(This->wined3d_texture);
402 else
403 ddraw_surface_cleanup(This);
404 LeaveCriticalSection(&ddraw_cs);
407 return ref;
410 static ULONG WINAPI ddraw_surface3_Release(IDirectDrawSurface3 *iface)
412 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
413 TRACE("iface %p.\n", iface);
415 return ddraw_surface7_Release(&This->IDirectDrawSurface7_iface);
418 static ULONG WINAPI ddraw_gamma_control_Release(IDirectDrawGammaControl *iface)
420 IDirectDrawSurfaceImpl *This = surface_from_gamma_control(iface);
421 TRACE("iface %p.\n", iface);
423 return ddraw_surface7_Release(&This->IDirectDrawSurface7_iface);
426 static ULONG WINAPI d3d_texture2_Release(IDirect3DTexture2 *iface)
428 IDirectDrawSurfaceImpl *This = surface_from_texture2(iface);
429 TRACE("iface %p.\n", iface);
431 return ddraw_surface7_Release(&This->IDirectDrawSurface7_iface);
434 static ULONG WINAPI d3d_texture1_Release(IDirect3DTexture *iface)
436 IDirectDrawSurfaceImpl *This = surface_from_texture1(iface);
437 TRACE("iface %p.\n", iface);
439 return ddraw_surface7_Release(&This->IDirectDrawSurface7_iface);
442 /*****************************************************************************
443 * IDirectDrawSurface7::GetAttachedSurface
445 * Returns an attached surface with the requested caps. Surface attachment
446 * and complex surfaces are not clearly described by the MSDN or sdk,
447 * so this method is tricky and likely to contain problems.
448 * This implementation searches the complex list first, then the
449 * attachment chain.
451 * The chains are searched from This down to the last surface in the chain,
452 * not from the first element in the chain. The first surface found is
453 * returned. The MSDN says that this method fails if more than one surface
454 * matches the caps, but it is not sure if that is right. The attachment
455 * structure may not even allow two matching surfaces.
457 * The found surface is AddRef-ed before it is returned.
459 * Params:
460 * Caps: Pointer to a DDCAPS2 structure describing the caps asked for
461 * Surface: Address to store the found surface
463 * Returns:
464 * DD_OK on success
465 * DDERR_INVALIDPARAMS if Caps or Surface is NULL
466 * DDERR_NOTFOUND if no surface was found
468 *****************************************************************************/
469 static HRESULT WINAPI ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7 *iface,
470 DDSCAPS2 *Caps, IDirectDrawSurface7 **Surface)
472 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
473 IDirectDrawSurfaceImpl *surf;
474 DDSCAPS2 our_caps;
475 int i;
477 TRACE("iface %p, caps %p, attachment %p.\n", iface, Caps, Surface);
479 EnterCriticalSection(&ddraw_cs);
481 if(This->version < 7)
483 /* Earlier dx apps put garbage into these members, clear them */
484 our_caps.dwCaps = Caps->dwCaps;
485 our_caps.dwCaps2 = 0;
486 our_caps.dwCaps3 = 0;
487 our_caps.dwCaps4 = 0;
489 else
491 our_caps = *Caps;
494 TRACE("(%p): Looking for caps: %x,%x,%x,%x\n", This, our_caps.dwCaps, our_caps.dwCaps2, our_caps.dwCaps3, our_caps.dwCaps4); /* FIXME: Better debugging */
496 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
498 surf = This->complex_array[i];
499 if(!surf) break;
501 if (TRACE_ON(ddraw))
503 TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf,
504 surf->surface_desc.ddsCaps.dwCaps,
505 surf->surface_desc.ddsCaps.dwCaps2,
506 surf->surface_desc.ddsCaps.dwCaps3,
507 surf->surface_desc.ddsCaps.dwCaps4);
510 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
511 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
513 /* MSDN: "This method fails if more than one surface is attached
514 * that matches the capabilities requested."
516 * Not sure how to test this.
519 TRACE("(%p): Returning surface %p\n", This, surf);
520 TRACE("(%p): mipmapcount=%d\n", This, surf->mipmap_level);
521 *Surface = &surf->IDirectDrawSurface7_iface;
522 ddraw_surface7_AddRef(*Surface);
523 LeaveCriticalSection(&ddraw_cs);
524 return DD_OK;
528 /* Next, look at the attachment chain */
529 surf = This;
531 while( (surf = surf->next_attached) )
533 if (TRACE_ON(ddraw))
535 TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf,
536 surf->surface_desc.ddsCaps.dwCaps,
537 surf->surface_desc.ddsCaps.dwCaps2,
538 surf->surface_desc.ddsCaps.dwCaps3,
539 surf->surface_desc.ddsCaps.dwCaps4);
542 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
543 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
545 TRACE("(%p): Returning surface %p\n", This, surf);
546 *Surface = &surf->IDirectDrawSurface7_iface;
547 ddraw_surface7_AddRef(*Surface);
548 LeaveCriticalSection(&ddraw_cs);
549 return DD_OK;
553 TRACE("(%p) Didn't find a valid surface\n", This);
554 LeaveCriticalSection(&ddraw_cs);
556 *Surface = NULL;
557 return DDERR_NOTFOUND;
560 static HRESULT WINAPI ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3 *iface,
561 DDSCAPS *caps, IDirectDrawSurface3 **attachment)
563 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
564 IDirectDrawSurface7 *attachment7;
565 IDirectDrawSurfaceImpl *attachment_impl;
566 DDSCAPS2 caps2;
567 HRESULT hr;
569 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
571 caps2.dwCaps = caps->dwCaps;
572 caps2.dwCaps2 = 0;
573 caps2.dwCaps3 = 0;
574 caps2.dwCaps4 = 0;
576 hr = ddraw_surface7_GetAttachedSurface(&This->IDirectDrawSurface7_iface,
577 &caps2, &attachment7);
578 if (FAILED(hr))
580 *attachment = NULL;
581 return hr;
583 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
584 *attachment = &attachment_impl->IDirectDrawSurface3_iface;
586 return hr;
589 /*****************************************************************************
590 * IDirectDrawSurface7::Lock
592 * Locks the surface and returns a pointer to the surface's memory
594 * Params:
595 * Rect: Rectangle to lock. If NULL, the whole surface is locked
596 * DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
597 * Flags: Locking flags, e.g Read only or write only
598 * h: An event handle that's not used and must be NULL
600 * Returns:
601 * DD_OK on success
602 * DDERR_INVALIDPARAMS if DDSD is NULL
603 * For more details, see IWineD3DSurface::LockRect
605 *****************************************************************************/
606 static HRESULT WINAPI ddraw_surface7_Lock(IDirectDrawSurface7 *iface,
607 RECT *Rect, DDSURFACEDESC2 *DDSD, DWORD Flags, HANDLE h)
609 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
610 WINED3DLOCKED_RECT LockedRect;
611 HRESULT hr;
613 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
614 iface, wine_dbgstr_rect(Rect), DDSD, Flags, h);
616 if(!DDSD)
617 return DDERR_INVALIDPARAMS;
619 /* This->surface_desc.dwWidth and dwHeight are changeable, thus lock */
620 EnterCriticalSection(&ddraw_cs);
622 /* Should I check for the handle to be NULL?
624 * The DDLOCK flags and the D3DLOCK flags are equal
625 * for the supported values. The others are ignored by WineD3D
628 if(DDSD->dwSize != sizeof(DDSURFACEDESC) &&
629 DDSD->dwSize != sizeof(DDSURFACEDESC2))
631 WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", DDERR_INVALIDPARAMS);
632 LeaveCriticalSection(&ddraw_cs);
633 return DDERR_INVALIDPARAMS;
636 /* Windows zeroes this if the rect is invalid */
637 DDSD->lpSurface = 0;
639 if (Rect)
641 if ((Rect->left < 0)
642 || (Rect->top < 0)
643 || (Rect->left > Rect->right)
644 || (Rect->top > Rect->bottom)
645 || (Rect->right > This->surface_desc.dwWidth)
646 || (Rect->bottom > This->surface_desc.dwHeight))
648 WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
649 LeaveCriticalSection(&ddraw_cs);
650 return DDERR_INVALIDPARAMS;
654 hr = wined3d_surface_map(This->wined3d_surface, &LockedRect, Rect, Flags);
655 if (FAILED(hr))
657 LeaveCriticalSection(&ddraw_cs);
658 switch(hr)
660 /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more
661 * specific error. But since IWineD3DSurface::LockRect returns that error in this
662 * only occasion, keep d3d8 and d3d9 free from the return value override. There are
663 * many different places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it
664 * is much easier to do it in one place in ddraw
666 case WINED3DERR_INVALIDCALL: return DDERR_SURFACEBUSY;
667 default: return hr;
671 /* Override the memory area. The pitch should be set already. Strangely windows
672 * does not set the LPSURFACE flag on locked surfaces !?!.
673 * DDSD->dwFlags |= DDSD_LPSURFACE;
675 This->surface_desc.lpSurface = LockedRect.pBits;
676 DD_STRUCT_COPY_BYSIZE(DDSD,&(This->surface_desc));
678 TRACE("locked surface returning description :\n");
679 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
681 LeaveCriticalSection(&ddraw_cs);
682 return DD_OK;
685 static HRESULT WINAPI ddraw_surface3_Lock(IDirectDrawSurface3 *iface, RECT *rect,
686 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
688 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
689 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
690 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
692 return ddraw_surface7_Lock(&This->IDirectDrawSurface7_iface,
693 rect, (DDSURFACEDESC2 *)surface_desc, flags, h);
696 /*****************************************************************************
697 * IDirectDrawSurface7::Unlock
699 * Unlocks an locked surface
701 * Params:
702 * Rect: Not used by this implementation
704 * Returns:
705 * D3D_OK on success
706 * For more details, see IWineD3DSurface::UnlockRect
708 *****************************************************************************/
709 static HRESULT WINAPI ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *pRect)
711 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
712 HRESULT hr;
714 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(pRect));
716 EnterCriticalSection(&ddraw_cs);
717 hr = wined3d_surface_unmap(This->wined3d_surface);
718 if (SUCCEEDED(hr))
720 This->surface_desc.lpSurface = NULL;
722 LeaveCriticalSection(&ddraw_cs);
723 return hr;
726 static HRESULT WINAPI ddraw_surface3_Unlock(IDirectDrawSurface3 *iface, void *data)
728 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
729 TRACE("iface %p, data %p.\n", iface, data);
731 /* data might not be the LPRECT of later versions, so drop it. */
732 return ddraw_surface7_Unlock(&This->IDirectDrawSurface7_iface, NULL);
735 /*****************************************************************************
736 * IDirectDrawSurface7::Flip
738 * Flips a surface with the DDSCAPS_FLIP flag. The flip is relayed to
739 * IWineD3DSurface::Flip. Because WineD3D doesn't handle attached surfaces,
740 * the flip target is passed to WineD3D, even if the app didn't specify one
742 * Params:
743 * DestOverride: Specifies the surface that will become the new front
744 * buffer. If NULL, the current back buffer is used
745 * Flags: some DirectDraw flags, see include/ddraw.h
747 * Returns:
748 * DD_OK on success
749 * DDERR_NOTFLIPPABLE if no flip target could be found
750 * DDERR_INVALIDOBJECT if the surface isn't a front buffer
751 * For more details, see IWineD3DSurface::Flip
753 *****************************************************************************/
754 static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *DestOverride, DWORD Flags)
756 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
757 IDirectDrawSurfaceImpl *Override = unsafe_impl_from_IDirectDrawSurface7(DestOverride);
758 IDirectDrawSurface7 *Override7;
759 HRESULT hr;
761 TRACE("iface %p, dst %p, flags %#x.\n", iface, DestOverride, Flags);
763 /* Flip has to be called from a front buffer
764 * What about overlay surfaces, AFAIK they can flip too?
766 if( !(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)) )
767 return DDERR_INVALIDOBJECT; /* Unchecked */
769 EnterCriticalSection(&ddraw_cs);
771 /* WineD3D doesn't keep track of attached surface, so find the target */
772 if(!Override)
774 DDSCAPS2 Caps;
776 memset(&Caps, 0, sizeof(Caps));
777 Caps.dwCaps |= DDSCAPS_BACKBUFFER;
778 hr = ddraw_surface7_GetAttachedSurface(iface, &Caps, &Override7);
779 if(hr != DD_OK)
781 ERR("Can't find a flip target\n");
782 LeaveCriticalSection(&ddraw_cs);
783 return DDERR_NOTFLIPPABLE; /* Unchecked */
785 Override = impl_from_IDirectDrawSurface7(Override7);
787 /* For the GetAttachedSurface */
788 ddraw_surface7_Release(Override7);
791 hr = wined3d_surface_flip(This->wined3d_surface, Override->wined3d_surface, Flags);
792 LeaveCriticalSection(&ddraw_cs);
793 return hr;
796 static HRESULT WINAPI ddraw_surface3_Flip(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *dst, DWORD flags)
798 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
799 IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst);
800 TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
802 return ddraw_surface7_Flip(&This->IDirectDrawSurface7_iface,
803 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
806 /*****************************************************************************
807 * IDirectDrawSurface7::Blt
809 * Performs a blit on the surface
811 * Params:
812 * DestRect: Destination rectangle, can be NULL
813 * SrcSurface: Source surface, can be NULL
814 * SrcRect: Source rectangle, can be NULL
815 * Flags: Blt flags
816 * DDBltFx: Some extended blt parameters, connected to the flags
818 * Returns:
819 * D3D_OK on success
820 * See IWineD3DSurface::Blt for more details
822 *****************************************************************************/
823 static HRESULT WINAPI ddraw_surface7_Blt(IDirectDrawSurface7 *iface, RECT *DestRect,
824 IDirectDrawSurface7 *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx)
826 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
827 IDirectDrawSurfaceImpl *Src = unsafe_impl_from_IDirectDrawSurface7(SrcSurface);
828 HRESULT hr;
830 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
831 iface, wine_dbgstr_rect(DestRect), SrcSurface, wine_dbgstr_rect(SrcRect), Flags, DDBltFx);
833 /* Check for validity of the flags here. WineD3D Has the software-opengl selection path and would have
834 * to check at 2 places, and sometimes do double checks. This also saves the call to wined3d :-)
836 if((Flags & DDBLT_KEYSRCOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYSRC)) {
837 WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
838 return DDERR_INVALIDPARAMS;
841 if((Flags & DDBLT_KEYDESTOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYDEST)) {
842 WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
843 return DDERR_INVALIDPARAMS;
846 /* Sizes can change, therefore hold the lock when testing the rectangles */
847 EnterCriticalSection(&ddraw_cs);
848 if(DestRect)
850 if(DestRect->top >= DestRect->bottom || DestRect->left >= DestRect->right ||
851 DestRect->right > This->surface_desc.dwWidth ||
852 DestRect->bottom > This->surface_desc.dwHeight)
854 WARN("Destination rectangle is invalid, returning DDERR_INVALIDRECT\n");
855 LeaveCriticalSection(&ddraw_cs);
856 return DDERR_INVALIDRECT;
859 if(Src && SrcRect)
861 if(SrcRect->top >= SrcRect->bottom || SrcRect->left >=SrcRect->right ||
862 SrcRect->right > Src->surface_desc.dwWidth ||
863 SrcRect->bottom > Src->surface_desc.dwHeight)
865 WARN("Source rectangle is invalid, returning DDERR_INVALIDRECT\n");
866 LeaveCriticalSection(&ddraw_cs);
867 return DDERR_INVALIDRECT;
871 if(Flags & DDBLT_KEYSRC && (!Src || !(Src->surface_desc.dwFlags & DDSD_CKSRCBLT))) {
872 WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
873 LeaveCriticalSection(&ddraw_cs);
874 return DDERR_INVALIDPARAMS;
877 /* TODO: Check if the DDBltFx contains any ddraw surface pointers. If it
878 * does, copy the struct, and replace the ddraw surfaces with the wined3d
879 * surfaces. So far no blitting operations using surfaces in the bltfx
880 * struct are supported anyway. */
881 hr = wined3d_surface_blt(This->wined3d_surface, DestRect, Src ? Src->wined3d_surface : NULL,
882 SrcRect, Flags, (WINEDDBLTFX *)DDBltFx, WINED3DTEXF_LINEAR);
884 LeaveCriticalSection(&ddraw_cs);
885 switch(hr)
887 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
888 case WINED3DERR_WRONGTEXTUREFORMAT: return DDERR_INVALIDPIXELFORMAT;
889 default: return hr;
893 static HRESULT WINAPI ddraw_surface3_Blt(IDirectDrawSurface3 *iface, RECT *dst_rect,
894 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
896 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
897 IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
898 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
899 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
901 return ddraw_surface7_Blt(&This->IDirectDrawSurface7_iface, dst_rect,
902 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
905 /*****************************************************************************
906 * IDirectDrawSurface7::AddAttachedSurface
908 * Attaches a surface to another surface. How the surface attachments work
909 * is not totally understood yet, and this method is prone to problems.
910 * he surface that is attached is AddRef-ed.
912 * Tests with complex surfaces suggest that the surface attachments form a
913 * tree, but no method to test this has been found yet.
915 * The attachment list consists of a first surface (first_attached) and
916 * for each surface a pointer to the next attached surface (next_attached).
917 * For the first surface, and a surface that has no attachments
918 * first_attached points to the surface itself. A surface that has
919 * no successors in the chain has next_attached set to NULL.
921 * Newly attached surfaces are attached right after the root surface.
922 * If a surface is attached to a complex surface compound, it's attached to
923 * the surface that the app requested, not the complex root. See
924 * GetAttachedSurface for a description how surfaces are found.
926 * This is how the current implementation works, and it was coded by looking
927 * at the needs of the applications.
929 * So far only Z-Buffer attachments are tested, and they are activated in
930 * WineD3D. Mipmaps could be tricky to activate in WineD3D.
931 * Back buffers should work in 2D mode, but they are not tested(They can be
932 * attached in older iface versions). Rendering to the front buffer and
933 * switching between that and double buffering is not yet implemented in
934 * WineD3D, so for 3D it might have unexpected results.
936 * ddraw_surface_attach_surface is the real thing,
937 * ddraw_surface7_AddAttachedSurface is a wrapper around it that
938 * performs additional checks. Version 7 of this interface is much more restrictive
939 * than its predecessors.
941 * Params:
942 * Attach: Surface to attach to iface
944 * Returns:
945 * DD_OK on success
946 * DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
948 *****************************************************************************/
949 static HRESULT ddraw_surface_attach_surface(IDirectDrawSurfaceImpl *This, IDirectDrawSurfaceImpl *Surf)
951 TRACE("surface %p, attachment %p.\n", This, Surf);
953 if(Surf == This)
954 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
956 EnterCriticalSection(&ddraw_cs);
958 /* Check if the surface is already attached somewhere */
959 if (Surf->next_attached || Surf->first_attached != Surf)
961 /* TODO: Test for the structure of the manual attachment. Is it a
962 * chain or a list? What happens if one surface is attached to 2
963 * different surfaces? */
964 WARN("Surface %p is already attached somewhere. next_attached %p, first_attached %p.\n",
965 Surf, Surf->next_attached, Surf->first_attached);
967 LeaveCriticalSection(&ddraw_cs);
968 return DDERR_SURFACEALREADYATTACHED;
971 /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
972 Surf->next_attached = This->next_attached;
973 Surf->first_attached = This->first_attached;
974 This->next_attached = Surf;
976 /* Check if the WineD3D depth stencil needs updating */
977 if(This->ddraw->d3ddevice)
979 IDirect3DDeviceImpl_UpdateDepthStencil(This->ddraw->d3ddevice);
982 ddraw_surface7_AddRef(&Surf->IDirectDrawSurface7_iface);
983 LeaveCriticalSection(&ddraw_cs);
984 return DD_OK;
987 static HRESULT WINAPI ddraw_surface7_AddAttachedSurface(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *Attach)
989 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
990 IDirectDrawSurfaceImpl *Surf = unsafe_impl_from_IDirectDrawSurface7(Attach);
992 TRACE("iface %p, attachment %p.\n", iface, Attach);
994 /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
995 if(!(Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
998 WARN("Application tries to attach a non Z buffer surface. caps %08x\n",
999 Surf->surface_desc.ddsCaps.dwCaps);
1000 return DDERR_CANNOTATTACHSURFACE;
1003 return ddraw_surface_attach_surface(This, Surf);
1006 static HRESULT WINAPI ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *attachment)
1008 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1009 IDirectDrawSurfaceImpl *attach_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
1011 TRACE("iface %p, attachment %p.\n", iface, attachment);
1013 /* Tests suggest that
1014 * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
1015 * -> offscreen plain surfaces can be attached to primaries
1016 * -> primaries can be attached to offscreen plain surfaces
1017 * -> z buffers can be attached to primaries */
1018 if (This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN)
1019 && attach_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN))
1021 /* Sizes have to match */
1022 if (attach_impl->surface_desc.dwWidth != This->surface_desc.dwWidth
1023 || attach_impl->surface_desc.dwHeight != This->surface_desc.dwHeight)
1025 WARN("Surface sizes do not match.\n");
1026 return DDERR_CANNOTATTACHSURFACE;
1028 /* OK */
1030 else if (This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE)
1031 && attach_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER))
1033 /* OK */
1035 else
1037 WARN("Invalid attachment combination.\n");
1038 return DDERR_CANNOTATTACHSURFACE;
1041 return ddraw_surface_attach_surface(This, attach_impl);
1044 /*****************************************************************************
1045 * IDirectDrawSurface7::DeleteAttachedSurface
1047 * Removes a surface from the attachment chain. The surface's refcount
1048 * is decreased by one after it has been removed
1050 * Params:
1051 * Flags: Some flags, not used by this implementation
1052 * Attach: Surface to detach
1054 * Returns:
1055 * DD_OK on success
1056 * DDERR_SURFACENOTATTACHED if the surface isn't attached to
1058 *****************************************************************************/
1059 static HRESULT WINAPI ddraw_surface7_DeleteAttachedSurface(IDirectDrawSurface7 *iface,
1060 DWORD Flags, IDirectDrawSurface7 *Attach)
1062 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1063 IDirectDrawSurfaceImpl *Surf = unsafe_impl_from_IDirectDrawSurface7(Attach);
1064 IDirectDrawSurfaceImpl *Prev = This;
1066 TRACE("iface %p, flags %#x, attachment %p.\n", iface, Flags, Attach);
1068 EnterCriticalSection(&ddraw_cs);
1069 if (!Surf || (Surf->first_attached != This) || (Surf == This) )
1071 LeaveCriticalSection(&ddraw_cs);
1072 return DDERR_CANNOTDETACHSURFACE;
1075 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
1076 if (This->surface_desc.ddsCaps.dwCaps &
1077 Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
1079 Surf->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
1080 /* FIXME: we should probably also subtract from dwMipMapCount of this
1081 * and all parent surfaces */
1084 /* Find the predecessor of the detached surface */
1085 while(Prev)
1087 if(Prev->next_attached == Surf) break;
1088 Prev = Prev->next_attached;
1091 /* There must be a surface, otherwise there's a bug */
1092 assert(Prev != NULL);
1094 /* Unchain the surface */
1095 Prev->next_attached = Surf->next_attached;
1096 Surf->next_attached = NULL;
1097 Surf->first_attached = Surf;
1099 /* Check if the WineD3D depth stencil needs updating */
1100 if(This->ddraw->d3ddevice)
1102 IDirect3DDeviceImpl_UpdateDepthStencil(This->ddraw->d3ddevice);
1105 ddraw_surface7_Release(Attach);
1106 LeaveCriticalSection(&ddraw_cs);
1107 return DD_OK;
1110 static HRESULT WINAPI ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3 *iface,
1111 DWORD flags, IDirectDrawSurface3 *attachment)
1113 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1114 IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
1115 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1117 return ddraw_surface7_DeleteAttachedSurface(&This->IDirectDrawSurface7_iface, flags,
1118 attachment_impl ? &attachment_impl->IDirectDrawSurface7_iface : NULL);
1121 /*****************************************************************************
1122 * IDirectDrawSurface7::AddOverlayDirtyRect
1124 * "This method is not currently implemented"
1126 * Params:
1127 * Rect: ?
1129 * Returns:
1130 * DDERR_UNSUPPORTED
1132 *****************************************************************************/
1133 static HRESULT WINAPI ddraw_surface7_AddOverlayDirtyRect(IDirectDrawSurface7 *iface, RECT *Rect)
1135 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(Rect));
1137 return DDERR_UNSUPPORTED; /* unchecked */
1140 static HRESULT WINAPI ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3 *iface, RECT *rect)
1142 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1143 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1145 return ddraw_surface7_AddOverlayDirtyRect(&This->IDirectDrawSurface7_iface, rect);
1148 /*****************************************************************************
1149 * IDirectDrawSurface7::GetDC
1151 * Returns a GDI device context for the surface
1153 * Params:
1154 * hdc: Address of a HDC variable to store the dc to
1156 * Returns:
1157 * DD_OK on success
1158 * DDERR_INVALIDPARAMS if hdc is NULL
1159 * For details, see IWineD3DSurface::GetDC
1161 *****************************************************************************/
1162 static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *hdc)
1164 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1165 HRESULT hr;
1167 TRACE("iface %p, dc %p.\n", iface, hdc);
1169 if(!hdc)
1170 return DDERR_INVALIDPARAMS;
1172 EnterCriticalSection(&ddraw_cs);
1173 hr = wined3d_surface_getdc(This->wined3d_surface, hdc);
1174 LeaveCriticalSection(&ddraw_cs);
1175 switch(hr)
1177 /* Some, but not all errors set *hdc to NULL. E.g. DCALREADYCREATED does not
1178 * touch *hdc
1180 case WINED3DERR_INVALIDCALL:
1181 if(hdc) *hdc = NULL;
1182 return DDERR_INVALIDPARAMS;
1184 default: return hr;
1188 static HRESULT WINAPI ddraw_surface3_GetDC(IDirectDrawSurface3 *iface, HDC *dc)
1190 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1191 TRACE("iface %p, dc %p.\n", iface, dc);
1193 return ddraw_surface7_GetDC(&This->IDirectDrawSurface7_iface, dc);
1196 /*****************************************************************************
1197 * IDirectDrawSurface7::ReleaseDC
1199 * Releases the DC that was constructed with GetDC
1201 * Params:
1202 * hdc: HDC to release
1204 * Returns:
1205 * DD_OK on success
1206 * For more details, see IWineD3DSurface::ReleaseDC
1208 *****************************************************************************/
1209 static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC hdc)
1211 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1212 HRESULT hr;
1214 TRACE("iface %p, dc %p.\n", iface, hdc);
1216 EnterCriticalSection(&ddraw_cs);
1217 hr = wined3d_surface_releasedc(This->wined3d_surface, hdc);
1218 LeaveCriticalSection(&ddraw_cs);
1219 return hr;
1222 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc)
1224 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1225 TRACE("iface %p, dc %p.\n", iface, dc);
1227 return ddraw_surface7_ReleaseDC(&This->IDirectDrawSurface7_iface, dc);
1230 /*****************************************************************************
1231 * IDirectDrawSurface7::GetCaps
1233 * Returns the surface's caps
1235 * Params:
1236 * Caps: Address to write the caps to
1238 * Returns:
1239 * DD_OK on success
1240 * DDERR_INVALIDPARAMS if Caps is NULL
1242 *****************************************************************************/
1243 static HRESULT WINAPI ddraw_surface7_GetCaps(IDirectDrawSurface7 *iface, DDSCAPS2 *Caps)
1245 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1247 TRACE("iface %p, caps %p.\n", iface, Caps);
1249 if(!Caps)
1250 return DDERR_INVALIDPARAMS;
1252 *Caps = This->surface_desc.ddsCaps;
1253 return DD_OK;
1256 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps)
1258 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1259 DDSCAPS2 caps2;
1260 HRESULT hr;
1262 TRACE("iface %p, caps %p.\n", iface, caps);
1264 hr = ddraw_surface7_GetCaps(&This->IDirectDrawSurface7_iface, &caps2);
1265 if (FAILED(hr)) return hr;
1267 caps->dwCaps = caps2.dwCaps;
1268 return hr;
1271 /*****************************************************************************
1272 * IDirectDrawSurface7::SetPriority
1274 * Sets a texture priority for managed textures.
1276 * Params:
1277 * Priority: The new priority
1279 * Returns:
1280 * DD_OK on success
1281 * For more details, see IWineD3DSurface::SetPriority
1283 *****************************************************************************/
1284 static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD Priority)
1286 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1287 HRESULT hr;
1289 TRACE("iface %p, priority %u.\n", iface, Priority);
1291 EnterCriticalSection(&ddraw_cs);
1292 hr = wined3d_surface_set_priority(This->wined3d_surface, Priority);
1293 LeaveCriticalSection(&ddraw_cs);
1294 return hr;
1297 /*****************************************************************************
1298 * IDirectDrawSurface7::GetPriority
1300 * Returns the surface's priority
1302 * Params:
1303 * Priority: Address of a variable to write the priority to
1305 * Returns:
1306 * D3D_OK on success
1307 * DDERR_INVALIDPARAMS if Priority == NULL
1308 * For more details, see IWineD3DSurface::GetPriority
1310 *****************************************************************************/
1311 static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *Priority)
1313 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1315 TRACE("iface %p, priority %p.\n", iface, Priority);
1317 if(!Priority)
1319 return DDERR_INVALIDPARAMS;
1322 EnterCriticalSection(&ddraw_cs);
1323 *Priority = wined3d_surface_get_priority(This->wined3d_surface);
1324 LeaveCriticalSection(&ddraw_cs);
1325 return DD_OK;
1328 /*****************************************************************************
1329 * IDirectDrawSurface7::SetPrivateData
1331 * Stores some data in the surface that is intended for the application's
1332 * use.
1334 * Params:
1335 * tag: GUID that identifies the data
1336 * Data: Pointer to the private data
1337 * Size: Size of the private data
1338 * Flags: Some flags
1340 * Returns:
1341 * D3D_OK on success
1342 * For more details, see IWineD3DSurface::SetPrivateData
1344 *****************************************************************************/
1345 static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface,
1346 REFGUID tag, void *Data, DWORD Size, DWORD Flags)
1348 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1349 HRESULT hr;
1351 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
1352 iface, debugstr_guid(tag), Data, Size, Flags);
1354 EnterCriticalSection(&ddraw_cs);
1355 hr = wined3d_surface_set_private_data(This->wined3d_surface, tag, Data, Size, Flags);
1356 LeaveCriticalSection(&ddraw_cs);
1357 switch(hr)
1359 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS;
1360 default: return hr;
1364 /*****************************************************************************
1365 * IDirectDrawSurface7::GetPrivateData
1367 * Returns the private data set with IDirectDrawSurface7::SetPrivateData
1369 * Params:
1370 * tag: GUID of the data to return
1371 * Data: Address where to write the data to
1372 * Size: Size of the buffer at Data
1374 * Returns:
1375 * DD_OK on success
1376 * DDERR_INVALIDPARAMS if Data is NULL
1377 * For more details, see IWineD3DSurface::GetPrivateData
1379 *****************************************************************************/
1380 static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *Data, DWORD *Size)
1382 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1383 HRESULT hr;
1385 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
1386 iface, debugstr_guid(tag), Data, Size);
1388 if(!Data)
1389 return DDERR_INVALIDPARAMS;
1391 EnterCriticalSection(&ddraw_cs);
1392 hr = wined3d_surface_get_private_data(This->wined3d_surface, tag, Data, Size);
1393 LeaveCriticalSection(&ddraw_cs);
1394 return hr;
1397 /*****************************************************************************
1398 * IDirectDrawSurface7::FreePrivateData
1400 * Frees private data stored in the surface
1402 * Params:
1403 * tag: Tag of the data to free
1405 * Returns:
1406 * D3D_OK on success
1407 * For more details, see IWineD3DSurface::FreePrivateData
1409 *****************************************************************************/
1410 static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag)
1412 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1413 HRESULT hr;
1415 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
1417 EnterCriticalSection(&ddraw_cs);
1418 hr = wined3d_surface_free_private_data(This->wined3d_surface, tag);
1419 LeaveCriticalSection(&ddraw_cs);
1420 return hr;
1423 /*****************************************************************************
1424 * IDirectDrawSurface7::PageLock
1426 * Prevents a sysmem surface from being paged out
1428 * Params:
1429 * Flags: Not used, must be 0(unchecked)
1431 * Returns:
1432 * DD_OK, because it's a stub
1434 *****************************************************************************/
1435 static HRESULT WINAPI ddraw_surface7_PageLock(IDirectDrawSurface7 *iface, DWORD Flags)
1437 TRACE("iface %p, flags %#x.\n", iface, Flags);
1439 /* This is Windows memory management related - we don't need this */
1440 return DD_OK;
1443 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags)
1445 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1446 TRACE("iface %p, flags %#x.\n", iface, flags);
1448 return ddraw_surface7_PageLock(&This->IDirectDrawSurface7_iface, flags);
1451 /*****************************************************************************
1452 * IDirectDrawSurface7::PageUnlock
1454 * Allows a sysmem surface to be paged out
1456 * Params:
1457 * Flags: Not used, must be 0(unchecked)
1459 * Returns:
1460 * DD_OK, because it's a stub
1462 *****************************************************************************/
1463 static HRESULT WINAPI ddraw_surface7_PageUnlock(IDirectDrawSurface7 *iface, DWORD Flags)
1465 TRACE("iface %p, flags %#x.\n", iface, Flags);
1467 return DD_OK;
1470 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags)
1472 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1473 TRACE("iface %p, flags %#x.\n", iface, flags);
1475 return ddraw_surface7_PageUnlock(&This->IDirectDrawSurface7_iface, flags);
1478 /*****************************************************************************
1479 * IDirectDrawSurface7::BltBatch
1481 * An unimplemented function
1483 * Params:
1486 * Returns:
1487 * DDERR_UNSUPPORTED
1489 *****************************************************************************/
1490 static HRESULT WINAPI ddraw_surface7_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
1492 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, Batch, Count, Flags);
1494 /* MSDN: "not currently implemented" */
1495 return DDERR_UNSUPPORTED;
1498 static HRESULT WINAPI ddraw_surface3_BltBatch(IDirectDrawSurface3 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
1500 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1501 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
1503 return ddraw_surface7_BltBatch(&This->IDirectDrawSurface7_iface, batch, count, flags);
1506 /*****************************************************************************
1507 * IDirectDrawSurface7::EnumAttachedSurfaces
1509 * Enumerates all surfaces attached to this surface
1511 * Params:
1512 * context: Pointer to pass unmodified to the callback
1513 * cb: Callback function to call for each surface
1515 * Returns:
1516 * DD_OK on success
1517 * DDERR_INVALIDPARAMS if cb is NULL
1519 *****************************************************************************/
1520 static HRESULT WINAPI ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7 *iface,
1521 void *context, LPDDENUMSURFACESCALLBACK7 cb)
1523 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1524 IDirectDrawSurfaceImpl *surf;
1525 DDSURFACEDESC2 desc;
1526 int i;
1528 /* Attached surfaces aren't handled in WineD3D */
1529 TRACE("iface %p, context %p, callback %p.\n", iface, context, cb);
1531 if(!cb)
1532 return DDERR_INVALIDPARAMS;
1534 EnterCriticalSection(&ddraw_cs);
1535 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
1537 surf = This->complex_array[i];
1538 if(!surf) break;
1540 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
1541 desc = surf->surface_desc;
1542 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
1543 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
1545 LeaveCriticalSection(&ddraw_cs);
1546 return DD_OK;
1550 for (surf = This->next_attached; surf != NULL; surf = surf->next_attached)
1552 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
1553 desc = surf->surface_desc;
1554 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
1555 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
1557 LeaveCriticalSection(&ddraw_cs);
1558 return DD_OK;
1562 TRACE(" end of enumeration.\n");
1564 LeaveCriticalSection(&ddraw_cs);
1565 return DD_OK;
1568 struct callback_info
1570 LPDDENUMSURFACESCALLBACK callback;
1571 void *context;
1574 static HRESULT CALLBACK EnumCallback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
1576 IDirectDrawSurfaceImpl *surface_impl = impl_from_IDirectDrawSurface7(surface);
1577 const struct callback_info *info = context;
1579 return info->callback((IDirectDrawSurface *)&surface_impl->IDirectDrawSurface3_iface,
1580 (DDSURFACEDESC *)surface_desc, info->context);
1583 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
1584 void *context, LPDDENUMSURFACESCALLBACK callback)
1586 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1587 struct callback_info info;
1589 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
1591 info.callback = callback;
1592 info.context = context;
1594 return ddraw_surface7_EnumAttachedSurfaces(&This->IDirectDrawSurface7_iface,
1595 &info, EnumCallback);
1598 /*****************************************************************************
1599 * IDirectDrawSurface7::EnumOverlayZOrders
1601 * "Enumerates the overlay surfaces on the specified destination"
1603 * Params:
1604 * Flags: DDENUMOVERLAYZ_BACKTOFRONT or DDENUMOVERLAYZ_FRONTTOBACK
1605 * context: context to pass back to the callback
1606 * cb: callback function to call for each enumerated surface
1608 * Returns:
1609 * DD_OK, because it's a stub
1611 *****************************************************************************/
1612 static HRESULT WINAPI ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7 *iface,
1613 DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK7 cb)
1615 FIXME("iface %p, flags %#x, context %p, callback %p stub!\n", iface, Flags, context, cb);
1617 return DD_OK;
1620 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
1621 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
1623 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1624 struct callback_info info;
1626 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
1628 info.callback = callback;
1629 info.context = context;
1631 return ddraw_surface7_EnumOverlayZOrders(&This->IDirectDrawSurface7_iface,
1632 flags, &info, EnumCallback);
1635 /*****************************************************************************
1636 * IDirectDrawSurface7::GetBltStatus
1638 * Returns the blitting status
1640 * Params:
1641 * Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
1643 * Returns:
1644 * See IWineD3DSurface::Blt
1646 *****************************************************************************/
1647 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags)
1649 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1650 HRESULT hr;
1652 TRACE("iface %p, flags %#x.\n", iface, Flags);
1654 EnterCriticalSection(&ddraw_cs);
1655 hr = wined3d_surface_get_blt_status(This->wined3d_surface, Flags);
1656 LeaveCriticalSection(&ddraw_cs);
1657 switch(hr)
1659 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS;
1660 default: return hr;
1664 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags)
1666 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1667 TRACE("iface %p, flags %#x.\n", iface, flags);
1669 return ddraw_surface7_GetBltStatus(&This->IDirectDrawSurface7_iface, flags);
1672 /*****************************************************************************
1673 * IDirectDrawSurface7::GetColorKey
1675 * Returns the color key assigned to the surface
1677 * Params:
1678 * Flags: Some flags
1679 * CKey: Address to store the key to
1681 * Returns:
1682 * DD_OK on success
1683 * DDERR_INVALIDPARAMS if CKey is NULL
1685 *****************************************************************************/
1686 static HRESULT WINAPI ddraw_surface7_GetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
1688 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1690 TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
1692 if(!CKey)
1693 return DDERR_INVALIDPARAMS;
1695 EnterCriticalSection(&ddraw_cs);
1697 switch (Flags)
1699 case DDCKEY_DESTBLT:
1700 if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT))
1702 LeaveCriticalSection(&ddraw_cs);
1703 return DDERR_NOCOLORKEY;
1705 *CKey = This->surface_desc.ddckCKDestBlt;
1706 break;
1708 case DDCKEY_DESTOVERLAY:
1709 if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY))
1711 LeaveCriticalSection(&ddraw_cs);
1712 return DDERR_NOCOLORKEY;
1714 *CKey = This->surface_desc.u3.ddckCKDestOverlay;
1715 break;
1717 case DDCKEY_SRCBLT:
1718 if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT))
1720 LeaveCriticalSection(&ddraw_cs);
1721 return DDERR_NOCOLORKEY;
1723 *CKey = This->surface_desc.ddckCKSrcBlt;
1724 break;
1726 case DDCKEY_SRCOVERLAY:
1727 if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY))
1729 LeaveCriticalSection(&ddraw_cs);
1730 return DDERR_NOCOLORKEY;
1732 *CKey = This->surface_desc.ddckCKSrcOverlay;
1733 break;
1735 default:
1736 LeaveCriticalSection(&ddraw_cs);
1737 return DDERR_INVALIDPARAMS;
1740 LeaveCriticalSection(&ddraw_cs);
1741 return DD_OK;
1744 static HRESULT WINAPI ddraw_surface3_GetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
1746 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1747 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
1749 return ddraw_surface7_GetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
1752 /*****************************************************************************
1753 * IDirectDrawSurface7::GetFlipStatus
1755 * Returns the flipping status of the surface
1757 * Params:
1758 * Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
1760 * Returns:
1761 * See IWineD3DSurface::GetFlipStatus
1763 *****************************************************************************/
1764 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags)
1766 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1767 HRESULT hr;
1769 TRACE("iface %p, flags %#x.\n", iface, Flags);
1771 EnterCriticalSection(&ddraw_cs);
1772 hr = wined3d_surface_get_flip_status(This->wined3d_surface, Flags);
1773 LeaveCriticalSection(&ddraw_cs);
1774 switch(hr)
1776 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS;
1777 default: return hr;
1781 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags)
1783 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1784 TRACE("iface %p, flags %#x.\n", iface, flags);
1786 return ddraw_surface7_GetFlipStatus(&This->IDirectDrawSurface7_iface, flags);
1789 /*****************************************************************************
1790 * IDirectDrawSurface7::GetOverlayPosition
1792 * Returns the display coordinates of a visible and active overlay surface
1794 * Params:
1798 * Returns:
1799 * DDERR_NOTAOVERLAYSURFACE, because it's a stub
1800 *****************************************************************************/
1801 static HRESULT WINAPI ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7 *iface, LONG *X, LONG *Y)
1803 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1804 HRESULT hr;
1806 TRACE("iface %p, x %p, y %p.\n", iface, X, Y);
1808 EnterCriticalSection(&ddraw_cs);
1809 hr = wined3d_surface_get_overlay_position(This->wined3d_surface, X, Y);
1810 LeaveCriticalSection(&ddraw_cs);
1811 return hr;
1814 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y)
1816 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1817 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
1819 return ddraw_surface7_GetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
1822 /*****************************************************************************
1823 * IDirectDrawSurface7::GetPixelFormat
1825 * Returns the pixel format of the Surface
1827 * Params:
1828 * PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
1829 * format should be written
1831 * Returns:
1832 * DD_OK on success
1833 * DDERR_INVALIDPARAMS if PixelFormat is NULL
1835 *****************************************************************************/
1836 static HRESULT WINAPI ddraw_surface7_GetPixelFormat(IDirectDrawSurface7 *iface, DDPIXELFORMAT *PixelFormat)
1838 /* What is DDERR_INVALIDSURFACETYPE for here? */
1839 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1841 TRACE("iface %p, pixel_format %p.\n", iface, PixelFormat);
1843 if(!PixelFormat)
1844 return DDERR_INVALIDPARAMS;
1846 EnterCriticalSection(&ddraw_cs);
1847 DD_STRUCT_COPY_BYSIZE(PixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
1848 LeaveCriticalSection(&ddraw_cs);
1850 return DD_OK;
1853 static HRESULT WINAPI ddraw_surface3_GetPixelFormat(IDirectDrawSurface3 *iface, DDPIXELFORMAT *pixel_format)
1855 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1856 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
1858 return ddraw_surface7_GetPixelFormat(&This->IDirectDrawSurface7_iface, pixel_format);
1861 /*****************************************************************************
1862 * IDirectDrawSurface7::GetSurfaceDesc
1864 * Returns the description of this surface
1866 * Params:
1867 * DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
1868 * surface desc
1870 * Returns:
1871 * DD_OK on success
1872 * DDERR_INVALIDPARAMS if DDSD is NULL
1874 *****************************************************************************/
1875 static HRESULT WINAPI ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD)
1877 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1879 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
1881 if(!DDSD)
1882 return DDERR_INVALIDPARAMS;
1884 if (DDSD->dwSize != sizeof(DDSURFACEDESC2))
1886 WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize);
1887 return DDERR_INVALIDPARAMS;
1890 EnterCriticalSection(&ddraw_cs);
1891 DD_STRUCT_COPY_BYSIZE(DDSD,&This->surface_desc);
1892 TRACE("Returning surface desc:\n");
1893 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
1895 LeaveCriticalSection(&ddraw_cs);
1896 return DD_OK;
1899 static HRESULT WINAPI ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3 *iface, DDSURFACEDESC *surface_desc)
1901 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1903 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1905 if (!surface_desc) return DDERR_INVALIDPARAMS;
1907 if (surface_desc->dwSize != sizeof(DDSURFACEDESC))
1909 WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc->dwSize);
1910 return DDERR_INVALIDPARAMS;
1913 EnterCriticalSection(&ddraw_cs);
1914 DD_STRUCT_COPY_BYSIZE(surface_desc, (DDSURFACEDESC *)&This->surface_desc);
1915 TRACE("Returning surface desc:\n");
1916 if (TRACE_ON(ddraw))
1918 /* DDRAW_dump_surface_desc handles the smaller size */
1919 DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
1922 LeaveCriticalSection(&ddraw_cs);
1923 return DD_OK;
1926 /*****************************************************************************
1927 * IDirectDrawSurface7::Initialize
1929 * Initializes the surface. This is a no-op in Wine
1931 * Params:
1932 * DD: Pointer to an DirectDraw interface
1933 * DDSD: Surface description for initialization
1935 * Returns:
1936 * DDERR_ALREADYINITIALIZED
1938 *****************************************************************************/
1939 static HRESULT WINAPI ddraw_surface7_Initialize(IDirectDrawSurface7 *iface,
1940 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
1942 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
1944 return DDERR_ALREADYINITIALIZED;
1947 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface,
1948 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
1950 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1951 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
1953 return ddraw_surface7_Initialize(&This->IDirectDrawSurface7_iface,
1954 ddraw, (DDSURFACEDESC2 *)surface_desc);
1957 /*****************************************************************************
1958 * IDirect3DTexture1::Initialize
1960 * The sdk says it's not implemented
1962 * Params:
1965 * Returns
1966 * DDERR_UNSUPPORTED
1968 *****************************************************************************/
1969 static HRESULT WINAPI d3d_texture1_Initialize(IDirect3DTexture *iface,
1970 IDirect3DDevice *device, IDirectDrawSurface *surface)
1972 TRACE("iface %p, device %p, surface %p.\n", iface, device, surface);
1974 return DDERR_UNSUPPORTED; /* Unchecked */
1977 /*****************************************************************************
1978 * IDirectDrawSurface7::IsLost
1980 * Checks if the surface is lost
1982 * Returns:
1983 * DD_OK, if the surface is usable
1984 * DDERR_ISLOST if the surface is lost
1985 * See IWineD3DSurface::IsLost for more details
1987 *****************************************************************************/
1988 static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface)
1990 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1991 HRESULT hr;
1993 TRACE("iface %p.\n", iface);
1995 EnterCriticalSection(&ddraw_cs);
1996 /* We lose the surface if the implementation was changed */
1997 if(This->ImplType != This->ddraw->ImplType)
1999 /* But this shouldn't happen. When we change the implementation,
2000 * all surfaces are re-created automatically, and their content
2001 * is copied
2003 ERR(" (%p) Implementation was changed from %d to %d\n", This, This->ImplType, This->ddraw->ImplType);
2004 LeaveCriticalSection(&ddraw_cs);
2005 return DDERR_SURFACELOST;
2008 hr = wined3d_surface_is_lost(This->wined3d_surface);
2009 LeaveCriticalSection(&ddraw_cs);
2010 switch(hr)
2012 /* D3D8 and 9 loose full devices, thus there's only a DEVICELOST error.
2013 * WineD3D uses the same error for surfaces
2015 case WINED3DERR_DEVICELOST: return DDERR_SURFACELOST;
2016 default: return hr;
2020 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface)
2022 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2023 TRACE("iface %p.\n", iface);
2025 return ddraw_surface7_IsLost(&This->IDirectDrawSurface7_iface);
2028 /*****************************************************************************
2029 * IDirectDrawSurface7::Restore
2031 * Restores a lost surface. This makes the surface usable again, but
2032 * doesn't reload its old contents
2034 * Returns:
2035 * DD_OK on success
2036 * See IWineD3DSurface::Restore for more details
2038 *****************************************************************************/
2039 static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface)
2041 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2042 HRESULT hr;
2044 TRACE("iface %p.\n", iface);
2046 EnterCriticalSection(&ddraw_cs);
2047 if(This->ImplType != This->ddraw->ImplType)
2049 /* Call the recreation callback. Make sure to AddRef first */
2050 IDirectDrawSurface_AddRef(iface);
2051 ddraw_recreate_surfaces_cb(iface, &This->surface_desc, NULL /* Not needed */);
2053 hr = wined3d_surface_restore(This->wined3d_surface);
2054 LeaveCriticalSection(&ddraw_cs);
2055 return hr;
2058 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface)
2060 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2061 TRACE("iface %p.\n", iface);
2063 return ddraw_surface7_Restore(&This->IDirectDrawSurface7_iface);
2066 /*****************************************************************************
2067 * IDirectDrawSurface7::SetOverlayPosition
2069 * Changes the display coordinates of an overlay surface
2071 * Params:
2072 * X:
2073 * Y:
2075 * Returns:
2076 * DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
2077 *****************************************************************************/
2078 static HRESULT WINAPI ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7 *iface, LONG X, LONG Y)
2080 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2081 HRESULT hr;
2083 TRACE("iface %p, x %d, y %d.\n", iface, X, Y);
2085 EnterCriticalSection(&ddraw_cs);
2086 hr = wined3d_surface_set_overlay_position(This->wined3d_surface, X, Y);
2087 LeaveCriticalSection(&ddraw_cs);
2088 return hr;
2091 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y)
2093 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2094 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
2096 return ddraw_surface7_SetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
2099 /*****************************************************************************
2100 * IDirectDrawSurface7::UpdateOverlay
2102 * Modifies the attributes of an overlay surface.
2104 * Params:
2105 * SrcRect: The section of the source being used for the overlay
2106 * DstSurface: Address of the surface that is overlaid
2107 * DstRect: Place of the overlay
2108 * Flags: some DDOVER_* flags
2110 * Returns:
2111 * DDERR_UNSUPPORTED, because we don't support overlays
2113 *****************************************************************************/
2114 static HRESULT WINAPI ddraw_surface7_UpdateOverlay(IDirectDrawSurface7 *iface, RECT *SrcRect,
2115 IDirectDrawSurface7 *DstSurface, RECT *DstRect, DWORD Flags, DDOVERLAYFX *FX)
2117 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2118 IDirectDrawSurfaceImpl *Dst = unsafe_impl_from_IDirectDrawSurface7(DstSurface);
2119 HRESULT hr;
2121 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
2122 iface, wine_dbgstr_rect(SrcRect), DstSurface, wine_dbgstr_rect(DstRect), Flags, FX);
2124 EnterCriticalSection(&ddraw_cs);
2125 hr = wined3d_surface_update_overlay(This->wined3d_surface, SrcRect,
2126 Dst ? Dst->wined3d_surface : NULL, DstRect, Flags, (WINEDDOVERLAYFX *)FX);
2127 LeaveCriticalSection(&ddraw_cs);
2128 switch(hr) {
2129 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS;
2130 case WINEDDERR_NOTAOVERLAYSURFACE: return DDERR_NOTAOVERLAYSURFACE;
2131 case WINEDDERR_OVERLAYNOTVISIBLE: return DDERR_OVERLAYNOTVISIBLE;
2132 default:
2133 return hr;
2137 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect,
2138 IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
2140 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2141 IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst_surface);
2142 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
2143 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
2145 return ddraw_surface7_UpdateOverlay(&This->IDirectDrawSurface7_iface, src_rect,
2146 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
2149 /*****************************************************************************
2150 * IDirectDrawSurface7::UpdateOverlayDisplay
2152 * The DX7 sdk says that it's not implemented
2154 * Params:
2155 * Flags: ?
2157 * Returns: DDERR_UNSUPPORTED, because we don't support overlays
2159 *****************************************************************************/
2160 static HRESULT WINAPI ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7 *iface, DWORD Flags)
2162 TRACE("iface %p, flags %#x.\n", iface, Flags);
2164 return DDERR_UNSUPPORTED;
2167 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags)
2169 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2170 TRACE("iface %p, flags %#x.\n", iface, flags);
2172 return ddraw_surface7_UpdateOverlayDisplay(&This->IDirectDrawSurface7_iface, flags);
2175 /*****************************************************************************
2176 * IDirectDrawSurface7::UpdateOverlayZOrder
2178 * Sets an overlay's Z order
2180 * Params:
2181 * Flags: DDOVERZ_* flags
2182 * DDSRef: Defines the relative position in the overlay chain
2184 * Returns:
2185 * DDERR_NOTOVERLAYSURFACE, because we don't support overlays
2187 *****************************************************************************/
2188 static HRESULT WINAPI ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7 *iface,
2189 DWORD Flags, IDirectDrawSurface7 *DDSRef)
2191 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2192 IDirectDrawSurfaceImpl *Ref = unsafe_impl_from_IDirectDrawSurface7(DDSRef);
2193 HRESULT hr;
2195 TRACE("iface %p, flags %#x, reference %p.\n", iface, Flags, DDSRef);
2197 EnterCriticalSection(&ddraw_cs);
2198 hr = wined3d_surface_update_overlay_z_order(This->wined3d_surface,
2199 Flags, Ref ? Ref->wined3d_surface : NULL);
2200 LeaveCriticalSection(&ddraw_cs);
2201 return hr;
2204 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
2205 DWORD flags, IDirectDrawSurface3 *reference)
2207 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2208 IDirectDrawSurfaceImpl *reference_impl = unsafe_impl_from_IDirectDrawSurface3(reference);
2209 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
2211 return ddraw_surface7_UpdateOverlayZOrder(&This->IDirectDrawSurface7_iface, flags,
2212 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
2215 /*****************************************************************************
2216 * IDirectDrawSurface7::GetDDInterface
2218 * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
2219 * surface belongs to
2221 * Params:
2222 * DD: Address to write the interface pointer to
2224 * Returns:
2225 * DD_OK on success
2226 * DDERR_INVALIDPARAMS if DD is NULL
2228 *****************************************************************************/
2229 static HRESULT WINAPI ddraw_surface7_GetDDInterface(IDirectDrawSurface7 *iface, void **DD)
2231 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2233 TRACE("iface %p, ddraw %p.\n", iface, DD);
2235 if(!DD)
2236 return DDERR_INVALIDPARAMS;
2238 switch(This->version)
2240 case 7:
2241 *DD = &This->ddraw->IDirectDraw7_iface;
2242 break;
2244 case 4:
2245 *DD = &This->ddraw->IDirectDraw4_iface;
2246 break;
2248 case 2:
2249 *DD = &This->ddraw->IDirectDraw2_iface;
2250 break;
2252 case 1:
2253 *DD = &This->ddraw->IDirectDraw_iface;
2254 break;
2257 IUnknown_AddRef((IUnknown *)*DD);
2259 return DD_OK;
2262 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw)
2264 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2265 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
2267 return ddraw_surface7_GetDDInterface(&This->IDirectDrawSurface7_iface, ddraw);
2270 /* This seems also windows implementation specific - I don't think WineD3D needs this */
2271 static HRESULT WINAPI ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7 *iface)
2273 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2274 volatile IDirectDrawSurfaceImpl* vThis = This;
2276 TRACE("iface %p.\n", iface);
2278 EnterCriticalSection(&ddraw_cs);
2279 /* A uniqueness value of 0 is apparently special.
2280 * This needs to be checked.
2281 * TODO: Write tests for this code and check if the volatile, interlocked stuff is really needed
2283 while (1) {
2284 DWORD old_uniqueness_value = vThis->uniqueness_value;
2285 DWORD new_uniqueness_value = old_uniqueness_value+1;
2287 if (old_uniqueness_value == 0) break;
2288 if (new_uniqueness_value == 0) new_uniqueness_value = 1;
2290 if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
2291 old_uniqueness_value,
2292 new_uniqueness_value)
2293 == old_uniqueness_value)
2294 break;
2297 LeaveCriticalSection(&ddraw_cs);
2298 return DD_OK;
2301 static HRESULT WINAPI ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7 *iface, DWORD *pValue)
2303 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2305 TRACE("iface %p, value %p.\n", iface, pValue);
2307 EnterCriticalSection(&ddraw_cs);
2308 *pValue = This->uniqueness_value;
2309 LeaveCriticalSection(&ddraw_cs);
2310 return DD_OK;
2313 /*****************************************************************************
2314 * IDirectDrawSurface7::SetLOD
2316 * Sets the level of detail of a texture
2318 * Params:
2319 * MaxLOD: LOD to set
2321 * Returns:
2322 * DD_OK on success
2323 * DDERR_INVALIDOBJECT if the surface is invalid for this method
2325 *****************************************************************************/
2326 static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD)
2328 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2329 HRESULT hr;
2331 TRACE("iface %p, lod %u.\n", iface, MaxLOD);
2333 EnterCriticalSection(&ddraw_cs);
2334 if (!(This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
2336 LeaveCriticalSection(&ddraw_cs);
2337 return DDERR_INVALIDOBJECT;
2340 if (!This->wined3d_texture)
2342 ERR("(%p) The DirectDraw texture has no WineD3DTexture!\n", This);
2343 LeaveCriticalSection(&ddraw_cs);
2344 return DDERR_INVALIDOBJECT;
2347 hr = wined3d_texture_set_lod(This->wined3d_texture, MaxLOD);
2348 LeaveCriticalSection(&ddraw_cs);
2349 return hr;
2352 /*****************************************************************************
2353 * IDirectDrawSurface7::GetLOD
2355 * Returns the level of detail of a Direct3D texture
2357 * Params:
2358 * MaxLOD: Address to write the LOD to
2360 * Returns:
2361 * DD_OK on success
2362 * DDERR_INVALIDPARAMS if MaxLOD is NULL
2363 * DDERR_INVALIDOBJECT if the surface is invalid for this method
2365 *****************************************************************************/
2366 static HRESULT WINAPI ddraw_surface7_GetLOD(IDirectDrawSurface7 *iface, DWORD *MaxLOD)
2368 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2370 TRACE("iface %p, lod %p.\n", iface, MaxLOD);
2372 if(!MaxLOD)
2373 return DDERR_INVALIDPARAMS;
2375 EnterCriticalSection(&ddraw_cs);
2376 if (!(This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
2378 LeaveCriticalSection(&ddraw_cs);
2379 return DDERR_INVALIDOBJECT;
2382 *MaxLOD = wined3d_texture_get_lod(This->wined3d_texture);
2383 LeaveCriticalSection(&ddraw_cs);
2384 return DD_OK;
2387 /*****************************************************************************
2388 * IDirectDrawSurface7::BltFast
2390 * Performs a fast Blit.
2392 * Params:
2393 * dstx: The x coordinate to blit to on the destination
2394 * dsty: The y coordinate to blit to on the destination
2395 * Source: The source surface
2396 * rsrc: The source rectangle
2397 * trans: Type of transfer. Some DDBLTFAST_* flags
2399 * Returns:
2400 * DD_OK on success
2401 * For more details, see IWineD3DSurface::BltFast
2403 *****************************************************************************/
2404 static HRESULT WINAPI ddraw_surface7_BltFast(IDirectDrawSurface7 *iface, DWORD dstx, DWORD dsty,
2405 IDirectDrawSurface7 *Source, RECT *rsrc, DWORD trans)
2407 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2408 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(Source);
2409 DWORD src_w, src_h, dst_w, dst_h;
2410 HRESULT hr;
2412 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
2413 iface, dstx, dsty, Source, wine_dbgstr_rect(rsrc), trans);
2415 dst_w = This->surface_desc.dwWidth;
2416 dst_h = This->surface_desc.dwHeight;
2418 /* Source must be != NULL, This is not checked by windows. Windows happily throws a 0xc0000005
2419 * in that case
2421 if(rsrc)
2423 if(rsrc->top > rsrc->bottom || rsrc->left > rsrc->right ||
2424 rsrc->right > src->surface_desc.dwWidth ||
2425 rsrc->bottom > src->surface_desc.dwHeight)
2427 WARN("Source rectangle is invalid, returning DDERR_INVALIDRECT\n");
2428 return DDERR_INVALIDRECT;
2431 src_w = rsrc->right - rsrc->left;
2432 src_h = rsrc->bottom - rsrc->top;
2434 else
2436 src_w = src->surface_desc.dwWidth;
2437 src_h = src->surface_desc.dwHeight;
2440 if (src_w > dst_w || dstx > dst_w - src_w
2441 || src_h > dst_h || dsty > dst_h - src_h)
2443 WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
2444 return DDERR_INVALIDRECT;
2447 EnterCriticalSection(&ddraw_cs);
2448 hr = wined3d_surface_bltfast(This->wined3d_surface, dstx, dsty,
2449 src ? src->wined3d_surface : NULL, rsrc, trans);
2450 LeaveCriticalSection(&ddraw_cs);
2451 switch(hr)
2453 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
2454 case WINED3DERR_WRONGTEXTUREFORMAT: return DDERR_INVALIDPIXELFORMAT;
2455 default: return hr;
2459 static HRESULT WINAPI ddraw_surface3_BltFast(IDirectDrawSurface3 *iface, DWORD dst_x, DWORD dst_y,
2460 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags)
2462 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2463 IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
2464 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
2465 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
2467 return ddraw_surface7_BltFast(&This->IDirectDrawSurface7_iface, dst_x, dst_y,
2468 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
2471 /*****************************************************************************
2472 * IDirectDrawSurface7::GetClipper
2474 * Returns the IDirectDrawClipper interface of the clipper assigned to this
2475 * surface
2477 * Params:
2478 * Clipper: Address to store the interface pointer at
2480 * Returns:
2481 * DD_OK on success
2482 * DDERR_INVALIDPARAMS if Clipper is NULL
2483 * DDERR_NOCLIPPERATTACHED if there's no clipper attached
2485 *****************************************************************************/
2486 static HRESULT WINAPI ddraw_surface7_GetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper **Clipper)
2488 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2490 TRACE("iface %p, clipper %p.\n", iface, Clipper);
2492 if(!Clipper)
2494 LeaveCriticalSection(&ddraw_cs);
2495 return DDERR_INVALIDPARAMS;
2498 EnterCriticalSection(&ddraw_cs);
2499 if(This->clipper == NULL)
2501 LeaveCriticalSection(&ddraw_cs);
2502 return DDERR_NOCLIPPERATTACHED;
2505 *Clipper = (IDirectDrawClipper *)This->clipper;
2506 IDirectDrawClipper_AddRef(*Clipper);
2507 LeaveCriticalSection(&ddraw_cs);
2508 return DD_OK;
2511 static HRESULT WINAPI ddraw_surface3_GetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper **clipper)
2513 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2514 TRACE("iface %p, clipper %p.\n", iface, clipper);
2516 return ddraw_surface7_GetClipper(&This->IDirectDrawSurface7_iface, clipper);
2519 /*****************************************************************************
2520 * IDirectDrawSurface7::SetClipper
2522 * Sets a clipper for the surface
2524 * Params:
2525 * Clipper: IDirectDrawClipper interface of the clipper to set
2527 * Returns:
2528 * DD_OK on success
2530 *****************************************************************************/
2531 static HRESULT WINAPI ddraw_surface7_SetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper *Clipper)
2533 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2534 IDirectDrawClipperImpl *oldClipper = This->clipper;
2535 HWND clipWindow;
2536 HRESULT hr;
2538 TRACE("iface %p, clipper %p.\n", iface, Clipper);
2540 EnterCriticalSection(&ddraw_cs);
2541 if ((IDirectDrawClipperImpl *)Clipper == This->clipper)
2543 LeaveCriticalSection(&ddraw_cs);
2544 return DD_OK;
2547 This->clipper = (IDirectDrawClipperImpl *)Clipper;
2549 if (Clipper != NULL)
2550 IDirectDrawClipper_AddRef(Clipper);
2551 if(oldClipper)
2552 IDirectDrawClipper_Release((IDirectDrawClipper *)oldClipper);
2554 hr = wined3d_surface_set_clipper(This->wined3d_surface,
2555 This->clipper ? This->clipper->wineD3DClipper : NULL);
2557 if (This->wined3d_swapchain)
2559 clipWindow = NULL;
2560 if(Clipper) {
2561 IDirectDrawClipper_GetHWnd(Clipper, &clipWindow);
2564 if (clipWindow)
2565 wined3d_swapchain_set_window(This->wined3d_swapchain, clipWindow);
2566 else
2567 wined3d_swapchain_set_window(This->wined3d_swapchain, This->ddraw->d3d_window);
2570 LeaveCriticalSection(&ddraw_cs);
2571 return hr;
2574 static HRESULT WINAPI ddraw_surface3_SetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper *clipper)
2576 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2577 TRACE("iface %p, clipper %p.\n", iface, clipper);
2579 return ddraw_surface7_SetClipper(&This->IDirectDrawSurface7_iface, clipper);
2582 /*****************************************************************************
2583 * IDirectDrawSurface7::SetSurfaceDesc
2585 * Sets the surface description. It can override the pixel format, the surface
2586 * memory, ...
2587 * It's not really tested.
2589 * Params:
2590 * DDSD: Pointer to the new surface description to set
2591 * Flags: Some flags
2593 * Returns:
2594 * DD_OK on success
2595 * DDERR_INVALIDPARAMS if DDSD is NULL
2597 *****************************************************************************/
2598 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags)
2600 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2601 enum wined3d_format_id newFormat = WINED3DFMT_UNKNOWN;
2602 HRESULT hr;
2604 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags);
2606 if(!DDSD)
2607 return DDERR_INVALIDPARAMS;
2609 EnterCriticalSection(&ddraw_cs);
2610 if (DDSD->dwFlags & DDSD_PIXELFORMAT)
2612 newFormat = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat);
2614 if(newFormat == WINED3DFMT_UNKNOWN)
2616 ERR("Requested to set an unknown pixelformat\n");
2617 LeaveCriticalSection(&ddraw_cs);
2618 return DDERR_INVALIDPARAMS;
2620 if(newFormat != PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat) )
2622 hr = wined3d_surface_set_format(This->wined3d_surface, newFormat);
2623 if (FAILED(hr))
2625 LeaveCriticalSection(&ddraw_cs);
2626 return hr;
2630 if (DDSD->dwFlags & DDSD_CKDESTOVERLAY)
2632 wined3d_surface_set_color_key(This->wined3d_surface, DDCKEY_DESTOVERLAY,
2633 (WINEDDCOLORKEY *)&DDSD->u3.ddckCKDestOverlay);
2635 if (DDSD->dwFlags & DDSD_CKDESTBLT)
2637 wined3d_surface_set_color_key(This->wined3d_surface, DDCKEY_DESTBLT,
2638 (WINEDDCOLORKEY *)&DDSD->ddckCKDestBlt);
2640 if (DDSD->dwFlags & DDSD_CKSRCOVERLAY)
2642 wined3d_surface_set_color_key(This->wined3d_surface, DDCKEY_SRCOVERLAY,
2643 (WINEDDCOLORKEY *)&DDSD->ddckCKSrcOverlay);
2645 if (DDSD->dwFlags & DDSD_CKSRCBLT)
2647 wined3d_surface_set_color_key(This->wined3d_surface, DDCKEY_SRCBLT,
2648 (WINEDDCOLORKEY *)&DDSD->ddckCKSrcBlt);
2650 if (DDSD->dwFlags & DDSD_LPSURFACE && DDSD->lpSurface)
2652 hr = wined3d_surface_set_mem(This->wined3d_surface, DDSD->lpSurface);
2653 if (FAILED(hr))
2655 /* No need for a trace here, wined3d does that for us */
2656 switch(hr)
2658 case WINED3DERR_INVALIDCALL:
2659 LeaveCriticalSection(&ddraw_cs);
2660 return DDERR_INVALIDPARAMS;
2661 default:
2662 break; /* Go on */
2667 This->surface_desc = *DDSD;
2669 LeaveCriticalSection(&ddraw_cs);
2670 return DD_OK;
2673 static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface,
2674 DDSURFACEDESC *surface_desc, DWORD flags)
2676 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2677 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
2679 return ddraw_surface7_SetSurfaceDesc(&This->IDirectDrawSurface7_iface,
2680 (DDSURFACEDESC2 *)surface_desc, flags);
2683 /*****************************************************************************
2684 * IDirectDrawSurface7::GetPalette
2686 * Returns the IDirectDrawPalette interface of the palette currently assigned
2687 * to the surface
2689 * Params:
2690 * Pal: Address to write the interface pointer to
2692 * Returns:
2693 * DD_OK on success
2694 * DDERR_INVALIDPARAMS if Pal is NULL
2696 *****************************************************************************/
2697 static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **Pal)
2699 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2700 struct wined3d_palette *wined3d_palette;
2701 HRESULT hr = DD_OK;
2703 TRACE("iface %p, palette %p.\n", iface, Pal);
2705 if(!Pal)
2706 return DDERR_INVALIDPARAMS;
2708 EnterCriticalSection(&ddraw_cs);
2709 wined3d_palette = wined3d_surface_get_palette(This->wined3d_surface);
2710 if (wined3d_palette)
2712 *Pal = wined3d_palette_get_parent(wined3d_palette);
2713 IDirectDrawPalette_AddRef(*Pal);
2715 else
2717 *Pal = NULL;
2718 hr = DDERR_NOPALETTEATTACHED;
2721 LeaveCriticalSection(&ddraw_cs);
2722 return hr;
2725 static HRESULT WINAPI ddraw_surface3_GetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette **palette)
2727 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2728 TRACE("iface %p, palette %p.\n", iface, palette);
2730 return ddraw_surface7_GetPalette(&This->IDirectDrawSurface7_iface, palette);
2733 /*****************************************************************************
2734 * SetColorKeyEnum
2736 * EnumAttachedSurface callback for SetColorKey. Used to set color keys
2737 * recursively in the surface tree
2739 *****************************************************************************/
2740 struct SCKContext
2742 HRESULT ret;
2743 WINEDDCOLORKEY *CKey;
2744 DWORD Flags;
2747 static HRESULT WINAPI
2748 SetColorKeyEnum(IDirectDrawSurface7 *surface,
2749 DDSURFACEDESC2 *desc,
2750 void *context)
2752 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(surface);
2753 struct SCKContext *ctx = context;
2754 HRESULT hr;
2756 hr = wined3d_surface_set_color_key(This->wined3d_surface, ctx->Flags, ctx->CKey);
2757 if (FAILED(hr))
2759 WARN("IWineD3DSurface_SetColorKey failed, hr = %08x\n", hr);
2760 ctx->ret = hr;
2763 ddraw_surface7_EnumAttachedSurfaces(surface, context, SetColorKeyEnum);
2764 ddraw_surface7_Release(surface);
2766 return DDENUMRET_OK;
2769 /*****************************************************************************
2770 * IDirectDrawSurface7::SetColorKey
2772 * Sets the color keying options for the surface. Observations showed that
2773 * in case of complex surfaces the color key has to be assigned to all
2774 * sublevels.
2776 * Params:
2777 * Flags: DDCKEY_*
2778 * CKey: The new color key
2780 * Returns:
2781 * DD_OK on success
2782 * See IWineD3DSurface::SetColorKey for details
2784 *****************************************************************************/
2785 static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
2787 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2788 DDCOLORKEY FixedCKey;
2789 struct SCKContext ctx = { DD_OK, (WINEDDCOLORKEY *) (CKey ? &FixedCKey : NULL), Flags };
2791 TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
2793 EnterCriticalSection(&ddraw_cs);
2794 if (CKey)
2796 FixedCKey = *CKey;
2797 /* Handle case where dwColorSpaceHighValue < dwColorSpaceLowValue */
2798 if (FixedCKey.dwColorSpaceHighValue < FixedCKey.dwColorSpaceLowValue)
2799 FixedCKey.dwColorSpaceHighValue = FixedCKey.dwColorSpaceLowValue;
2801 switch (Flags & ~DDCKEY_COLORSPACE)
2803 case DDCKEY_DESTBLT:
2804 This->surface_desc.ddckCKDestBlt = FixedCKey;
2805 This->surface_desc.dwFlags |= DDSD_CKDESTBLT;
2806 break;
2808 case DDCKEY_DESTOVERLAY:
2809 This->surface_desc.u3.ddckCKDestOverlay = FixedCKey;
2810 This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
2811 break;
2813 case DDCKEY_SRCOVERLAY:
2814 This->surface_desc.ddckCKSrcOverlay = FixedCKey;
2815 This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
2816 break;
2818 case DDCKEY_SRCBLT:
2819 This->surface_desc.ddckCKSrcBlt = FixedCKey;
2820 This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
2821 break;
2823 default:
2824 LeaveCriticalSection(&ddraw_cs);
2825 return DDERR_INVALIDPARAMS;
2828 else
2830 switch (Flags & ~DDCKEY_COLORSPACE)
2832 case DDCKEY_DESTBLT:
2833 This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
2834 break;
2836 case DDCKEY_DESTOVERLAY:
2837 This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
2838 break;
2840 case DDCKEY_SRCOVERLAY:
2841 This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
2842 break;
2844 case DDCKEY_SRCBLT:
2845 This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
2846 break;
2848 default:
2849 LeaveCriticalSection(&ddraw_cs);
2850 return DDERR_INVALIDPARAMS;
2853 ctx.ret = wined3d_surface_set_color_key(This->wined3d_surface, Flags, ctx.CKey);
2854 ddraw_surface7_EnumAttachedSurfaces(iface, &ctx, SetColorKeyEnum);
2855 LeaveCriticalSection(&ddraw_cs);
2856 switch(ctx.ret)
2858 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS;
2859 default: return ctx.ret;
2863 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
2865 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2866 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
2868 return ddraw_surface7_SetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
2871 /*****************************************************************************
2872 * IDirectDrawSurface7::SetPalette
2874 * Assigns a DirectDrawPalette object to the surface
2876 * Params:
2877 * Pal: Interface to the palette to set
2879 * Returns:
2880 * DD_OK on success
2882 *****************************************************************************/
2883 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *Pal)
2885 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2886 IDirectDrawPalette *oldPal;
2887 IDirectDrawSurfaceImpl *surf;
2888 IDirectDrawPaletteImpl *PalImpl = (IDirectDrawPaletteImpl *)Pal;
2889 HRESULT hr;
2891 TRACE("iface %p, palette %p.\n", iface, Pal);
2893 if (!(This->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
2894 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8))) {
2895 return DDERR_INVALIDPIXELFORMAT;
2898 /* Find the old palette */
2899 EnterCriticalSection(&ddraw_cs);
2900 hr = IDirectDrawSurface_GetPalette(iface, &oldPal);
2901 if(hr != DD_OK && hr != DDERR_NOPALETTEATTACHED)
2903 LeaveCriticalSection(&ddraw_cs);
2904 return hr;
2906 if(oldPal) IDirectDrawPalette_Release(oldPal); /* For the GetPalette */
2908 /* Set the new Palette */
2909 wined3d_surface_set_palette(This->wined3d_surface, PalImpl ? PalImpl->wineD3DPalette : NULL);
2910 /* AddRef the Palette */
2911 if(Pal) IDirectDrawPalette_AddRef(Pal);
2913 /* Release the old palette */
2914 if(oldPal) IDirectDrawPalette_Release(oldPal);
2916 /* If this is a front buffer, also update the back buffers
2917 * TODO: How do things work for palettized cube textures?
2919 if(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
2921 /* For primary surfaces the tree is just a list, so the simpler scheme fits too */
2922 DDSCAPS2 caps2 = { DDSCAPS_PRIMARYSURFACE, 0, 0, 0 };
2924 surf = This;
2925 while(1)
2927 IDirectDrawSurface7 *attach;
2928 HRESULT hr;
2929 hr = ddraw_surface7_GetAttachedSurface(&surf->IDirectDrawSurface7_iface, &caps2, &attach);
2930 if(hr != DD_OK)
2932 break;
2935 TRACE("Setting palette on %p\n", attach);
2936 ddraw_surface7_SetPalette(attach, Pal);
2937 surf = impl_from_IDirectDrawSurface7(attach);
2938 ddraw_surface7_Release(attach);
2942 LeaveCriticalSection(&ddraw_cs);
2943 return DD_OK;
2946 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette)
2948 IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2949 TRACE("iface %p, palette %p.\n", iface, palette);
2951 return ddraw_surface7_SetPalette(&This->IDirectDrawSurface7_iface, palette);
2954 /**********************************************************
2955 * IDirectDrawGammaControl::GetGammaRamp
2957 * Returns the current gamma ramp for a surface
2959 * Params:
2960 * flags: Ignored
2961 * gamma_ramp: Address to write the ramp to
2963 * Returns:
2964 * DD_OK on success
2965 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
2967 **********************************************************/
2968 static HRESULT WINAPI ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl *iface,
2969 DWORD flags, DDGAMMARAMP *gamma_ramp)
2971 IDirectDrawSurfaceImpl *surface = surface_from_gamma_control(iface);
2973 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
2975 if (!gamma_ramp)
2977 WARN("Invalid gamma_ramp passed.\n");
2978 return DDERR_INVALIDPARAMS;
2981 EnterCriticalSection(&ddraw_cs);
2982 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2984 /* Note: DDGAMMARAMP is compatible with WINED3DGAMMARAMP. */
2985 wined3d_device_get_gamma_ramp(surface->ddraw->wined3d_device, 0, (WINED3DGAMMARAMP *)gamma_ramp);
2987 else
2989 ERR("Not implemented for non-primary surfaces.\n");
2991 LeaveCriticalSection(&ddraw_cs);
2993 return DD_OK;
2996 /**********************************************************
2997 * IDirectDrawGammaControl::SetGammaRamp
2999 * Sets the red, green and blue gamma ramps for
3001 * Params:
3002 * flags: Can be DDSGR_CALIBRATE to request calibration
3003 * gamma_ramp: Structure containing the new gamma ramp
3005 * Returns:
3006 * DD_OK on success
3007 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
3009 **********************************************************/
3010 static HRESULT WINAPI ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl *iface,
3011 DWORD flags, DDGAMMARAMP *gamma_ramp)
3013 IDirectDrawSurfaceImpl *surface = surface_from_gamma_control(iface);
3015 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
3017 if (!gamma_ramp)
3019 WARN("Invalid gamma_ramp passed.\n");
3020 return DDERR_INVALIDPARAMS;
3023 EnterCriticalSection(&ddraw_cs);
3024 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
3026 /* Note: DDGAMMARAMP is compatible with WINED3DGAMMARAMP */
3027 wined3d_device_set_gamma_ramp(surface->ddraw->wined3d_device, 0, flags, (WINED3DGAMMARAMP *)gamma_ramp);
3029 else
3031 ERR("Not implemented for non-primary surfaces.\n");
3033 LeaveCriticalSection(&ddraw_cs);
3035 return DD_OK;
3038 /*****************************************************************************
3039 * IDirect3DTexture2::PaletteChanged
3041 * Informs the texture about a palette change
3043 * Params:
3044 * start: Start index of the change
3045 * count: The number of changed entries
3047 * Returns
3048 * D3D_OK, because it's a stub
3050 *****************************************************************************/
3051 static HRESULT WINAPI d3d_texture2_PaletteChanged(IDirect3DTexture2 *iface, DWORD start, DWORD count)
3053 FIXME("iface %p, start %u, count %u stub!\n", iface, start, count);
3055 return D3D_OK;
3058 static HRESULT WINAPI d3d_texture1_PaletteChanged(IDirect3DTexture *iface, DWORD start, DWORD count)
3060 IDirectDrawSurfaceImpl *surface = surface_from_texture1(iface);
3062 TRACE("iface %p, start %u, count %u.\n", iface, start, count);
3064 return d3d_texture2_PaletteChanged((IDirect3DTexture2 *)&surface->IDirect3DTexture2_vtbl, start, count);
3067 /*****************************************************************************
3068 * IDirect3DTexture::Unload
3070 * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
3073 * Returns:
3074 * DDERR_UNSUPPORTED
3076 *****************************************************************************/
3077 static HRESULT WINAPI d3d_texture1_Unload(IDirect3DTexture *iface)
3079 WARN("iface %p. Not implemented.\n", iface);
3081 return DDERR_UNSUPPORTED;
3084 /*****************************************************************************
3085 * IDirect3DTexture2::GetHandle
3087 * Returns handle for the texture. At the moment, the interface
3088 * to the IWineD3DTexture is used.
3090 * Params:
3091 * device: Device this handle is assigned to
3092 * handle: Address to store the handle at.
3094 * Returns:
3095 * D3D_OK
3097 *****************************************************************************/
3098 static HRESULT WINAPI d3d_texture2_GetHandle(IDirect3DTexture2 *iface,
3099 IDirect3DDevice2 *device, D3DTEXTUREHANDLE *handle)
3101 IDirectDrawSurfaceImpl *surface = surface_from_texture2(iface);
3103 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
3105 EnterCriticalSection(&ddraw_cs);
3107 if (!surface->Handle)
3109 DWORD h = ddraw_allocate_handle(&device_from_device2(device)->handle_table, surface, DDRAW_HANDLE_SURFACE);
3110 if (h == DDRAW_INVALID_HANDLE)
3112 ERR("Failed to allocate a texture handle.\n");
3113 LeaveCriticalSection(&ddraw_cs);
3114 return DDERR_OUTOFMEMORY;
3117 surface->Handle = h + 1;
3120 TRACE("Returning handle %08x.\n", surface->Handle);
3121 *handle = surface->Handle;
3123 LeaveCriticalSection(&ddraw_cs);
3125 return D3D_OK;
3128 static HRESULT WINAPI d3d_texture1_GetHandle(IDirect3DTexture *iface,
3129 IDirect3DDevice *device, D3DTEXTUREHANDLE *handle)
3131 IDirect3DTexture2 *texture2 = (IDirect3DTexture2 *)&surface_from_texture1(iface)->IDirect3DTexture2_vtbl;
3132 IDirect3DDevice2 *device2 = (IDirect3DDevice2 *)&device_from_device1(device)->IDirect3DDevice2_vtbl;
3134 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
3136 return d3d_texture2_GetHandle(texture2, device2, handle);
3139 /*****************************************************************************
3140 * get_sub_mimaplevel
3142 * Helper function that returns the next mipmap level
3144 * tex_ptr: Surface of which to return the next level
3146 *****************************************************************************/
3147 static IDirectDrawSurfaceImpl *get_sub_mimaplevel(IDirectDrawSurfaceImpl *surface)
3149 /* Now go down the mipmap chain to the next surface */
3150 static DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, 0 };
3151 IDirectDrawSurface7 *next_level;
3152 HRESULT hr;
3154 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, &mipmap_caps, &next_level);
3155 if (FAILED(hr)) return NULL;
3157 ddraw_surface7_Release(next_level);
3159 return impl_from_IDirectDrawSurface7(next_level);
3162 /*****************************************************************************
3163 * IDirect3DTexture2::Load
3165 * Loads a texture created with the DDSCAPS_ALLOCONLOAD
3167 * This function isn't relayed to WineD3D because the whole interface is
3168 * implemented in DDraw only. For speed improvements a implementation which
3169 * takes OpenGL more into account could be placed into WineD3D.
3171 * Params:
3172 * src_texture: Address of the texture to load
3174 * Returns:
3175 * D3D_OK on success
3176 * D3DERR_TEXTURE_LOAD_FAILED.
3178 *****************************************************************************/
3179 static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTexture2 *src_texture)
3181 IDirectDrawSurfaceImpl *dst_surface = surface_from_texture2(iface);
3182 IDirectDrawSurfaceImpl *src_surface = surface_from_texture2(src_texture);
3183 HRESULT hr;
3185 TRACE("iface %p, src_texture %p.\n", iface, src_texture);
3187 if (src_surface == dst_surface)
3189 TRACE("copying surface %p to surface %p, why?\n", src_surface, dst_surface);
3190 return D3D_OK;
3193 EnterCriticalSection(&ddraw_cs);
3195 if (((src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
3196 != (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP))
3197 || (src_surface->surface_desc.u2.dwMipMapCount != dst_surface->surface_desc.u2.dwMipMapCount))
3199 ERR("Trying to load surfaces with different mip-map counts.\n");
3202 for (;;)
3204 struct wined3d_palette *wined3d_dst_pal, *wined3d_src_pal;
3205 IDirectDrawPalette *dst_pal = NULL, *src_pal = NULL;
3206 DDSURFACEDESC *src_desc, *dst_desc;
3208 TRACE("Copying surface %p to surface %p (mipmap level %d).\n",
3209 src_surface, dst_surface, src_surface->mipmap_level);
3211 /* Suppress the ALLOCONLOAD flag */
3212 dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
3214 /* Get the palettes */
3215 wined3d_dst_pal = wined3d_surface_get_palette(dst_surface->wined3d_surface);
3216 if (wined3d_dst_pal)
3217 dst_pal = wined3d_palette_get_parent(wined3d_dst_pal);
3219 wined3d_src_pal = wined3d_surface_get_palette(src_surface->wined3d_surface);
3220 if (wined3d_src_pal)
3221 src_pal = wined3d_palette_get_parent(wined3d_src_pal);
3223 if (src_pal)
3225 PALETTEENTRY palent[256];
3227 if (!dst_pal)
3229 LeaveCriticalSection(&ddraw_cs);
3230 return DDERR_NOPALETTEATTACHED;
3232 IDirectDrawPalette_GetEntries(src_pal, 0, 0, 256, palent);
3233 IDirectDrawPalette_SetEntries(dst_pal, 0, 0, 256, palent);
3236 /* Copy one surface on the other */
3237 dst_desc = (DDSURFACEDESC *)&(dst_surface->surface_desc);
3238 src_desc = (DDSURFACEDESC *)&(src_surface->surface_desc);
3240 if ((src_desc->dwWidth != dst_desc->dwWidth) || (src_desc->dwHeight != dst_desc->dwHeight))
3242 /* Should also check for same pixel format, u1.lPitch, ... */
3243 ERR("Error in surface sizes.\n");
3244 LeaveCriticalSection(&ddraw_cs);
3245 return D3DERR_TEXTURE_LOAD_FAILED;
3247 else
3249 WINED3DLOCKED_RECT src_rect, dst_rect;
3251 /* Copy also the ColorKeying stuff */
3252 if (src_desc->dwFlags & DDSD_CKSRCBLT)
3254 dst_desc->dwFlags |= DDSD_CKSRCBLT;
3255 dst_desc->ddckCKSrcBlt.dwColorSpaceLowValue = src_desc->ddckCKSrcBlt.dwColorSpaceLowValue;
3256 dst_desc->ddckCKSrcBlt.dwColorSpaceHighValue = src_desc->ddckCKSrcBlt.dwColorSpaceHighValue;
3259 /* Copy the main memory texture into the surface that corresponds
3260 * to the OpenGL texture object. */
3262 hr = wined3d_surface_map(src_surface->wined3d_surface, &src_rect, NULL, 0);
3263 if (FAILED(hr))
3265 ERR("Failed to lock source surface, hr %#x.\n", hr);
3266 LeaveCriticalSection(&ddraw_cs);
3267 return D3DERR_TEXTURE_LOAD_FAILED;
3270 hr = wined3d_surface_map(dst_surface->wined3d_surface, &dst_rect, NULL, 0);
3271 if (FAILED(hr))
3273 ERR("Failed to lock destination surface, hr %#x.\n", hr);
3274 wined3d_surface_unmap(src_surface->wined3d_surface);
3275 LeaveCriticalSection(&ddraw_cs);
3276 return D3DERR_TEXTURE_LOAD_FAILED;
3279 if (dst_surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
3280 memcpy(dst_rect.pBits, src_rect.pBits, src_surface->surface_desc.u1.dwLinearSize);
3281 else
3282 memcpy(dst_rect.pBits, src_rect.pBits, src_rect.Pitch * src_desc->dwHeight);
3284 wined3d_surface_unmap(src_surface->wined3d_surface);
3285 wined3d_surface_unmap(dst_surface->wined3d_surface);
3288 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
3289 src_surface = get_sub_mimaplevel(src_surface);
3290 else
3291 src_surface = NULL;
3293 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
3294 dst_surface = get_sub_mimaplevel(dst_surface);
3295 else
3296 dst_surface = NULL;
3298 if (!src_surface || !dst_surface)
3300 if (src_surface != dst_surface)
3301 ERR("Loading surface with different mipmap structure.\n");
3302 break;
3306 LeaveCriticalSection(&ddraw_cs);
3308 return hr;
3311 static HRESULT WINAPI d3d_texture1_Load(IDirect3DTexture *iface, IDirect3DTexture *src_texture)
3313 TRACE("iface %p, src_texture %p.\n", iface, src_texture);
3315 return d3d_texture2_Load((IDirect3DTexture2 *)&surface_from_texture1(iface)->IDirect3DTexture2_vtbl,
3316 src_texture ? (IDirect3DTexture2 *)&surface_from_texture1(src_texture)->IDirect3DTexture2_vtbl : NULL);
3319 /*****************************************************************************
3320 * The VTable
3321 *****************************************************************************/
3323 static const struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl =
3325 /* IUnknown */
3326 ddraw_surface7_QueryInterface,
3327 ddraw_surface7_AddRef,
3328 ddraw_surface7_Release,
3329 /* IDirectDrawSurface */
3330 ddraw_surface7_AddAttachedSurface,
3331 ddraw_surface7_AddOverlayDirtyRect,
3332 ddraw_surface7_Blt,
3333 ddraw_surface7_BltBatch,
3334 ddraw_surface7_BltFast,
3335 ddraw_surface7_DeleteAttachedSurface,
3336 ddraw_surface7_EnumAttachedSurfaces,
3337 ddraw_surface7_EnumOverlayZOrders,
3338 ddraw_surface7_Flip,
3339 ddraw_surface7_GetAttachedSurface,
3340 ddraw_surface7_GetBltStatus,
3341 ddraw_surface7_GetCaps,
3342 ddraw_surface7_GetClipper,
3343 ddraw_surface7_GetColorKey,
3344 ddraw_surface7_GetDC,
3345 ddraw_surface7_GetFlipStatus,
3346 ddraw_surface7_GetOverlayPosition,
3347 ddraw_surface7_GetPalette,
3348 ddraw_surface7_GetPixelFormat,
3349 ddraw_surface7_GetSurfaceDesc,
3350 ddraw_surface7_Initialize,
3351 ddraw_surface7_IsLost,
3352 ddraw_surface7_Lock,
3353 ddraw_surface7_ReleaseDC,
3354 ddraw_surface7_Restore,
3355 ddraw_surface7_SetClipper,
3356 ddraw_surface7_SetColorKey,
3357 ddraw_surface7_SetOverlayPosition,
3358 ddraw_surface7_SetPalette,
3359 ddraw_surface7_Unlock,
3360 ddraw_surface7_UpdateOverlay,
3361 ddraw_surface7_UpdateOverlayDisplay,
3362 ddraw_surface7_UpdateOverlayZOrder,
3363 /* IDirectDrawSurface2 */
3364 ddraw_surface7_GetDDInterface,
3365 ddraw_surface7_PageLock,
3366 ddraw_surface7_PageUnlock,
3367 /* IDirectDrawSurface3 */
3368 ddraw_surface7_SetSurfaceDesc,
3369 /* IDirectDrawSurface4 */
3370 ddraw_surface7_SetPrivateData,
3371 ddraw_surface7_GetPrivateData,
3372 ddraw_surface7_FreePrivateData,
3373 ddraw_surface7_GetUniquenessValue,
3374 ddraw_surface7_ChangeUniquenessValue,
3375 /* IDirectDrawSurface7 */
3376 ddraw_surface7_SetPriority,
3377 ddraw_surface7_GetPriority,
3378 ddraw_surface7_SetLOD,
3379 ddraw_surface7_GetLOD,
3382 static const struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl =
3384 /* IUnknown */
3385 ddraw_surface3_QueryInterface,
3386 ddraw_surface3_AddRef,
3387 ddraw_surface3_Release,
3388 /* IDirectDrawSurface */
3389 ddraw_surface3_AddAttachedSurface,
3390 ddraw_surface3_AddOverlayDirtyRect,
3391 ddraw_surface3_Blt,
3392 ddraw_surface3_BltBatch,
3393 ddraw_surface3_BltFast,
3394 ddraw_surface3_DeleteAttachedSurface,
3395 ddraw_surface3_EnumAttachedSurfaces,
3396 ddraw_surface3_EnumOverlayZOrders,
3397 ddraw_surface3_Flip,
3398 ddraw_surface3_GetAttachedSurface,
3399 ddraw_surface3_GetBltStatus,
3400 ddraw_surface3_GetCaps,
3401 ddraw_surface3_GetClipper,
3402 ddraw_surface3_GetColorKey,
3403 ddraw_surface3_GetDC,
3404 ddraw_surface3_GetFlipStatus,
3405 ddraw_surface3_GetOverlayPosition,
3406 ddraw_surface3_GetPalette,
3407 ddraw_surface3_GetPixelFormat,
3408 ddraw_surface3_GetSurfaceDesc,
3409 ddraw_surface3_Initialize,
3410 ddraw_surface3_IsLost,
3411 ddraw_surface3_Lock,
3412 ddraw_surface3_ReleaseDC,
3413 ddraw_surface3_Restore,
3414 ddraw_surface3_SetClipper,
3415 ddraw_surface3_SetColorKey,
3416 ddraw_surface3_SetOverlayPosition,
3417 ddraw_surface3_SetPalette,
3418 ddraw_surface3_Unlock,
3419 ddraw_surface3_UpdateOverlay,
3420 ddraw_surface3_UpdateOverlayDisplay,
3421 ddraw_surface3_UpdateOverlayZOrder,
3422 /* IDirectDrawSurface2 */
3423 ddraw_surface3_GetDDInterface,
3424 ddraw_surface3_PageLock,
3425 ddraw_surface3_PageUnlock,
3426 /* IDirectDrawSurface3 */
3427 ddraw_surface3_SetSurfaceDesc,
3430 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl =
3432 ddraw_gamma_control_QueryInterface,
3433 ddraw_gamma_control_AddRef,
3434 ddraw_gamma_control_Release,
3435 ddraw_gamma_control_GetGammaRamp,
3436 ddraw_gamma_control_SetGammaRamp,
3439 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl =
3441 d3d_texture2_QueryInterface,
3442 d3d_texture2_AddRef,
3443 d3d_texture2_Release,
3444 d3d_texture2_GetHandle,
3445 d3d_texture2_PaletteChanged,
3446 d3d_texture2_Load,
3449 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl =
3451 d3d_texture1_QueryInterface,
3452 d3d_texture1_AddRef,
3453 d3d_texture1_Release,
3454 d3d_texture1_Initialize,
3455 d3d_texture1_GetHandle,
3456 d3d_texture1_PaletteChanged,
3457 d3d_texture1_Load,
3458 d3d_texture1_Unload,
3461 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7 *iface)
3463 if (!iface) return NULL;
3464 assert(iface->lpVtbl == &ddraw_surface7_vtbl);
3465 return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface7_iface);
3468 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4 *iface)
3470 if (!iface) return NULL;
3471 assert(iface->lpVtbl == (struct IDirectDrawSurface4Vtbl *)&ddraw_surface7_vtbl);
3472 return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface7_iface);
3475 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface)
3477 if (!iface) return NULL;
3478 assert(iface->lpVtbl == &ddraw_surface3_vtbl);
3479 return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface3_iface);
3482 static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *parent)
3484 IDirectDrawSurfaceImpl *surface = parent;
3486 TRACE("surface %p.\n", surface);
3488 /* Check for attached surfaces and detach them. */
3489 if (surface->first_attached != surface)
3491 IDirectDrawSurface7 *root = &surface->first_attached->IDirectDrawSurface7_iface;
3492 IDirectDrawSurface7 *detach = &surface->IDirectDrawSurface7_iface;
3494 /* Well, this shouldn't happen: The surface being attached is
3495 * referenced in AddAttachedSurface(), so it shouldn't be released
3496 * until DeleteAttachedSurface() is called, because the refcount is
3497 * held. It looks like the application released it often enough to
3498 * force this. */
3499 WARN("Surface is still attached to surface %p.\n", surface->first_attached);
3501 /* The refcount will drop to -1 here */
3502 if (FAILED(IDirectDrawSurface7_DeleteAttachedSurface(root, 0, detach)))
3503 ERR("DeleteAttachedSurface failed.\n");
3506 while (surface->next_attached)
3508 IDirectDrawSurface7 *root = &surface->IDirectDrawSurface7_iface;
3509 IDirectDrawSurface7 *detach = &surface->next_attached->IDirectDrawSurface7_iface;
3511 if (FAILED(IDirectDrawSurface7_DeleteAttachedSurface(root, 0, detach)))
3512 ERR("DeleteAttachedSurface failed.\n");
3515 /* Having a texture handle set implies that the device still exists. */
3516 if (surface->Handle)
3517 ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE);
3519 /* Reduce the ddraw surface count. */
3520 InterlockedDecrement(&surface->ddraw->surfaces);
3521 list_remove(&surface->surface_list_entry);
3523 HeapFree(GetProcessHeap(), 0, surface);
3526 const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops =
3528 ddraw_surface_wined3d_object_destroyed,
3531 static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent)
3533 IDirectDrawSurfaceImpl *surface = parent;
3535 TRACE("surface %p.\n", surface);
3537 ddraw_surface_cleanup(surface);
3540 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops =
3542 ddraw_texture_wined3d_object_destroyed,
3545 HRESULT ddraw_surface_create_texture(IDirectDrawSurfaceImpl *surface)
3547 const DDSURFACEDESC2 *desc = &surface->surface_desc;
3548 enum wined3d_format_id format;
3549 WINED3DPOOL pool;
3550 UINT levels;
3552 if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
3553 levels = desc->u2.dwMipMapCount;
3554 else
3555 levels = 1;
3557 /* DDSCAPS_SYSTEMMEMORY textures are in WINED3DPOOL_SYSTEMMEM.
3558 * Should I forward the MANAGED cap to the managed pool? */
3559 if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
3560 pool = WINED3DPOOL_SYSTEMMEM;
3561 else
3562 pool = WINED3DPOOL_DEFAULT;
3564 format = PixelFormat_DD2WineD3D(&surface->surface_desc.u4.ddpfPixelFormat);
3565 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3566 return wined3d_texture_create_cube(surface->ddraw->wined3d_device, desc->dwWidth,
3567 levels, 0, format, pool, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
3568 else
3569 return wined3d_texture_create_2d(surface->ddraw->wined3d_device, desc->dwWidth, desc->dwHeight,
3570 levels, 0, format, pool, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
3573 HRESULT ddraw_surface_init(IDirectDrawSurfaceImpl *surface, IDirectDrawImpl *ddraw,
3574 DDSURFACEDESC2 *desc, UINT mip_level, WINED3DSURFTYPE surface_type)
3576 struct wined3d_resource_desc wined3d_desc;
3577 struct wined3d_resource *wined3d_resource;
3578 WINED3DPOOL pool = WINED3DPOOL_DEFAULT;
3579 enum wined3d_format_id format;
3580 DWORD usage = 0;
3581 HRESULT hr;
3583 if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
3584 && !((desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
3585 && (desc->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)))
3587 /* Tests show surfaces without memory flags get these flags added
3588 * right after creation. */
3589 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
3592 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
3594 usage |= WINED3DUSAGE_RENDERTARGET;
3595 desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
3598 if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && !(desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
3600 usage |= WINED3DUSAGE_RENDERTARGET;
3603 if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
3605 usage |= WINED3DUSAGE_OVERLAY;
3608 if (ddraw->depthstencil || (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
3610 /* The depth stencil creation callback sets this flag. Set the
3611 * wined3d usage to let it know it's a depth/stencil surface. */
3612 usage |= WINED3DUSAGE_DEPTHSTENCIL;
3615 if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
3617 pool = WINED3DPOOL_SYSTEMMEM;
3619 else if (desc->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
3621 pool = WINED3DPOOL_MANAGED;
3622 /* Managed textures have the system memory flag set. */
3623 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
3625 else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
3627 /* Videomemory adds localvidmem. This is mutually exclusive with
3628 * systemmemory and texturemanage. */
3629 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
3632 format = PixelFormat_DD2WineD3D(&desc->u4.ddpfPixelFormat);
3633 if (format == WINED3DFMT_UNKNOWN)
3635 WARN("Unsupported / unknown pixelformat.\n");
3636 return DDERR_INVALIDPIXELFORMAT;
3639 surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl;
3640 surface->IDirectDrawSurface3_iface.lpVtbl = &ddraw_surface3_vtbl;
3641 surface->IDirectDrawGammaControl_vtbl = &ddraw_gamma_control_vtbl;
3642 surface->IDirect3DTexture2_vtbl = &d3d_texture2_vtbl;
3643 surface->IDirect3DTexture_vtbl = &d3d_texture1_vtbl;
3644 surface->ref = 1;
3645 surface->version = 7;
3646 surface->ddraw = ddraw;
3648 copy_to_surfacedesc2(&surface->surface_desc, desc);
3650 surface->first_attached = surface;
3651 surface->ImplType = surface_type;
3653 hr = wined3d_surface_create(ddraw->wined3d_device, desc->dwWidth, desc->dwHeight, format,
3654 TRUE /* Lockable */, FALSE /* Discard */, mip_level, usage, pool,
3655 WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, surface_type, surface,
3656 &ddraw_surface_wined3d_parent_ops, &surface->wined3d_surface);
3657 if (FAILED(hr))
3659 WARN("Failed to create wined3d surface, hr %#x.\n", hr);
3660 return hr;
3663 surface->surface_desc.dwFlags |= DDSD_PIXELFORMAT;
3664 wined3d_resource = wined3d_surface_get_resource(surface->wined3d_surface);
3665 wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
3667 format = wined3d_desc.format;
3668 if (format == WINED3DFMT_UNKNOWN)
3670 FIXME("IWineD3DSurface::GetDesc returned WINED3DFMT_UNKNOWN.\n");
3672 PixelFormat_WineD3DtoDD(&surface->surface_desc.u4.ddpfPixelFormat, format);
3674 /* Anno 1602 stores the pitch right after surface creation, so make sure
3675 * it's there. TODO: Test other fourcc formats. */
3676 if (format == WINED3DFMT_DXT1 || format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3
3677 || format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5)
3679 surface->surface_desc.dwFlags |= DDSD_LINEARSIZE;
3680 if (format == WINED3DFMT_DXT1)
3682 surface->surface_desc.u1.dwLinearSize = max(4, wined3d_desc.width) * max(4, wined3d_desc.height) / 2;
3684 else
3686 surface->surface_desc.u1.dwLinearSize = max(4, wined3d_desc.width) * max(4, wined3d_desc.height);
3689 else
3691 surface->surface_desc.dwFlags |= DDSD_PITCH;
3692 surface->surface_desc.u1.lPitch = wined3d_surface_get_pitch(surface->wined3d_surface);
3695 if (desc->dwFlags & DDSD_CKDESTOVERLAY)
3697 wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_DESTOVERLAY,
3698 (WINEDDCOLORKEY *)&desc->u3.ddckCKDestOverlay);
3700 if (desc->dwFlags & DDSD_CKDESTBLT)
3702 wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_DESTBLT,
3703 (WINEDDCOLORKEY *)&desc->ddckCKDestBlt);
3705 if (desc->dwFlags & DDSD_CKSRCOVERLAY)
3707 wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_SRCOVERLAY,
3708 (WINEDDCOLORKEY *)&desc->ddckCKSrcOverlay);
3710 if (desc->dwFlags & DDSD_CKSRCBLT)
3712 wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_SRCBLT,
3713 (WINEDDCOLORKEY *)&desc->ddckCKSrcBlt);
3715 if (desc->dwFlags & DDSD_LPSURFACE)
3717 hr = wined3d_surface_set_mem(surface->wined3d_surface, desc->lpSurface);
3718 if (FAILED(hr))
3720 ERR("Failed to set surface memory, hr %#x.\n", hr);
3721 wined3d_surface_decref(surface->wined3d_surface);
3722 return hr;
3726 return DD_OK;