[PATCH 5/6] d2d1: Introduce new ID3D10Device access wrappers.

Rémi Bernon rbernon at codeweavers.com
Mon Jan 18 06:57:45 CST 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/d2d1/bitmap.c            |  47 +++++++++--
 dlls/d2d1/brush.c             |  10 ++-
 dlls/d2d1/d2d1_private.h      |   4 +-
 dlls/d2d1/device.c            | 147 ++++++++++++++++++++++++++--------
 dlls/d2d1/wic_render_target.c |  24 +++++-
 5 files changed, 188 insertions(+), 44 deletions(-)

diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c
index bc58d7d92d5..51fefe535fa 100644
--- a/dlls/d2d1/bitmap.c
+++ b/dlls/d2d1/bitmap.c
@@ -152,6 +152,7 @@ static HRESULT STDMETHODCALLTYPE d2d_bitmap_CopyFromMemory(ID2D1Bitmap1 *iface,
     struct d2d_bitmap *bitmap = impl_from_ID2D1Bitmap1(iface);
     ID3D10Device *device;
     D3D10_BOX box;
+    HRESULT hr;
 
     TRACE("iface %p, dst_rect %p, src_data %p, pitch %u.\n", iface, dst_rect, src_data, pitch);
 
@@ -165,10 +166,15 @@ static HRESULT STDMETHODCALLTYPE d2d_bitmap_CopyFromMemory(ID2D1Bitmap1 *iface,
         box.back = 1;
     }
 
-    ID3D10Resource_GetDevice(bitmap->resource, &device);
+    if (FAILED(hr = d2d_device_get_d3d10_device(bitmap->device, &device)))
+    {
+        ERR("Failed to get ID3D10Device interface, hr %#x.\n", hr);
+        return hr;
+    }
+
     ID3D10Device_UpdateSubresource(device, bitmap->resource, 0, dst_rect ? &box : NULL, src_data, pitch, 0);
-    ID3D10Device_Release(device);
 
+    d2d_device_release_d3d10_device(bitmap->device, device);
     return S_OK;
 }
 
