From 843b306004f731e36e9d9d9336228cd2c06f9128 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Wed, 20 Aug 2014 14:14:23 +0200
Subject: wined3d: Put update_surface checks back in place

Unfortunately I can't remove the code from surface_update_from_surface
yet because blits depend on them.
---
 dlls/wined3d/device.c          | 68 ++++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/surface.c         |  2 +-
 dlls/wined3d/wined3d_private.h |  1 +
 3 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 819e6de..e804afe 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -3773,6 +3773,13 @@ HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device,
         struct wined3d_surface *src_surface, const RECT *src_rect,
         struct wined3d_surface *dst_surface, const POINT *dst_point)
 {
+    const struct wined3d_format *src_format = src_surface->resource.format;
+    const struct wined3d_format *dst_format = dst_surface->resource.format;
+    UINT update_w, update_h;
+    UINT dst_w, dst_h;
+    RECT r, dst_rect;
+    POINT p;
+
     TRACE("device %p, src_surface %p, src_rect %s, dst_surface %p, dst_point %s.\n",
             device, src_surface, wine_dbgstr_rect(src_rect),
             dst_surface, wine_dbgstr_point(dst_point));
@@ -3784,6 +3791,67 @@ HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device,
         return WINED3DERR_INVALIDCALL;
     }
 
+    if (src_format->id != dst_format->id)
+    {
+        WARN("Source and destination surfaces should have the same format.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (!dst_point)
+    {
+        p.x = 0;
+        p.y = 0;
+        dst_point = &p;
+    }
+    else if (dst_point->x < 0 || dst_point->y < 0)
+    {
+        WARN("Invalid destination point.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if (!src_rect)
+    {
+        r.left = 0;
+        r.top = 0;
+        r.right = src_surface->resource.width;
+        r.bottom = src_surface->resource.height;
+        src_rect = &r;
+    }
+    else if (src_rect->left < 0 || src_rect->left >= src_rect->right
+            || src_rect->top < 0 || src_rect->top >= src_rect->bottom)
+    {
+        WARN("Invalid source rectangle.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    dst_w = dst_surface->resource.width;
+    dst_h = dst_surface->resource.height;
+
+    update_w = src_rect->right - src_rect->left;
+    update_h = src_rect->bottom - src_rect->top;
+
+    if (update_w > dst_w || dst_point->x > dst_w - update_w
+            || update_h > dst_h || dst_point->y > dst_h - update_h)
+    {
+        WARN("Destination out of bounds.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if ((src_surface->container->resource.format_flags & WINED3DFMT_FLAG_BLOCKS)
+            && !surface_check_block_align_rect(src_surface, src_rect))
+    {
+        WARN("Source rectangle not block-aligned.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    SetRect(&dst_rect, dst_point->x, dst_point->y, dst_point->x + update_w, dst_point->y + update_h);
+    if ((dst_surface->container->resource.format_flags & WINED3DFMT_FLAG_BLOCKS)
+            && !surface_check_block_align_rect(dst_surface, &dst_rect))
+    {
+        WARN("Destination rectangle not block-aligned.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
     if (wined3d_settings.cs_multithreaded)
     {
         FIXME("Waiting for cs.\n");
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 2d98a93..5a2b14e 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1371,7 +1371,7 @@ static BOOL surface_check_block_align(struct wined3d_surface *surface, const str
     return wined3d_resource_check_block_align(&surface->resource, box);
 }
 
-static BOOL surface_check_block_align_rect(struct wined3d_surface *surface, const RECT *rect)
+BOOL surface_check_block_align_rect(struct wined3d_surface *surface, const RECT *rect)
 {
     struct wined3d_box box = {rect->left, rect->top, rect->right, rect->bottom, 0, 1};
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 73da744..99212de 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2494,6 +2494,7 @@ void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct w
 void surface_blt_ugly(struct wined3d_surface *dst_surface, const RECT *dst_rect_in,
         struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags,
         const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
+BOOL surface_check_block_align_rect(struct wined3d_surface *surface, const RECT *rect) DECLSPEC_HIDDEN;
 
 void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3d_context *context,
         const RECT *src_rect, const RECT *dst_rect, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
-- 
2.6.0

