Henri Verbeet : ddraw: Add support for clipped blits.

Alexandre Julliard julliard at winehq.org
Tue Dec 13 13:01:24 CST 2011


Module: wine
Branch: master
Commit: 10d2a9375ddfac47de8957c7d126a28d82f15701
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=10d2a9375ddfac47de8957c7d126a28d82f15701

Author: Henri Verbeet <hverbeet at 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)




More information about the wine-cvs mailing list