From 06106e2810d110b9137f30d61bbed0917cde39fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Tue, 25 Jul 2006 16:38:02 +0200 Subject: [PATCH] ddraw: Support using an application-provided surface pointer. --- dlls/ddraw/ddraw.c | 17 ++++++----- dlls/ddraw/surface.c | 9 ++++++ dlls/wined3d/surface.c | 50 ++++++++++++++++++++++++++++++++ dlls/wined3d/surface_gdi.c | 13 +++++++++ dlls/wined3d/wined3d_private.h | 6 ++-- include/wine/wined3d_interface.h | 2 ++ 6 files changed, 88 insertions(+), 9 deletions(-) diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index bd13d563f57..44fe5a09687 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -1790,13 +1790,6 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, } } - /* Get the surface parameters */ - if ( pDDSD->dwFlags & DDSD_LPSURFACE) - { - ERR("(%p) Using a passed surface pointer is not yet supported\n", This); - assert(0); - } - /* Get the correct wined3d usage */ if (pDDSD->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER | @@ -1995,6 +1988,16 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, DDCKEY_SRCBLT, &pDDSD->ddckCKSrcBlt); } + if ( pDDSD->dwFlags & DDSD_LPSURFACE) + { + hr = IWineD3DSurface_SetMem((*ppSurf)->WineD3DSurface, pDDSD->lpSurface); + if(hr != WINED3D_OK) + { + /* No need for a trace here, wined3d does that for us */ + IDirectDrawSurface7_Release(ICOM_INTERFACE((*ppSurf), IDirectDrawSurface7)); + return hr; + } + } return DD_OK; } diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index a9086d2f4fc..587a3e9339c 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -1933,6 +1933,15 @@ IDirectDrawSurfaceImpl_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDCKEY_SRCBLT, &DDSD->ddckCKSrcBlt); } + if (DDSD->dwFlags & DDSD_LPSURFACE) + { + hr = IWineD3DSurface_SetMem(This->WineD3DSurface, DDSD->lpSurface); + if(hr != WINED3D_OK) + { + /* No need for a trace here, wined3d does that for us */ + return hr; + } + } This->surface_desc = *DDSD; diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 9c2ed607eaf..df35fc65972 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -102,6 +102,7 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) { This->dib.bitmap_data = NULL; This->resource.allocatedMemory = NULL; } + IWineD3DSurface_SetMem(iface, NULL); IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface); if(iface == device->ddraw_primary) @@ -1161,6 +1162,11 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) { TRACE("(%p)->(%p)\n",This,pHDC); + if(This->Flags & SFLAG_USERPTR) { + ERR("Not supported on surfaces with an application-provided surfaces\n"); + return DDERR_NODC; + } + /* Give more detailed info for ddraw */ if (This->Flags & SFLAG_DCINUSE) return DDERR_DCALREADYCREATED; @@ -2104,6 +2110,49 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORM return WINED3D_OK; } +HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) { + IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + + /* Render targets depend on their hdc, and we can't create a hdc on a user pointer */ + if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) { + ERR("Not supported on render targets\n"); + return WINED3DERR_INVALIDCALL; + } + + if(This->Flags & (SFLAG_LOCKED | SFLAG_DCINUSE)) { + WARN("Surface is locked or the HDC is in use\n"); + return WINED3DERR_INVALIDCALL; + } + + if(Mem && Mem != This->resource.allocatedMemory) { + + /* Do I have to copy the old surface content? */ + if(This->Flags & SFLAG_DIBSECTION) { + /* Release the DC. No need to hold the critical section for the update + * Thread because this thread runs only on front buffers, but this method + * fails for render targets in the check above. + */ + SelectObject(This->hDC, This->dib.holdbitmap); + DeleteDC(This->hDC); + /* Release the DIB section */ + DeleteObject(This->dib.DIBsection); + This->dib.bitmap_data = NULL; + This->resource.allocatedMemory = NULL; + This->hDC = NULL; + This->Flags &= ~SFLAG_DIBSECTION; + } else if(!(This->Flags & SFLAG_USERPTR)) { + HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory); + } + This->resource.allocatedMemory = Mem; + This->Flags |= SFLAG_USERPTR; + } else if(This->Flags & SFLAG_USERPTR) { + /* Lockrect and GetDC will re-create the dib section and allocated memory */ + This->resource.allocatedMemory = NULL; + This->Flags &= ~SFLAG_USERPTR; + } + return WINED3D_OK; +} + /* TODO: replace this function with context management routines */ HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL inTexture) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; @@ -2975,6 +3024,7 @@ const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl = IWineD3DSurfaceImpl_RealizePalette, IWineD3DSurfaceImpl_SetColorKey, IWineD3DSurfaceImpl_GetPitch, + IWineD3DSurfaceImpl_SetMem, /* Internal use: */ IWineD3DSurfaceImpl_CleanDirtyRect, IWineD3DSurfaceImpl_AddDirtyRect, diff --git a/dlls/wined3d/surface_gdi.c b/dlls/wined3d/surface_gdi.c index bb07afa07ea..9609ebd8e36 100644 --- a/dlls/wined3d/surface_gdi.c +++ b/dlls/wined3d/surface_gdi.c @@ -178,6 +178,18 @@ IWineGDISurfaceImpl_LockRect(IWineD3DSurface *iface, TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory); + if(!This->resource.allocatedMemory) { + HDC hdc; + HRESULT hr; + /* This happens on gdi surfaces if the application set a user pointer and resets it. + * Recreate the DIB section + */ + hr = IWineD3DSurface_GetDC(iface, &hdc); /* will recursively call lockrect, do not set the LOCKED flag to this line */ + if(hr != WINED3D_OK) return hr; + hr = IWineD3DSurface_ReleaseDC(iface, hdc); + if(hr != WINED3D_OK) return hr; + } + pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface); if (NULL == pRect) @@ -1570,6 +1582,7 @@ const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl = IWineD3DSurfaceImpl_RealizePalette, IWineD3DSurfaceImpl_SetColorKey, IWineD3DSurfaceImpl_GetPitch, + IWineD3DSurfaceImpl_SetMem, /* Internal use: */ IWineD3DSurfaceImpl_CleanDirtyRect, IWineD3DSurfaceImpl_AddDirtyRect, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 1f51e3b19ad..d0fb485bb9c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -929,6 +929,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC); HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC); DWORD WINAPI IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface *iface); HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface); +HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem); /* Surface flags: */ #define SFLAG_OVERSIZE 0x00000001 /* Surface is bigger than gl size, blts only */ @@ -948,7 +949,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface); #define SFLAG_GLDIRTY 0x00004000 /* The opengl texture is more up to date than the surface mem */ #define SFLAG_LOST 0x00008000 /* Surface lost flag for DDraw */ #define SFLAG_FORCELOAD 0x00010000 /* To force PreLoading of a scratch cursor */ - +#define SFLAG_USERPTR 0x00020000 /* The application allocated the memory for this surface */ /* In some conditions the surface memory must not be freed: * SFLAG_OVERSIZE: Not all data can be kept in GL @@ -967,7 +968,8 @@ HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface); SFLAG_LOCKED | \ SFLAG_ACTIVELOCK | \ SFLAG_DYNLOCK | \ - SFLAG_DYNCHANGE ) + SFLAG_DYNCHANGE | \ + SFLAG_USERPTR) BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4]); diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h index 1c971144ee7..2104aaa2b52 100644 --- a/include/wine/wined3d_interface.h +++ b/include/wine/wined3d_interface.h @@ -1130,6 +1130,7 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWineD3DResource) STDMETHOD(RealizePalette)(THIS) PURE; STDMETHOD(SetColorKey)(THIS_ DWORD Flags, DDCOLORKEY *CKey) PURE; STDMETHOD_(DWORD,GetPitch)(THIS) PURE; + STDMETHOD(SetMem)(THIS_ void *mem) PURE; /* Internally used methods */ STDMETHOD(CleanDirtyRect)(THIS) PURE; STDMETHOD(AddDirtyRect)(THIS_ CONST RECT* pRect) PURE; @@ -1181,6 +1182,7 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWineD3DResource) #define IWineD3DSurface_RealizePalette(p) (p)->lpVtbl->RealizePalette(p) #define IWineD3DSurface_SetColorKey(p, a, b) (p)->lpVtbl->SetColorKey(p, a, b) #define IWineD3DSurface_GetPitch(p) (p)->lpVtbl->GetPitch(p) +#define IWineD3DSurface_SetMem(p, a) (p)->lpVtbl->SetMem(p, a) /*** IWineD3DSurface (Internal, no d3d mapping) methods ***/ #define IWineD3DSurface_CleanDirtyRect(p) (p)->lpVtbl->CleanDirtyRect(p) #define IWineD3DSurface_AddDirtyRect(p,a) (p)->lpVtbl->AddDirtyRect(p,a)