@@ -316,6 +322,7 @@ HRESULT d2d_bitmap_create(struct d2d_device_context *context, D2D1_SIZE_U size,
     D2D1_BITMAP_PROPERTIES1 bitmap_desc;
     D3D10_TEXTURE2D_DESC texture_desc;
     ID3D10Texture2D *texture;
+    ID3D10Device *d3d10_device;
     HRESULT hr;
 
     if (!format_supported(&desc->pixelFormat))
@@ -360,10 +367,17 @@ HRESULT d2d_bitmap_create(struct d2d_device_context *context, D2D1_SIZE_U size,
     resource_data.pSysMem = src_data;
     resource_data.SysMemPitch = pitch;
 
-    if (FAILED(hr = ID3D10Device_CreateTexture2D(context->d3d_device, &texture_desc,
+    if (FAILED(hr = d2d_device_get_d3d10_device(context->device, &d3d10_device)))
+    {
+        ERR("Failed to get ID3D10Device interface, hr %#x.\n", hr);
+        return hr;
+    }
+
+    if (FAILED(hr = ID3D10Device_CreateTexture2D(d3d10_device, &texture_desc,
             src_data ? &resource_data : NULL, &texture)))
     {
         ERR("Failed to create texture, hr %#x.\n", hr);
+        d2d_device_release_d3d10_device(context->device, d3d10_device);
         return hr;
     }
 
@@ -374,6 +388,7 @@ HRESULT d2d_bitmap_create(struct d2d_device_context *context, D2D1_SIZE_U size,
     }
     ID3D10Texture2D_Release(texture);
 
+    d2d_device_release_d3d10_device(context->device, d3d10_device);
     return *bitmap ? S_OK : E_OUTOFMEMORY;
 }
 
@@ -386,9 +401,15 @@ HRESULT d2d_bitmap_create_shared(struct d2d_device_context *context, REFIID iid,
     {
         struct d2d_bitmap *src_impl = unsafe_impl_from_ID2D1Bitmap(data);
         ID2D1Factory *factory;
-        ID3D10Device *device;
+        ID3D10Device *device, *context_device;
         HRESULT hr = S_OK;
 
+        if (FAILED(hr = d2d_device_get_d3d10_device(context->device, &context_device)))
+        {
+            ERR("Failed to get ID3D10Device interface, hr %#x.\n", hr);
+            goto failed;
+        }
+
         ID2D1Device_GetFactory(src_impl->device, &factory);
         if (factory != context->factory)
         {
@@ -400,7 +421,7 @@ HRESULT d2d_bitmap_create_shared(struct d2d_device_context *context, REFIID iid,
 
         ID3D10Resource_GetDevice(src_impl->resource, &device);
         ID3D10Device_Release(device);
-        if (device != context->d3d_device)
+        if (device != context_device)
         {
             hr = D2DERR_UNSUPPORTED_OPERATION;
             goto failed;
@@ -434,6 +455,7 @@ HRESULT d2d_bitmap_create_shared(struct d2d_device_context *context, REFIID iid,
         TRACE("Created bitmap %p.\n", *bitmap);
 
     failed:
+        d2d_device_release_d3d10_device(context->device, context_device);
         return hr;
     }
 
@@ -443,26 +465,35 @@ HRESULT d2d_bitmap_create_shared(struct d2d_device_context *context, REFIID iid,
         IDXGISurface *surface = data;
         ID3D10Resource *resource;
         D2D1_SIZE_U pixel_size;
-        ID3D10Device *device;
+        ID3D10Device *device, *context_device;
         HRESULT hr;
 
+        if (FAILED(hr = d2d_device_get_d3d10_device(context->device, &context_device)))
+        {
+            ERR("Failed to get ID3D10Device interface, hr %#x.\n", hr);
+            return hr;
+        }
+
         if (FAILED(IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
         {
             WARN("Failed to get d3d resource from dxgi surface.\n");
+            d2d_device_release_d3d10_device(context->device, context_device);
             return E_FAIL;
         }
 
         ID3D10Resource_GetDevice(resource, &device);
         ID3D10Device_Release(device);
-        if (device != context->d3d_device)
+        if (device != context_device)
         {
             ID3D10Resource_Release(resource);
+            d2d_device_release_d3d10_device(context->device, context_device);
             return D2DERR_UNSUPPORTED_OPERATION;
         }
 
         if (!(*bitmap = heap_alloc_zero(sizeof(**bitmap))))
         {
             ID3D10Resource_Release(resource);
+            d2d_device_release_d3d10_device(context->device, context_device);
             return E_OUTOFMEMORY;
         }
 
@@ -471,6 +502,7 @@ HRESULT d2d_bitmap_create_shared(struct d2d_device_context *context, REFIID iid,
         {
             WARN("Failed to get surface desc, hr %#x.\n", hr);
             ID3D10Resource_Release(resource);
+            d2d_device_release_d3d10_device(context->device, context_device);
             return hr;
         }
 
@@ -501,6 +533,7 @@ HRESULT d2d_bitmap_create_shared(struct d2d_device_context *context, REFIID iid,
         ID3D10Resource_Release(resource);
         TRACE("Created bitmap %p.\n", *bitmap);
 
+        d2d_device_release_d3d10_device(context->device, context_device);
         return S_OK;
     }
 
diff --git a/dlls/d2d1/brush.c b/dlls/d2d1/brush.c
index 07d2e26a143..cc02495a116 100644
--- a/dlls/d2d1/brush.c
+++ b/dlls/d2d1/brush.c
@@ -1267,6 +1267,7 @@ HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_brush *opacity_b
     D3D10_SUBRESOURCE_DATA buffer_data;
     struct d2d_ps_cb cb_data = {0};
     D3D10_BUFFER_DESC buffer_desc;
+    ID3D10Device *d3d10_device;
     HRESULT hr;
 
     cb_data.outline = outline;
@@ -1286,9 +1287,16 @@ HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_brush *opacity_b
     buffer_data.SysMemPitch = 0;
     buffer_data.SysMemSlicePitch = 0;
 
-    if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, ps_cb)))
+    if (FAILED(hr = d2d_device_get_d3d10_device(render_target->device, &d3d10_device)))
+    {
+        ERR("Failed to acquire D3D10 device, hr %#x.\n", hr);
+        return hr;
+    }
+
+    if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, ps_cb)))
         ERR("Failed to create constant buffer, hr %#x.\n", hr);
 
+    d2d_device_release_d3d10_device(render_target->device, d3d10_device);
     return hr;
 }
 
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 153113cafa9..cb3421478f0 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -139,7 +139,6 @@ struct d2d_device_context
 
     ID2D1Factory *factory;
     ID2D1Device *device;
-    ID3D10Device *d3d_device;
     struct d2d_bitmap *target;
     ID3D10StateBlock *stateblock;
     struct d2d_shape_resources shape_resources[D2D_SHAPE_TYPE_COUNT];
@@ -543,6 +542,9 @@ struct d2d_device
     ID3D10Multithread *d3d10_mt;
 };
 
+HRESULT d2d_device_get_d3d10_device(ID2D1Device *iface, ID3D10Device **d3d10_device) DECLSPEC_HIDDEN;
+void d2d_device_release_d3d10_device(ID2D1Device *iface, ID3D10Device *d3d10_device) DECLSPEC_HIDDEN;
+
 void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *factory, IDXGIDevice *dxgi_device) DECLSPEC_HIDDEN;
 
 struct d2d_effect
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c
index acbcab5caeb..cfa28e984f9 100644
--- a/dlls/d2d1/device.c
+++ b/dlls/d2d1/device.c
@@ -122,7 +122,7 @@ static void d2d_device_context_draw(struct d2d_device_context *render_target, en
         ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
 {
     struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
-    ID3D10Device *device = render_target->d3d_device;
+    ID3D10Device *device = NULL;
     D3D10_RECT scissor_rect;
     unsigned int offset;
     D3D10_VIEWPORT vp;
@@ -135,9 +135,16 @@ static void d2d_device_context_draw(struct d2d_device_context *render_target, en
     vp.MinDepth = 0.0f;
     vp.MaxDepth = 1.0f;
 
+    if (FAILED(hr = d2d_device_get_d3d10_device(render_target->device, &device)))
+    {
+        ERR("Failed to get ID3D10Device interface, hr %#x.\n", hr);
+        return;
+    }
+
     if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
     {
         WARN("Failed to capture stateblock, hr %#x.\n", hr);
+        d2d_device_release_d3d10_device(render_target->device, device);
         return;
     }
 
@@ -188,6 +195,8 @@ static void d2d_device_context_draw(struct d2d_device_context *render_target, en
 
     if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
         WARN("Failed to apply stateblock, hr %#x.\n", hr);
+
+    d2d_device_release_d3d10_device(render_target->device, device);
 }
 
 static void d2d_device_context_set_error(struct d2d_device_context *context, HRESULT code)
@@ -274,7 +283,6 @@ static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
         context->stateblock->lpVtbl->Release(context->stateblock);
         if (context->target)
             ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
-        ID3D10Device_Release(context->d3d_device);
         ID2D1Factory_Release(context->factory);
         ID2D1Device_Release(context->device);
         heap_free(context);
@@ -438,15 +446,23 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateGradientStopCollection
 {
     struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
     struct d2d_gradient *object;
+    ID3D10Device *d3d10_device;
     HRESULT hr;
 
     TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
             iface, stops, stop_count, gamma, extend_mode, gradient);
 
-    if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, render_target->d3d_device,
+    if (FAILED(hr = d2d_device_get_d3d10_device(render_target->device, &d3d10_device)))
+    {
+        ERR("Failed to get ID3D10Device1 interface, hr %#x.\n", hr);
+        return hr;
+    }
+
+    if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, d3d10_device,
             stops, stop_count, gamma, extend_mode, &object)))
         *gradient = &object->ID2D1GradientStopCollection_iface;
 
+    d2d_device_release_d3d10_device(render_target->device, d3d10_device);
     return hr;
 }
 
@@ -702,6 +718,7 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
     D3D10_SUBRESOURCE_DATA buffer_data;
     D3D10_BUFFER_DESC buffer_desc;
     const D2D1_MATRIX_3X2_F *w;
+    ID3D10Device *d3d10_device;
     float tmp_x, tmp_y;
     HRESULT hr;
     struct
@@ -748,9 +765,16 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
     buffer_data.SysMemPitch = 0;
     buffer_data.SysMemSlicePitch = 0;
 
-    if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
+    if (FAILED(hr = d2d_device_get_d3d10_device(render_target->device, &d3d10_device)))
+    {
+        ERR("Failed to get ID3D10Device1 interface, hr %#x.\n", hr);
+        return;
+    }
+
+    if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &vs_cb)))
     {
         WARN("Failed to create constant buffer, hr %#x.\n", hr);
+        d2d_device_release_d3d10_device(render_target->device, d3d10_device);
         return;
     }
 
