wined3d: Don't DISCARD or NOOVERWRITE non-dynamic buffers.
authorStefan Dösinger <stefan@codeweavers.com>
Thu, 11 Mar 2010 11:05:23 +0000 (12:05 +0100)
committerAlexandre Julliard <julliard@winehq.org>
Tue, 16 Mar 2010 16:02:34 +0000 (17:02 +0100)
Shaiya locks a non-dynamic buffer with the DISCARD flag and expects
the contents to be retained. The SDK says DISCARD requires dynamic
resources, and Windows 7 returns an error in this situation, crashing
Shaiya. This patch sticks to the Windows XP behavior and allows the
lock, but ignores the DISCARD flag to retain the buffer contents.

dlls/wined3d/buffer.c

index e22d311beb9d47ef2aeaa3807496eec9cbba6e38..86d6fb4cd63cad4e3641ca79a5242443211a1a82 100644 (file)
@@ -1033,7 +1033,7 @@ static WINED3DRESOURCETYPE STDMETHODCALLTYPE buffer_GetType(IWineD3DBuffer *ifac
 
 /* IWineD3DBuffer methods */
 
-static DWORD buffer_sanitize_flags(DWORD flags)
+static DWORD buffer_sanitize_flags(struct wined3d_buffer *buffer, DWORD flags)
 {
     /* Not all flags make sense together, but Windows never returns an error. Catch the
      * cases that could cause issues */
@@ -1055,6 +1055,11 @@ static DWORD buffer_sanitize_flags(DWORD flags)
         WARN("WINED3DLOCK_DISCARD and WINED3DLOCK_NOOVERWRITE used together, ignoring\n");
         return 0;
     }
+    else if (flags & (WINED3DLOCK_DISCARD | WINED3DLOCK_NOOVERWRITE) && !(buffer->resource.usage & WINED3DUSAGE_DYNAMIC))
+    {
+        WARN("DISCARD or NOOVERWRITE lock on non-dynamic buffer, ignoring\n");
+        return 0;
+    }
 
     return flags;
 }
@@ -1085,7 +1090,7 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset,
 
     TRACE("iface %p, offset %u, size %u, data %p, flags %#x\n", iface, offset, size, data, flags);
 
-    flags = buffer_sanitize_flags(flags);
+    flags = buffer_sanitize_flags(This, flags);
     if (!(flags & WINED3DLOCK_READONLY))
     {
         if (!buffer_add_dirty_area(This, offset, size)) return E_OUTOFMEMORY;