WineD3D: Read the screen when locking the front buffer
Stefan Dösinger
stefandoesinger at gmx.at
Sat Sep 9 06:43:07 CDT 2006
Windowed(DDSCL_NORMAL) DDraw apps can mix DDraw and GDI rendering on the same
window. Our GDI surface implementation BitBlts the contents of the front
buffer onto the window when the front buffer is modified. Simmilarly, the gdi
contents have to read when the front buffer is locked.
This used to be the QuickTime hack in CrossOver. My concerns regarding double
buffering vanished when I noticed that double buffering is not allowed in
DDSCL_NORMAL mode(see the previous patch). We only have to read the content
when we are not in fullscreen mode, and we do not have to care about double
buffer flipping.
One issue is that reading from gdi takes some time, no matter how big the read
area is. This is due to the lack of a gdi engine. So it is assumed that when
the application specifies a rectangle to lock that it knows pretty well which
parts it wants locked, so no readback is done with the assumption that the
app doesn't lock areas with gdi-drawn contents.
This patch depends on the "pass the fullscreen flag to wined3d" patch, but not
necessarily on the double buffering test. The test is mainly to show that we
do not have to care for double buffering when reading into the front buffer.
-------------- next part --------------
From a7e8373eda0d70a93feec74e8c23544e335eef35 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Stefan_D=F6singer?= <stefan at codeweavers.com>
Date: Sat, 9 Sep 2006 11:36:51 +0200
Subject: [PATCH] WineD3D: Read the gdi content when locking the front buffer in windowed mode
---
dlls/wined3d/surface_gdi.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/dlls/wined3d/surface_gdi.c b/dlls/wined3d/surface_gdi.c
index 9609ebd..548a29c 100644
--- a/dlls/wined3d/surface_gdi.c
+++ b/dlls/wined3d/surface_gdi.c
@@ -122,6 +122,39 @@ #endif
}
/*****************************************************************************
+ * x11_copy_from_screen
+ *
+ * Reads the contents of a window into the front buffer
+ *
+ *****************************************************************************/
+static void x11_copy_from_screen(IWineD3DSurfaceImpl* This,
+ const RECT *rc)
+{
+ if (This->resource.usage & WINED3DUSAGE_RENDERTARGET)
+ {
+ HWND hDisplayWnd = This->resource.wineD3DDevice->ddraw_window;
+ HDC hDisplayDC = GetDC(hDisplayWnd);
+ RECT drawrect;
+
+ drawrect.left = 0;
+ drawrect.right = This->currentDesc.Width;
+ drawrect.top = 0;
+ drawrect.bottom = This->currentDesc.Height;
+ if (rc)
+ IntersectRect(&drawrect,&drawrect,rc);
+
+ BitBlt(This->hDC,
+ drawrect.left, drawrect.top,
+ drawrect.right-drawrect.left, drawrect.bottom-drawrect.top,
+ hDisplayDC,
+ drawrect.left, drawrect.top,
+ SRCCOPY
+ );
+ ReleaseDC(hDisplayWnd, hDisplayDC);
+ }
+}
+
+/*****************************************************************************
* IWineD3DSurface::PreLoad, GDI version
*
* This call is unsupported on GDI surfaces, if it's called something went
@@ -239,6 +272,23 @@ IWineGDISurfaceImpl_LockRect(IWineD3DSur
This->lockedRect.bottom = pRect->bottom;
}
+ /* DDraw apps can share ddraw operation with GDI if not in exclusive mode. This surface
+ * implementation BitBlts the front buffer's content onto the GDI device context. In the
+ * same way as we write to GDI we have to read from there when we lock the primary surface.
+ *
+ * Reading from GDI is slow, so do it only when the app locks the whole surface. If the app
+ * specifies a rectangle to lock it is assumed that the app knows what part it wants to lock.
+ *
+ * There is no need to take care for gdi readback for back buffers, or in the Flip method,
+ * because double buffered surfaces can only be created in DDSCL_EXCLUSIVE mode, and in
+ * this mode gdi stuff can't be done anyway.
+ */
+ if(!pRect && iface == This->resource.wineD3DDevice->ddraw_primary &&
+ !This->resource.wineD3DDevice->ddraw_fullscreen)
+ {
+ x11_copy_from_screen(This, NULL);
+ }
+
/* No dirtifying is needed for this surface implementation */
TRACE("returning memory@%p, pitch(%d)\n", pLockedRect->pBits, pLockedRect->Pitch);
--
1.4.1.1
More information about the wine-patches
mailing list