ddrawex: Implement a GetDC special behavior Internet Explorer depends on.
Tests show that in ddrawex.dll it is legal to create a surface with both DDSCAPS_VIDEOMEMORY and DDSCAPS_SYSTEMMEMORY flag set. A surface created that way shows different behavior in IDirectDrawSurface::GetDC.
This commit is contained in:
parent
0d80130aa2
commit
da6c9e4cc2
|
@ -387,6 +387,8 @@ IDirectDraw4Impl_CreateSurface(IDirectDraw4 *iface,
|
|||
{
|
||||
IDirectDrawImpl *This = impl_from_dd4(iface);
|
||||
HRESULT hr;
|
||||
const DWORD perm_dc_flags = DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
|
||||
BOOL permanent_dc;
|
||||
TRACE("(%p)(%p, %p, %p)\n", This, DDSD, Surf, UnkOuter);
|
||||
|
||||
if(UnkOuter != NULL)
|
||||
|
@ -395,8 +397,25 @@ IDirectDraw4Impl_CreateSurface(IDirectDraw4 *iface,
|
|||
FIXME("Implement aggregation for ddrawex surfaces\n");
|
||||
}
|
||||
|
||||
/* plain ddraw.dll refuses to create a surface that has both VIDMEM and SYSMEM flags
|
||||
* set. In ddrawex this succeeds, and the GetDC() call changes the behavior. The DC
|
||||
* is permanently valid, and the surface can be locked between GetDC() and ReleaseDC()
|
||||
* calls. GetDC() can be called more than once too
|
||||
*/
|
||||
if((DDSD->ddsCaps.dwCaps & perm_dc_flags) == perm_dc_flags)
|
||||
{
|
||||
permanent_dc = TRUE;
|
||||
DDSD->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
|
||||
DDSD->ddsCaps.dwCaps |= DDSCAPS_OWNDC;
|
||||
}
|
||||
else
|
||||
{
|
||||
permanent_dc = FALSE;
|
||||
}
|
||||
|
||||
hr = IDirectDraw4_CreateSurface(This->parent, DDSD, Surf, UnkOuter);
|
||||
*Surf = dds_get_outer(*Surf);
|
||||
if(permanent_dc) prepare_permanent_dc(*Surf);
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
|
|
@ -100,6 +100,9 @@ typedef struct
|
|||
/* The interface we're forwarding to */
|
||||
IDirectDrawSurface4 *parent;
|
||||
|
||||
BOOL permanent_dc;
|
||||
HDC hdc;
|
||||
|
||||
/* An UUID we use to store the outer surface as private data in the inner surface */
|
||||
#define IID_DDrawexPriv IID_IDirectDrawSurface4
|
||||
|
||||
|
@ -107,5 +110,6 @@ typedef struct
|
|||
|
||||
IDirectDrawSurface4 *dds_get_outer(IDirectDrawSurface4 *inner);
|
||||
IDirectDrawSurface4 *dds_get_inner(IDirectDrawSurface4 *outer);
|
||||
HRESULT prepare_permanent_dc(IDirectDrawSurface4 *iface);
|
||||
|
||||
#endif /* __WINE_DLLS_DDRAWEX_DDRAWEX_PRIVATE_H */
|
||||
|
|
|
@ -563,7 +563,16 @@ IDirectDrawSurface4Impl_GetDC(IDirectDrawSurface4 *iface,
|
|||
{
|
||||
IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
|
||||
TRACE("(%p)->(%p)\n", This, hdc);
|
||||
return IDirectDrawSurface4_GetDC(This->parent, hdc);
|
||||
if(This->permanent_dc)
|
||||
{
|
||||
TRACE("Returning stored dc %p\n", This->hdc);
|
||||
*hdc = This->hdc;
|
||||
return DD_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return IDirectDrawSurface4_GetDC(This->parent, hdc);
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
|
@ -654,8 +663,17 @@ IDirectDrawSurface4Impl_GetSurfaceDesc(IDirectDrawSurface4 *iface,
|
|||
DDSURFACEDESC2 *DDSD)
|
||||
{
|
||||
IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
|
||||
HRESULT hr;
|
||||
TRACE("(%p)->(%p)\n", This, DDSD);
|
||||
return IDirectDrawSurface4_GetSurfaceDesc(This->parent, DDSD);
|
||||
hr = IDirectDrawSurface4_GetSurfaceDesc(This->parent, DDSD);
|
||||
|
||||
if(SUCCEEDED(hr) && This->permanent_dc)
|
||||
{
|
||||
DDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
|
||||
DDSD->ddsCaps.dwCaps &= ~DDSCAPS_OWNDC;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
|
@ -731,8 +749,17 @@ IDirectDrawSurface4Impl_Lock(IDirectDrawSurface4 *iface,
|
|||
HANDLE h)
|
||||
{
|
||||
IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
|
||||
HRESULT hr;
|
||||
TRACE("(%p)->(%p,%p,0x%08x,%p)\n", This, Rect, DDSD, Flags, h);
|
||||
return IDirectDrawSurface4_Lock(This->parent, Rect, DDSD, Flags, h);
|
||||
hr = IDirectDrawSurface4_Lock(This->parent, Rect, DDSD, Flags, h);
|
||||
|
||||
if(SUCCEEDED(hr) && This->permanent_dc)
|
||||
{
|
||||
DDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
|
||||
DDSD->ddsCaps.dwCaps &= ~DDSCAPS_OWNDC;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
|
@ -759,7 +786,15 @@ IDirectDrawSurface4Impl_ReleaseDC(IDirectDrawSurface4 *iface,
|
|||
{
|
||||
IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
|
||||
TRACE("(%p)->(%p)\n", This, hdc);
|
||||
return IDirectDrawSurface4_ReleaseDC(This->parent, hdc);
|
||||
if(This->permanent_dc)
|
||||
{
|
||||
TRACE("Surface has a permanent DC, not doing anything\n");
|
||||
return DD_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return IDirectDrawSurface4_ReleaseDC(This->parent, hdc);
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
|
@ -1259,3 +1294,15 @@ IDirectDrawSurface4 *dds_get_inner(IDirectDrawSurface4 *outer)
|
|||
if(This == NULL) return NULL;
|
||||
return This->parent;
|
||||
}
|
||||
|
||||
HRESULT prepare_permanent_dc(IDirectDrawSurface4 *iface)
|
||||
{
|
||||
IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
|
||||
HRESULT hr;
|
||||
This->permanent_dc = TRUE;
|
||||
|
||||
hr = IDirectDrawSurface4_GetDC(This->parent, &This->hdc);
|
||||
if(FAILED(hr)) return hr;
|
||||
hr = IDirectDrawSurface4_ReleaseDC(This->parent, This->hdc);
|
||||
return hr;
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ static void CapsTest(void)
|
|||
ddsd.dwWidth = 64;
|
||||
ddsd.dwHeight = 64;
|
||||
hr = IDirectDraw_CreateSurface(dd1, &ddsd, &surf, NULL);
|
||||
todo_wine ok(hr == DD_OK, "Creating a SYSMEM | VIDMEM surface returned 0x%08x, expected DD_OK\n", hr);
|
||||
ok(hr == DD_OK, "Creating a SYSMEM | VIDMEM surface returned 0x%08x, expected DD_OK\n", hr);
|
||||
if(surf) IDirectDrawSurface_Release(surf);
|
||||
|
||||
IDirectDraw_Release(dd1);
|
||||
|
|
Loading…
Reference in New Issue