@@ -758,6 +782,7 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
     {
         WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
         ID3D10Buffer_Release(vs_cb);
+        d2d_device_release_d3d10_device(render_target->device, d3d10_device);
         return;
     }
 
@@ -766,6 +791,7 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
         WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
         ID3D10Buffer_Release(vs_cb);
         ID3D10Buffer_Release(ps_cb_bezier);
+        d2d_device_release_d3d10_device(render_target->device, d3d10_device);
         return;
     }
 
@@ -775,7 +801,7 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
         buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
         buffer_data.pSysMem = geometry->outline.faces;
 
-        if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
+        if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &ib)))
         {
             WARN("Failed to create index buffer, hr %#x.\n", hr);
             goto done;
@@ -785,7 +811,7 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
         buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
         buffer_data.pSysMem = geometry->outline.vertices;
 
-        if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
+        if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &vb)))
         {
             ERR("Failed to create vertex buffer, hr %#x.\n", hr);
             ID3D10Buffer_Release(ib);
@@ -805,7 +831,7 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
         buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
         buffer_data.pSysMem = geometry->outline.bezier_faces;
 
-        if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
+        if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &ib)))
         {
             WARN("Failed to create beziers index buffer, hr %#x.\n", hr);
             goto done;
@@ -815,7 +841,7 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
         buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
         buffer_data.pSysMem = geometry->outline.beziers;
 
-        if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
+        if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &vb)))
         {
             ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
             ID3D10Buffer_Release(ib);
@@ -836,7 +862,7 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
         buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
         buffer_data.pSysMem = geometry->outline.arc_faces;
 
-        if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
+        if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &ib)))
         {
             WARN("Failed to create arcs index buffer, hr %#x.\n", hr);
             goto done;
@@ -846,7 +872,7 @@ static void d2d_device_context_draw_geometry(struct d2d_device_context *render_t
         buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
         buffer_data.pSysMem = geometry->outline.arcs;
 
-        if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
+        if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &vb)))
         {
             ERR("Failed to create arcs vertex buffer, hr %#x.\n", hr);
             ID3D10Buffer_Release(ib);
@@ -865,6 +891,7 @@ done:
     ID3D10Buffer_Release(ps_cb_arc);
     ID3D10Buffer_Release(ps_cb_bezier);
     ID3D10Buffer_Release(vs_cb);
+    d2d_device_release_d3d10_device(render_target->device, d3d10_device);
 }
 
 static void STDMETHODCALLTYPE d2d_device_context_DrawGeometry(ID2D1DeviceContext *iface,
@@ -890,6 +917,7 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t
     D3D10_SUBRESOURCE_DATA buffer_data;
     D3D10_BUFFER_DESC buffer_desc;
     D2D1_MATRIX_3X2_F *w;
+    ID3D10Device *d3d10_device;
     float tmp_x, tmp_y;
     HRESULT hr;
     struct
@@ -936,9 +964,16 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t
     buffer_data.SysMemPitch = 0;
     buffer_data.SysMemSlicePitch = 0;
 
-    if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
+    if (FAILED(hr = d2d_device_get_d3d10_device(render_target->device, &d3d10_device)))
+    {
+        ERR("Failed to get ID3D10Device1 interface, hr %#x.\n", hr);
+        return;
+    }
+
+    if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &vs_cb)))
     {
         WARN("Failed to create constant buffer, hr %#x.\n", hr);
+        d2d_device_release_d3d10_device(render_target->device, d3d10_device);
         return;
     }
 
