Nikolay Sivov : d2d1: Validate bitmap options against surface description in CreateBitmapFromDxgiSurface().

Alexandre Julliard julliard at winehq.org
Tue May 31 15:58:00 CDT 2022


Module: wine
Branch: master
Commit: ab70e9c4f4f43e4af5728286aa72ae88f539f57e
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=ab70e9c4f4f43e4af5728286aa72ae88f539f57e

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Mon May 30 12:52:17 2022 +0300

d2d1: Validate bitmap options against surface description in CreateBitmapFromDxgiSurface().

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>

---

 dlls/d2d1/device.c     | 56 +++++++++++++++++++++++++++++++++++++++++--
 dlls/d2d1/tests/d2d1.c | 65 ++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 109 insertions(+), 12 deletions(-)

diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c
index b7faf33e266..12aa2acc331 100644
--- a/dlls/d2d1/device.c
+++ b/dlls/d2d1/device.c
@@ -1856,17 +1856,69 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromWicCol
     return E_NOTIMPL;
 }
 
+static BOOL d2d_bitmap_check_options_with_surface(unsigned int options, unsigned int surface_options)
+{
+    switch (options)
+    {
+        case D2D1_BITMAP_OPTIONS_NONE:
+        case D2D1_BITMAP_OPTIONS_TARGET:
+        case D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW:
+        case D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE:
+        case D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE:
+        case D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ:
+        case D2D1_BITMAP_OPTIONS_CANNOT_DRAW:
+            break;
+        default:
+            WARN("Invalid bitmap options %#x.\n", options);
+            return FALSE;
+    }
+
+    if (options && (options & D2D1_BITMAP_OPTIONS_TARGET) != (surface_options & D2D1_BITMAP_OPTIONS_TARGET))
+        return FALSE;
+    if (options & D2D1_BITMAP_OPTIONS_TARGET)
+    {
+        if (!(options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW) && (surface_options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW))
+            return FALSE;
+        if (options & D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE && !(surface_options & D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE))
+            return FALSE;
+        return TRUE;
+    }
+
+    if (options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW)
+    {
+        if (!(surface_options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW))
+            return FALSE;
+
+        if (options & D2D1_BITMAP_OPTIONS_CPU_READ && !(surface_options & D2D1_BITMAP_OPTIONS_CPU_READ))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(ID2D1DeviceContext *iface,
         IDXGISurface *surface, const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
 {
     struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
     D2D1_BITMAP_PROPERTIES1 bitmap_desc;
+    unsigned int surface_options;
     struct d2d_bitmap *object;
     HRESULT hr;
 
     TRACE("iface %p, surface %p, desc %p, bitmap %p.\n", iface, surface, desc, bitmap);
 
-    if (!desc)
+    surface_options = d2d_get_bitmap_options_for_surface(surface);
+
+    if (desc)
+    {
+        if (!d2d_bitmap_check_options_with_surface(desc->bitmapOptions, surface_options))
+        {
+            WARN("Incompatible bitmap options %#x, surface options %#x.\n",
+                    desc->bitmapOptions, surface_options);
+            return E_INVALIDARG;
+        }
+    }
+    else
     {
         DXGI_SURFACE_DESC surface_desc;
 
@@ -1879,7 +1931,7 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(
         memset(&bitmap_desc, 0, sizeof(bitmap_desc));
         bitmap_desc.pixelFormat.format = surface_desc.Format;
         bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
-        bitmap_desc.bitmapOptions = d2d_get_bitmap_options_for_surface(surface);
+        bitmap_desc.bitmapOptions = surface_options;
         desc = &bitmap_desc;
     }
 
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 5185c07c29b..c73039504d3 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -1213,6 +1213,24 @@ static BOOL init_test_context_(unsigned int line, struct d2d1_test_context *ctx,
     return TRUE;
 }
 
+#define check_bitmap_options(b, o) check_bitmap_options_(__LINE__, b, o)
+static void check_bitmap_options_(unsigned int line, ID2D1Bitmap *bitmap, DWORD expected_options)
+{
+    D2D1_BITMAP_OPTIONS options;
+    ID2D1Bitmap1 *bitmap1;
+    HRESULT hr;
+
+    hr = ID2D1Bitmap_QueryInterface(bitmap, &IID_ID2D1Bitmap1, (void **)&bitmap1);
+    if (FAILED(hr))
+        return;
+
+    options = ID2D1Bitmap1_GetOptions(bitmap1);
+    ok_(__FILE__, line)(options == expected_options, "Got unexpected bitmap options %#x, expected %#lx.\n",
+            options, expected_options);
+
+    ID2D1Bitmap1_Release(bitmap1);
+}
+
 #define check_bitmap_surface(b, s, o) check_bitmap_surface_(__LINE__, b, s, o)
 static void check_bitmap_surface_(unsigned int line, ID2D1Bitmap *bitmap, BOOL has_surface, DWORD expected_options)
 {
@@ -11605,6 +11623,7 @@ static void test_bitmap_map(BOOL d3d11)
     };
     D2D1_BITMAP_PROPERTIES1 bitmap_desc;
     D3D11_TEXTURE2D_DESC texture_desc;
+    ID2D1Bitmap *bitmap2, *bitmap3;
     struct d2d1_test_context ctx;
     D2D1_MAPPED_RECT mapped_rect;
     ID3D11Device *d3d_device;
@@ -11612,7 +11631,6 @@ static void test_bitmap_map(BOOL d3d11)
     unsigned int i, options;
     IDXGISurface *surface;
     ID2D1Bitmap1 *bitmap;
-    ID2D1Bitmap *bitmap2;
     D2D1_SIZE_U size;
     HRESULT hr;
 
@@ -11768,14 +11786,13 @@ static void test_bitmap_map(BOOL d3d11)
     hr = ID2D1DeviceContext_CreateSharedBitmap(ctx.context, &IID_IDXGISurface, surface,
             (const D2D1_BITMAP_PROPERTIES *)&bitmap_desc, &bitmap2);
     ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+    check_bitmap_options(bitmap2, D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ);
 
-    hr = ID2D1Bitmap_QueryInterface(bitmap2, &IID_ID2D1Bitmap1, (void **)&bitmap);
+    hr = ID2D1DeviceContext_CreateSharedBitmap(ctx.context, &IID_ID2D1Bitmap, bitmap2, NULL, &bitmap3);
     ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
-    options = ID2D1Bitmap1_GetOptions(bitmap);
-    ok(options == (D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ),
-            "Unexpected options %#x.\n", options);
+    check_bitmap_options(bitmap3, D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ);
+    ID2D1Bitmap_Release(bitmap3);
 
-    ID2D1Bitmap1_Release(bitmap);
     ID2D1Bitmap_Release(bitmap2);
 
     hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, NULL, &bitmap);
@@ -11788,9 +11805,7 @@ static void test_bitmap_map(BOOL d3d11)
     /* Options incompatible with the surface. */
     bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET;
     hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, &bitmap_desc, &bitmap);
-    todo_wine
     ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
-    if (SUCCEEDED(hr)) ID2D1Bitmap1_Release(bitmap);
     bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_NONE;
     hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, &bitmap_desc, &bitmap);
     todo_wine
@@ -11798,9 +11813,7 @@ static void test_bitmap_map(BOOL d3d11)
     if (SUCCEEDED(hr)) ID2D1Bitmap1_Release(bitmap);
     bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
     hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, &bitmap_desc, &bitmap);
-    todo_wine
     ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
-    if (SUCCEEDED(hr)) ID2D1Bitmap1_Release(bitmap);
 
     /* Create without D2D1_BITMAP_OPTIONS_CPU_READ, surface supports CPU reads. */
     bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
@@ -11813,6 +11826,38 @@ static void test_bitmap_map(BOOL d3d11)
     ID3D11Texture2D_Release(texture);
     IDXGISurface_Release(surface);
 
+    /* Surface D2D1_BITMAP_OPTIONS_TARGET */
+    texture_desc.Width = 4;
+    texture_desc.Height = 4;
+    texture_desc.MipLevels = 1;
+    texture_desc.ArraySize = 1;
+    texture_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+    texture_desc.SampleDesc.Count = 1;
+    texture_desc.SampleDesc.Quality = 0;
+    texture_desc.Usage = D3D11_USAGE_DEFAULT;
+    texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+    texture_desc.CPUAccessFlags = 0;
+    texture_desc.MiscFlags = 0;
+
+    hr = ID3D11Device_CreateTexture2D(d3d_device, &texture_desc, NULL, &texture);
+    ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+    hr = ID3D11Texture2D_QueryInterface(texture, &IID_IDXGISurface, (void **)&surface);
+    ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+    bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_TARGET;
+    hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, &bitmap_desc, &bitmap);
+    ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+    ID2D1Bitmap1_Release(bitmap);
+
+    bitmap_desc.bitmapOptions = 0;
+    hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(ctx.context, surface, &bitmap_desc, &bitmap);
+    ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+    check_bitmap_options((ID2D1Bitmap *)bitmap, 0);
+    ID2D1Bitmap1_Release(bitmap);
+
+    ID3D11Texture2D_Release(texture);
+    IDXGISurface_Release(surface);
+
     ID3D11Device_Release(d3d_device);
 
     release_test_context(&ctx);




More information about the wine-cvs mailing list