diff --git a/dlls/wined3d/surface_gdi.c b/dlls/wined3d/surface_gdi.c index 0246782..430ba1e 100644 --- a/dlls/wined3d/surface_gdi.c +++ b/dlls/wined3d/surface_gdi.c @@ -28,6 +28,7 @@ #include "config.h" #include "wine/port.h" #include "wined3d_private.h" +#include "ddraw.h" #include @@ -149,6 +150,32 @@ IWineGDISurfaceImpl_LockRect(IWineD3DSurface *iface, This->resource.allocatedMemory = This->dib.bitmap_data; } + /* Lockrect returns the content of the screen in the front buffer. This can make problems if + * the application unlocks the surface without rewriting some parts of the screen. In this case + * a undefined(most likely memset(0)-black) pixels are written back, which most notably affects + * quicktime. Thus read the screen back when locking the front buffer. Unfortunately this readback + * is slow, so avoid the problem if possible: + * + * -> No readback in fullscreen situations. It is just not needed + * -> No readback if the ddraw window is not NULL. we didn't find an app yet overwriting just one + * Window's contents + * -> If DDLOCK_WRITEONLY is not specified. That's a quicktime hack to speed up video playing + * -> Of course also do it only if the surface if the front buffer + */ + if(!(Flags & DDLOCK_WRITEONLY)) { + IWineD3DSwapChainImpl *swapchain = NULL; + IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain); + + if(swapchain) { + if(swapchain->presentParms.Windowed && + !swapchain->win_handle && + iface == swapchain->front_buffer) { + x11_copy_from_screen(swapchain, NULL); + } + IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); + } + } + return IWineD3DBaseSurfaceImpl_LockRect(iface, pLockedRect, pRect, Flags); } diff --git a/dlls/wined3d/swapchain_gdi.c b/dlls/wined3d/swapchain_gdi.c index 5968201..b1edda6 100644 --- a/dlls/wined3d/swapchain_gdi.c +++ b/dlls/wined3d/swapchain_gdi.c @@ -157,6 +157,46 @@ void x11_copy_to_screen(IWineD3DSwapChainImpl *This, const RECT *rc) } } +/***************************************************************************** + * x11_copy_from_screen + * + * Reads the contents of a window into the front buffer + * + *****************************************************************************/ +void x11_copy_from_screen(IWineD3DSwapChainImpl *This, const RECT *rc) +{ + IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->front_buffer; + + HWND hDisplayWnd = This->win_handle; + HDC hDisplayDC = GetDC(hDisplayWnd); + RECT drawrect, winrect; + POINT offset = {0,0}; + + drawrect.left = 0; + drawrect.right = front->currentDesc.Width; + drawrect.top = 0; + drawrect.bottom = front->currentDesc.Height; + if (rc) + IntersectRect(&drawrect,&drawrect,rc); + + if(This->presentParms.Windowed && hDisplayWnd) { + ClientToScreen(hDisplayWnd, &offset); + GetClientRect(hDisplayWnd, &winrect); + drawrect.right = min(drawrect.right, winrect.right - winrect.left); + drawrect.bottom = min(drawrect.bottom, winrect.bottom - winrect.top); + } + + + BitBlt(front->hDC, + drawrect.left, drawrect.top, + drawrect.right-drawrect.left, drawrect.bottom-drawrect.top, + hDisplayDC, + drawrect.left - offset.x, drawrect.top - offset.y, + SRCCOPY + ); + ReleaseDC(hDisplayWnd, hDisplayDC); +} + static HRESULT WINAPI IWineGDISwapChainImpl_SetDestWindowOverride(IWineD3DSwapChain *iface, HWND window) { IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 5f88afd..e6c9d9c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2429,6 +2429,7 @@ typedef struct IWineD3DSwapChainImpl const IWineD3DSwapChainVtbl IWineGDISwapChain_Vtbl DECLSPEC_HIDDEN; void x11_copy_to_screen(IWineD3DSwapChainImpl *This, const RECT *rc) DECLSPEC_HIDDEN; +void x11_copy_from_screen(IWineD3DSwapChainImpl *This, const RECT *rc); HRESULT WINAPI IWineD3DBaseSwapChainImpl_QueryInterface(IWineD3DSwapChain *iface, REFIID riid, LPVOID *ppobj) DECLSPEC_HIDDEN;