@@ -946,6 +981,7 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t
     {
         WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
         ID3D10Buffer_Release(vs_cb);
+        d2d_device_release_d3d10_device(render_target->device, d3d10_device);
         return;
     }
 
@@ -954,6 +990,7 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t
         WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
         ID3D10Buffer_Release(vs_cb);
         ID3D10Buffer_Release(ps_cb_bezier);
+        d2d_device_release_d3d10_device(render_target->device, d3d10_device);
         return;
     }
 
@@ -963,7 +1000,7 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t
         buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
         buffer_data.pSysMem = geometry->fill.faces;
 
-        if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
+        if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &ib)))
         {
             WARN("Failed to create index buffer, hr %#x.\n", hr);
             goto done;
@@ -973,7 +1010,7 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t
         buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
         buffer_data.pSysMem = geometry->fill.vertices;
 
-        if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
+        if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &vb)))
         {
             ERR("Failed to create vertex buffer, hr %#x.\n", hr);
             ID3D10Buffer_Release(ib);
@@ -993,7 +1030,7 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t
         buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
         buffer_data.pSysMem = geometry->fill.bezier_vertices;
 
-        if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
+        if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &vb)))
         {
             ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
             goto done;
@@ -1011,7 +1048,7 @@ static void d2d_device_context_fill_geometry(struct d2d_device_context *render_t
         buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
         buffer_data.pSysMem = geometry->fill.arc_vertices;
 
-        if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
+        if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &vb)))
         {
             ERR("Failed to create arc vertex buffer, hr %#x.\n", hr);
             goto done;
@@ -1027,6 +1064,7 @@ done:
     ID3D10Buffer_Release(ps_cb_arc);
     ID3D10Buffer_Release(ps_cb_bezier);
     ID3D10Buffer_Release(vs_cb);
+    d2d_device_release_d3d10_device(render_target->device, d3d10_device);
 }
 
 static void STDMETHODCALLTYPE d2d_device_context_FillGeometry(ID2D1DeviceContext *iface,
@@ -1622,6 +1660,7 @@ static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface
     D3D10_SUBRESOURCE_DATA buffer_data;
     struct d2d_ps_cb ps_cb_data = {0};
     D3D10_BUFFER_DESC buffer_desc;
+    ID3D10Device *d3d10_device;
     ID3D10Buffer *vs_cb, *ps_cb;
     D2D1_COLOR_F *c;
     HRESULT hr;
@@ -1656,9 +1695,16 @@ static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface
     buffer_data.SysMemPitch = 0;
     buffer_data.SysMemSlicePitch = 0;
 
-    if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
+    if (FAILED(hr = d2d_device_get_d3d10_device(render_target->device, &d3d10_device)))
+    {
+        ERR("Failed to get ID3D10Device1 interface, hr %#x.\n", hr);
+        return;
+    }
+
+    if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &vs_cb)))
     {
         WARN("Failed to create constant buffer, hr %#x.\n", hr);
+        d2d_device_release_d3d10_device(render_target->device, d3d10_device);
         return;
     }
 
