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
27 #include "wine/port.h"
35 #define NONAMELESSUNION
41 #include "wine/exception.h"
46 #include "ddraw_private.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
51 static inline IDirectDrawSurfaceImpl *surface_from_gamma_control(IDirectDrawGammaControl *iface)
53 return (IDirectDrawSurfaceImpl *)((char*)iface
54 - FIELD_OFFSET(IDirectDrawSurfaceImpl, IDirectDrawGammaControl_vtbl));
57 /*****************************************************************************
58 * IUnknown parts follow
59 *****************************************************************************/
61 /*****************************************************************************
62 * IDirectDrawSurface7::QueryInterface
64 * A normal QueryInterface implementation. For QueryInterface rules
65 * see ddraw.c, IDirectDraw7::QueryInterface. This method
66 * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
67 * in all versions, the IDirectDrawGammaControl interface and it can
68 * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
71 * riid: The interface id queried for
72 * obj: Address to write the pointer to
76 * E_NOINTERFACE if the requested interface wasn't found
78 *****************************************************************************/
79 static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface, REFIID riid, void **obj)
81 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
83 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
87 return DDERR_INVALIDPARAMS;
89 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),obj);
90 if (IsEqualGUID(riid, &IID_IUnknown)
91 || IsEqualGUID(riid, &IID_IDirectDrawSurface7)
92 || IsEqualGUID(riid, &IID_IDirectDrawSurface4) )
94 IUnknown_AddRef(iface);
96 TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This, *obj);
99 else if( IsEqualGUID(riid, &IID_IDirectDrawSurface3)
100 || IsEqualGUID(riid, &IID_IDirectDrawSurface2)
101 || IsEqualGUID(riid, &IID_IDirectDrawSurface) )
103 IUnknown_AddRef(iface);
104 *obj = &This->IDirectDrawSurface3_vtbl;
105 TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
108 else if( IsEqualGUID(riid, &IID_IDirectDrawGammaControl) )
110 IUnknown_AddRef(iface);
111 *obj = &This->IDirectDrawGammaControl_vtbl;
112 TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This, *obj);
115 else if( IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D) ||
116 IsEqualGUID(riid, &IID_IDirect3DHALDevice)||
117 IsEqualGUID(riid, &IID_IDirect3DRGBDevice) )
119 IDirect3DDevice7 *d3d;
121 /* Call into IDirect3D7 for creation */
122 IDirect3D7_CreateDevice((IDirect3D7 *)&This->ddraw->IDirect3D7_vtbl, riid, (IDirectDrawSurface7 *)This, &d3d);
126 *obj = (IDirect3DDevice *)&((IDirect3DDeviceImpl *)d3d)->IDirect3DDevice_vtbl;
127 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
131 WARN("Unable to create a IDirect3DDevice instance, returning E_NOINTERFACE\n");
132 return E_NOINTERFACE;
134 else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
135 IsEqualGUID( &IID_IDirect3DTexture2, riid ))
137 if (IsEqualGUID( &IID_IDirect3DTexture, riid ))
139 *obj = &This->IDirect3DTexture_vtbl;
140 TRACE(" returning Direct3DTexture interface at %p.\n", *obj);
144 *obj = &This->IDirect3DTexture2_vtbl;
145 TRACE(" returning Direct3DTexture2 interface at %p.\n", *obj);
147 IUnknown_AddRef( (IUnknown *) *obj);
151 ERR("No interface\n");
152 return E_NOINTERFACE;
155 static HRESULT WINAPI ddraw_surface3_QueryInterface(IDirectDrawSurface3 *iface, REFIID riid, void **object)
157 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
159 return ddraw_surface7_QueryInterface((IDirectDrawSurface7 *)surface_from_surface3(iface), riid, object);
162 static HRESULT WINAPI ddraw_gamma_control_QueryInterface(IDirectDrawGammaControl *iface, REFIID riid, void **object)
164 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
166 return ddraw_surface7_QueryInterface((IDirectDrawSurface7 *)surface_from_gamma_control(iface), riid, object);
169 /*****************************************************************************
170 * IDirectDrawSurface7::AddRef
172 * A normal addref implementation
177 *****************************************************************************/
178 static ULONG WINAPI ddraw_surface7_AddRef(IDirectDrawSurface7 *iface)
180 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
181 ULONG refCount = InterlockedIncrement(&This->ref);
183 if (refCount == 1 && This->WineD3DSurface)
185 EnterCriticalSection(&ddraw_cs);
186 IWineD3DSurface_AddRef(This->WineD3DSurface);
187 LeaveCriticalSection(&ddraw_cs);
190 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
194 static ULONG WINAPI ddraw_surface3_AddRef(IDirectDrawSurface3 *iface)
196 TRACE("iface %p.\n", iface);
198 return ddraw_surface7_AddRef((IDirectDrawSurface7 *)surface_from_surface3(iface));
201 static ULONG WINAPI ddraw_gamma_control_AddRef(IDirectDrawGammaControl *iface)
203 TRACE("iface %p.\n", iface);
205 return ddraw_surface7_AddRef((IDirectDrawSurface7 *)surface_from_gamma_control(iface));
208 /*****************************************************************************
209 * ddraw_surface_destroy
211 * A helper function for IDirectDrawSurface7::Release
213 * Frees the surface, regardless of its refcount.
214 * See IDirectDrawSurface7::Release for more information
217 * This: Surface to free
219 *****************************************************************************/
220 void ddraw_surface_destroy(IDirectDrawSurfaceImpl *This)
222 TRACE("(%p)\n", This);
224 /* Check the refcount and give a warning */
227 /* This can happen when a complex surface is destroyed,
228 * because the 2nd surface was addref()ed when the app
229 * called GetAttachedSurface
231 WARN("(%p): Destroying surface with refount %d\n", This, This->ref);
234 /* Check for attached surfaces and detach them */
235 if(This->first_attached != This)
237 /* Well, this shouldn't happen: The surface being attached is addref()ed
238 * in AddAttachedSurface, so it shouldn't be released until DeleteAttachedSurface
239 * is called, because the refcount is held. It looks like the app released()
240 * it often enough to force this
242 IDirectDrawSurface7 *root = (IDirectDrawSurface7 *)This->first_attached;
243 IDirectDrawSurface7 *detach = (IDirectDrawSurface7 *)This;
245 FIXME("(%p) Freeing a surface that is attached to surface %p\n", This, This->first_attached);
247 /* The refcount will drop to -1 here */
248 if(IDirectDrawSurface7_DeleteAttachedSurface(root, 0, detach) != DD_OK)
250 ERR("(%p) DeleteAttachedSurface failed!\n", This);
254 while(This->next_attached != NULL)
256 IDirectDrawSurface7 *root = (IDirectDrawSurface7 *)This;
257 IDirectDrawSurface7 *detach = (IDirectDrawSurface7 *)This->next_attached;
259 if(IDirectDrawSurface7_DeleteAttachedSurface(root, 0, detach) != DD_OK)
261 ERR("(%p) DeleteAttachedSurface failed!\n", This);
266 /* Now destroy the surface. Wait: It could have been released if we are a texture */
267 if(This->WineD3DSurface)
268 IWineD3DSurface_Release(This->WineD3DSurface);
270 /* Having a texture handle set implies that the device still exists */
273 ddraw_free_handle(&This->ddraw->d3ddevice->handle_table, This->Handle - 1, DDRAW_HANDLE_SURFACE);
276 /* Reduce the ddraw surface count */
277 InterlockedDecrement(&This->ddraw->surfaces);
278 list_remove(&This->surface_list_entry);
280 HeapFree(GetProcessHeap(), 0, This);
283 /*****************************************************************************
284 * IDirectDrawSurface7::Release
286 * Reduces the surface's refcount by 1. If the refcount falls to 0, the
287 * surface is destroyed.
289 * Destroying the surface is a bit tricky. For the connection between
290 * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
291 * It has a nice graph explaining the connection.
293 * What happens here is basically this:
294 * When a surface is destroyed, its WineD3DSurface is released,
295 * and the refcount of the DirectDraw interface is reduced by 1. If it has
296 * complex surfaces attached to it, then these surfaces are destroyed too,
297 * regardless of their refcount. If any surface being destroyed has another
298 * surface attached to it (with a "soft" attachment, not complex), then
299 * this surface is detached with DeleteAttachedSurface.
301 * When the surface is a texture, the WineD3DTexture is released.
302 * If the surface is the Direct3D render target, then the D3D
303 * capabilities of the WineD3DDevice are uninitialized, which causes the
304 * swapchain to be released.
306 * When a complex sublevel falls to ref zero, then this is ignored.
311 *****************************************************************************/
312 static ULONG WINAPI ddraw_surface7_Release(IDirectDrawSurface7 *iface)
314 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
316 TRACE("(%p) : Releasing from %d\n", This, This->ref);
317 ref = InterlockedDecrement(&This->ref);
322 IDirectDrawSurfaceImpl *surf;
323 IDirectDrawImpl *ddraw;
324 IUnknown *ifaceToRelease = This->ifaceToRelease;
327 /* Complex attached surfaces are destroyed implicitly when the root is released */
328 EnterCriticalSection(&ddraw_cs);
329 if(!This->is_complex_root)
331 WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
332 LeaveCriticalSection(&ddraw_cs);
337 /* If it's a texture, destroy the WineD3DTexture.
338 * WineD3D will destroy the IParent interfaces
339 * of the sublevels, which destroys the WineD3DSurfaces.
340 * Set the surfaces to NULL to avoid destroying them again later
342 if(This->wineD3DTexture)
344 IWineD3DBaseTexture_Release(This->wineD3DTexture);
346 /* If it's the RenderTarget, destroy the d3ddevice */
347 else if(This->wineD3DSwapChain)
349 if((ddraw->d3d_initialized) && (This == ddraw->d3d_target)) {
350 TRACE("(%p) Destroying the render target, uninitializing D3D\n", This);
352 /* Unset any index buffer, just to be sure */
353 IWineD3DDevice_SetIndexBuffer(ddraw->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
354 IWineD3DDevice_SetDepthStencilSurface(ddraw->wineD3DDevice, NULL);
355 IWineD3DDevice_SetVertexDeclaration(ddraw->wineD3DDevice, NULL);
356 for(i = 0; i < ddraw->numConvertedDecls; i++)
358 IWineD3DVertexDeclaration_Release(ddraw->decls[i].decl);
360 HeapFree(GetProcessHeap(), 0, ddraw->decls);
361 ddraw->numConvertedDecls = 0;
363 if (FAILED(IWineD3DDevice_Uninit3D(ddraw->wineD3DDevice, D3D7CB_DestroySwapChain)))
366 ERR("(%p) Failed to uninit 3D\n", This);
370 /* Free the d3d window if one was created */
371 if(ddraw->d3d_window != 0 && ddraw->d3d_window != ddraw->dest_window)
373 TRACE(" (%p) Destroying the hidden render window %p\n", This, ddraw->d3d_window);
374 DestroyWindow(ddraw->d3d_window);
375 ddraw->d3d_window = 0;
377 /* Unset the pointers */
380 This->wineD3DSwapChain = NULL; /* Uninit3D releases the swapchain */
381 ddraw->d3d_initialized = FALSE;
382 ddraw->d3d_target = NULL;
384 IWineD3DDevice_UninitGDI(ddraw->wineD3DDevice, D3D7CB_DestroySwapChain);
385 This->wineD3DSwapChain = NULL;
388 /* Reset to the default surface implementation type. This is needed if apps use
389 * non render target surfaces and expect blits to work after destroying the render
392 * TODO: Recreate existing offscreen surfaces
394 ddraw->ImplType = DefaultSurfaceType;
396 /* Write a trace because D3D unloading was the reason for many
397 * crashes during development.
399 TRACE("(%p) D3D unloaded\n", This);
402 /* The refcount test shows that the palette is detached when the surface is destroyed */
403 IDirectDrawSurface7_SetPalette((IDirectDrawSurface7 *)This, NULL);
405 /* Loop through all complex attached surfaces,
408 * Yet again, only the root can have more than one complexly attached surface, all the others
409 * have a total of one;
411 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
413 if(!This->complex_array[i]) break;
415 surf = This->complex_array[i];
416 This->complex_array[i] = NULL;
419 IDirectDrawSurfaceImpl *destroy = surf;
420 surf = surf->complex_array[0]; /* Iterate through the "tree" */
421 ddraw_surface_destroy(destroy); /* Destroy it */
425 /* Destroy the root surface. */
426 ddraw_surface_destroy(This);
428 /* Reduce the ddraw refcount */
429 if(ifaceToRelease) IUnknown_Release(ifaceToRelease);
430 LeaveCriticalSection(&ddraw_cs);
436 static ULONG WINAPI ddraw_surface3_Release(IDirectDrawSurface3 *iface)
438 TRACE("iface %p.\n", iface);
440 return ddraw_surface7_Release((IDirectDrawSurface7 *)surface_from_surface3(iface));
443 static ULONG WINAPI ddraw_gamma_control_Release(IDirectDrawGammaControl *iface)
445 TRACE("iface %p.\n", iface);
447 return ddraw_surface7_Release((IDirectDrawSurface7 *)surface_from_gamma_control(iface));
450 /*****************************************************************************
451 * IDirectDrawSurface7::GetAttachedSurface
453 * Returns an attached surface with the requested caps. Surface attachment
454 * and complex surfaces are not clearly described by the MSDN or sdk,
455 * so this method is tricky and likely to contain problems.
456 * This implementation searches the complex list first, then the
459 * The chains are searched from This down to the last surface in the chain,
460 * not from the first element in the chain. The first surface found is
461 * returned. The MSDN says that this method fails if more than one surface
462 * matches the caps, but it is not sure if that is right. The attachment
463 * structure may not even allow two matching surfaces.
465 * The found surface is AddRef-ed before it is returned.
468 * Caps: Pointer to a DDCAPS2 structure describing the caps asked for
469 * Surface: Address to store the found surface
473 * DDERR_INVALIDPARAMS if Caps or Surface is NULL
474 * DDERR_NOTFOUND if no surface was found
476 *****************************************************************************/
477 static HRESULT WINAPI ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7 *iface,
478 DDSCAPS2 *Caps, IDirectDrawSurface7 **Surface)
480 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
481 IDirectDrawSurfaceImpl *surf;
485 TRACE("(%p)->(%p,%p)\n", This, Caps, Surface);
486 EnterCriticalSection(&ddraw_cs);
488 if(This->version < 7)
490 /* Earlier dx apps put garbage into these members, clear them */
491 our_caps.dwCaps = Caps->dwCaps;
492 our_caps.dwCaps2 = 0;
493 our_caps.dwCaps3 = 0;
494 our_caps.dwCaps4 = 0;
501 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 */
503 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
505 surf = This->complex_array[i];
510 TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf,
511 surf->surface_desc.ddsCaps.dwCaps,
512 surf->surface_desc.ddsCaps.dwCaps2,
513 surf->surface_desc.ddsCaps.dwCaps3,
514 surf->surface_desc.ddsCaps.dwCaps4);
517 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
518 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
520 /* MSDN: "This method fails if more than one surface is attached
521 * that matches the capabilities requested."
523 * Not sure how to test this.
526 TRACE("(%p): Returning surface %p\n", This, surf);
527 TRACE("(%p): mipmapcount=%d\n", This, surf->mipmap_level);
528 *Surface = (IDirectDrawSurface7 *)surf;
529 ddraw_surface7_AddRef(*Surface);
530 LeaveCriticalSection(&ddraw_cs);
535 /* Next, look at the attachment chain */
538 while( (surf = surf->next_attached) )
542 TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf,
543 surf->surface_desc.ddsCaps.dwCaps,
544 surf->surface_desc.ddsCaps.dwCaps2,
545 surf->surface_desc.ddsCaps.dwCaps3,
546 surf->surface_desc.ddsCaps.dwCaps4);
549 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
550 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
552 TRACE("(%p): Returning surface %p\n", This, surf);
553 *Surface = (IDirectDrawSurface7 *)surf;
554 ddraw_surface7_AddRef(*Surface);
555 LeaveCriticalSection(&ddraw_cs);
560 TRACE("(%p) Didn't find a valid surface\n", This);
561 LeaveCriticalSection(&ddraw_cs);
564 return DDERR_NOTFOUND;
567 static HRESULT WINAPI ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3 *iface,
568 DDSCAPS *caps, IDirectDrawSurface3 **attachment)
570 IDirectDrawSurface7 *attachment7;
574 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
576 caps2.dwCaps = caps->dwCaps;
581 hr = ddraw_surface7_GetAttachedSurface((IDirectDrawSurface7 *)surface_from_surface3(iface),
582 &caps2, &attachment7);
583 if (FAILED(hr)) *attachment = NULL;
584 else *attachment = attachment7 ?
585 (IDirectDrawSurface3 *)&((IDirectDrawSurfaceImpl *)attachment7)->IDirectDrawSurface3_vtbl : NULL;
590 /*****************************************************************************
591 * IDirectDrawSurface7::Lock
593 * Locks the surface and returns a pointer to the surface's memory
596 * Rect: Rectangle to lock. If NULL, the whole surface is locked
597 * DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
598 * Flags: Locking flags, e.g Read only or write only
599 * h: An event handle that's not used and must be NULL
603 * DDERR_INVALIDPARAMS if DDSD is NULL
604 * For more details, see IWineD3DSurface::LockRect
606 *****************************************************************************/
607 static HRESULT WINAPI ddraw_surface7_Lock(IDirectDrawSurface7 *iface,
608 RECT *Rect, DDSURFACEDESC2 *DDSD, DWORD Flags, HANDLE h)
610 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
611 WINED3DLOCKED_RECT LockedRect;
613 TRACE("(%p)->(%p,%p,%x,%p)\n", This, Rect, DDSD, Flags, h);
616 return DDERR_INVALIDPARAMS;
618 /* This->surface_desc.dwWidth and dwHeight are changeable, thus lock */
619 EnterCriticalSection(&ddraw_cs);
621 /* Should I check for the handle to be NULL?
623 * The DDLOCK flags and the D3DLOCK flags are equal
624 * for the supported values. The others are ignored by WineD3D
627 if(DDSD->dwSize != sizeof(DDSURFACEDESC) &&
628 DDSD->dwSize != sizeof(DDSURFACEDESC2))
630 WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", DDERR_INVALIDPARAMS);
631 LeaveCriticalSection(&ddraw_cs);
632 return DDERR_INVALIDPARAMS;
635 /* Windows zeroes this if the rect is invalid */
642 || (Rect->left > Rect->right)
643 || (Rect->top > Rect->bottom)
644 || (Rect->right > This->surface_desc.dwWidth)
645 || (Rect->bottom > This->surface_desc.dwHeight))
647 WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
648 LeaveCriticalSection(&ddraw_cs);
649 return DDERR_INVALIDPARAMS;
653 hr = IWineD3DSurface_LockRect(This->WineD3DSurface,
659 LeaveCriticalSection(&ddraw_cs);
662 /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more
663 * specific error. But since IWineD3DSurface::LockRect returns that error in this
664 * only occasion, keep d3d8 and d3d9 free from the return value override. There are
665 * many different places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it
666 * is much easier to do it in one place in ddraw
668 case WINED3DERR_INVALIDCALL: return DDERR_SURFACEBUSY;
673 /* Override the memory area. The pitch should be set already. Strangely windows
674 * does not set the LPSURFACE flag on locked surfaces !?!.
675 * DDSD->dwFlags |= DDSD_LPSURFACE;
677 This->surface_desc.lpSurface = LockedRect.pBits;
678 DD_STRUCT_COPY_BYSIZE(DDSD,&(This->surface_desc));
680 TRACE("locked surface returning description :\n");
681 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
683 LeaveCriticalSection(&ddraw_cs);
687 static HRESULT WINAPI ddraw_surface3_Lock(IDirectDrawSurface3 *iface, RECT *rect,
688 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
690 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
691 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
693 return ddraw_surface7_Lock((IDirectDrawSurface7 *)surface_from_surface3(iface),
694 rect, (DDSURFACEDESC2 *)surface_desc, flags, h);
697 /*****************************************************************************
698 * IDirectDrawSurface7::Unlock
700 * Unlocks an locked surface
703 * Rect: Not used by this implementation
707 * For more details, see IWineD3DSurface::UnlockRect
709 *****************************************************************************/
710 static HRESULT WINAPI ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *pRect)
712 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
714 TRACE("(%p)->(%p)\n", This, pRect);
716 EnterCriticalSection(&ddraw_cs);
717 hr = IWineD3DSurface_UnlockRect(This->WineD3DSurface);
720 This->surface_desc.lpSurface = NULL;
722 LeaveCriticalSection(&ddraw_cs);
726 static HRESULT WINAPI ddraw_surface3_Unlock(IDirectDrawSurface3 *iface, void *data)
728 TRACE("iface %p, data %p.\n", iface, data);
730 /* data might not be the LPRECT of later versions, so drop it. */
731 return ddraw_surface7_Unlock((IDirectDrawSurface7 *)surface_from_surface3(iface), NULL);
734 /*****************************************************************************
735 * IDirectDrawSurface7::Flip
737 * Flips a surface with the DDSCAPS_FLIP flag. The flip is relayed to
738 * IWineD3DSurface::Flip. Because WineD3D doesn't handle attached surfaces,
739 * the flip target is passed to WineD3D, even if the app didn't specify one
742 * DestOverride: Specifies the surface that will become the new front
743 * buffer. If NULL, the current back buffer is used
744 * Flags: some DirectDraw flags, see include/ddraw.h
748 * DDERR_NOTFLIPPABLE if no flip target could be found
749 * DDERR_INVALIDOBJECT if the surface isn't a front buffer
750 * For more details, see IWineD3DSurface::Flip
752 *****************************************************************************/
753 static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *DestOverride, DWORD Flags)
755 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
756 IDirectDrawSurfaceImpl *Override = (IDirectDrawSurfaceImpl *)DestOverride;
757 IDirectDrawSurface7 *Override7;
759 TRACE("(%p)->(%p,%x)\n", This, DestOverride, Flags);
761 /* Flip has to be called from a front buffer
762 * What about overlay surfaces, AFAIK they can flip too?
764 if( !(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)) )
765 return DDERR_INVALIDOBJECT; /* Unchecked */
767 EnterCriticalSection(&ddraw_cs);
769 /* WineD3D doesn't keep track of attached surface, so find the target */
774 memset(&Caps, 0, sizeof(Caps));
775 Caps.dwCaps |= DDSCAPS_BACKBUFFER;
776 hr = ddraw_surface7_GetAttachedSurface(iface, &Caps, &Override7);
779 ERR("Can't find a flip target\n");
780 LeaveCriticalSection(&ddraw_cs);
781 return DDERR_NOTFLIPPABLE; /* Unchecked */
783 Override = (IDirectDrawSurfaceImpl *)Override7;
785 /* For the GetAttachedSurface */
786 ddraw_surface7_Release(Override7);
789 hr = IWineD3DSurface_Flip(This->WineD3DSurface,
790 Override->WineD3DSurface,
792 LeaveCriticalSection(&ddraw_cs);
796 static HRESULT WINAPI ddraw_surface3_Flip(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *dst, DWORD flags)
798 TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
800 return ddraw_surface7_Flip((IDirectDrawSurface7 *)surface_from_surface3(iface),
801 dst ? (IDirectDrawSurface7 *)surface_from_surface3(dst) : NULL, flags);
804 /*****************************************************************************
805 * IDirectDrawSurface7::Blt
807 * Performs a blit on the surface
810 * DestRect: Destination rectangle, can be NULL
811 * SrcSurface: Source surface, can be NULL
812 * SrcRect: Source rectangle, can be NULL
814 * DDBltFx: Some extended blt parameters, connected to the flags
818 * See IWineD3DSurface::Blt for more details
820 *****************************************************************************/
821 static HRESULT WINAPI ddraw_surface7_Blt(IDirectDrawSurface7 *iface, RECT *DestRect,
822 IDirectDrawSurface7 *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx)
824 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
825 IDirectDrawSurfaceImpl *Src = (IDirectDrawSurfaceImpl *)SrcSurface;
827 TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, Src, SrcRect, Flags, DDBltFx);
829 /* Check for validity of the flags here. WineD3D Has the software-opengl selection path and would have
830 * to check at 2 places, and sometimes do double checks. This also saves the call to wined3d :-)
832 if((Flags & DDBLT_KEYSRCOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYSRC)) {
833 WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
834 return DDERR_INVALIDPARAMS;
837 if((Flags & DDBLT_KEYDESTOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYDEST)) {
838 WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
839 return DDERR_INVALIDPARAMS;
842 /* Sizes can change, therefore hold the lock when testing the rectangles */
843 EnterCriticalSection(&ddraw_cs);
846 if(DestRect->top >= DestRect->bottom || DestRect->left >= DestRect->right ||
847 DestRect->right > This->surface_desc.dwWidth ||
848 DestRect->bottom > This->surface_desc.dwHeight)
850 WARN("Destination rectangle is invalid, returning DDERR_INVALIDRECT\n");
851 LeaveCriticalSection(&ddraw_cs);
852 return DDERR_INVALIDRECT;
857 if(SrcRect->top >= SrcRect->bottom || SrcRect->left >=SrcRect->right ||
858 SrcRect->right > Src->surface_desc.dwWidth ||
859 SrcRect->bottom > Src->surface_desc.dwHeight)
861 WARN("Source rectangle is invalid, returning DDERR_INVALIDRECT\n");
862 LeaveCriticalSection(&ddraw_cs);
863 return DDERR_INVALIDRECT;
867 if(Flags & DDBLT_KEYSRC && (!Src || !(Src->surface_desc.dwFlags & DDSD_CKSRCBLT))) {
868 WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
869 LeaveCriticalSection(&ddraw_cs);
870 return DDERR_INVALIDPARAMS;
873 /* TODO: Check if the DDBltFx contains any ddraw surface pointers. If it does, copy the struct,
874 * and replace the ddraw surfaces with the wined3d surfaces
875 * So far no blitting operations using surfaces in the bltfx struct are supported anyway.
877 hr = IWineD3DSurface_Blt(This->WineD3DSurface,
879 Src ? Src->WineD3DSurface : NULL,
882 (WINEDDBLTFX *) DDBltFx,
885 LeaveCriticalSection(&ddraw_cs);
888 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
889 case WINED3DERR_WRONGTEXTUREFORMAT: return DDERR_INVALIDPIXELFORMAT;
894 static HRESULT WINAPI ddraw_surface3_Blt(IDirectDrawSurface3 *iface, RECT *dst_rect,
895 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
897 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %p, flags %#x, fx %p.\n",
898 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
900 return ddraw_surface7_Blt((IDirectDrawSurface7 *)surface_from_surface3(iface), dst_rect,
901 src_surface ? (IDirectDrawSurface7 *)surface_from_surface3(src_surface) : NULL, src_rect, flags, fx);
904 /*****************************************************************************
905 * IDirectDrawSurface7::AddAttachedSurface
907 * Attaches a surface to another surface. How the surface attachments work
908 * is not totally understood yet, and this method is prone to problems.
909 * he surface that is attached is AddRef-ed.
911 * Tests with complex surfaces suggest that the surface attachments form a
912 * tree, but no method to test this has been found yet.
914 * The attachment list consists of a first surface (first_attached) and
915 * for each surface a pointer to the next attached surface (next_attached).
916 * For the first surface, and a surface that has no attachments
917 * first_attached points to the surface itself. A surface that has
918 * no successors in the chain has next_attached set to NULL.
920 * Newly attached surfaces are attached right after the root surface.
921 * If a surface is attached to a complex surface compound, it's attached to
922 * the surface that the app requested, not the complex root. See
923 * GetAttachedSurface for a description how surfaces are found.
925 * This is how the current implementation works, and it was coded by looking
926 * at the needs of the applications.
928 * So far only Z-Buffer attachments are tested, and they are activated in
929 * WineD3D. Mipmaps could be tricky to activate in WineD3D.
930 * Back buffers should work in 2D mode, but they are not tested(They can be
931 * attached in older iface versions). Rendering to the front buffer and
932 * switching between that and double buffering is not yet implemented in
933 * WineD3D, so for 3D it might have unexpected results.
935 * ddraw_surface_attach_surface is the real thing,
936 * ddraw_surface7_AddAttachedSurface is a wrapper around it that
937 * performs additional checks. Version 7 of this interface is much more restrictive
938 * than its predecessors.
941 * Attach: Surface to attach to iface
945 * DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
947 *****************************************************************************/
948 static HRESULT WINAPI ddraw_surface_attach_surface(IDirectDrawSurfaceImpl *This, IDirectDrawSurfaceImpl *Surf)
950 TRACE("(%p)->(%p)\n", This, Surf);
953 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
955 EnterCriticalSection(&ddraw_cs);
957 /* Check if the surface is already attached somewhere */
958 if( (Surf->next_attached != NULL) ||
959 (Surf->first_attached != Surf) )
961 /* TODO: Test for the structure of the manual attachment. Is it a chain or a list?
962 * What happens if one surface is attached to 2 different surfaces?
964 FIXME("(%p) The Surface %p is already attached somewhere else: next_attached = %p, first_attached = %p, can't handle by now\n", This, Surf, Surf->next_attached, Surf->first_attached);
965 LeaveCriticalSection(&ddraw_cs);
966 return DDERR_SURFACEALREADYATTACHED;
969 /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
970 Surf->next_attached = This->next_attached;
971 Surf->first_attached = This->first_attached;
972 This->next_attached = Surf;
974 /* Check if the WineD3D depth stencil needs updating */
975 if(This->ddraw->d3ddevice)
977 IDirect3DDeviceImpl_UpdateDepthStencil(This->ddraw->d3ddevice);
980 ddraw_surface7_AddRef((IDirectDrawSurface7 *)Surf);
981 LeaveCriticalSection(&ddraw_cs);
985 static HRESULT WINAPI ddraw_surface7_AddAttachedSurface(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *Attach)
987 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
988 IDirectDrawSurfaceImpl *Surf = (IDirectDrawSurfaceImpl *)Attach;
990 /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
991 if(!(Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
994 WARN("Application tries to attach a non Z buffer surface. caps %08x\n",
995 Surf->surface_desc.ddsCaps.dwCaps);
996 return DDERR_CANNOTATTACHSURFACE;
999 return ddraw_surface_attach_surface(This, Surf);
1002 static HRESULT WINAPI ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *attachment)
1004 IDirectDrawSurfaceImpl *surface = surface_from_surface3(iface);
1005 IDirectDrawSurfaceImpl *attach_impl = surface_from_surface3(attachment);
1007 TRACE("iface %p, attachment %p.\n", iface, attachment);
1009 /* Tests suggest that
1010 * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
1011 * -> offscreen plain surfaces can be attached to primaries
1012 * -> primaries can be attached to offscreen plain surfaces
1013 * -> z buffers can be attached to primaries */
1014 if (surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN)
1015 && attach_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN))
1017 /* Sizes have to match */
1018 if (attach_impl->surface_desc.dwWidth != surface->surface_desc.dwWidth
1019 || attach_impl->surface_desc.dwHeight != surface->surface_desc.dwHeight)
1021 WARN("Surface sizes do not match.\n");
1022 return DDERR_CANNOTATTACHSURFACE;
1026 else if (surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE)
1027 && attach_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER))
1033 WARN("Invalid attachment combination.\n");
1034 return DDERR_CANNOTATTACHSURFACE;
1037 return ddraw_surface_attach_surface(surface, attach_impl);
1040 /*****************************************************************************
1041 * IDirectDrawSurface7::DeleteAttachedSurface
1043 * Removes a surface from the attachment chain. The surface's refcount
1044 * is decreased by one after it has been removed
1047 * Flags: Some flags, not used by this implementation
1048 * Attach: Surface to detach
1052 * DDERR_SURFACENOTATTACHED if the surface isn't attached to
1054 *****************************************************************************/
1055 static HRESULT WINAPI ddraw_surface7_DeleteAttachedSurface(IDirectDrawSurface7 *iface,
1056 DWORD Flags, IDirectDrawSurface7 *Attach)
1058 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1059 IDirectDrawSurfaceImpl *Surf = (IDirectDrawSurfaceImpl *)Attach;
1060 IDirectDrawSurfaceImpl *Prev = This;
1061 TRACE("(%p)->(%08x,%p)\n", This, Flags, Surf);
1063 EnterCriticalSection(&ddraw_cs);
1064 if (!Surf || (Surf->first_attached != This) || (Surf == This) )
1066 LeaveCriticalSection(&ddraw_cs);
1067 return DDERR_CANNOTDETACHSURFACE;
1070 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
1071 if (This->surface_desc.ddsCaps.dwCaps &
1072 Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
1074 Surf->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
1075 /* FIXME: we should probably also subtract from dwMipMapCount of this
1076 * and all parent surfaces */
1079 /* Find the predecessor of the detached surface */
1082 if(Prev->next_attached == Surf) break;
1083 Prev = Prev->next_attached;
1086 /* There must be a surface, otherwise there's a bug */
1087 assert(Prev != NULL);
1089 /* Unchain the surface */
1090 Prev->next_attached = Surf->next_attached;
1091 Surf->next_attached = NULL;
1092 Surf->first_attached = Surf;
1094 /* Check if the WineD3D depth stencil needs updating */
1095 if(This->ddraw->d3ddevice)
1097 IDirect3DDeviceImpl_UpdateDepthStencil(This->ddraw->d3ddevice);
1100 ddraw_surface7_Release(Attach);
1101 LeaveCriticalSection(&ddraw_cs);
1105 static HRESULT WINAPI ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3 *iface,
1106 DWORD flags, IDirectDrawSurface3 *attachment)
1108 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1110 return ddraw_surface7_DeleteAttachedSurface((IDirectDrawSurface7 *)surface_from_surface3(iface), flags,
1111 attachment ? (IDirectDrawSurface7 *)surface_from_surface3(attachment) : NULL);
1114 /*****************************************************************************
1115 * IDirectDrawSurface7::AddOverlayDirtyRect
1117 * "This method is not currently implemented"
1125 *****************************************************************************/
1126 static HRESULT WINAPI ddraw_surface7_AddOverlayDirtyRect(IDirectDrawSurface7 *iface, RECT *Rect)
1128 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1129 TRACE("(%p)->(%p)\n",This,Rect);
1131 /* MSDN says it's not implemented. I could forward it to WineD3D,
1132 * then we'd implement it, but I don't think that's a good idea
1133 * (Stefan Dösinger)
1136 return IWineD3DSurface_AddOverlayDirtyRect(This->WineD3DSurface, pRect);
1138 return DDERR_UNSUPPORTED; /* unchecked */
1141 static HRESULT WINAPI ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3 *iface, RECT *rect)
1143 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1145 return ddraw_surface7_AddOverlayDirtyRect((IDirectDrawSurface7 *)surface_from_surface3(iface), rect);
1148 /*****************************************************************************
1149 * IDirectDrawSurface7::GetDC
1151 * Returns a GDI device context for the surface
1154 * hdc: Address of a HDC variable to store the dc to
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 = (IDirectDrawSurfaceImpl *)iface;
1166 TRACE("(%p)->(%p): Relay\n", This, hdc);
1169 return DDERR_INVALIDPARAMS;
1171 EnterCriticalSection(&ddraw_cs);
1172 hr = IWineD3DSurface_GetDC(This->WineD3DSurface,
1174 LeaveCriticalSection(&ddraw_cs);
1177 /* Some, but not all errors set *hdc to NULL. E.g. DCALREADYCREATED does not
1180 case WINED3DERR_INVALIDCALL:
1181 if(hdc) *hdc = NULL;
1182 return DDERR_INVALIDPARAMS;
1188 static HRESULT WINAPI ddraw_surface3_GetDC(IDirectDrawSurface3 *iface, HDC *dc)
1190 TRACE("iface %p, dc %p.\n", iface, dc);
1192 return ddraw_surface7_GetDC((IDirectDrawSurface7 *)surface_from_surface3(iface), dc);
1195 /*****************************************************************************
1196 * IDirectDrawSurface7::ReleaseDC
1198 * Releases the DC that was constructed with GetDC
1201 * hdc: HDC to release
1205 * For more details, see IWineD3DSurface::ReleaseDC
1207 *****************************************************************************/
1208 static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC hdc)
1210 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1212 TRACE("(%p)->(%p): Relay\n", This, hdc);
1214 EnterCriticalSection(&ddraw_cs);
1215 hr = IWineD3DSurface_ReleaseDC(This->WineD3DSurface, hdc);
1216 LeaveCriticalSection(&ddraw_cs);
1220 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc)
1222 TRACE("iface %p, dc %p.\n", iface, dc);
1224 return ddraw_surface7_ReleaseDC((IDirectDrawSurface7 *)surface_from_surface3(iface), dc);
1227 /*****************************************************************************
1228 * IDirectDrawSurface7::GetCaps
1230 * Returns the surface's caps
1233 * Caps: Address to write the caps to
1237 * DDERR_INVALIDPARAMS if Caps is NULL
1239 *****************************************************************************/
1240 static HRESULT WINAPI ddraw_surface7_GetCaps(IDirectDrawSurface7 *iface, DDSCAPS2 *Caps)
1242 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1243 TRACE("(%p)->(%p)\n",This,Caps);
1246 return DDERR_INVALIDPARAMS;
1248 *Caps = This->surface_desc.ddsCaps;
1252 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps)
1257 TRACE("iface %p, caps %p.\n", iface, caps);
1259 hr = ddraw_surface7_GetCaps((IDirectDrawSurface7 *)surface_from_surface3(iface), &caps2);
1260 if (FAILED(hr)) return hr;
1262 caps->dwCaps = caps2.dwCaps;
1266 /*****************************************************************************
1267 * IDirectDrawSurface7::SetPriority
1269 * Sets a texture priority for managed textures.
1272 * Priority: The new priority
1276 * For more details, see IWineD3DSurface::SetPriority
1278 *****************************************************************************/
1279 static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD Priority)
1281 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1283 TRACE("(%p)->(%d): Relay!\n",This,Priority);
1285 EnterCriticalSection(&ddraw_cs);
1286 hr = IWineD3DSurface_SetPriority(This->WineD3DSurface, Priority);
1287 LeaveCriticalSection(&ddraw_cs);
1291 /*****************************************************************************
1292 * IDirectDrawSurface7::GetPriority
1294 * Returns the surface's priority
1297 * Priority: Address of a variable to write the priority to
1301 * DDERR_INVALIDPARAMS if Priority == NULL
1302 * For more details, see IWineD3DSurface::GetPriority
1304 *****************************************************************************/
1305 static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *Priority)
1307 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1308 TRACE("(%p)->(%p): Relay\n",This,Priority);
1312 return DDERR_INVALIDPARAMS;
1315 EnterCriticalSection(&ddraw_cs);
1316 *Priority = IWineD3DSurface_GetPriority(This->WineD3DSurface);
1317 LeaveCriticalSection(&ddraw_cs);
1321 /*****************************************************************************
1322 * IDirectDrawSurface7::SetPrivateData
1324 * Stores some data in the surface that is intended for the application's
1328 * tag: GUID that identifies the data
1329 * Data: Pointer to the private data
1330 * Size: Size of the private data
1335 * For more details, see IWineD3DSurface::SetPrivateData
1337 *****************************************************************************/
1338 static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface,
1339 REFGUID tag, void *Data, DWORD Size, DWORD Flags)
1341 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1343 TRACE("(%p)->(%s,%p,%d,%x): Relay\n", This, debugstr_guid(tag), Data, Size, Flags);
1345 EnterCriticalSection(&ddraw_cs);
1346 hr = IWineD3DSurface_SetPrivateData(This->WineD3DSurface,
1351 LeaveCriticalSection(&ddraw_cs);
1354 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS;
1359 /*****************************************************************************
1360 * IDirectDrawSurface7::GetPrivateData
1362 * Returns the private data set with IDirectDrawSurface7::SetPrivateData
1365 * tag: GUID of the data to return
1366 * Data: Address where to write the data to
1367 * Size: Size of the buffer at Data
1371 * DDERR_INVALIDPARAMS if Data is NULL
1372 * For more details, see IWineD3DSurface::GetPrivateData
1374 *****************************************************************************/
1375 static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *Data, DWORD *Size)
1377 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1379 TRACE("(%p)->(%s,%p,%p): Relay\n", This, debugstr_guid(tag), Data, Size);
1382 return DDERR_INVALIDPARAMS;
1384 EnterCriticalSection(&ddraw_cs);
1385 hr = IWineD3DSurface_GetPrivateData(This->WineD3DSurface,
1389 LeaveCriticalSection(&ddraw_cs);
1393 /*****************************************************************************
1394 * IDirectDrawSurface7::FreePrivateData
1396 * Frees private data stored in the surface
1399 * tag: Tag of the data to free
1403 * For more details, see IWineD3DSurface::FreePrivateData
1405 *****************************************************************************/
1406 static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag)
1408 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1410 TRACE("(%p)->(%s): Relay\n", This, debugstr_guid(tag));
1412 EnterCriticalSection(&ddraw_cs);
1413 hr = IWineD3DSurface_FreePrivateData(This->WineD3DSurface, tag);
1414 LeaveCriticalSection(&ddraw_cs);
1418 /*****************************************************************************
1419 * IDirectDrawSurface7::PageLock
1421 * Prevents a sysmem surface from being paged out
1424 * Flags: Not used, must be 0(unchecked)
1427 * DD_OK, because it's a stub
1429 *****************************************************************************/
1430 static HRESULT WINAPI ddraw_surface7_PageLock(IDirectDrawSurface7 *iface, DWORD Flags)
1432 TRACE("(%p)->(%x)\n", iface, Flags);
1434 /* This is Windows memory management related - we don't need this */
1438 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags)
1440 TRACE("iface %p, flags %#x.\n", iface, flags);
1442 return ddraw_surface7_PageLock((IDirectDrawSurface7 *)surface_from_surface3(iface), flags);
1445 /*****************************************************************************
1446 * IDirectDrawSurface7::PageUnlock
1448 * Allows a sysmem surface to be paged out
1451 * Flags: Not used, must be 0(unchecked)
1454 * DD_OK, because it's a stub
1456 *****************************************************************************/
1457 static HRESULT WINAPI ddraw_surface7_PageUnlock(IDirectDrawSurface7 *iface, DWORD Flags)
1459 TRACE("(%p)->(%x)\n", iface, Flags);
1464 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags)
1466 TRACE("iface %p, flags %#x.\n", iface, flags);
1468 return ddraw_surface7_PageUnlock((IDirectDrawSurface7 *)surface_from_surface3(iface), flags);
1471 /*****************************************************************************
1472 * IDirectDrawSurface7::BltBatch
1474 * An unimplemented function
1482 *****************************************************************************/
1483 static HRESULT WINAPI ddraw_surface7_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
1485 TRACE("(%p)->(%p,%d,%08x)\n",iface,Batch,Count,Flags);
1487 /* MSDN: "not currently implemented" */
1488 return DDERR_UNSUPPORTED;
1491 static HRESULT WINAPI ddraw_surface3_BltBatch(IDirectDrawSurface3 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
1493 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
1495 return ddraw_surface7_BltBatch((IDirectDrawSurface7 *)surface_from_surface3(iface), batch, count, flags);
1498 /*****************************************************************************
1499 * IDirectDrawSurface7::EnumAttachedSurfaces
1501 * Enumerates all surfaces attached to this surface
1504 * context: Pointer to pass unmodified to the callback
1505 * cb: Callback function to call for each surface
1509 * DDERR_INVALIDPARAMS if cb is NULL
1511 *****************************************************************************/
1512 static HRESULT WINAPI ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7 *iface,
1513 void *context, LPDDENUMSURFACESCALLBACK7 cb)
1515 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1516 IDirectDrawSurfaceImpl *surf;
1517 DDSURFACEDESC2 desc;
1520 /* Attached surfaces aren't handled in WineD3D */
1521 TRACE("(%p)->(%p,%p)\n",This,context,cb);
1524 return DDERR_INVALIDPARAMS;
1526 EnterCriticalSection(&ddraw_cs);
1527 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
1529 surf = This->complex_array[i];
1532 ddraw_surface7_AddRef((IDirectDrawSurface7 *)surf);
1533 desc = surf->surface_desc;
1534 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
1535 if (cb((IDirectDrawSurface7 *)surf, &desc, context) == DDENUMRET_CANCEL)
1537 LeaveCriticalSection(&ddraw_cs);
1542 for (surf = This->next_attached; surf != NULL; surf = surf->next_attached)
1544 ddraw_surface7_AddRef((IDirectDrawSurface7 *)surf);
1545 desc = surf->surface_desc;
1546 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
1547 if (cb((IDirectDrawSurface7 *)surf, &desc, context) == DDENUMRET_CANCEL)
1549 LeaveCriticalSection(&ddraw_cs);
1554 TRACE(" end of enumeration.\n");
1556 LeaveCriticalSection(&ddraw_cs);
1560 struct callback_info
1562 LPDDENUMSURFACESCALLBACK callback;
1566 static HRESULT CALLBACK EnumCallback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
1568 const struct callback_info *info = context;
1570 return info->callback((IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface)->IDirectDrawSurface3_vtbl,
1571 (DDSURFACEDESC *)surface_desc, info->context);
1574 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
1575 void *context, LPDDENUMSURFACESCALLBACK callback)
1577 struct callback_info info;
1579 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
1581 info.callback = callback;
1582 info.context = context;
1584 return ddraw_surface7_EnumAttachedSurfaces((IDirectDrawSurface7 *)surface_from_surface3(iface),
1585 &info, EnumCallback);
1588 /*****************************************************************************
1589 * IDirectDrawSurface7::EnumOverlayZOrders
1591 * "Enumerates the overlay surfaces on the specified destination"
1594 * Flags: DDENUMOVERLAYZ_BACKTOFRONT or DDENUMOVERLAYZ_FRONTTOBACK
1595 * context: context to pass back to the callback
1596 * cb: callback function to call for each enumerated surface
1599 * DD_OK, because it's a stub
1601 *****************************************************************************/
1602 static HRESULT WINAPI ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7 *iface,
1603 DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK7 cb)
1605 FIXME("(%p)->(%x,%p,%p): Stub!\n", iface, Flags, context, cb);
1610 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
1611 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
1613 struct callback_info info;
1615 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
1617 info.callback = callback;
1618 info.context = context;
1620 return ddraw_surface7_EnumOverlayZOrders((IDirectDrawSurface7 *)surface_from_surface3(iface),
1621 flags, &info, EnumCallback);
1624 /*****************************************************************************
1625 * IDirectDrawSurface7::GetBltStatus
1627 * Returns the blitting status
1630 * Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
1633 * See IWineD3DSurface::Blt
1635 *****************************************************************************/
1636 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags)
1638 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1640 TRACE("(%p)->(%x): Relay\n", This, Flags);
1642 EnterCriticalSection(&ddraw_cs);
1643 hr = IWineD3DSurface_GetBltStatus(This->WineD3DSurface, Flags);
1644 LeaveCriticalSection(&ddraw_cs);
1647 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS;
1652 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags)
1654 TRACE("iface %p, flags %#x.\n", iface, flags);
1656 return ddraw_surface7_GetBltStatus((IDirectDrawSurface7 *)surface_from_surface3(iface), flags);
1659 /*****************************************************************************
1660 * IDirectDrawSurface7::GetColorKey
1662 * Returns the color key assigned to the surface
1666 * CKey: Address to store the key to
1670 * DDERR_INVALIDPARAMS if CKey is NULL
1672 *****************************************************************************/
1673 static HRESULT WINAPI ddraw_surface7_GetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
1675 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1676 TRACE("(%p)->(%08x,%p)\n", This, Flags, CKey);
1679 return DDERR_INVALIDPARAMS;
1681 EnterCriticalSection(&ddraw_cs);
1685 case DDCKEY_DESTBLT:
1686 if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT))
1688 LeaveCriticalSection(&ddraw_cs);
1689 return DDERR_NOCOLORKEY;
1691 *CKey = This->surface_desc.ddckCKDestBlt;
1694 case DDCKEY_DESTOVERLAY:
1695 if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY))
1697 LeaveCriticalSection(&ddraw_cs);
1698 return DDERR_NOCOLORKEY;
1700 *CKey = This->surface_desc.u3.ddckCKDestOverlay;
1704 if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT))
1706 LeaveCriticalSection(&ddraw_cs);
1707 return DDERR_NOCOLORKEY;
1709 *CKey = This->surface_desc.ddckCKSrcBlt;
1712 case DDCKEY_SRCOVERLAY:
1713 if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY))
1715 LeaveCriticalSection(&ddraw_cs);
1716 return DDERR_NOCOLORKEY;
1718 *CKey = This->surface_desc.ddckCKSrcOverlay;
1722 LeaveCriticalSection(&ddraw_cs);
1723 return DDERR_INVALIDPARAMS;
1726 LeaveCriticalSection(&ddraw_cs);
1730 static HRESULT WINAPI ddraw_surface3_GetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
1732 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
1734 return ddraw_surface7_GetColorKey((IDirectDrawSurface7 *)surface_from_surface3(iface), flags, color_key);
1737 /*****************************************************************************
1738 * IDirectDrawSurface7::GetFlipStatus
1740 * Returns the flipping status of the surface
1743 * Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
1746 * See IWineD3DSurface::GetFlipStatus
1748 *****************************************************************************/
1749 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags)
1751 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1753 TRACE("(%p)->(%x): Relay\n", This, Flags);
1755 EnterCriticalSection(&ddraw_cs);
1756 hr = IWineD3DSurface_GetFlipStatus(This->WineD3DSurface, Flags);
1757 LeaveCriticalSection(&ddraw_cs);
1760 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS;
1765 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags)
1767 TRACE("iface %p, flags %#x.\n", iface, flags);
1769 return ddraw_surface7_GetFlipStatus((IDirectDrawSurface7 *)surface_from_surface3(iface), flags);
1772 /*****************************************************************************
1773 * IDirectDrawSurface7::GetOverlayPosition
1775 * Returns the display coordinates of a visible and active overlay surface
1782 * DDERR_NOTAOVERLAYSURFACE, because it's a stub
1783 *****************************************************************************/
1784 static HRESULT WINAPI ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7 *iface, LONG *X, LONG *Y)
1786 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1788 TRACE("(%p)->(%p,%p): Relay\n", This, X, Y);
1790 EnterCriticalSection(&ddraw_cs);
1791 hr = IWineD3DSurface_GetOverlayPosition(This->WineD3DSurface,
1794 LeaveCriticalSection(&ddraw_cs);
1798 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y)
1800 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
1802 return ddraw_surface7_GetOverlayPosition((IDirectDrawSurface7 *)surface_from_surface3(iface), x, y);
1805 /*****************************************************************************
1806 * IDirectDrawSurface7::GetPixelFormat
1808 * Returns the pixel format of the Surface
1811 * PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
1812 * format should be written
1816 * DDERR_INVALIDPARAMS if PixelFormat is NULL
1818 *****************************************************************************/
1819 static HRESULT WINAPI ddraw_surface7_GetPixelFormat(IDirectDrawSurface7 *iface, DDPIXELFORMAT *PixelFormat)
1821 /* What is DDERR_INVALIDSURFACETYPE for here? */
1822 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1823 TRACE("(%p)->(%p)\n",This,PixelFormat);
1826 return DDERR_INVALIDPARAMS;
1828 EnterCriticalSection(&ddraw_cs);
1829 DD_STRUCT_COPY_BYSIZE(PixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
1830 LeaveCriticalSection(&ddraw_cs);
1835 static HRESULT WINAPI ddraw_surface3_GetPixelFormat(IDirectDrawSurface3 *iface, DDPIXELFORMAT *pixel_format)
1837 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
1839 return ddraw_surface7_GetPixelFormat((IDirectDrawSurface7 *)surface_from_surface3(iface), pixel_format);
1842 /*****************************************************************************
1843 * IDirectDrawSurface7::GetSurfaceDesc
1845 * Returns the description of this surface
1848 * DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
1853 * DDERR_INVALIDPARAMS if DDSD is NULL
1855 *****************************************************************************/
1856 static HRESULT WINAPI ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD)
1858 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1860 TRACE("(%p)->(%p)\n",This,DDSD);
1863 return DDERR_INVALIDPARAMS;
1865 if (DDSD->dwSize != sizeof(DDSURFACEDESC2))
1867 WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize);
1868 return DDERR_INVALIDPARAMS;
1871 EnterCriticalSection(&ddraw_cs);
1872 DD_STRUCT_COPY_BYSIZE(DDSD,&This->surface_desc);
1873 TRACE("Returning surface desc:\n");
1874 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
1876 LeaveCriticalSection(&ddraw_cs);
1880 static HRESULT WINAPI ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3 *iface, DDSURFACEDESC *surface_desc)
1882 IDirectDrawSurfaceImpl *surface = surface_from_surface3(iface);
1884 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1886 if (!surface_desc) return DDERR_INVALIDPARAMS;
1888 if (surface_desc->dwSize != sizeof(DDSURFACEDESC))
1890 WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc->dwSize);
1891 return DDERR_INVALIDPARAMS;
1894 EnterCriticalSection(&ddraw_cs);
1895 DD_STRUCT_COPY_BYSIZE(surface_desc, (DDSURFACEDESC *)&surface->surface_desc);
1896 TRACE("Returning surface desc:\n");
1897 if (TRACE_ON(ddraw))
1899 /* DDRAW_dump_surface_desc handles the smaller size */
1900 DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
1903 LeaveCriticalSection(&ddraw_cs);
1907 /*****************************************************************************
1908 * IDirectDrawSurface7::Initialize
1910 * Initializes the surface. This is a no-op in Wine
1913 * DD: Pointer to an DirectDraw interface
1914 * DDSD: Surface description for initialization
1917 * DDERR_ALREADYINITIALIZED
1919 *****************************************************************************/
1920 static HRESULT WINAPI ddraw_surface7_Initialize(IDirectDrawSurface7 *iface,
1921 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
1923 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
1925 return DDERR_ALREADYINITIALIZED;
1928 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface,
1929 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
1931 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
1933 return ddraw_surface7_Initialize((IDirectDrawSurface7 *)surface_from_surface3(iface),
1934 ddraw, (DDSURFACEDESC2 *)surface_desc);
1937 /*****************************************************************************
1938 * IDirectDrawSurface7::IsLost
1940 * Checks if the surface is lost
1943 * DD_OK, if the surface is usable
1944 * DDERR_ISLOST if the surface is lost
1945 * See IWineD3DSurface::IsLost for more details
1947 *****************************************************************************/
1948 static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface)
1950 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1952 TRACE("(%p)\n", This);
1954 EnterCriticalSection(&ddraw_cs);
1955 /* We lose the surface if the implementation was changed */
1956 if(This->ImplType != This->ddraw->ImplType)
1958 /* But this shouldn't happen. When we change the implementation,
1959 * all surfaces are re-created automatically, and their content
1962 ERR(" (%p) Implementation was changed from %d to %d\n", This, This->ImplType, This->ddraw->ImplType);
1963 LeaveCriticalSection(&ddraw_cs);
1964 return DDERR_SURFACELOST;
1967 hr = IWineD3DSurface_IsLost(This->WineD3DSurface);
1968 LeaveCriticalSection(&ddraw_cs);
1971 /* D3D8 and 9 loose full devices, thus there's only a DEVICELOST error.
1972 * WineD3D uses the same error for surfaces
1974 case WINED3DERR_DEVICELOST: return DDERR_SURFACELOST;
1979 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface)
1981 TRACE("iface %p.\n", iface);
1983 return ddraw_surface7_IsLost((IDirectDrawSurface7 *)surface_from_surface3(iface));
1986 /*****************************************************************************
1987 * IDirectDrawSurface7::Restore
1989 * Restores a lost surface. This makes the surface usable again, but
1990 * doesn't reload its old contents
1994 * See IWineD3DSurface::Restore for more details
1996 *****************************************************************************/
1997 static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface)
1999 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2001 TRACE("(%p)\n", This);
2003 EnterCriticalSection(&ddraw_cs);
2004 if(This->ImplType != This->ddraw->ImplType)
2006 /* Call the recreation callback. Make sure to AddRef first */
2007 IDirectDrawSurface_AddRef(iface);
2008 ddraw_recreate_surfaces_cb(iface, &This->surface_desc, NULL /* Not needed */);
2010 hr = IWineD3DSurface_Restore(This->WineD3DSurface);
2011 LeaveCriticalSection(&ddraw_cs);
2015 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface)
2017 TRACE("iface %p.\n", iface);
2019 return ddraw_surface7_Restore((IDirectDrawSurface7 *)surface_from_surface3(iface));
2022 /*****************************************************************************
2023 * IDirectDrawSurface7::SetOverlayPosition
2025 * Changes the display coordinates of an overlay surface
2032 * DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
2033 *****************************************************************************/
2034 static HRESULT WINAPI ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7 *iface, LONG X, LONG Y)
2036 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2038 TRACE("(%p)->(%d,%d): Relay\n", This, X, Y);
2040 EnterCriticalSection(&ddraw_cs);
2041 hr = IWineD3DSurface_SetOverlayPosition(This->WineD3DSurface,
2044 LeaveCriticalSection(&ddraw_cs);
2048 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y)
2050 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
2052 return ddraw_surface7_SetOverlayPosition((IDirectDrawSurface7 *)surface_from_surface3(iface), x, y);
2055 /*****************************************************************************
2056 * IDirectDrawSurface7::UpdateOverlay
2058 * Modifies the attributes of an overlay surface.
2061 * SrcRect: The section of the source being used for the overlay
2062 * DstSurface: Address of the surface that is overlaid
2063 * DstRect: Place of the overlay
2064 * Flags: some DDOVER_* flags
2067 * DDERR_UNSUPPORTED, because we don't support overlays
2069 *****************************************************************************/
2070 static HRESULT WINAPI ddraw_surface7_UpdateOverlay(IDirectDrawSurface7 *iface, RECT *SrcRect,
2071 IDirectDrawSurface7 *DstSurface, RECT *DstRect, DWORD Flags, DDOVERLAYFX *FX)
2073 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2074 IDirectDrawSurfaceImpl *Dst = (IDirectDrawSurfaceImpl *)DstSurface;
2076 TRACE("(%p)->(%p,%p,%p,%x,%p): Relay\n", This, SrcRect, Dst, DstRect, Flags, FX);
2078 EnterCriticalSection(&ddraw_cs);
2079 hr = IWineD3DSurface_UpdateOverlay(This->WineD3DSurface,
2081 Dst ? Dst->WineD3DSurface : NULL,
2084 (WINEDDOVERLAYFX *) FX);
2085 LeaveCriticalSection(&ddraw_cs);
2087 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS;
2088 case WINEDDERR_NOTAOVERLAYSURFACE: return DDERR_NOTAOVERLAYSURFACE;
2089 case WINEDDERR_OVERLAYNOTVISIBLE: return DDERR_OVERLAYNOTVISIBLE;
2095 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect,
2096 IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
2098 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
2099 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
2101 return ddraw_surface7_UpdateOverlay((IDirectDrawSurface7 *)surface_from_surface3(iface), src_rect,
2102 dst_surface ? (IDirectDrawSurface7 *)surface_from_surface3(dst_surface) : NULL, dst_rect, flags, fx);
2105 /*****************************************************************************
2106 * IDirectDrawSurface7::UpdateOverlayDisplay
2108 * The DX7 sdk says that it's not implemented
2113 * Returns: DDERR_UNSUPPORTED, because we don't support overlays
2115 *****************************************************************************/
2116 static HRESULT WINAPI ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7 *iface, DWORD Flags)
2118 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2119 TRACE("(%p)->(%x)\n", This, Flags);
2120 return DDERR_UNSUPPORTED;
2123 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags)
2125 TRACE("iface %p, flags %#x.\n", iface, flags);
2127 return ddraw_surface7_UpdateOverlayDisplay((IDirectDrawSurface7 *)surface_from_surface3(iface), flags);
2130 /*****************************************************************************
2131 * IDirectDrawSurface7::UpdateOverlayZOrder
2133 * Sets an overlay's Z order
2136 * Flags: DDOVERZ_* flags
2137 * DDSRef: Defines the relative position in the overlay chain
2140 * DDERR_NOTOVERLAYSURFACE, because we don't support overlays
2142 *****************************************************************************/
2143 static HRESULT WINAPI ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7 *iface,
2144 DWORD Flags, IDirectDrawSurface7 *DDSRef)
2146 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2147 IDirectDrawSurfaceImpl *Ref = (IDirectDrawSurfaceImpl *)DDSRef;
2150 TRACE("(%p)->(%x,%p): Relay\n", This, Flags, Ref);
2151 EnterCriticalSection(&ddraw_cs);
2152 hr = IWineD3DSurface_UpdateOverlayZOrder(This->WineD3DSurface,
2154 Ref ? Ref->WineD3DSurface : NULL);
2155 LeaveCriticalSection(&ddraw_cs);
2159 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
2160 DWORD flags, IDirectDrawSurface3 *reference)
2162 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
2164 return ddraw_surface7_UpdateOverlayZOrder((IDirectDrawSurface7 *)surface_from_surface3(iface), flags,
2165 reference ? (IDirectDrawSurface7 *)surface_from_surface3(reference) : NULL);
2168 /*****************************************************************************
2169 * IDirectDrawSurface7::GetDDInterface
2171 * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
2172 * surface belongs to
2175 * DD: Address to write the interface pointer to
2179 * DDERR_INVALIDPARAMS if DD is NULL
2181 *****************************************************************************/
2182 static HRESULT WINAPI ddraw_surface7_GetDDInterface(IDirectDrawSurface7 *iface, void **DD)
2184 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2186 TRACE("(%p)->(%p)\n",This,DD);
2189 return DDERR_INVALIDPARAMS;
2191 switch(This->version)
2198 *DD = &This->ddraw->IDirectDraw4_vtbl;
2202 *DD = &This->ddraw->IDirectDraw2_vtbl;
2206 *DD = &This->ddraw->IDirectDraw_vtbl;
2210 IUnknown_AddRef((IUnknown *)*DD);
2215 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw)
2217 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
2219 return ddraw_surface7_GetDDInterface((IDirectDrawSurface7 *)surface_from_surface3(iface), ddraw);
2222 /* This seems also windows implementation specific - I don't think WineD3D needs this */
2223 static HRESULT WINAPI ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7 *iface)
2225 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2226 volatile IDirectDrawSurfaceImpl* vThis = This;
2228 TRACE("(%p)\n",This);
2229 EnterCriticalSection(&ddraw_cs);
2230 /* A uniqueness value of 0 is apparently special.
2231 * This needs to be checked.
2232 * TODO: Write tests for this code and check if the volatile, interlocked stuff is really needed
2235 DWORD old_uniqueness_value = vThis->uniqueness_value;
2236 DWORD new_uniqueness_value = old_uniqueness_value+1;
2238 if (old_uniqueness_value == 0) break;
2239 if (new_uniqueness_value == 0) new_uniqueness_value = 1;
2241 if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
2242 old_uniqueness_value,
2243 new_uniqueness_value)
2244 == old_uniqueness_value)
2248 LeaveCriticalSection(&ddraw_cs);
2252 static HRESULT WINAPI ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7 *iface, DWORD *pValue)
2254 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2256 TRACE("(%p)->(%p)\n",This,pValue);
2257 EnterCriticalSection(&ddraw_cs);
2258 *pValue = This->uniqueness_value;
2259 LeaveCriticalSection(&ddraw_cs);
2263 /*****************************************************************************
2264 * IDirectDrawSurface7::SetLOD
2266 * Sets the level of detail of a texture
2269 * MaxLOD: LOD to set
2273 * DDERR_INVALIDOBJECT if the surface is invalid for this method
2275 *****************************************************************************/
2276 static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD)
2278 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2280 TRACE("(%p)->(%d)\n", This, MaxLOD);
2282 EnterCriticalSection(&ddraw_cs);
2283 if (!(This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
2285 LeaveCriticalSection(&ddraw_cs);
2286 return DDERR_INVALIDOBJECT;
2289 if(!This->wineD3DTexture)
2291 ERR("(%p) The DirectDraw texture has no WineD3DTexture!\n", This);
2292 LeaveCriticalSection(&ddraw_cs);
2293 return DDERR_INVALIDOBJECT;
2296 hr = IWineD3DBaseTexture_SetLOD(This->wineD3DTexture,
2298 LeaveCriticalSection(&ddraw_cs);
2302 /*****************************************************************************
2303 * IDirectDrawSurface7::GetLOD
2305 * Returns the level of detail of a Direct3D texture
2308 * MaxLOD: Address to write the LOD to
2312 * DDERR_INVALIDPARAMS if MaxLOD is NULL
2313 * DDERR_INVALIDOBJECT if the surface is invalid for this method
2315 *****************************************************************************/
2316 static HRESULT WINAPI ddraw_surface7_GetLOD(IDirectDrawSurface7 *iface, DWORD *MaxLOD)
2318 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2319 TRACE("(%p)->(%p)\n", This, MaxLOD);
2322 return DDERR_INVALIDPARAMS;
2324 EnterCriticalSection(&ddraw_cs);
2325 if (!(This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
2327 LeaveCriticalSection(&ddraw_cs);
2328 return DDERR_INVALIDOBJECT;
2331 *MaxLOD = IWineD3DBaseTexture_GetLOD(This->wineD3DTexture);
2332 LeaveCriticalSection(&ddraw_cs);
2336 /*****************************************************************************
2337 * IDirectDrawSurface7::BltFast
2339 * Performs a fast Blit.
2342 * dstx: The x coordinate to blit to on the destination
2343 * dsty: The y coordinate to blit to on the destination
2344 * Source: The source surface
2345 * rsrc: The source rectangle
2346 * trans: Type of transfer. Some DDBLTFAST_* flags
2350 * For more details, see IWineD3DSurface::BltFast
2352 *****************************************************************************/
2353 static HRESULT WINAPI ddraw_surface7_BltFast(IDirectDrawSurface7 *iface, DWORD dstx, DWORD dsty,
2354 IDirectDrawSurface7 *Source, RECT *rsrc, DWORD trans)
2356 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2357 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)Source;
2358 DWORD src_w, src_h, dst_w, dst_h;
2360 TRACE("(%p)->(%d,%d,%p,%p,%d): Relay\n", This, dstx, dsty, Source, rsrc, trans);
2362 dst_w = This->surface_desc.dwWidth;
2363 dst_h = This->surface_desc.dwHeight;
2365 /* Source must be != NULL, This is not checked by windows. Windows happily throws a 0xc0000005
2370 if(rsrc->top > rsrc->bottom || rsrc->left > rsrc->right ||
2371 rsrc->right > src->surface_desc.dwWidth ||
2372 rsrc->bottom > src->surface_desc.dwHeight)
2374 WARN("Source rectangle is invalid, returning DDERR_INVALIDRECT\n");
2375 return DDERR_INVALIDRECT;
2378 src_w = rsrc->right - rsrc->left;
2379 src_h = rsrc->bottom - rsrc->top;
2383 src_w = src->surface_desc.dwWidth;
2384 src_h = src->surface_desc.dwHeight;
2387 if (src_w > dst_w || dstx > dst_w - src_w
2388 || src_h > dst_h || dsty > dst_h - src_h)
2390 WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
2391 return DDERR_INVALIDRECT;
2394 EnterCriticalSection(&ddraw_cs);
2395 hr = IWineD3DSurface_BltFast(This->WineD3DSurface,
2397 src ? src->WineD3DSurface : NULL,
2400 LeaveCriticalSection(&ddraw_cs);
2403 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
2404 case WINED3DERR_WRONGTEXTUREFORMAT: return DDERR_INVALIDPIXELFORMAT;
2409 static HRESULT WINAPI ddraw_surface3_BltFast(IDirectDrawSurface3 *iface, DWORD dst_x, DWORD dst_y,
2410 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags)
2412 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
2413 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
2415 return ddraw_surface7_BltFast((IDirectDrawSurface7 *)surface_from_surface3(iface), dst_x, dst_y,
2416 src_surface ? (IDirectDrawSurface7 *)surface_from_surface3(src_surface) : NULL, src_rect, flags);
2419 /*****************************************************************************
2420 * IDirectDrawSurface7::GetClipper
2422 * Returns the IDirectDrawClipper interface of the clipper assigned to this
2426 * Clipper: Address to store the interface pointer at
2430 * DDERR_INVALIDPARAMS if Clipper is NULL
2431 * DDERR_NOCLIPPERATTACHED if there's no clipper attached
2433 *****************************************************************************/
2434 static HRESULT WINAPI ddraw_surface7_GetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper **Clipper)
2436 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2437 TRACE("(%p)->(%p)\n", This, Clipper);
2441 LeaveCriticalSection(&ddraw_cs);
2442 return DDERR_INVALIDPARAMS;
2445 EnterCriticalSection(&ddraw_cs);
2446 if(This->clipper == NULL)
2448 LeaveCriticalSection(&ddraw_cs);
2449 return DDERR_NOCLIPPERATTACHED;
2452 *Clipper = (IDirectDrawClipper *)This->clipper;
2453 IDirectDrawClipper_AddRef(*Clipper);
2454 LeaveCriticalSection(&ddraw_cs);
2458 static HRESULT WINAPI ddraw_surface3_GetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper **clipper)
2460 TRACE("iface %p, clipper %p.\n", iface, clipper);
2462 return ddraw_surface7_GetClipper((IDirectDrawSurface7 *)surface_from_surface3(iface), clipper);
2465 /*****************************************************************************
2466 * IDirectDrawSurface7::SetClipper
2468 * Sets a clipper for the surface
2471 * Clipper: IDirectDrawClipper interface of the clipper to set
2476 *****************************************************************************/
2477 static HRESULT WINAPI ddraw_surface7_SetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper *Clipper)
2479 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2480 IDirectDrawClipperImpl *oldClipper = This->clipper;
2483 TRACE("(%p)->(%p)\n",This,Clipper);
2485 EnterCriticalSection(&ddraw_cs);
2486 if ((IDirectDrawClipperImpl *)Clipper == This->clipper)
2488 LeaveCriticalSection(&ddraw_cs);
2492 This->clipper = (IDirectDrawClipperImpl *)Clipper;
2494 if (Clipper != NULL)
2495 IDirectDrawClipper_AddRef(Clipper);
2497 IDirectDrawClipper_Release((IDirectDrawClipper *)oldClipper);
2499 hr = IWineD3DSurface_SetClipper(This->WineD3DSurface, This->clipper ? This->clipper->wineD3DClipper : NULL);
2501 if(This->wineD3DSwapChain) {
2504 IDirectDrawClipper_GetHWnd(Clipper, &clipWindow);
2508 IWineD3DSwapChain_SetDestWindowOverride(This->wineD3DSwapChain,
2511 IWineD3DSwapChain_SetDestWindowOverride(This->wineD3DSwapChain,
2512 This->ddraw->d3d_window);
2516 LeaveCriticalSection(&ddraw_cs);
2520 static HRESULT WINAPI ddraw_surface3_SetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper *clipper)
2522 TRACE("iface %p, clipper %p.\n", iface, clipper);
2524 return ddraw_surface7_SetClipper((IDirectDrawSurface7 *)surface_from_surface3(iface), clipper);
2527 /*****************************************************************************
2528 * IDirectDrawSurface7::SetSurfaceDesc
2530 * Sets the surface description. It can override the pixel format, the surface
2532 * It's not really tested.
2535 * DDSD: Pointer to the new surface description to set
2540 * DDERR_INVALIDPARAMS if DDSD is NULL
2542 *****************************************************************************/
2543 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags)
2545 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2546 WINED3DFORMAT newFormat = WINED3DFMT_UNKNOWN;
2548 TRACE("(%p)->(%p,%x)\n", This, DDSD, Flags);
2551 return DDERR_INVALIDPARAMS;
2553 EnterCriticalSection(&ddraw_cs);
2554 if (DDSD->dwFlags & DDSD_PIXELFORMAT)
2556 newFormat = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat);
2558 if(newFormat == WINED3DFMT_UNKNOWN)
2560 ERR("Requested to set an unknown pixelformat\n");
2561 LeaveCriticalSection(&ddraw_cs);
2562 return DDERR_INVALIDPARAMS;
2564 if(newFormat != PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat) )
2566 hr = IWineD3DSurface_SetFormat(This->WineD3DSurface,
2570 LeaveCriticalSection(&ddraw_cs);
2575 if (DDSD->dwFlags & DDSD_CKDESTOVERLAY)
2577 IWineD3DSurface_SetColorKey(This->WineD3DSurface,
2579 (WINEDDCOLORKEY *) &DDSD->u3.ddckCKDestOverlay);
2581 if (DDSD->dwFlags & DDSD_CKDESTBLT)
2583 IWineD3DSurface_SetColorKey(This->WineD3DSurface,
2585 (WINEDDCOLORKEY *) &DDSD->ddckCKDestBlt);
2587 if (DDSD->dwFlags & DDSD_CKSRCOVERLAY)
2589 IWineD3DSurface_SetColorKey(This->WineD3DSurface,
2591 (WINEDDCOLORKEY *) &DDSD->ddckCKSrcOverlay);
2593 if (DDSD->dwFlags & DDSD_CKSRCBLT)
2595 IWineD3DSurface_SetColorKey(This->WineD3DSurface,
2597 (WINEDDCOLORKEY *) &DDSD->ddckCKSrcBlt);
2599 if (DDSD->dwFlags & DDSD_LPSURFACE && DDSD->lpSurface)
2601 hr = IWineD3DSurface_SetMem(This->WineD3DSurface, DDSD->lpSurface);
2602 if(hr != WINED3D_OK)
2604 /* No need for a trace here, wined3d does that for us */
2607 case WINED3DERR_INVALIDCALL:
2608 LeaveCriticalSection(&ddraw_cs);
2609 return DDERR_INVALIDPARAMS;
2616 This->surface_desc = *DDSD;
2618 LeaveCriticalSection(&ddraw_cs);
2622 static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface,
2623 DDSURFACEDESC *surface_desc, DWORD flags)
2625 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
2627 return ddraw_surface7_SetSurfaceDesc((IDirectDrawSurface7 *)surface_from_surface3(iface),
2628 (DDSURFACEDESC2 *)surface_desc, flags);
2631 /*****************************************************************************
2632 * IDirectDrawSurface7::GetPalette
2634 * Returns the IDirectDrawPalette interface of the palette currently assigned
2638 * Pal: Address to write the interface pointer to
2642 * DDERR_INVALIDPARAMS if Pal is NULL
2644 *****************************************************************************/
2645 static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **Pal)
2647 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2648 IWineD3DPalette *wPal;
2650 TRACE("(%p)->(%p): Relay\n", This, Pal);
2653 return DDERR_INVALIDPARAMS;
2655 EnterCriticalSection(&ddraw_cs);
2656 hr = IWineD3DSurface_GetPalette(This->WineD3DSurface, &wPal);
2659 LeaveCriticalSection(&ddraw_cs);
2665 hr = IWineD3DPalette_GetParent(wPal, (IUnknown **) Pal);
2670 hr = DDERR_NOPALETTEATTACHED;
2673 LeaveCriticalSection(&ddraw_cs);
2677 static HRESULT WINAPI ddraw_surface3_GetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette **palette)
2679 TRACE("iface %p, palette %p.\n", iface, palette);
2681 return ddraw_surface7_GetPalette((IDirectDrawSurface7 *)surface_from_surface3(iface), palette);
2684 /*****************************************************************************
2687 * EnumAttachedSurface callback for SetColorKey. Used to set color keys
2688 * recursively in the surface tree
2690 *****************************************************************************/
2694 WINEDDCOLORKEY *CKey;
2698 static HRESULT WINAPI
2699 SetColorKeyEnum(IDirectDrawSurface7 *surface,
2700 DDSURFACEDESC2 *desc,
2703 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)surface;
2704 struct SCKContext *ctx = context;
2707 hr = IWineD3DSurface_SetColorKey(This->WineD3DSurface,
2712 WARN("IWineD3DSurface_SetColorKey failed, hr = %08x\n", hr);
2716 ddraw_surface7_EnumAttachedSurfaces(surface, context, SetColorKeyEnum);
2717 ddraw_surface7_Release(surface);
2719 return DDENUMRET_OK;
2722 /*****************************************************************************
2723 * IDirectDrawSurface7::SetColorKey
2725 * Sets the color keying options for the surface. Observations showed that
2726 * in case of complex surfaces the color key has to be assigned to all
2731 * CKey: The new color key
2735 * See IWineD3DSurface::SetColorKey for details
2737 *****************************************************************************/
2738 static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
2740 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2741 DDCOLORKEY FixedCKey;
2742 struct SCKContext ctx = { DD_OK, (WINEDDCOLORKEY *) (CKey ? &FixedCKey : NULL), Flags };
2743 TRACE("(%p)->(%x,%p)\n", This, Flags, CKey);
2745 EnterCriticalSection(&ddraw_cs);
2749 /* Handle case where dwColorSpaceHighValue < dwColorSpaceLowValue */
2750 if (FixedCKey.dwColorSpaceHighValue < FixedCKey.dwColorSpaceLowValue)
2751 FixedCKey.dwColorSpaceHighValue = FixedCKey.dwColorSpaceLowValue;
2753 switch (Flags & ~DDCKEY_COLORSPACE)
2755 case DDCKEY_DESTBLT:
2756 This->surface_desc.ddckCKDestBlt = FixedCKey;
2757 This->surface_desc.dwFlags |= DDSD_CKDESTBLT;
2760 case DDCKEY_DESTOVERLAY:
2761 This->surface_desc.u3.ddckCKDestOverlay = FixedCKey;
2762 This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
2765 case DDCKEY_SRCOVERLAY:
2766 This->surface_desc.ddckCKSrcOverlay = FixedCKey;
2767 This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
2771 This->surface_desc.ddckCKSrcBlt = FixedCKey;
2772 This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
2776 LeaveCriticalSection(&ddraw_cs);
2777 return DDERR_INVALIDPARAMS;
2782 switch (Flags & ~DDCKEY_COLORSPACE)
2784 case DDCKEY_DESTBLT:
2785 This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
2788 case DDCKEY_DESTOVERLAY:
2789 This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
2792 case DDCKEY_SRCOVERLAY:
2793 This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
2797 This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
2801 LeaveCriticalSection(&ddraw_cs);
2802 return DDERR_INVALIDPARAMS;
2805 ctx.ret = IWineD3DSurface_SetColorKey(This->WineD3DSurface, Flags, ctx.CKey);
2806 ddraw_surface7_EnumAttachedSurfaces(iface, &ctx, SetColorKeyEnum);
2807 LeaveCriticalSection(&ddraw_cs);
2810 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS;
2811 default: return ctx.ret;
2815 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
2817 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
2819 return ddraw_surface7_SetColorKey((IDirectDrawSurface7 *)surface_from_surface3(iface), flags, color_key);
2822 /*****************************************************************************
2823 * IDirectDrawSurface7::SetPalette
2825 * Assigns a DirectDrawPalette object to the surface
2828 * Pal: Interface to the palette to set
2833 *****************************************************************************/
2834 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *Pal)
2836 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
2837 IDirectDrawPalette *oldPal;
2838 IDirectDrawSurfaceImpl *surf;
2839 IDirectDrawPaletteImpl *PalImpl = (IDirectDrawPaletteImpl *)Pal;
2841 TRACE("(%p)->(%p)\n", This, Pal);
2843 if (!(This->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
2844 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8))) {
2845 return DDERR_INVALIDPIXELFORMAT;
2848 /* Find the old palette */
2849 EnterCriticalSection(&ddraw_cs);
2850 hr = IDirectDrawSurface_GetPalette(iface, &oldPal);
2851 if(hr != DD_OK && hr != DDERR_NOPALETTEATTACHED)
2853 LeaveCriticalSection(&ddraw_cs);
2856 if(oldPal) IDirectDrawPalette_Release(oldPal); /* For the GetPalette */
2858 /* Set the new Palette */
2859 IWineD3DSurface_SetPalette(This->WineD3DSurface,
2860 PalImpl ? PalImpl->wineD3DPalette : NULL);
2861 /* AddRef the Palette */
2862 if(Pal) IDirectDrawPalette_AddRef(Pal);
2864 /* Release the old palette */
2865 if(oldPal) IDirectDrawPalette_Release(oldPal);
2867 /* If this is a front buffer, also update the back buffers
2868 * TODO: How do things work for palettized cube textures?
2870 if(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
2872 /* For primary surfaces the tree is just a list, so the simpler scheme fits too */
2873 DDSCAPS2 caps2 = { DDSCAPS_PRIMARYSURFACE, 0, 0, 0 };
2878 IDirectDrawSurface7 *attach;
2880 hr = ddraw_surface7_GetAttachedSurface((IDirectDrawSurface7 *)surf, &caps2, &attach);
2886 TRACE("Setting palette on %p\n", attach);
2887 ddraw_surface7_SetPalette(attach, Pal);
2888 surf = (IDirectDrawSurfaceImpl *)attach;
2889 ddraw_surface7_Release(attach);
2893 LeaveCriticalSection(&ddraw_cs);
2897 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette)
2899 TRACE("iface %p, palette %p.\n", iface, palette);
2901 return ddraw_surface7_SetPalette((IDirectDrawSurface7 *)surface_from_surface3(iface), palette);
2904 /**********************************************************
2905 * IDirectDrawGammaControl::GetGammaRamp
2907 * Returns the current gamma ramp for a surface
2911 * gamma_ramp: Address to write the ramp to
2915 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
2917 **********************************************************/
2918 static HRESULT WINAPI ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl *iface,
2919 DWORD flags, DDGAMMARAMP *gamma_ramp)
2921 IDirectDrawSurfaceImpl *surface = surface_from_gamma_control(iface);
2923 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
2927 WARN("Invalid gamma_ramp passed.\n");
2928 return DDERR_INVALIDPARAMS;
2931 EnterCriticalSection(&ddraw_cs);
2932 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2934 /* Note: DDGAMMARAMP is compatible with WINED3DGAMMARAMP. */
2935 IWineD3DDevice_GetGammaRamp(surface->ddraw->wineD3DDevice, 0, (WINED3DGAMMARAMP *)gamma_ramp);
2939 ERR("Not implemented for non-primary surfaces.\n");
2941 LeaveCriticalSection(&ddraw_cs);
2946 /**********************************************************
2947 * IDirectDrawGammaControl::SetGammaRamp
2949 * Sets the red, green and blue gamma ramps for
2952 * flags: Can be DDSGR_CALIBRATE to request calibration
2953 * gamma_ramp: Structure containing the new gamma ramp
2957 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
2959 **********************************************************/
2960 static HRESULT WINAPI ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl *iface,
2961 DWORD flags, DDGAMMARAMP *gamma_ramp)
2963 IDirectDrawSurfaceImpl *surface = surface_from_gamma_control(iface);
2965 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
2969 WARN("Invalid gamma_ramp passed.\n");
2970 return DDERR_INVALIDPARAMS;
2973 EnterCriticalSection(&ddraw_cs);
2974 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2976 /* Note: DDGAMMARAMP is compatible with WINED3DGAMMARAMP */
2977 IWineD3DDevice_SetGammaRamp(surface->ddraw->wineD3DDevice, 0, flags, (WINED3DGAMMARAMP *)gamma_ramp);
2981 ERR("Not implemented for non-primary surfaces.\n");
2983 LeaveCriticalSection(&ddraw_cs);
2988 /*****************************************************************************
2990 *****************************************************************************/
2992 const IDirectDrawSurface7Vtbl IDirectDrawSurface7_Vtbl =
2995 ddraw_surface7_QueryInterface,
2996 ddraw_surface7_AddRef,
2997 ddraw_surface7_Release,
2998 /* IDirectDrawSurface */
2999 ddraw_surface7_AddAttachedSurface,
3000 ddraw_surface7_AddOverlayDirtyRect,
3002 ddraw_surface7_BltBatch,
3003 ddraw_surface7_BltFast,
3004 ddraw_surface7_DeleteAttachedSurface,
3005 ddraw_surface7_EnumAttachedSurfaces,
3006 ddraw_surface7_EnumOverlayZOrders,
3007 ddraw_surface7_Flip,
3008 ddraw_surface7_GetAttachedSurface,
3009 ddraw_surface7_GetBltStatus,
3010 ddraw_surface7_GetCaps,
3011 ddraw_surface7_GetClipper,
3012 ddraw_surface7_GetColorKey,
3013 ddraw_surface7_GetDC,
3014 ddraw_surface7_GetFlipStatus,
3015 ddraw_surface7_GetOverlayPosition,
3016 ddraw_surface7_GetPalette,
3017 ddraw_surface7_GetPixelFormat,
3018 ddraw_surface7_GetSurfaceDesc,
3019 ddraw_surface7_Initialize,
3020 ddraw_surface7_IsLost,
3021 ddraw_surface7_Lock,
3022 ddraw_surface7_ReleaseDC,
3023 ddraw_surface7_Restore,
3024 ddraw_surface7_SetClipper,
3025 ddraw_surface7_SetColorKey,
3026 ddraw_surface7_SetOverlayPosition,
3027 ddraw_surface7_SetPalette,
3028 ddraw_surface7_Unlock,
3029 ddraw_surface7_UpdateOverlay,
3030 ddraw_surface7_UpdateOverlayDisplay,
3031 ddraw_surface7_UpdateOverlayZOrder,
3032 /* IDirectDrawSurface2 */
3033 ddraw_surface7_GetDDInterface,
3034 ddraw_surface7_PageLock,
3035 ddraw_surface7_PageUnlock,
3036 /* IDirectDrawSurface3 */
3037 ddraw_surface7_SetSurfaceDesc,
3038 /* IDirectDrawSurface4 */
3039 ddraw_surface7_SetPrivateData,
3040 ddraw_surface7_GetPrivateData,
3041 ddraw_surface7_FreePrivateData,
3042 ddraw_surface7_GetUniquenessValue,
3043 ddraw_surface7_ChangeUniquenessValue,
3044 /* IDirectDrawSurface7 */
3045 ddraw_surface7_SetPriority,
3046 ddraw_surface7_GetPriority,
3047 ddraw_surface7_SetLOD,
3048 ddraw_surface7_GetLOD,
3051 const IDirectDrawSurface3Vtbl IDirectDrawSurface3_Vtbl =
3054 ddraw_surface3_QueryInterface,
3055 ddraw_surface3_AddRef,
3056 ddraw_surface3_Release,
3057 /* IDirectDrawSurface */
3058 ddraw_surface3_AddAttachedSurface,
3059 ddraw_surface3_AddOverlayDirtyRect,
3061 ddraw_surface3_BltBatch,
3062 ddraw_surface3_BltFast,
3063 ddraw_surface3_DeleteAttachedSurface,
3064 ddraw_surface3_EnumAttachedSurfaces,
3065 ddraw_surface3_EnumOverlayZOrders,
3066 ddraw_surface3_Flip,
3067 ddraw_surface3_GetAttachedSurface,
3068 ddraw_surface3_GetBltStatus,
3069 ddraw_surface3_GetCaps,
3070 ddraw_surface3_GetClipper,
3071 ddraw_surface3_GetColorKey,
3072 ddraw_surface3_GetDC,
3073 ddraw_surface3_GetFlipStatus,
3074 ddraw_surface3_GetOverlayPosition,
3075 ddraw_surface3_GetPalette,
3076 ddraw_surface3_GetPixelFormat,
3077 ddraw_surface3_GetSurfaceDesc,
3078 ddraw_surface3_Initialize,
3079 ddraw_surface3_IsLost,
3080 ddraw_surface3_Lock,
3081 ddraw_surface3_ReleaseDC,
3082 ddraw_surface3_Restore,
3083 ddraw_surface3_SetClipper,
3084 ddraw_surface3_SetColorKey,
3085 ddraw_surface3_SetOverlayPosition,
3086 ddraw_surface3_SetPalette,
3087 ddraw_surface3_Unlock,
3088 ddraw_surface3_UpdateOverlay,
3089 ddraw_surface3_UpdateOverlayDisplay,
3090 ddraw_surface3_UpdateOverlayZOrder,
3091 /* IDirectDrawSurface2 */
3092 ddraw_surface3_GetDDInterface,
3093 ddraw_surface3_PageLock,
3094 ddraw_surface3_PageUnlock,
3095 /* IDirectDrawSurface3 */
3096 ddraw_surface3_SetSurfaceDesc,
3099 const IDirectDrawGammaControlVtbl IDirectDrawGammaControl_Vtbl =
3101 ddraw_gamma_control_QueryInterface,
3102 ddraw_gamma_control_AddRef,
3103 ddraw_gamma_control_Release,
3104 ddraw_gamma_control_GetGammaRamp,
3105 ddraw_gamma_control_SetGammaRamp,