Module: wine Branch: master Commit: 10d2a9375ddfac47de8957c7d126a28d82f15701 URL: http://source.winehq.org/git/wine.git/?a=commit;h=10d2a9375ddfac47de8957c7d1...
Author: Henri Verbeet hverbeet@codeweavers.com Date: Mon Dec 12 20:53:56 2011 +0100
ddraw: Add support for clipped blits.
---
dlls/ddraw/surface.c | 136 ++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 122 insertions(+), 14 deletions(-)
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 86d02c5..d110acc 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -1270,6 +1270,125 @@ static HRESULT WINAPI ddraw_surface1_Flip(IDirectDrawSurface *iface, IDirectDraw dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags); }
+static HRESULT ddraw_surface_blt_clipped(IDirectDrawSurfaceImpl *dst_surface, const RECT *dst_rect_in, + IDirectDrawSurfaceImpl *src_surface, const RECT *src_rect_in, DWORD flags, + const WINEDDBLTFX *fx, WINED3DTEXTUREFILTERTYPE filter) +{ + struct wined3d_surface *wined3d_src_surface = src_surface ? src_surface->wined3d_surface : NULL; + RECT src_rect, dst_rect; + float scale_x, scale_y; + const RECT *clip_rect; + UINT clip_list_size; + RGNDATA *clip_list; + HRESULT hr = DD_OK; + UINT i; + + if (!dst_surface->clipper) + { + if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) + hr = ddraw_surface_update_frontbuffer(src_surface, src_rect_in, TRUE); + if (SUCCEEDED(hr)) + hr = wined3d_surface_blt(dst_surface->wined3d_surface, dst_rect_in, + wined3d_src_surface, src_rect_in, flags, fx, filter); + if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)) + hr = ddraw_surface_update_frontbuffer(dst_surface, dst_rect_in, FALSE); + + return hr; + } + + if (!dst_rect_in) + { + dst_rect.left = 0; + dst_rect.top = 0; + dst_rect.right = dst_surface->surface_desc.dwWidth; + dst_rect.bottom = dst_surface->surface_desc.dwHeight; + } + else + { + dst_rect = *dst_rect_in; + } + + if (IsRectEmpty(&dst_rect)) + return DDERR_INVALIDRECT; + + if (src_surface) + { + if (!src_rect_in) + { + src_rect.left = 0; + src_rect.top = 0; + src_rect.right = src_surface->surface_desc.dwWidth; + src_rect.bottom = src_surface->surface_desc.dwHeight; + } + else + { + src_rect = *src_rect_in; + } + + if (IsRectEmpty(&src_rect)) + return DDERR_INVALIDRECT; + } + else + { + SetRect(&src_rect, 0, 0, 0, 0); + } + + scale_x = (float)(src_rect.right - src_rect.left) / (float)(dst_rect.right - dst_rect.left); + scale_y = (float)(src_rect.bottom - src_rect.top) / (float)(dst_rect.bottom - dst_rect.top); + + if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface, + &dst_rect, NULL, &clip_list_size))) + { + WARN("Failed to get clip list size, hr %#x.\n", hr); + return hr; + } + + if (!(clip_list = HeapAlloc(GetProcessHeap(), 0, clip_list_size))) + { + WARN("Failed to allocate clip list.\n"); + return E_OUTOFMEMORY; + } + + if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface, + &dst_rect, clip_list, &clip_list_size))) + { + WARN("Failed to get clip list, hr %#x.\n", hr); + return hr; + } + + clip_rect = (RECT *)clip_list->Buffer; + for (i = 0; i < clip_list->rdh.nCount; ++i) + { + RECT src_rect_clipped = src_rect; + + if (src_surface) + { + src_rect_clipped.left += (clip_rect[i].left - dst_rect.left) * scale_x; + src_rect_clipped.top += (clip_rect[i].top - dst_rect.top) * scale_y; + src_rect_clipped.right -= (dst_rect.right - clip_rect[i].right) * scale_x; + src_rect_clipped.bottom -= (dst_rect.bottom - clip_rect[i].bottom) * scale_y; + + if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) + { + if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE))) + break; + } + } + + if (FAILED(hr = wined3d_surface_blt(dst_surface->wined3d_surface, &clip_rect[i], + wined3d_src_surface, &src_rect_clipped, flags, fx, filter))) + break; + + if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) + { + if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE))) + break; + } + } + + return hr; +} + /***************************************************************************** * IDirectDrawSurface7::Blt * @@ -1322,13 +1441,8 @@ static HRESULT WINAPI ddraw_surface7_Blt(IDirectDrawSurface7 *iface, RECT *DestR * does, copy the struct, and replace the ddraw surfaces with the wined3d * surfaces. So far no blitting operations using surfaces in the bltfx * struct are supported anyway. */ - if (Src && Src->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) - hr = ddraw_surface_update_frontbuffer(Src, SrcRect, TRUE); - if (SUCCEEDED(hr)) - hr = wined3d_surface_blt(This->wined3d_surface, DestRect, Src ? Src->wined3d_surface : NULL, - SrcRect, Flags, (WINEDDBLTFX *)DDBltFx, WINED3DTEXF_LINEAR); - if (SUCCEEDED(hr) && (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)) - hr = ddraw_surface_update_frontbuffer(This, DestRect, FALSE); + hr = ddraw_surface_blt_clipped(This, DestRect, Src, SrcRect, + Flags, (WINEDDBLTFX *)DDBltFx, WINED3DTEXF_LINEAR);
wined3d_mutex_unlock(); switch(hr) @@ -3756,13 +3870,7 @@ static HRESULT WINAPI ddraw_surface7_BltFast(IDirectDrawSurface7 *iface, DWORD d flags |= WINEDDBLT_DONOTWAIT;
wined3d_mutex_lock(); - if (src->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) - hr = ddraw_surface_update_frontbuffer(src, rsrc, TRUE); - if (SUCCEEDED(hr)) - hr = wined3d_surface_blt(This->wined3d_surface, &dst_rect, - src->wined3d_surface, rsrc, flags, NULL, WINED3DTEXF_POINT); - if (SUCCEEDED(hr) && (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)) - hr = ddraw_surface_update_frontbuffer(This, &dst_rect, FALSE); + hr = ddraw_surface_blt_clipped(This, &dst_rect, src, rsrc, flags, NULL, WINED3DTEXF_POINT); wined3d_mutex_unlock();
switch(hr)