[PATCH 9/9] d2d1: Partially implement ID2D1Bitmap1

Lucian Poston lucian.poston at gmail.com
Tue Nov 21 02:41:13 CST 2017


https://bugs.winehq.org/show_bug.cgi?id=44052

Signed-off-by: Lucian Poston <lucian.poston at gmail.com>
---
 dlls/d2d1/bitmap.c         | 132 ++++++++++++++++++++++++++++++++++++++++-----
 dlls/d2d1/d2d1_private.h   |   6 +++
 dlls/d2d1/device_context.c |  51 +++++++++++++++++-
 3 files changed, 173 insertions(+), 16 deletions(-)

diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c
index 54202a6b13..576645f05e 100644
--- a/dlls/d2d1/bitmap.c
+++ b/dlls/d2d1/bitmap.c
@@ -29,6 +29,30 @@ static inline struct d2d_bitmap *impl_from_ID2D1Bitmap(ID2D1Bitmap1 *iface)
     return CONTAINING_RECORD(iface, struct d2d_bitmap, ID2D1Bitmap_iface);
 }
 
+static D2D1_BITMAP_PROPERTIES1 bitmap_properties_to_properties1(
+        const D2D1_BITMAP_PROPERTIES *desc)
+{
+    D2D1_BITMAP_PROPERTIES1 d;
+    d.bitmapOptions = D2D1_BITMAP_OPTIONS_NONE;
+    d.colorContext = NULL;
+    if (desc == NULL)
+    {
+        d.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
+        d.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
+        d.dpiX = 96.0f;
+        d.dpiY = 96.0f;
+    }
+    else
+    {
+        d.pixelFormat.format = desc->pixelFormat.format;
+        d.pixelFormat.alphaMode = desc->pixelFormat.alphaMode;
+        d.dpiX = desc->dpiX;
+        d.dpiY = desc->dpiY;
+    }
+
+    return d;
+}
+
 static HRESULT STDMETHODCALLTYPE d2d_bitmap_QueryInterface(ID2D1Bitmap1 *iface, REFIID iid, void **out)
 {
     TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
@@ -69,6 +93,10 @@ static ULONG STDMETHODCALLTYPE d2d_bitmap_Release(ID2D1Bitmap1 *iface)
 
     if (!refcount)
     {
+        if (bitmap->color_context)
+            ID2D1ColorContext_Release(bitmap->color_context);
+        if (bitmap->surface)
+            IDXGISurface_Release(bitmap->surface);
         ID3D10ShaderResourceView_Release(bitmap->view);
         ID2D1Factory_Release(bitmap->factory);
         HeapFree(GetProcessHeap(), 0, bitmap);
@@ -193,8 +221,19 @@ static HRESULT WINAPI d2d_bitmap1_GetSurface(
         IDXGISurface **dxgiSurface)
 {
     struct d2d_bitmap *This = impl_from_ID2D1Bitmap(iface);
-    FIXME("%p stub!\n", This);
-    return E_NOTIMPL;
+
+    TRACE("This %p, dxgiSurface %p.\n", This, dxgiSurface);
+    if (dxgiSurface == NULL)
+        return E_POINTER;
+
+    if (This->surface)
+    {
+        IDXGISurface_AddRef(This->surface);
+    }
+
+    *dxgiSurface = This->surface;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI d2d_bitmap1_Map(
@@ -271,7 +310,8 @@ static BOOL format_supported(const D2D1_PIXEL_FORMAT *format)
 }
 
 static void d2d_bitmap_init(struct d2d_bitmap *bitmap, ID2D1Factory *factory,
-        ID3D10ShaderResourceView *view, D2D1_SIZE_U size, const D2D1_BITMAP_PROPERTIES *desc)
+        ID3D10ShaderResourceView *view, D2D1_SIZE_U size, const D2D1_BITMAP_PROPERTIES1 *desc,
+        IDXGISurface *surface)
 {
     bitmap->ID2D1Bitmap_iface.lpVtbl = &d2d_bitmap_vtbl;
     bitmap->refcount = 1;
@@ -281,6 +321,12 @@ static void d2d_bitmap_init(struct d2d_bitmap *bitmap, ID2D1Factory *factory,
     bitmap->format = desc->pixelFormat;
     bitmap->dpi_x = desc->dpiX;
     bitmap->dpi_y = desc->dpiY;
+    bitmap->options = desc->bitmapOptions;
+    if (surface)
+        IDXGISurface_AddRef(bitmap->surface = surface);
+
+    if (desc->colorContext)
+        FIXME("Ignoring ID2D1ColorContext");
 
     if (bitmap->dpi_x == 0.0f && bitmap->dpi_y == 0.0f)
     {
@@ -292,16 +338,18 @@ static void d2d_bitmap_init(struct d2d_bitmap *bitmap, ID2D1Factory *factory,
 HRESULT d2d_bitmap_create(ID2D1Factory *factory, ID3D10Device *device, D2D1_SIZE_U size, const void *src_data,
         UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, struct d2d_bitmap **bitmap)
 {
+    D2D1_BITMAP_PROPERTIES1 d = bitmap_properties_to_properties1(desc);
     D3D10_SUBRESOURCE_DATA resource_data;
     D3D10_TEXTURE2D_DESC texture_desc;
     ID3D10ShaderResourceView *view;
     ID3D10Texture2D *texture;
+    IDXGISurface *surface;
     HRESULT hr;
 
-    if (!format_supported(&desc->pixelFormat))
+    if (!format_supported(&d.pixelFormat))
     {
         WARN("Tried to create bitmap with unsupported format {%#x / %#x}.\n",
-                desc->pixelFormat.format, desc->pixelFormat.alphaMode);
+                d.pixelFormat.format, d.pixelFormat.alphaMode);
         return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
     }
 
@@ -309,7 +357,7 @@ HRESULT d2d_bitmap_create(ID2D1Factory *factory, ID3D10Device *device, D2D1_SIZE
     texture_desc.Height = size.height;
     texture_desc.MipLevels = 1;
     texture_desc.ArraySize = 1;
-    texture_desc.Format = desc->pixelFormat.format;
+    texture_desc.Format = d.pixelFormat.format;
     texture_desc.SampleDesc.Count = 1;
     texture_desc.SampleDesc.Quality = 0;
     texture_desc.Usage = D3D10_USAGE_DEFAULT;
@@ -327,29 +375,87 @@ HRESULT d2d_bitmap_create(ID2D1Factory *factory, ID3D10Device *device, D2D1_SIZE
         return hr;
     }
 
+    if (FAILED(hr = ID3D10Texture2D_QueryInterface(texture, &IID_IDXGISurface, (void **)&surface)))
+    {
+        surface = NULL;
+        WARN("Texture2D had no underlying DXGISurface");
+    }
+
     hr = ID3D10Device_CreateShaderResourceView(device, (ID3D10Resource *)texture, NULL, &view);
     ID3D10Texture2D_Release(texture);
     if (FAILED(hr))
     {
+        if (surface) IDXGISurface_Release(surface);
         ERR("Failed to create view, hr %#x.\n", hr);
         return hr;
     }
 
     if ((*bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**bitmap))))
     {
-        d2d_bitmap_init(*bitmap, factory, view, size, desc);
+        d2d_bitmap_init(*bitmap, factory, view, size, &d, surface);
         TRACE("Created bitmap %p.\n", *bitmap);
     }
 
     ID3D10ShaderResourceView_Release(view);
+    if (surface) IDXGISurface_Release(surface);
 
     return *bitmap ? S_OK : E_OUTOFMEMORY;
 }
 
+HRESULT d2d_bitmap_create_from_dxgi(ID2D1Factory *factory, IDXGISurface *surface,
+        D2D1_SIZE_U size, const void *src_data, UINT32 pitch,
+        const D2D1_BITMAP_PROPERTIES1 *desc, struct d2d_bitmap **bitmap)
+{
+    ID3D10ShaderResourceView *view;
+    DXGI_SURFACE_DESC surface_desc;
+    ID3D10Resource *resource;
+    D2D1_SIZE_U pixel_size;
+    ID3D10Device *device;
+    HRESULT hr;
+
+    if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
+    {
+        WARN("Failed to get surface desc, hr %#x.\n", hr);
+        return hr;
+    }
+
+    pixel_size.width = surface_desc.Width;
+    pixel_size.height = surface_desc.Height;
+
+    if (FAILED(IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource,
+                    (void **)&resource)))
+    {
+        WARN("Failed to get d3d10 resource from dxgi surface.\n");
+        return E_FAIL;
+    }
+
+    ID3D10Resource_GetDevice(resource, &device);
+    hr = ID3D10Device_CreateShaderResourceView(device, resource, NULL, &view);
+    ID3D10Device_Release(device);
+    ID3D10Resource_Release(resource);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create shader resource view, hr %#x.\n", hr);
+        return hr;
+    }
+
+    if (!(*bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**bitmap))))
+    {
+        ID3D10ShaderResourceView_Release(view);
+        return E_OUTOFMEMORY;
+    }
+
+    d2d_bitmap_init(*bitmap, factory, view, pixel_size, desc, surface);
+    ID3D10ShaderResourceView_Release(view);
+    TRACE("Created bitmap %p.\n", *bitmap);
+
+    return S_OK;
+}
+
 HRESULT d2d_bitmap_create_shared(ID2D1RenderTarget *render_target, ID3D10Device *target_device,
         REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, struct d2d_bitmap **bitmap)
 {
-    D2D1_BITMAP_PROPERTIES d;
+    D2D1_BITMAP_PROPERTIES1 d = bitmap_properties_to_properties1(desc);
     ID2D1Factory *factory;
 
     if (IsEqualGUID(iid, &IID_ID2D1Bitmap))
@@ -378,13 +484,12 @@ HRESULT d2d_bitmap_create_shared(ID2D1RenderTarget *render_target, ID3D10Device
             d.pixelFormat = src_impl->format;
             d.dpiX = src_impl->dpi_x;
             d.dpiY = src_impl->dpi_y;
-            desc = &d;
         }
 
-        if (!format_supported(&desc->pixelFormat))
+        if (!format_supported(&d.pixelFormat))
         {
             WARN("Tried to create bitmap with unsupported format {%#x / %#x}.\n",
-                    desc->pixelFormat.format, desc->pixelFormat.alphaMode);
+                    d.pixelFormat.format, d.pixelFormat.alphaMode);
             hr = D2DERR_UNSUPPORTED_PIXEL_FORMAT;
             goto failed;
         }
@@ -395,7 +500,7 @@ HRESULT d2d_bitmap_create_shared(ID2D1RenderTarget *render_target, ID3D10Device
             goto failed;
         }
 
-        d2d_bitmap_init(*bitmap, factory, src_impl->view, src_impl->pixel_size, desc);
+        d2d_bitmap_init(*bitmap, factory, src_impl->view, src_impl->pixel_size, &d, src_impl->surface);
         TRACE("Created bitmap %p.\n", *bitmap);
 
     failed:
@@ -441,7 +546,6 @@ HRESULT d2d_bitmap_create_shared(ID2D1RenderTarget *render_target, ID3D10Device
             return E_OUTOFMEMORY;
         }
 
-        d = *desc;
         if (d.dpiX == 0.0f || d.dpiY == 0.0f)
         {
             float dpi_x, dpi_y;
@@ -464,7 +568,7 @@ HRESULT d2d_bitmap_create_shared(ID2D1RenderTarget *render_target, ID3D10Device
         pixel_size.height = surface_desc.Height;
 
         ID2D1RenderTarget_GetFactory(render_target, &factory);
-        d2d_bitmap_init(*bitmap, factory, view, pixel_size, &d);
+        d2d_bitmap_init(*bitmap, factory, view, pixel_size, &d, surface);
         ID3D10ShaderResourceView_Release(view);
         ID2D1Factory_Release(factory);
         TRACE("Created bitmap %p.\n", *bitmap);
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 90ccc66a7d..c42b94886a 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -333,10 +333,16 @@ struct d2d_bitmap
     D2D1_PIXEL_FORMAT format;
     float dpi_x;
     float dpi_y;
+    D2D1_BITMAP_OPTIONS options;
+    ID2D1ColorContext *color_context;
+    IDXGISurface *surface;
 };
 
 HRESULT d2d_bitmap_create(ID2D1Factory *factory, ID3D10Device *device, D2D1_SIZE_U size, const void *src_data,
         UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, struct d2d_bitmap **bitmap) DECLSPEC_HIDDEN;
+HRESULT d2d_bitmap_create_from_dxgi(ID2D1Factory *factory, IDXGISurface *surface,
+        D2D1_SIZE_U size, const void *src_data, UINT32 pitch,
+        const D2D1_BITMAP_PROPERTIES1 *desc, struct d2d_bitmap **bitmap) DECLSPEC_HIDDEN;
 HRESULT d2d_bitmap_create_shared(ID2D1RenderTarget *render_target, ID3D10Device *device, REFIID iid, void *data,
         const D2D1_BITMAP_PROPERTIES *desc, struct d2d_bitmap **bitmap) DECLSPEC_HIDDEN;
 HRESULT d2d_bitmap_create_from_wic_bitmap(ID2D1Factory *factory, ID3D10Device *device, IWICBitmapSource *bitmap_source,
diff --git a/dlls/d2d1/device_context.c b/dlls/d2d1/device_context.c
index ef0fb88cba..b8b814935b 100644
--- a/dlls/d2d1/device_context.c
+++ b/dlls/d2d1/device_context.c
@@ -718,8 +718,55 @@ static HRESULT WINAPI d2d_device_context_CreateBitmapFromDxgiSurface(
         ID2D1Bitmap1 **bitmap)
 {
     struct d2d_device_context *This = impl_from_ID2D1DeviceContext(iface);
-    FIXME("%p stub!\n", This);
-    return E_NOTIMPL;
+    struct d2d_bitmap *bitmap_impl;
+    DXGI_MAPPED_RECT locked_rect;
+    D2D1_BITMAP_PROPERTIES1 bitmap_desc;
+    HRESULT hr;
+    DXGI_SURFACE_DESC dxgi_surface_desc;
+    D2D1_SIZE_U size;
+    ID2D1Factory *factory;
+
+    TRACE("This %p, surface %p, bitmapProperties %p, bitmap %p.\n",
+            This, surface, bitmapProperties, bitmap);
+    if (surface == NULL || bitmap == NULL)
+        return E_POINTER;
+
+    if (FAILED(hr = IDXGISurface_GetDesc(surface, &dxgi_surface_desc)))
+    {
+        WARN("Failed to get surface description, hr %#x.\n", hr);
+        return hr;
+    }
+
+    size.width = dxgi_surface_desc.Width;
+    size.height = dxgi_surface_desc.Height;
+
+    if (bitmapProperties == NULL)
+    {
+        bitmap_desc.pixelFormat.format = dxgi_surface_desc.Format;
+        bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
+        bitmap_desc.dpiX = 96.0f;
+        bitmap_desc.dpiY = 96.0f;
+        bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_NONE;
+        bitmap_desc.colorContext = NULL;
+    }
+    else
+    {
+        bitmap_desc = *bitmapProperties;
+    }
+
+    ID2D1Device_GetFactory(This->device, &factory);
+    hr = d2d_bitmap_create_from_dxgi(factory, surface, size, locked_rect.pBits,
+                    locked_rect.Pitch, &bitmap_desc, &bitmap_impl);
+    ID2D1Factory_Release(factory);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create bitmap, hr %#x.\n", hr);
+        return hr;
+    }
+
+    *bitmap = &bitmap_impl->ID2D1Bitmap_iface;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI d2d_device_context_CreateEffect(
-- 
2.13.6




More information about the wine-devel mailing list