Module: wine Branch: master Commit: 0fb41a8845ff2d3fe111ee4ea394b5286ad24c71 URL: http://source.winehq.org/git/wine.git/?a=commit;h=0fb41a8845ff2d3fe111ee4ea3...
Author: Stefan Dösinger stefan@codeweavers.com Date: Sun Apr 29 12:48:34 2007 +0200
wined3d: Make the blit -> flip work for windowed rendering.
---
dlls/ddraw/ddraw.c | 9 +++ dlls/ddraw/surface.c | 2 +- dlls/wined3d/surface.c | 129 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 96 insertions(+), 44 deletions(-)
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index 953b5ea..36b3a95 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -1445,6 +1445,7 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf, IWineD3DSurface *wineD3DSurface; HRESULT hr; void *tmp; + IWineD3DClipper *clipper = NULL;
WINED3DSURFACE_DESC Desc; WINED3DFORMAT Format; @@ -1480,6 +1481,8 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf, IWineD3DSurface_Release(wineD3DSurface); }
+ /* get the clipper */ + IWineD3DSurface_GetClipper(wineD3DSurface, &clipper);
/* Get the surface properties */ Desc.Format = &Format; @@ -1514,6 +1517,8 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf, if(hr != D3D_OK) return hr;
+ IWineD3DSurface_SetClipper(surfImpl->WineD3DSurface, clipper); + /* Update the IParent if it exists */ if(parImpl) { @@ -1530,6 +1535,10 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf,
surfImpl->ImplType = This->ImplType;
+ if(clipper) + { + IWineD3DClipper_Release(clipper); + } return DDENUMRET_OK; }
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 9cf0f0a..5f26526 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -1966,7 +1966,7 @@ IDirectDrawSurfaceImpl_SetClipper(IDirectDrawSurface7 *iface, if(oldClipper) IDirectDrawClipper_Release(ICOM_INTERFACE(oldClipper, IDirectDrawClipper));
- return DD_OK; + return IWineD3DSurface_SetClipper(This->WineD3DSurface, This->clipper->wineD3DClipper); }
/***************************************************************************** diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index df308fe..9a41f8f 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -2605,7 +2605,6 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice; IWineD3DSwapChainImpl *srcSwapchain = NULL, *dstSwapchain = NULL; IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface; - BOOL SrcOK = TRUE;
TRACE("(%p)->(%p,%p,%p,%08x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
@@ -2644,58 +2643,102 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * }
/* The only case where both surfaces on a swapchain are supported is a back buffer -> front buffer blit on the same swapchain */ - if(dstSwapchain && dstSwapchain == srcSwapchain) { + if(dstSwapchain && dstSwapchain == srcSwapchain && dstSwapchain->backBuffer && + ((IWineD3DSurface *) This == dstSwapchain->frontBuffer) && SrcSurface == dstSwapchain->backBuffer[0]) { /* Half-life does a Blt from the back buffer to the front buffer, * Full surface size, no flags... Use present instead + * + * This path will only be entered for d3d7 and ddraw apps, because d3d8/9 offer no way to blit TO the front buffer */
/* Check rects - IWineD3DDevice_Present doesn't handle them */ - if( SrcRect ) { - if( (SrcRect->left == 0) && (SrcRect->top == 0) && - (SrcRect->right == Src->currentDesc.Width) && (SrcRect->bottom == Src->currentDesc.Height) ) { - SrcOK = TRUE; + while(1) + { + RECT mySrcRect; + TRACE("Looking if a Present can be done... "); + /* Source Rectangle must be full surface */ + if( SrcRect ) { + if(SrcRect->left != 0 || SrcRect->top != 0 || + SrcRect->right != Src->currentDesc.Width || SrcRect->bottom != Src->currentDesc.Height) { + TRACE("No, Source rectangle doesn't match\n"); + break; + } + } + mySrcRect.left = 0; + mySrcRect.top = 0; + mySrcRect.right = Src->currentDesc.Width; + mySrcRect.bottom = Src->currentDesc.Height; + + /* No stretching may occur */ + if(mySrcRect.right != rect.x2 - rect.x1 || + mySrcRect.bottom != rect.y2 - rect.y1) { + TRACE("No, stretching is done\n"); + break; } - } else { - SrcOK = TRUE; - } - - /* Check the Destination rect and the surface sizes */ - if(SrcOK && - (rect.x1 == 0) && (rect.y1 == 0) && - (rect.x2 == This->currentDesc.Width) && (rect.y2 == This->currentDesc.Height) && - (This->currentDesc.Width == Src->currentDesc.Width) && - (This->currentDesc.Height == Src->currentDesc.Height)) { - /* These flags are unimportant for the flag check, remove them */ - - if((Flags & ~(WINEDDBLT_DONOTWAIT | WINEDDBLT_WAIT)) == 0) { - if( dstSwapchain->backBuffer && ((IWineD3DSurface *) This == dstSwapchain->frontBuffer) && - SrcSurface == dstSwapchain->backBuffer[0] ) { - - WINED3DSWAPEFFECT orig_swap = dstSwapchain->presentParms.SwapEffect; - - /* The idea behind this is that a glReadPixels and a glDrawPixels call - * take very long, while a flip is fast. - * This applies to Half-Life, which does such Blts every time it finished - * a frame, and to Prince of Persia 3D, which uses this to draw at least the main - * menu. This is also used by all apps when they do windowed rendering - * - * The problem is that flipping is not really the same as copying. After a - * Blt the front buffer is a copy of the back buffer, and the back buffer is - * untouched. Therefore it's necessary to override the swap effect - * and to set it back after the flip. - */ - - dstSwapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY;
- TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n"); - IWineD3DDevice_Present((IWineD3DDevice *) This->resource.wineD3DDevice, - NULL, NULL, 0, NULL); + /* Destination must be full surface or match the clipping rectangle */ + if(This->clipper && ((IWineD3DClipperImpl *) This->clipper)->hWnd) + { + RECT cliprect; + POINT pos[2]; + GetClientRect(((IWineD3DClipperImpl *) This->clipper)->hWnd, &cliprect); + pos[0].x = rect.x1; + pos[0].y = rect.y1; + pos[1].x = rect.x2; + pos[1].y = rect.y2; + MapWindowPoints(GetDesktopWindow(), ((IWineD3DClipperImpl *) This->clipper)->hWnd, + pos, 2); + + if(pos[0].x != cliprect.left || pos[0].y != cliprect.top || + pos[1].x != cliprect.right || pos[1].y != cliprect.bottom) + { + TRACE("No, dest rectangle doesn't match(clipper)\n"); + TRACE("Clip rect at (%d,%d)-(%d,%d)\n", cliprect.left, cliprect.top, cliprect.right, cliprect.bottom); + TRACE("Blt dest: (%d,%d)-(%d,%d)\n", rect.x1, rect.y1, rect.x2, rect.y2); + break; + } + } + else + { + if(rect.x1 != 0 || rect.y1 != 0 || + rect.x2 != This->currentDesc.Width || rect.y2 != This->currentDesc.Height) { + TRACE("No, dest rectangle doesn't match(surface size)\n"); + break; + } + }
- dstSwapchain->presentParms.SwapEffect = orig_swap; + TRACE("Yes\n");
- return WINED3D_OK; - } + /* These flags are unimportant for the flag check, remove them */ + if((Flags & ~(WINEDDBLT_DONOTWAIT | WINEDDBLT_WAIT)) == 0) { + WINED3DSWAPEFFECT orig_swap = dstSwapchain->presentParms.SwapEffect; + + /* The idea behind this is that a glReadPixels and a glDrawPixels call + * take very long, while a flip is fast. + * This applies to Half-Life, which does such Blts every time it finished + * a frame, and to Prince of Persia 3D, which uses this to draw at least the main + * menu. This is also used by all apps when they do windowed rendering + * + * The problem is that flipping is not really the same as copying. After a + * Blt the front buffer is a copy of the back buffer, and the back buffer is + * untouched. Therefore it's necessary to override the swap effect + * and to set it back after the flip. + * + * Windowed Direct3D < 7 apps do the same. The D3D7 sdk demso are nice + * testcases. + */ + + dstSwapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY; + + TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n"); + IWineD3DDevice_Present((IWineD3DDevice *) This->resource.wineD3DDevice, + NULL, NULL, 0, NULL); + + dstSwapchain->presentParms.SwapEffect = orig_swap; + + return WINED3D_OK; } + break; }
TRACE("Unsupported blit between buffers on the same swapchain\n");