[PATCH v3 1/3] d2d1: Implement ID2D1Bitmap1::Map().

Dmitry Timoshkov dmitry at baikal.ru
Fri May 27 04:22:27 CDT 2022


v2: Support only D2D1_MAP_OPTIONS_READ and always use staging resource.
v3: Handle texture creation failure, fix staging resource leak.

Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
 dlls/d2d1/bitmap.c       | 53 ++++++++++++++++++++++++++++++++++++++--
 dlls/d2d1/d2d1_private.h |  1 +
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c
index 971e3c7ff6b..a75a9be62be 100644
--- a/dlls/d2d1/bitmap.c
+++ b/dlls/d2d1/bitmap.c
@@ -66,6 +66,8 @@ static ULONG STDMETHODCALLTYPE d2d_bitmap_Release(ID2D1Bitmap1 *iface)
 
     if (!refcount)
     {
+        if (bitmap->staging_resource)
+            ID3D11Resource_Release(bitmap->staging_resource);
         if (bitmap->srv)
             ID3D11ShaderResourceView_Release(bitmap->srv);
         if (bitmap->rtv)
@@ -229,9 +231,56 @@ static HRESULT STDMETHODCALLTYPE d2d_bitmap_GetSurface(ID2D1Bitmap1 *iface, IDXG
 static HRESULT STDMETHODCALLTYPE d2d_bitmap_Map(ID2D1Bitmap1 *iface, D2D1_MAP_OPTIONS options,
         D2D1_MAPPED_RECT *mapped_rect)
 {
-    FIXME("iface %p, options %#x, mapped_rect %p stub!\n", iface, options, mapped_rect);
+    struct d2d_bitmap *bitmap = impl_from_ID2D1Bitmap1(iface);
+    ID3D11Device *device;
+    ID3D11DeviceContext *context;
+    D3D11_TEXTURE2D_DESC texture_desc;
+    ID3D11Texture2D *staging_texture;
+    D3D11_MAPPED_SUBRESOURCE mapped_subresource;
+    HRESULT hr;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, options %#x, mapped_rect %p.\n", iface, options, mapped_rect);
+
+    if (options != D2D1_MAP_OPTIONS_READ)
+    {
+        FIXME("Unhandled map options %#x.\n", options);
+        return E_INVALIDARG;
+    }
+
+    if (!(bitmap->options & D2D1_BITMAP_OPTIONS_CPU_READ))
+        return E_INVALIDARG;
+
+    if (bitmap->staging_resource)
+        return D2DERR_WRONG_STATE;
+
+    ID3D11Resource_GetDevice(bitmap->resource, &device);
+    ID3D11Device_GetImmediateContext(device, &context);
+    ID3D11Texture2D_GetDesc((ID3D11Texture2D *)bitmap->resource, &texture_desc);
+
+    texture_desc.Usage = D3D11_USAGE_STAGING;
+    texture_desc.BindFlags = 0;
+    texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+    if (SUCCEEDED(hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &staging_texture)))
+    {
+        ID3D11DeviceContext_CopyResource(context, (ID3D11Resource *)staging_texture, bitmap->resource);
+        if (SUCCEEDED(hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)staging_texture, 0,
+                D3D11_MAP_READ, 0, &mapped_subresource)))
+        {
+            mapped_rect->pitch = mapped_subresource.RowPitch;
+            mapped_rect->bits = mapped_subresource.pData;
+            bitmap->staging_resource = (ID3D11Resource *)staging_texture;
+        }
+        else
+        {
+            WARN("Failed to map resource, hr %#lx.\n", hr);
+            ID3D11Texture2D_Release(staging_texture);
+        }
+    }
+
+    ID3D11DeviceContext_Release(context);
+    ID3D11Device_Release(device);
+
+    return hr;
 }
 
 static HRESULT STDMETHODCALLTYPE d2d_bitmap_Unmap(ID2D1Bitmap1 *iface)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 8edfa030ee1..b886ac52dd9 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -395,6 +395,7 @@ struct d2d_bitmap
     ID3D11RenderTargetView *rtv;
     IDXGISurface *surface;
     ID3D11Resource *resource;
+    ID3D11Resource *staging_resource;
     D2D1_SIZE_U pixel_size;
     D2D1_PIXEL_FORMAT format;
     float dpi_x;
-- 
2.36.1




More information about the wine-devel mailing list