@@ -1679,10 +1725,11 @@ static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface
     buffer_desc.ByteWidth = sizeof(ps_cb_data);
     buffer_data.pSysMem = &ps_cb_data;
 
-    if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ps_cb)))
+    if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device, &buffer_desc, &buffer_data, &ps_cb)))
     {
         WARN("Failed to create constant buffer, hr %#x.\n", hr);
         ID3D10Buffer_Release(vs_cb);
+        d2d_device_release_d3d10_device(render_target->device, d3d10_device);
         return;
     }
 
@@ -1691,6 +1738,7 @@ static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface
 
     ID3D10Buffer_Release(ps_cb);
     ID3D10Buffer_Release(vs_cb);
+    d2d_device_release_d3d10_device(render_target->device, d3d10_device);
 }
 
 static void STDMETHODCALLTYPE d2d_device_context_BeginDraw(ID2D1DeviceContext *iface)
@@ -2028,6 +2076,7 @@ static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext *i
     struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
     struct d2d_bitmap *bitmap_impl;
     D3D10_BLEND_DESC blend_desc;
+    ID3D10Device *d3d10_device;
     ID2D1Bitmap *bitmap;
     HRESULT hr;
 
@@ -2077,8 +2126,17 @@ static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext *i
     }
     blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
     blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
-    if (FAILED(hr = ID3D10Device_CreateBlendState(context->d3d_device, &blend_desc, &context->bs)))
+
+    if (FAILED(hr = d2d_device_get_d3d10_device(context->device, &d3d10_device)))
+    {
+        ERR("Failed to get ID3D10Device1 interface, hr %#x.\n", hr);
+        return;
+    }
+
+    if (FAILED(hr = ID3D10Device_CreateBlendState(d3d10_device, &blend_desc, &context->bs)))
         WARN("Failed to create blend state, hr %#x.\n", hr);
+
+    d2d_device_release_d3d10_device(context->device, d3d10_device);
 }
 
 static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext *iface, ID2D1Image **target)
@@ -2803,17 +2861,42 @@ static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_targe
     d2d_gdi_interop_render_target_ReleaseDC,
 };
 
+HRESULT d2d_device_get_d3d10_device(ID2D1Device *iface, ID3D10Device **d3d10_device)
+{
+    struct d2d_device *device = unsafe_impl_from_ID2D1Device(iface);
+
+    if (!device->d3d10_device)
+    {
+        WARN("Failed to get device interface.\n");
+        return E_NOINTERFACE;
+    }
+
+    if (device->d3d10_mt) ID3D10Multithread_Enter(device->d3d10_mt);
+
+    ID3D10Device_AddRef(*d3d10_device = device->d3d10_device);
+    return S_OK;
+}
+
+void d2d_device_release_d3d10_device(ID2D1Device *iface, ID3D10Device *d3d10_device)
+{
+    struct d2d_device *device = unsafe_impl_from_ID2D1Device(iface);
+
+    ID3D10Device_Release(d3d10_device);
+
+    if (device->d3d10_mt) ID3D10Multithread_Leave(device->d3d10_mt);
+}
+
 static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Device *device,
         IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
 {
     D3D10_SUBRESOURCE_DATA buffer_data;
     D3D10_STATE_BLOCK_MASK state_mask;
-    struct d2d_device *device_impl;
     IDWriteFactory *dwrite_factory;
     D3D10_RASTERIZER_DESC rs_desc;
     D3D10_BUFFER_DESC buffer_desc;
     unsigned int i;
     HRESULT hr;
+    ID3D10Device *d3d10_device = NULL;
 
     static const D3D10_INPUT_ELEMENT_DESC il_desc_outline[] =
     {
@@ -3874,14 +3957,12 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
     render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
     render_target->ops = ops;
 
-    device_impl = unsafe_impl_from_ID2D1Device(device);
-    if (!device_impl->d3d10_device)
+    if (FAILED(hr = d2d_device_get_d3d10_device(device, &d3d10_device)))
     {
-        WARN("Failed to get device interface.\n");
+        ERR("Failed to get ID3D10Device interface, hr %#x.\n", hr);
         ID2D1Factory_Release(render_target->factory);
-        return E_NOINTERFACE;
+        return hr;
     }
-    ID3D10Device_AddRef(render_target->d3d_device = device_impl->d3d10_device);
 
     if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
     {
@@ -3889,7 +3970,7 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
         goto err;
     }
 
-    if (FAILED(hr = D3D10CreateStateBlock(render_target->d3d_device, &state_mask, &render_target->stateblock)))
+    if (FAILED(hr = D3D10CreateStateBlock(d3d10_device, &state_mask, &render_target->stateblock)))
     {
         WARN("Failed to create stateblock, hr %#x.\n", hr);
         goto err;
@@ -3899,14 +3980,14 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
     {
         const struct shape_info *si = &shape_info[i];
 
-        if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->d3d_device, si->il_desc, si->il_element_count,
+        if (FAILED(hr = ID3D10Device_CreateInputLayout(d3d10_device, si->il_desc, si->il_element_count,
                 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
         {
             WARN("Failed to create input layout for shape type %#x, hr %#x.\n", si->shape_type, hr);
             goto err;
         }
 
-        if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->d3d_device, si->vs_code,
+        if (FAILED(hr = ID3D10Device_CreateVertexShader(d3d10_device, si->vs_code,
                 si->vs_code_size, &render_target->shape_resources[si->shape_type].vs)))
         {
             WARN("Failed to create vertex shader for shape type %#x, hr %#x.\n", si->shape_type, hr);
@@ -3915,7 +3996,7 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
 
     }
 
-    if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->d3d_device,
+    if (FAILED(hr = ID3D10Device_CreatePixelShader(d3d10_device,
             ps_code, sizeof(ps_code), &render_target->ps)))
     {
         WARN("Failed to create pixel shader, hr %#x.\n", hr);
@@ -3932,7 +4013,7 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
     buffer_data.SysMemPitch = 0;
     buffer_data.SysMemSlicePitch = 0;
 
-    if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
+    if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device,
             &buffer_desc, &buffer_data, &render_target->ib)))
     {
         WARN("Failed to create clear index buffer, hr %#x.\n", hr);
@@ -3944,7 +4025,7 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
     buffer_data.pSysMem = quad;
 
     render_target->vb_stride = sizeof(*quad);
-    if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
+    if (FAILED(hr = ID3D10Device_CreateBuffer(d3d10_device,
             &buffer_desc, &buffer_data, &render_target->vb)))
     {
         WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
@@ -3961,7 +4042,7 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
     rs_desc.ScissorEnable = TRUE;
     rs_desc.MultisampleEnable = FALSE;
     rs_desc.AntialiasedLineEnable = FALSE;
-    if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->d3d_device, &rs_desc, &render_target->rs)))
+    if (FAILED(hr = ID3D10Device_CreateRasterizerState(d3d10_device, &rs_desc, &render_target->rs)))
     {
         WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
         goto err;
@@ -3994,6 +4075,7 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
     render_target->desc.dpiX = 96.0f;
     render_target->desc.dpiY = 96.0f;
 
+    d2d_device_release_d3d10_device(render_target->device, d3d10_device);
     return S_OK;
 
 err:
@@ -4016,8 +4098,7 @@ err:
     }
     if (render_target->stateblock)
         render_target->stateblock->lpVtbl->Release(render_target->stateblock);
-    if (render_target->d3d_device)
-        ID3D10Device_Release(render_target->d3d_device);
+    d2d_device_release_d3d10_device(render_target->device, d3d10_device);
     ID2D1Device_Release(render_target->device);
     ID2D1Factory_Release(render_target->factory);
     return hr;
diff --git a/dlls/d2d1/wic_render_target.c b/dlls/d2d1/wic_render_target.c
index 9b57a5d2c34..2d8d7edcd9b 100644
--- a/dlls/d2d1/wic_render_target.c
+++ b/dlls/d2d1/wic_render_target.c
@@ -31,15 +31,34 @@ static HRESULT d2d_wic_render_target_present(IUnknown *outer_unknown)
 {
     struct d2d_wic_render_target *render_target = impl_from_IUnknown(outer_unknown);
     D3D10_MAPPED_TEXTURE2D mapped_texture;
+    ID2D1DeviceContext *d2d1_context;
     ID3D10Resource *src_resource;
     IWICBitmapLock *bitmap_lock;
     UINT dst_size, dst_pitch;
     ID3D10Device *device;
+    ID2D1Device *d2d1_device;
     WICRect dst_rect;
     BYTE *src, *dst;
     unsigned int i;
     HRESULT hr;
 
+    if (FAILED(hr = ID2D1RenderTarget_QueryInterface(render_target->dxgi_target,
+            &IID_ID2D1DeviceContext, (void **)&d2d1_context)))
+    {
+        WARN("Failed to retrieve ID2D1DeviceContext interface, hr %#x.\n", hr);
+        return hr;
+    }
+
+    ID2D1DeviceContext_GetDevice(d2d1_context, &d2d1_device);
+
+    if (FAILED(hr = d2d_device_get_d3d10_device(d2d1_device, &device)))
+    {
+        ERR("Failed to get ID3D10Device interface, hr %#x.\n", hr);
+        ID2D1DeviceContext_Release(d2d1_context);
+        ID2D1Device_Release(d2d1_device);
+        return hr;
+    }
+
     if (FAILED(hr = IDXGISurface_QueryInterface(render_target->dxgi_surface,
             &IID_ID3D10Resource, (void **)&src_resource)))
     {
@@ -47,9 +66,7 @@ static HRESULT d2d_wic_render_target_present(IUnknown *outer_unknown)
         goto end;
     }
 
-    ID3D10Texture2D_GetDevice(render_target->readback_texture, &device);
     ID3D10Device_CopyResource(device, (ID3D10Resource *)render_target->readback_texture, src_resource);
-    ID3D10Device_Release(device);
     ID3D10Resource_Release(src_resource);
 
     dst_rect.X = 0;
@@ -96,6 +113,9 @@ static HRESULT d2d_wic_render_target_present(IUnknown *outer_unknown)
     IWICBitmapLock_Release(bitmap_lock);
 
 end:
+    d2d_device_release_d3d10_device(d2d1_device, device);
+    ID2D1DeviceContext_Release(d2d1_context);
+    ID2D1Device_Release(d2d1_device);
     return S_OK;
 }
 
-- 
2.30.0




More information about the wine-devel mailing list