Commit 06106e28 authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

ddraw: Support using an application-provided surface pointer.

parent aff9f4c1
......@@ -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;
}
......
......@@ -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;
......
......@@ -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,
......
......@@ -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,
......
......@@ -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]);
......
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment