[PATCH] DDrawex: Implement a GetDC special Internet Explorer =

Stefan Doesinger stefan at codeweavers.com
Thu Dec 18 16:13:06 CST 2008


depends on=0A=
=0A=
Tests that will follow this patch show that in ddrawex.dll it is legal =
to create a surface with both DDSCAPS_VIDEOMEMORY and=0A=
DDSCAPS_SYSTEMMEMORY flag set. A surface created that way shows =
different behavior in IDirectDrawSurface::GetDC. It is valid to call any=0A=
number of nested GetDC calls, and a DC is still valid after ReleaseDC. =
Furthermore it is possible to lock the surface while a DC is=0A=
active.=0A=
=0A=
This suggests that the surface behaves like a DIB section. In fact =
SYSTEMMEMORY surfaces are at least in our ddraw code just DIB=0A=
sections, so this sort of code is valid at least for offscreen surfaces. =
Obviously it would break 3D rendering with those surfaces, but=0A=
ddrawex doesn't support 3D rendering at all as far as I can see. (It is =
a special ddraw library that is used by Internet Explorer and=0A=
plugins)=0A=
=0A=
What real bug does that fix? Transparent PNG emulation with =
dxdrans.dll's AlphaImageLoader in IE 6.=0A=
---=0A=
 dlls/ddrawex/ddraw.c           |   19 ++++++++++++++=0A=
 dlls/ddrawex/ddrawex_private.h |    4 +++=0A=
 dlls/ddrawex/surface.c         |   55 =
+++++++++++++++++++++++++++++++++++++---=0A=
 dlls/ddrawex/tests/surface.c   |    2 +-=0A=
 4 files changed, 75 insertions(+), 5 deletions(-)=0A=
=0A=
diff --git a/dlls/ddrawex/ddraw.c b/dlls/ddrawex/ddraw.c=0A=
index 9645a3d..9e8066a 100644=0A=
--- a/dlls/ddrawex/ddraw.c=0A=
+++ b/dlls/ddrawex/ddraw.c=0A=
@@ -387,6 +387,8 @@ IDirectDraw4Impl_CreateSurface(IDirectDraw4 *iface,=0A=
 {=0A=
     IDirectDrawImpl *This =3D impl_from_dd4(iface);=0A=
     HRESULT hr;=0A=
+    const DWORD perm_dc_flags =3D DDSCAPS_VIDEOMEMORY | =
DDSCAPS_SYSTEMMEMORY;=0A=
+    BOOL permanent_dc;=0A=
     TRACE("(%p)(%p, %p, %p)\n", This, DDSD, Surf, UnkOuter);=0A=
 =0A=
     if(UnkOuter !=3D NULL)=0A=
@@ -395,8 +397,25 @@ IDirectDraw4Impl_CreateSurface(IDirectDraw4 *iface,=0A=
         FIXME("Implement aggregation for ddrawex surfaces\n");=0A=
     }=0A=
 =0A=
+    /* plain ddraw.dll refuses to create a surface that has both VIDMEM =
and SYSMEM flags=0A=
+     * set. In ddrawex this succeeds, and the GetDC() call changes the =
behavior. The DC=0A=
+     * is permanently valid, and the surface can be locked between =
GetDC() and ReleaseDC()=0A=
+     * calls. GetDC() can be called more than once too=0A=
+     */=0A=
+    if((DDSD->ddsCaps.dwCaps & perm_dc_flags) =3D=3D perm_dc_flags)=0A=
+    {=0A=
+        permanent_dc =3D TRUE;=0A=
+        DDSD->ddsCaps.dwCaps &=3D ~DDSCAPS_VIDEOMEMORY;=0A=
+        DDSD->ddsCaps.dwCaps |=3D DDSCAPS_OWNDC;=0A=
+    }=0A=
+    else=0A=
+    {=0A=
+        permanent_dc =3D FALSE;=0A=
+    }=0A=
+=0A=
     hr =3D IDirectDraw4_CreateSurface(This->parent, DDSD, Surf, =
UnkOuter);=0A=
     *Surf =3D dds_get_outer(*Surf);=0A=
+    if(permanent_dc) prepare_permanent_dc(*Surf);=0A=
     return hr;=0A=
 }=0A=
 =0A=
diff --git a/dlls/ddrawex/ddrawex_private.h =
b/dlls/ddrawex/ddrawex_private.h=0A=
index ea8956f..3e2dfaa 100644=0A=
--- a/dlls/ddrawex/ddrawex_private.h=0A=
+++ b/dlls/ddrawex/ddrawex_private.h=0A=
@@ -100,6 +100,9 @@ typedef struct=0A=
     /* The interface we're forwarding to */=0A=
     IDirectDrawSurface4 *parent;=0A=
 =0A=
+    BOOL permanent_dc;=0A=
+    HDC hdc;=0A=
+=0A=
     /* An UUID we use to store the outer surface as private data in the =
inner surface */=0A=
     #define IID_DDrawexPriv IID_IDirectDrawSurface4=0A=
 =0A=
@@ -107,5 +110,6 @@ typedef struct=0A=
 =0A=
 IDirectDrawSurface4 *dds_get_outer(IDirectDrawSurface4 *inner);=0A=
 IDirectDrawSurface4 *dds_get_inner(IDirectDrawSurface4 *outer);=0A=
+HRESULT prepare_permanent_dc(IDirectDrawSurface4 *iface);=0A=
 =0A=
 #endif /* __WINE_DLLS_DDRAWEX_DDRAWEX_PRIVATE_H */=0A=
diff --git a/dlls/ddrawex/surface.c b/dlls/ddrawex/surface.c=0A=
index 9b16ce5..106b027 100644=0A=
--- a/dlls/ddrawex/surface.c=0A=
+++ b/dlls/ddrawex/surface.c=0A=
@@ -563,7 +563,16 @@ IDirectDrawSurface4Impl_GetDC(IDirectDrawSurface4 =
*iface,=0A=
 {=0A=
     IDirectDrawSurfaceImpl *This =3D impl_from_dds4(iface);=0A=
     TRACE("(%p)->(%p)\n", This, hdc);=0A=
-    return IDirectDrawSurface4_GetDC(This->parent, hdc);=0A=
+    if(This->permanent_dc)=0A=
+    {=0A=
+        TRACE("Returning stored dc %p\n", This->hdc);=0A=
+        *hdc =3D This->hdc;=0A=
+        return DD_OK;=0A=
+    }=0A=
+    else=0A=
+    {=0A=
+        return IDirectDrawSurface4_GetDC(This->parent, hdc);=0A=
+    }=0A=
 }=0A=
 =0A=
 static HRESULT WINAPI=0A=
@@ -654,8 +663,17 @@ =
IDirectDrawSurface4Impl_GetSurfaceDesc(IDirectDrawSurface4 *iface,=0A=
                                        DDSURFACEDESC2 *DDSD)=0A=
 {=0A=
     IDirectDrawSurfaceImpl *This =3D impl_from_dds4(iface);=0A=
+    HRESULT hr;=0A=
     TRACE("(%p)->(%p)\n", This, DDSD);=0A=
-    return IDirectDrawSurface4_GetSurfaceDesc(This->parent, DDSD);=0A=
+    hr =3D IDirectDrawSurface4_GetSurfaceDesc(This->parent, DDSD);=0A=
+=0A=
+    if(SUCCEEDED(hr) && This->permanent_dc)=0A=
+    {=0A=
+        DDSD->ddsCaps.dwCaps |=3D DDSCAPS_VIDEOMEMORY;=0A=
+        DDSD->ddsCaps.dwCaps &=3D ~DDSCAPS_OWNDC;=0A=
+    }=0A=
+=0A=
+    return hr;=0A=
 }=0A=
 =0A=
 static HRESULT WINAPI=0A=
@@ -731,8 +749,17 @@ IDirectDrawSurface4Impl_Lock(IDirectDrawSurface4 =
*iface,=0A=
                              HANDLE h)=0A=
 {=0A=
     IDirectDrawSurfaceImpl *This =3D impl_from_dds4(iface);=0A=
+    HRESULT hr;=0A=
     TRACE("(%p)->(%p,%p,0x%08x,%p)\n", This, Rect, DDSD, Flags, h);=0A=
-    return IDirectDrawSurface4_Lock(This->parent, Rect, DDSD, Flags, h);=0A=
+    hr =3D IDirectDrawSurface4_Lock(This->parent, Rect, DDSD, Flags, h);=0A=
+=0A=
+    if(SUCCEEDED(hr) && This->permanent_dc)=0A=
+    {=0A=
+        DDSD->ddsCaps.dwCaps |=3D DDSCAPS_VIDEOMEMORY;=0A=
+        DDSD->ddsCaps.dwCaps &=3D ~DDSCAPS_OWNDC;=0A=
+    }=0A=
+=0A=
+    return hr;=0A=
 }=0A=
 =0A=
 static HRESULT WINAPI=0A=
@@ -759,7 +786,15 @@ =
IDirectDrawSurface4Impl_ReleaseDC(IDirectDrawSurface4 *iface,=0A=
 {=0A=
     IDirectDrawSurfaceImpl *This =3D impl_from_dds4(iface);=0A=
     TRACE("(%p)->(%p)\n", This, hdc);=0A=
-    return IDirectDrawSurface4_ReleaseDC(This->parent, hdc);=0A=
+    if(This->permanent_dc)=0A=
+    {=0A=
+        TRACE("Surface has a permanent DC, not doing anything\n");=0A=
+        return DD_OK;=0A=
+    }=0A=
+    else=0A=
+    {=0A=
+        return IDirectDrawSurface4_ReleaseDC(This->parent, hdc);=0A=
+    }=0A=
 }=0A=
 =0A=
 static HRESULT WINAPI=0A=
@@ -1259,3 +1294,15 @@ IDirectDrawSurface4 =
*dds_get_inner(IDirectDrawSurface4 *outer)=0A=
     if(This =3D=3D NULL) return NULL;=0A=
     return This->parent;=0A=
 }=0A=
+=0A=
+HRESULT prepare_permanent_dc(IDirectDrawSurface4 *iface)=0A=
+{=0A=
+    IDirectDrawSurfaceImpl *This =3D impl_from_dds4(iface);=0A=
+    HRESULT hr;=0A=
+    This->permanent_dc =3D TRUE;=0A=
+=0A=
+    hr =3D IDirectDrawSurface4_GetDC(This->parent, &This->hdc);=0A=
+    if(FAILED(hr)) return hr;=0A=
+    hr =3D IDirectDrawSurface4_ReleaseDC(This->parent, This->hdc);=0A=
+    return hr;=0A=
+}=0A=
diff --git a/dlls/ddrawex/tests/surface.c b/dlls/ddrawex/tests/surface.c=0A=
index 0eba34d..f0ac444 100644=0A=
--- a/dlls/ddrawex/tests/surface.c=0A=
+++ b/dlls/ddrawex/tests/surface.c=0A=
@@ -161,7 +161,7 @@ static void CapsTest(void)=0A=
     ddsd.dwWidth =3D 64;=0A=
     ddsd.dwHeight =3D 64;=0A=
     hr =3D IDirectDraw_CreateSurface(dd1, &ddsd, &surf, NULL);=0A=
-    todo_wine ok(hr =3D=3D DD_OK, "Creating a SYSMEM | VIDMEM surface =
returned 0x%08x, expected DD_OK\n", hr);=0A=
+    ok(hr =3D=3D DD_OK, "Creating a SYSMEM | VIDMEM surface returned =
0x%08x, expected DD_OK\n", hr);=0A=
     if(surf) IDirectDrawSurface_Release(surf);=0A=
 =0A=
     IDirectDraw_Release(dd1);=0A=
-- =0A=
1.6.0.6=0A=
=0A=

------=_NextPart_000_0030_01C970CF.A707B090--




More information about the wine-patches mailing list