Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/tests/d2d1.c | 163 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 148 insertions(+), 15 deletions(-)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 3005b43e44..dcd8c30688 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -795,6 +795,8 @@ static void check_bitmap_surface_(unsigned int line, ID2D1Bitmap *bitmap, BOOL h { D3D10_TEXTURE2D_DESC desc; ID3D10Texture2D *texture; + D2D1_SIZE_U pixel_size; + DWORD bind_flags;
ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get bitmap surface, hr %#x.\n", hr); ok_(__FILE__, line)(!!surface, "Expected surface instance.\n"); @@ -805,12 +807,29 @@ static void check_bitmap_surface_(unsigned int line, ID2D1Bitmap *bitmap, BOOL h
ID3D10Texture2D_GetDesc(texture, &desc); ok_(__FILE__, line)(desc.Usage == 0, "Unexpected usage %#x.\n", desc.Usage); - ok_(__FILE__, line)(desc.BindFlags == (options & D2D1_BITMAP_OPTIONS_TARGET ? - D3D10_BIND_RENDER_TARGET : D3D10_BIND_SHADER_RESOURCE), - "Unexpected bind flags %#x, bitmap options %#x.\n", desc.BindFlags, options); + + switch (options & (D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW)) + { + case D2D1_BITMAP_OPTIONS_TARGET: + bind_flags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; + break; + case D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW: + bind_flags = D3D10_BIND_RENDER_TARGET; + break; + default: + bind_flags = D3D10_BIND_SHADER_RESOURCE; + break; + } + + ok_(__FILE__, line)(desc.BindFlags == bind_flags, "Unexpected bind flags %#x, bitmap options %#x.\n", + desc.BindFlags, options); ok_(__FILE__, line)(desc.CPUAccessFlags == 0, "Unexpected cpu access flags %#x.\n", desc.CPUAccessFlags); ok_(__FILE__, line)(desc.MiscFlags == 0, "Unexpected misc flags %#x.\n", desc.MiscFlags);
+ pixel_size = ID2D1Bitmap_GetPixelSize(bitmap); + ok_(__FILE__, line)(desc.Width == pixel_size.width && desc.Height == pixel_size.height, + "Mismatching texture size.\n"); + ID3D10Texture2D_Release(texture);
IDXGISurface_Release(surface); @@ -5234,6 +5253,96 @@ static void test_hwnd_target(void) ID2D1Factory_Release(factory); }
+static void test_compatible_target_size(ID2D1RenderTarget *rt) +{ + static const D2D1_SIZE_F size_1_0 = { 1.0f, 0.0f }; + static const D2D1_SIZE_F size_1_1 = { 1.0f, 1.0f }; + static const D2D1_SIZE_U px_size_1_1 = { 1, 1 }; + static const D2D1_SIZE_U zero_px_size; + static const D2D1_SIZE_F zero_size; + static const struct size_test + { + const D2D1_SIZE_U *pixel_size; + const D2D1_SIZE_F *size; + } + size_tests[] = + { + { &zero_px_size, NULL }, + { &zero_px_size, &zero_size }, + { NULL, &zero_size }, + { NULL, &size_1_0 }, + { &px_size_1_1, &size_1_1 }, + }; + float dpi_x, dpi_y, rt_dpi_x, rt_dpi_y; + D2D1_SIZE_U pixel_size, expected_size; + ID2D1BitmapRenderTarget *bitmap_rt; + ID2D1DeviceContext *context; + unsigned int i; + HRESULT hr; + + ID2D1RenderTarget_GetDpi(rt, &rt_dpi_x, &rt_dpi_y); + + for (i = 0; i < ARRAY_SIZE(size_tests); ++i) + { + hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, size_tests[i].size, size_tests[i].pixel_size, NULL, + D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &bitmap_rt); + todo_wine + ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr); + if (FAILED(hr)) + return; + + if (size_tests[i].pixel_size) + expected_size = *size_tests[i].pixel_size; + else if (size_tests[i].size) + { + expected_size.width = ceilf((size_tests[i].size->width * rt_dpi_x) / 96.0f); + expected_size.height = ceilf((size_tests[i].size->height * rt_dpi_y) / 96.0f); + } + else + expected_size = ID2D1RenderTarget_GetPixelSize(rt); + + pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(bitmap_rt); + ok(!memcmp(&pixel_size, &expected_size, sizeof(pixel_size)), "%u: unexpected target size %u x %u.\n", + i, pixel_size.width, pixel_size.height); + + ID2D1BitmapRenderTarget_GetDpi(bitmap_rt, &dpi_x, &dpi_y); + if (size_tests[i].pixel_size && size_tests[i].size && size_tests[i].size->width != 0.0f + && size_tests[i].size->height != 0.0f) + { + ok(dpi_x == pixel_size.width * 96.0f / size_tests[i].size->width + && dpi_y == pixel_size.height * 96.0f / size_tests[i].size->height, + "%u: unexpected target dpi %.8e x %.8e.\n", i, dpi_x, dpi_y); + } + else + ok(dpi_x == rt_dpi_x && dpi_y == rt_dpi_y, "%u: unexpected target dpi %.8e x %.8e.\n", i, dpi_x, dpi_y); + ID2D1BitmapRenderTarget_Release(bitmap_rt); + } + + pixel_size.height = pixel_size.width = 0; + hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, NULL, &pixel_size, NULL, + D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &bitmap_rt); + ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr); + + if (SUCCEEDED(ID2D1BitmapRenderTarget_QueryInterface(bitmap_rt, &IID_ID2D1DeviceContext, (void **)&context))) + { + ID2D1Bitmap *bitmap; + + pixel_size = ID2D1DeviceContext_GetPixelSize(context); + ok(pixel_size.width == 0 && pixel_size.height == 0, "Unexpected target size %u x %u.\n", + pixel_size.width, pixel_size.height); + + ID2D1DeviceContext_GetTarget(context, (ID2D1Image **)&bitmap); + pixel_size = ID2D1Bitmap_GetPixelSize(bitmap); + ok(pixel_size.width == 0 && pixel_size.height == 0, "Unexpected target size %u x %u.\n", + pixel_size.width, pixel_size.height); + ID2D1Bitmap_Release(bitmap); + + ID2D1DeviceContext_Release(context); + } + + ID2D1BitmapRenderTarget_Release(bitmap_rt); +} + static void test_bitmap_target(void) { D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc; @@ -5280,6 +5389,8 @@ static void test_bitmap_target(void) hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &hwnd_rt); ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
+ test_compatible_target_size((ID2D1RenderTarget *)hwnd_rt); + hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, NULL, NULL, NULL, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt); ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr); @@ -5393,13 +5504,15 @@ static void test_bitmap_target(void) desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT; desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; - desc.dpiX = 96.0f; + desc.dpiX = 192.0f; desc.dpiY = 96.0f; desc.usage = D2D1_RENDER_TARGET_USAGE_NONE; desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT; hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &dc_rt); ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
+ test_compatible_target_size((ID2D1RenderTarget *)dc_rt); + hr = ID2D1DCRenderTarget_CreateCompatibleRenderTarget(dc_rt, NULL, NULL, NULL, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt); ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr); @@ -6748,13 +6861,13 @@ static void test_create_device(void) #define check_rt_bitmap_surface(r, s, o) check_rt_bitmap_surface_(__LINE__, r, s, o) static void check_rt_bitmap_surface_(unsigned int line, ID2D1RenderTarget *rt, BOOL has_surface, DWORD options) { + ID2D1BitmapRenderTarget *compatible_rt; D2D1_BITMAP_PROPERTIES bitmap_desc; - ID2D1RenderTarget *compatible_rt; IWICImagingFactory *wic_factory; + ID2D1Bitmap *bitmap, *bitmap2; ID2D1DeviceContext *context; ID2D1DCRenderTarget *dc_rt; IWICBitmap *wic_bitmap; - ID2D1Bitmap *bitmap; ID2D1Image *target; D2D1_SIZE_U size; HRESULT hr; @@ -6833,10 +6946,10 @@ static void check_rt_bitmap_surface_(unsigned int line, ID2D1RenderTarget *rt, B ID2D1DeviceContext_GetDevice(context, &device);
hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, NULL, NULL, NULL, - D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, (ID2D1BitmapRenderTarget **)&compatible_rt); + D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &compatible_rt); ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create compatible render target, hr %#x.\n", hr);
- hr = ID2D1RenderTarget_QueryInterface(compatible_rt, &IID_ID2D1DeviceContext, (void **)&context2); + hr = ID2D1BitmapRenderTarget_QueryInterface(compatible_rt, &IID_ID2D1DeviceContext, (void **)&context2); ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get device context, hr %#x.\n", hr);
ID2D1DeviceContext_GetDevice(context2, &device2); @@ -6845,20 +6958,34 @@ static void check_rt_bitmap_surface_(unsigned int line, ID2D1RenderTarget *rt, B ID2D1Device_Release(device); ID2D1Device_Release(device2);
- ID2D1DeviceContext_Release(context2); - - hr = ID2D1RenderTarget_CreateBitmap(compatible_rt, size, bitmap_data, sizeof(*bitmap_data), &bitmap_desc, &bitmap); + hr = ID2D1BitmapRenderTarget_CreateBitmap(compatible_rt, size, bitmap_data, sizeof(*bitmap_data), &bitmap_desc, &bitmap); ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr); - check_bitmap_surface_(line, bitmap, has_surface, options); - ID2D1RenderTarget_Release(compatible_rt); + ID2D1Bitmap_Release(bitmap);
+ hr = ID2D1BitmapRenderTarget_GetBitmap(compatible_rt, &bitmap); + ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to get compatible target bitmap, hr %#x.\n", hr); + + bitmap2 = NULL; + ID2D1DeviceContext_GetTarget(context2, (ID2D1Image **)&bitmap2); + todo_wine + ok_(__FILE__, line)(bitmap2 == bitmap, "Unexpected bitmap.\n"); + + if (bitmap2) + { + check_bitmap_surface_(line, bitmap, has_surface, D2D1_BITMAP_OPTIONS_TARGET); + + ID2D1Bitmap_Release(bitmap2); + } ID2D1Bitmap_Release(bitmap); + + ID2D1BitmapRenderTarget_Release(compatible_rt); + ID2D1DeviceContext_Release(context2); } else { hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, NULL, NULL, NULL, - D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, (ID2D1BitmapRenderTarget **)&compatible_rt); + D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &compatible_rt); todo_wine ok_(__FILE__, line)(hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT, "Unexpected hr %#x.\n", hr); } @@ -7024,7 +7151,13 @@ if (SUCCEEDED(hr)) hr = ID2D1Factory1_CreateDCRenderTarget(factory, &rt_desc, (ID2D1DCRenderTarget **)&rt); ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
- check_rt_bitmap_surface(rt, FALSE, D2D1_BITMAP_OPTIONS_NONE); + hr = ID2D1RenderTarget_QueryInterface(rt, &IID_ID2D1DeviceContext, (void **)&device_context); + ok(SUCCEEDED(hr), "Failed to get device context, hr %#x.\n", hr); + + ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap); + ok(!bitmap, "Unexpected target.\n"); + + ID2D1DeviceContext_Release(device_context); ID2D1RenderTarget_Release(rt);
/* HWND target */
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/device.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index be31ecafc8..d1c1845171 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -1783,10 +1783,17 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBit D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap) { - FIXME("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p stub!\n", + struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface); + struct d2d_bitmap *object; + HRESULT hr; + + TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n", iface, size.width, size.height, src_data, pitch, desc, bitmap);
- return E_NOTIMPL; + if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc, &object))) + *bitmap = &object->ID2D1Bitmap1_iface; + + return hr; }
static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap(
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/bitmap.c | 12 ++++++++++-- dlls/d2d1/tests/d2d1.c | 24 +++++++++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c index 85514627ca..fde348fa1c 100644 --- a/dlls/d2d1/bitmap.c +++ b/dlls/d2d1/bitmap.c @@ -315,8 +315,16 @@ HRESULT d2d_bitmap_create(struct d2d_device_context *context, D2D1_SIZE_U size, return D2DERR_UNSUPPORTED_PIXEL_FORMAT; }
- texture_desc.Width = size.width; - texture_desc.Height = size.height; + if (size.width == 0 || size.height == 0) + { + texture_desc.Width = 1; + texture_desc.Height = 1; + } + else + { + texture_desc.Width = size.width; + texture_desc.Height = size.height; + } texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = desc->pixelFormat.format; diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index dcd8c30688..80660b00f9 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -827,7 +827,10 @@ static void check_bitmap_surface_(unsigned int line, ID2D1Bitmap *bitmap, BOOL h ok_(__FILE__, line)(desc.MiscFlags == 0, "Unexpected misc flags %#x.\n", desc.MiscFlags);
pixel_size = ID2D1Bitmap_GetPixelSize(bitmap); - ok_(__FILE__, line)(desc.Width == pixel_size.width && desc.Height == pixel_size.height, + if (pixel_size.width == 0 || pixel_size.height == 0) + ok_(__FILE__, line)(desc.Width == 1 && desc.Height == 1, "Expected dummy 1x1 texture.\n"); + else + ok_(__FILE__, line)(desc.Width == pixel_size.width && desc.Height == pixel_size.height, "Mismatching texture size.\n");
ID3D10Texture2D_Release(texture); @@ -6890,6 +6893,25 @@ static void check_rt_bitmap_surface_(unsigned int line, ID2D1RenderTarget *rt, B
ID2D1Bitmap_Release(bitmap);
+ /* Zero sized bitmaps. */ + set_size_u(&size, 0, 0); + hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap); + ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr); + check_bitmap_surface_(line, bitmap, has_surface, options); + ID2D1Bitmap_Release(bitmap); + + set_size_u(&size, 2, 0); + hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap); + ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr); + check_bitmap_surface_(line, bitmap, has_surface, options); + ID2D1Bitmap_Release(bitmap); + + set_size_u(&size, 0, 2); + hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap); + ok_(__FILE__, line)(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr); + check_bitmap_surface_(line, bitmap, has_surface, options); + ID2D1Bitmap_Release(bitmap); + /* WIC bitmap. */ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/device.c | 1 + dlls/d2d1/tests/d2d1.c | 64 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-)
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index d1c1845171..9bf8ef65ac 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -1852,6 +1852,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 = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; desc = &bitmap_desc; } diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 80660b00f9..f4e2f1c39d 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -7019,6 +7019,41 @@ static void check_rt_bitmap_surface_(unsigned int line, ID2D1RenderTarget *rt, B ID2D1DCRenderTarget_Release(dc_rt); }
+static IDXGISurface *create_surface(IDXGIDevice *dxgi_device, DXGI_FORMAT format) +{ + D3D10_TEXTURE2D_DESC texture_desc; + ID3D10Texture2D *texture; + ID3D10Device *d3d_device; + IDXGISurface *surface; + HRESULT hr; + + texture_desc.Width = 1; + texture_desc.Height = 1; + texture_desc.MipLevels = 1; + texture_desc.ArraySize = 1; + texture_desc.Format = format; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.Usage = D3D10_USAGE_DEFAULT; + texture_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + texture_desc.CPUAccessFlags = 0; + texture_desc.MiscFlags = 0; + + hr = IDXGIDevice_QueryInterface(dxgi_device, &IID_ID3D10Device, (void **)&d3d_device); + ok(SUCCEEDED(hr), "Failed to get device interface, hr %#x.\n", hr); + + hr = ID3D10Device_CreateTexture2D(d3d_device, &texture_desc, NULL, &texture); + ok(SUCCEEDED(hr), "Failed to create a texture, hr %#x.\n", hr); + + hr = ID3D10Texture2D_QueryInterface(texture, &IID_IDXGISurface, (void **)&surface); + ok(SUCCEEDED(hr), "Failed to get surface interface, hr %#x.\n", hr); + + ID3D10Device_Release(d3d_device); + ID3D10Texture2D_Release(texture); + + return surface; +} + static void test_bitmap_surface(void) { static const struct bitmap_format_test @@ -7050,12 +7085,13 @@ static void test_bitmap_surface(void) D2D1_RENDER_TARGET_PROPERTIES rt_desc; D2D1_BITMAP_PROPERTIES1 bitmap_desc; ID2D1DeviceContext *device_context; + IDXGISurface *surface, *surface2; + D2D1_PIXEL_FORMAT pixel_format; ID3D10Device1 *d3d_device; IDXGISwapChain *swapchain; IDXGIDevice *dxgi_device; ID2D1Factory1 *factory; ID2D1RenderTarget *rt; - IDXGISurface *surface; ID2D1Bitmap1 *bitmap; ID2D1Device *device; ID2D1Image *target; @@ -7121,8 +7157,6 @@ if (SUCCEEDED(hr)) { for (i = 0; i < ARRAY_SIZE(bitmap_format_tests); ++i) { - D2D1_PIXEL_FORMAT pixel_format; - memset(&bitmap_desc, 0, sizeof(bitmap_desc)); bitmap_desc.pixelFormat = bitmap_format_tests[i].original; bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; @@ -7143,9 +7177,33 @@ if (SUCCEEDED(hr)) } }
+ /* A8 surface */ + hr = IDXGISurface_GetDevice(surface, &IID_IDXGIDevice, (void **)&dxgi_device); + ok(SUCCEEDED(hr), "Failed to get the device, hr %#x.\n", hr); + + surface2 = create_surface(dxgi_device, DXGI_FORMAT_A8_UNORM); + + hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(device_context, surface2, NULL, &bitmap); + ok(SUCCEEDED(hr) || broken(hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT) /* Win7 */, + "Failed to create a bitmap, hr %#x.\n", hr); + + if (SUCCEEDED(hr)) + { + pixel_format = ID2D1Bitmap1_GetPixelFormat(bitmap); + ok(pixel_format.alphaMode == D2D1_ALPHA_MODE_PREMULTIPLIED, "Unexpected alpha mode %#x.\n", pixel_format.alphaMode); + + ID2D1Bitmap1_Release(bitmap); + } + + IDXGIDevice_Release(dxgi_device); + IDXGISurface_Release(surface2); + hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(device_context, surface, NULL, &bitmap); ok(SUCCEEDED(hr), "Failed to create a bitmap, hr %#x.\n", hr);
+ pixel_format = ID2D1Bitmap1_GetPixelFormat(bitmap); + ok(pixel_format.alphaMode == D2D1_ALPHA_MODE_PREMULTIPLIED, "Unexpected alpha mode %#x.\n", pixel_format.alphaMode); + check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW); check_rt_bitmap_surface((ID2D1RenderTarget *)device_context, TRUE, D2D1_BITMAP_OPTIONS_NONE);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/bitmap.c | 23 ++- dlls/d2d1/bitmap_render_target.c | 74 +++------ dlls/d2d1/d2d1_private.h | 6 +- dlls/d2d1/dc_render_target.c | 96 +++++------ dlls/d2d1/device.c | 269 +++++++++++++++++-------------- dlls/d2d1/hwnd_render_target.c | 19 ++- dlls/d2d1/tests/d2d1.c | 64 +++++--- 7 files changed, 290 insertions(+), 261 deletions(-)
diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c index fde348fa1c..dd15714153 100644 --- a/dlls/d2d1/bitmap.c +++ b/dlls/d2d1/bitmap.c @@ -70,6 +70,8 @@ static ULONG STDMETHODCALLTYPE d2d_bitmap_Release(ID2D1Bitmap1 *iface) if (!refcount) { ID3D10ShaderResourceView_Release(bitmap->view); + if (bitmap->rtv) + ID3D10RenderTargetView_Release(bitmap->rtv); if (bitmap->surface) IDXGISurface_Release(bitmap->surface); ID2D1Factory_Release(bitmap->factory); @@ -274,6 +276,10 @@ static BOOL format_supported(const D2D1_PIXEL_FORMAT *format) static void d2d_bitmap_init(struct d2d_bitmap *bitmap, struct d2d_device_context *context, ID3D10ShaderResourceView *view, D2D1_SIZE_U size, const D2D1_BITMAP_PROPERTIES1 *desc) { + ID3D10Resource *resource; + ID3D10Device *d3d_device; + HRESULT hr; + bitmap->ID2D1Bitmap1_iface.lpVtbl = &d2d_bitmap_vtbl; bitmap->refcount = 1; ID2D1Factory_AddRef(bitmap->factory = context->factory); @@ -283,15 +289,22 @@ static void d2d_bitmap_init(struct d2d_bitmap *bitmap, struct d2d_device_context bitmap->dpi_x = desc->dpiX; bitmap->dpi_y = desc->dpiY; bitmap->options = desc->bitmapOptions; - if (d2d_device_context_is_dxgi_target(context)) - { - ID3D10Resource *resource;
- ID3D10ShaderResourceView_GetResource(bitmap->view, &resource); + ID3D10ShaderResourceView_GetResource(bitmap->view, &resource); + + if (d2d_device_context_is_dxgi_target(context)) ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface, (void **)&bitmap->surface); - ID3D10Resource_Release(resource); + + if (bitmap->options & D2D1_BITMAP_OPTIONS_TARGET) + { + ID3D10Resource_GetDevice(resource, &d3d_device); + if (FAILED(hr = ID3D10Device_CreateRenderTargetView(d3d_device, resource, NULL, &bitmap->rtv))) + WARN("Failed to create rtv, hr %#x.\n", hr); + ID3D10Device_Release(d3d_device); }
+ ID3D10Resource_Release(resource); + if (bitmap->dpi_x == 0.0f && bitmap->dpi_y == 0.0f) { bitmap->dpi_x = 96.0f; diff --git a/dlls/d2d1/bitmap_render_target.c b/dlls/d2d1/bitmap_render_target.c index df5b013a0b..836fa567e7 100644 --- a/dlls/d2d1/bitmap_render_target.c +++ b/dlls/d2d1/bitmap_render_target.c @@ -69,7 +69,8 @@ static ULONG STDMETHODCALLTYPE d2d_bitmap_render_target_Release(ID2D1BitmapRende if (!refcount) { IUnknown_Release(render_target->dxgi_inner); - ID2D1Bitmap_Release(render_target->bitmap); + if (render_target->bitmap) + ID2D1Bitmap_Release(render_target->bitmap); heap_free(render_target); }
@@ -733,10 +734,9 @@ HRESULT d2d_bitmap_render_target_init(struct d2d_bitmap_render_target *render_ta D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options) { D2D1_RENDER_TARGET_PROPERTIES dxgi_rt_desc; - D2D1_BITMAP_PROPERTIES bitmap_desc; - D3D10_TEXTURE2D_DESC texture_desc; - IDXGISurface *dxgi_surface; - ID3D10Texture2D *texture; + D2D1_BITMAP_PROPERTIES1 bitmap_desc; + ID2D1DeviceContext *context; + D2D1_SIZE_U bitmap_size; HRESULT hr;
if (options) @@ -750,24 +750,24 @@ HRESULT d2d_bitmap_render_target_init(struct d2d_bitmap_render_target *render_ta
if (pixel_size) { - texture_desc.Width = pixel_size->width; - texture_desc.Height = pixel_size->height; + bitmap_size.width = pixel_size->width; + bitmap_size.height = pixel_size->height; } else if (size) { - texture_desc.Width = ceilf((size->width * parent_target->desc.dpiX) / 96.0f); - texture_desc.Height = ceilf((size->height * parent_target->desc.dpiY) / 96.0f); + bitmap_size.width = ceilf((size->width * parent_target->desc.dpiX) / 96.0f); + bitmap_size.height = ceilf((size->height * parent_target->desc.dpiY) / 96.0f); } else { - texture_desc.Width = parent_target->pixel_size.width; - texture_desc.Height = parent_target->pixel_size.height; + bitmap_size.width = parent_target->pixel_size.width; + bitmap_size.height = parent_target->pixel_size.height; }
- if (size) + if (size && size->width != 0.0f && size->height != 0.0f) { - dxgi_rt_desc.dpiX = (texture_desc.Width * 96.0f) / size->width; - dxgi_rt_desc.dpiY = (texture_desc.Height * 96.0f) / size->height; + dxgi_rt_desc.dpiX = (bitmap_size.width * 96.0f) / size->width; + dxgi_rt_desc.dpiY = (bitmap_size.height * 96.0f) / size->height; } else { @@ -776,46 +776,21 @@ HRESULT d2d_bitmap_render_target_init(struct d2d_bitmap_render_target *render_ta }
if (!pixel_format || pixel_format->format == DXGI_FORMAT_UNKNOWN) - texture_desc.Format = parent_target->desc.pixelFormat.format; + dxgi_rt_desc.pixelFormat.format = parent_target->desc.pixelFormat.format; else - texture_desc.Format = pixel_format->format; - dxgi_rt_desc.pixelFormat.format = texture_desc.Format; + dxgi_rt_desc.pixelFormat.format = pixel_format->format;
if (!pixel_format || pixel_format->alphaMode == D2D1_ALPHA_MODE_UNKNOWN) dxgi_rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; else dxgi_rt_desc.pixelFormat.alphaMode = pixel_format->alphaMode;
- texture_desc.MipLevels = 1; - texture_desc.ArraySize = 1; - texture_desc.SampleDesc.Count = 1; - texture_desc.SampleDesc.Quality = 0; - texture_desc.Usage = D3D10_USAGE_DEFAULT; - texture_desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; - texture_desc.CPUAccessFlags = 0; - texture_desc.MiscFlags = 0; - - if (FAILED(hr = ID3D10Device_CreateTexture2D(parent_target->d3d_device, &texture_desc, NULL, &texture))) - { - WARN("Failed to create texture, hr %#x.\n", hr); - return hr; - } - - hr = ID3D10Texture2D_QueryInterface(texture, &IID_IDXGISurface, (void **)&dxgi_surface); - ID3D10Texture2D_Release(texture); - if (FAILED(hr)) - { - WARN("Failed to get DXGI surface interface, hr %#x.\n", hr); - return hr; - } - - if (FAILED(hr = d2d_d3d_create_render_target(parent_target->device, dxgi_surface, + if (FAILED(hr = d2d_d3d_create_render_target(parent_target->device, NULL, (IUnknown *)&render_target->ID2D1BitmapRenderTarget_iface, parent_target->ops ? &d2d_bitmap_render_target_ops : NULL, &dxgi_rt_desc, (void **)&render_target->dxgi_inner))) { WARN("Failed to create DXGI surface render target, hr %#x.\n", hr); - IDXGISurface_Release(dxgi_surface); return hr; }
@@ -824,20 +799,23 @@ HRESULT d2d_bitmap_render_target_init(struct d2d_bitmap_render_target *render_ta { WARN("Failed to retrieve ID2D1RenderTarget interface, hr %#x.\n", hr); IUnknown_Release(render_target->dxgi_inner); - IDXGISurface_Release(dxgi_surface); return hr; }
bitmap_desc.pixelFormat = dxgi_rt_desc.pixelFormat; bitmap_desc.dpiX = dxgi_rt_desc.dpiX; bitmap_desc.dpiY = dxgi_rt_desc.dpiY; - - hr = ID2D1RenderTarget_CreateSharedBitmap(render_target->dxgi_target, &IID_IDXGISurface, dxgi_surface, - &bitmap_desc, &render_target->bitmap); - IDXGISurface_Release(dxgi_surface); + bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET; + bitmap_desc.colorContext = NULL; + + ID2D1RenderTarget_QueryInterface(render_target->dxgi_target, &IID_ID2D1DeviceContext, (void **)&context); + hr = ID2D1DeviceContext_CreateBitmap(context, bitmap_size, NULL, 0, &bitmap_desc, + (ID2D1Bitmap1 **)&render_target->bitmap); + ID2D1DeviceContext_SetTarget(context, (ID2D1Image *)render_target->bitmap); + ID2D1DeviceContext_Release(context); if (FAILED(hr)) { - WARN("Failed to create shared bitmap, hr %#x.\n", hr); + WARN("Failed to create target bitmap, hr %#x.\n", hr); ID2D1RenderTarget_Release(render_target->dxgi_target); IUnknown_Release(render_target->dxgi_inner); return hr; diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index 726d143d86..0a5bc36c9a 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -136,7 +136,7 @@ struct d2d_device_context ID2D1Factory *factory; ID2D1Device *device; ID3D10Device *d3d_device; - ID3D10RenderTargetView *view; + struct d2d_bitmap *target; ID3D10StateBlock *stateblock; struct d2d_shape_resources shape_resources[D2D_SHAPE_TYPE_COUNT]; ID3D10PixelShader *ps; @@ -159,7 +159,6 @@ struct d2d_device_context HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, IUnknown *outer_unknown, const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target) DECLSPEC_HIDDEN; -HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *render_target, IDXGISurface1 *surface) DECLSPEC_HIDDEN;
static inline BOOL d2d_device_context_is_dxgi_target(const struct d2d_device_context *context) { @@ -191,6 +190,8 @@ struct d2d_dc_render_target LONG refcount;
IDXGISurface1 *dxgi_surface; + D2D1_PIXEL_FORMAT pixel_format; + ID3D10Device1 *d3d_device; ID2D1RenderTarget *dxgi_target; IUnknown *dxgi_inner;
@@ -345,6 +346,7 @@ struct d2d_bitmap
ID2D1Factory *factory; ID3D10ShaderResourceView *view; + ID3D10RenderTargetView *rtv; IDXGISurface *surface; D2D1_SIZE_U pixel_size; D2D1_PIXEL_FORMAT format; diff --git a/dlls/d2d1/dc_render_target.c b/dlls/d2d1/dc_render_target.c index 9a0f458faf..b4306fb2fe 100644 --- a/dlls/d2d1/dc_render_target.c +++ b/dlls/d2d1/dc_render_target.c @@ -99,7 +99,9 @@ static ULONG STDMETHODCALLTYPE d2d_dc_render_target_Release(ID2D1DCRenderTarget if (!refcount) { IUnknown_Release(render_target->dxgi_inner); - IDXGISurface1_Release(render_target->dxgi_surface); + if (render_target->dxgi_surface) + IDXGISurface1_Release(render_target->dxgi_surface); + ID3D10Device1_Release(render_target->d3d_device); heap_free(render_target); }
@@ -686,8 +688,9 @@ static HRESULT STDMETHODCALLTYPE d2d_dc_render_target_BindDC(ID2D1DCRenderTarget struct d2d_dc_render_target *render_target = impl_from_ID2D1DCRenderTarget(iface); D3D10_TEXTURE2D_DESC texture_desc; IDXGISurface1 *dxgi_surface; + ID2D1DeviceContext *context; ID3D10Texture2D *texture; - ID3D10Device *device; + ID2D1Bitmap1 *bitmap; HRESULT hr;
TRACE("iface %p, hdc %p, rect %s.\n", iface, hdc, wine_dbgstr_rect(rect)); @@ -695,27 +698,19 @@ static HRESULT STDMETHODCALLTYPE d2d_dc_render_target_BindDC(ID2D1DCRenderTarget if (!hdc) return E_INVALIDARG;
- /* Recreate surface using specified size and original texture description. */ - if (FAILED(hr = IDXGISurface1_QueryInterface(render_target->dxgi_surface, &IID_ID3D10Texture2D, (void **)&texture))) - { - WARN("Failed to get texture interface, hr %#x.\n", hr); - return hr; - } - - ID3D10Texture2D_GetDesc(texture, &texture_desc); - ID3D10Texture2D_Release(texture); texture_desc.Width = rect->right - rect->left; texture_desc.Height = rect->bottom - rect->top; + texture_desc.MipLevels = 1; + texture_desc.ArraySize = 1; + texture_desc.Format = render_target->pixel_format.format; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.Usage = D3D10_USAGE_DEFAULT; + texture_desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; + texture_desc.CPUAccessFlags = 0; + texture_desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
- if (FAILED(hr = IDXGISurface1_GetDevice(render_target->dxgi_surface, &IID_ID3D10Device, (void **)&device))) - { - WARN("Failed to get device from dxgi surface, hr %#x.\n", hr); - return hr; - } - - hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, &texture); - ID3D10Device_Release(device); - if (FAILED(hr)) + if (FAILED(hr = ID3D10Device1_CreateTexture2D(render_target->d3d_device, &texture_desc, NULL, &texture))) { WARN("Failed to create texture, hr %#x.\n", hr); return hr; @@ -730,14 +725,24 @@ static HRESULT STDMETHODCALLTYPE d2d_dc_render_target_BindDC(ID2D1DCRenderTarget }
/* Switch dxgi target to new surface. */ - if (FAILED(hr = d2d_d3d_render_target_create_rtv(render_target->dxgi_target, dxgi_surface))) + ID2D1RenderTarget_QueryInterface(render_target->dxgi_target, &IID_ID2D1DeviceContext, (void **)&context); + hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(context, (IDXGISurface *)dxgi_surface, NULL, &bitmap); + if (SUCCEEDED(hr)) { - WARN("Failed to set new surface, hr %#x.\n", hr); + ID2D1DeviceContext_SetTarget(context, (ID2D1Image *)bitmap); + ID2D1Bitmap1_Release(bitmap); + } + ID2D1DeviceContext_Release(context); + + if (FAILED(hr)) + { + WARN("Failed to create new target bitmap, hr %#x.\n", hr); IDXGISurface1_Release(dxgi_surface); return hr; }
- IDXGISurface1_Release(render_target->dxgi_surface); + if (render_target->dxgi_surface) + IDXGISurface1_Release(render_target->dxgi_surface); render_target->dxgi_surface = dxgi_surface;
render_target->hdc = hdc; @@ -816,8 +821,6 @@ static const struct d2d_device_context_ops d2d_dc_render_target_ops = HRESULT d2d_dc_render_target_init(struct d2d_dc_render_target *render_target, ID2D1Factory1 *factory, ID3D10Device1 *d3d_device, const D2D1_RENDER_TARGET_PROPERTIES *desc) { - D3D10_TEXTURE2D_DESC texture_desc; - ID3D10Texture2D *texture; IDXGIDevice *dxgi_device; ID2D1Device *device; HRESULT hr; @@ -828,14 +831,8 @@ HRESULT d2d_dc_render_target_init(struct d2d_dc_render_target *render_target, ID SetRectEmpty(&render_target->dst_rect); render_target->hdc = NULL;
- /* Dummy 1x1 texture, recreated on BindDC(). */ - texture_desc.Width = 1; - texture_desc.Height = 1; - texture_desc.MipLevels = 1; - texture_desc.ArraySize = 1; - - texture_desc.Format = desc->pixelFormat.format; - switch (texture_desc.Format) + render_target->pixel_format = desc->pixelFormat; + switch (desc->pixelFormat.format) { case DXGI_FORMAT_B8G8R8A8_UNORM: if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_PREMULTIPLIED @@ -843,31 +840,10 @@ HRESULT d2d_dc_render_target_init(struct d2d_dc_render_target *render_target, ID break;
default: - FIXME("Unhandled format %#x, alpha mode %u.\n", texture_desc.Format, desc->pixelFormat.alphaMode); + FIXME("Unhandled format %#x, alpha mode %u.\n", desc->pixelFormat.format, desc->pixelFormat.alphaMode); return D2DERR_UNSUPPORTED_PIXEL_FORMAT; }
- texture_desc.SampleDesc.Count = 1; - texture_desc.SampleDesc.Quality = 0; - texture_desc.Usage = D3D10_USAGE_DEFAULT; - texture_desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; - texture_desc.CPUAccessFlags = 0; - texture_desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE; - - if (FAILED(hr = ID3D10Device1_CreateTexture2D(d3d_device, &texture_desc, NULL, &texture))) - { - WARN("Failed to create texture, hr %#x.\n", hr); - return hr; - } - - hr = ID3D10Texture2D_QueryInterface(texture, &IID_IDXGISurface1, (void **)&render_target->dxgi_surface); - ID3D10Texture2D_Release(texture); - if (FAILED(hr)) - { - WARN("Failed to get DXGI surface interface, hr %#x.\n", hr); - return hr; - } - if (FAILED(hr = ID3D10Device1_QueryInterface(d3d_device, &IID_IDXGIDevice, (void **)&dxgi_device))) { WARN("Failed to get DXGI device interface, hr %#x.\n", hr); @@ -882,14 +858,12 @@ HRESULT d2d_dc_render_target_init(struct d2d_dc_render_target *render_target, ID return hr; }
- hr = d2d_d3d_create_render_target(device, (IDXGISurface *)render_target->dxgi_surface, - (IUnknown *)&render_target->ID2D1DCRenderTarget_iface, &d2d_dc_render_target_ops, - desc, (void **)&render_target->dxgi_inner); + hr = d2d_d3d_create_render_target(device, NULL, (IUnknown *)&render_target->ID2D1DCRenderTarget_iface, + &d2d_dc_render_target_ops, desc, (void **)&render_target->dxgi_inner); ID2D1Device_Release(device); if (FAILED(hr)) { WARN("Failed to create DXGI surface render target, hr %#x.\n", hr); - IDXGISurface1_Release(render_target->dxgi_surface); return hr; }
@@ -898,9 +872,11 @@ HRESULT d2d_dc_render_target_init(struct d2d_dc_render_target *render_target, ID { WARN("Failed to retrieve ID2D1RenderTarget interface, hr %#x.\n", hr); IUnknown_Release(render_target->dxgi_inner); - IDXGISurface1_Release(render_target->dxgi_surface); return hr; }
+ render_target->d3d_device = d3d_device; + ID3D10Device1_AddRef(render_target->d3d_device); + return S_OK; } diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index 9bf8ef65ac..04d58ae8d1 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -43,6 +43,8 @@ static inline struct d2d_device *impl_from_ID2D1Device(ID2D1Device *iface) return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface); }
+static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface); + static ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect) { ID2D1Brush *brush = NULL; @@ -175,7 +177,7 @@ static void d2d_device_context_draw(struct d2d_device_context *render_target, en } ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect); ID3D10Device_RSSetState(device, render_target->rs); - ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL); + ID3D10Device_OMSetRenderTargets(device, 1, &render_target->target->rtv, NULL); if (brush) { ID3D10Device_OMSetBlendState(device, render_target->bs, blend_factor, D3D10_DEFAULT_SAMPLE_MASK); @@ -261,7 +263,8 @@ static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface) IDWriteRenderingParams_Release(context->default_text_rendering_params); if (context->text_rendering_params) IDWriteRenderingParams_Release(context->text_rendering_params); - ID3D10BlendState_Release(context->bs); + if (context->bs) + ID3D10BlendState_Release(context->bs); ID3D10RasterizerState_Release(context->rs); ID3D10Buffer_Release(context->vb); ID3D10Buffer_Release(context->ib); @@ -272,7 +275,8 @@ static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface) ID3D10InputLayout_Release(context->shape_resources[i].il); } context->stateblock->lpVtbl->Release(context->stateblock); - ID3D10RenderTargetView_Release(context->view); + if (context->target) + ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface); ID3D10Device_Release(context->d3d_device); ID2D1Factory_Release(context->factory); ID2D1Device_Release(context->device); @@ -1979,14 +1983,95 @@ static void STDMETHODCALLTYPE d2d_device_context_GetDevice(ID2D1DeviceContext *i ID2D1Device_AddRef(*device); }
+static void d2d_device_context_reset_target(struct d2d_device_context *context) +{ + if (!context->target) + return; + + ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface); + context->target = NULL; + + context->desc.dpiX = 96.0f; + context->desc.dpiY = 96.0f; + + memset(&context->desc.pixelFormat, 0, sizeof(context->desc.pixelFormat)); + memset(&context->pixel_size, 0, sizeof(context->pixel_size)); + + ID3D10BlendState_Release(context->bs); + context->bs = NULL; +} + static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext *iface, ID2D1Image *target) { - FIXME("iface %p, target %p stub!\n", iface, target); + struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface); + struct d2d_bitmap *bitmap_impl; + D3D10_BLEND_DESC blend_desc; + ID2D1Bitmap *bitmap; + HRESULT hr; + + TRACE("iface %p, target %p.\n", iface, target); + + if (!target) + { + d2d_device_context_reset_target(context); + return; + } + + if (FAILED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap))) + { + FIXME("Only bitmap targets are supported.\n"); + return; + } + + bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap); + + if (!(bitmap_impl->options & D2D1_BITMAP_OPTIONS_TARGET)) + { + context->error.code = D2DERR_INVALID_TARGET; + context->error.tag1 = context->drawing_state.tag1; + context->error.tag2 = context->drawing_state.tag2; + return; + } + + d2d_device_context_reset_target(context); + + /* Set sizes and pixel format. */ + context->desc.dpiX = bitmap_impl->dpi_x; + context->desc.dpiY = bitmap_impl->dpi_y; + context->pixel_size = bitmap_impl->pixel_size; + context->desc.pixelFormat = bitmap_impl->format; + context->target = bitmap_impl; + + memset(&blend_desc, 0, sizeof(blend_desc)); + blend_desc.BlendEnable[0] = TRUE; + blend_desc.SrcBlend = D3D10_BLEND_ONE; + blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA; + blend_desc.BlendOp = D3D10_BLEND_OP_ADD; + if (context->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE) + { + blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO; + blend_desc.DestBlendAlpha = D3D10_BLEND_ONE; + } + else + { + blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE; + blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA; + } + 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))) + WARN("Failed to create blend state, hr %#x.\n", hr); }
static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext *iface, ID2D1Image **target) { - FIXME("iface %p, target %p stub!\n", iface, target); + struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface); + + TRACE("iface %p, target %p.\n", iface, target); + + *target = context->target ? (ID2D1Image *)&context->target->ID2D1Bitmap1_iface : NULL; + if (*target) + ID2D1Image_AddRef(*target); }
static void STDMETHODCALLTYPE d2d_device_context_SetRenderingControls(ID2D1DeviceContext *iface, @@ -2538,7 +2623,7 @@ static HRESULT d2d_device_context_get_surface(struct d2d_device_context *render_ ID3D10Resource *resource; HRESULT hr;
- ID3D10RenderTargetView_GetResource(render_target->view, &resource); + ID3D10RenderTargetView_GetResource(render_target->target->rtv, &resource); hr = ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface); ID3D10Resource_Release(resource); if (FAILED(hr)) @@ -2600,17 +2685,14 @@ static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_targe };
static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Device *device, - IDXGISurface *surface, IUnknown *outer_unknown, const struct d2d_device_context_ops *ops, - const D2D1_RENDER_TARGET_PROPERTIES *desc) + IUnknown *outer_unknown, const struct d2d_device_context_ops *ops) { D3D10_SUBRESOURCE_DATA buffer_data; D3D10_STATE_BLOCK_MASK state_mask; - DXGI_SURFACE_DESC surface_desc; + struct d2d_device *device_impl; IDWriteFactory *dwrite_factory; D3D10_RASTERIZER_DESC rs_desc; D3D10_BUFFER_DESC buffer_desc; - D3D10_BLEND_DESC blend_desc; - ID3D10Resource *resource; unsigned int i; HRESULT hr;
@@ -3460,25 +3542,6 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, { 1.0f, -1.0f}, }; static const UINT16 indices[] = {0, 1, 2, 2, 1, 3}; - float dpi_x, dpi_y; - - dpi_x = desc->dpiX; - dpi_y = desc->dpiY; - - if (dpi_x == 0.0f && dpi_y == 0.0f) - { - dpi_x = 96.0f; - dpi_y = 96.0f; - } - else if (dpi_x <= 0.0f || dpi_y <= 0.0f) - return E_INVALIDARG; - - if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE) - WARN("Ignoring render target type %#x.\n", desc->type); - if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE) - FIXME("Ignoring render target usage %#x.\n", desc->usage); - if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT) - WARN("Ignoring feature level %#x.\n", desc->minLevel);
render_target->ID2D1DeviceContext_iface.lpVtbl = &d2d_device_context_vtbl; render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl; @@ -3492,27 +3555,14 @@ 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;
- if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->d3d_device))) + device_impl = unsafe_impl_from_ID2D1Device(device); + if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device, &IID_ID3D10Device, (void **)&render_target->d3d_device))) { WARN("Failed to get device interface, hr %#x.\n", hr); ID2D1Factory_Release(render_target->factory); return hr; }
- if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource))) - { - WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr); - goto err; - } - - hr = ID3D10Device_CreateRenderTargetView(render_target->d3d_device, resource, NULL, &render_target->view); - ID3D10Resource_Release(resource); - if (FAILED(hr)) - { - WARN("Failed to create rendertarget view, hr %#x.\n", hr); - goto err; - } - if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask))) { WARN("Failed to create stateblock mask, hr %#x.\n", hr); @@ -3597,29 +3647,6 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, goto err; }
- memset(&blend_desc, 0, sizeof(blend_desc)); - blend_desc.BlendEnable[0] = TRUE; - blend_desc.SrcBlend = D3D10_BLEND_ONE; - blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA; - blend_desc.BlendOp = D3D10_BLEND_OP_ADD; - if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE) - { - blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO; - blend_desc.DestBlendAlpha = D3D10_BLEND_ONE; - } - else - { - blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE; - blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA; - } - blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD; - blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL; - if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->d3d_device, &blend_desc, &render_target->bs))) - { - WARN("Failed to create blend state, hr %#x.\n", hr); - goto err; - } - if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory))) { @@ -3635,15 +3662,6 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, goto err; }
- if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc))) - { - WARN("Failed to get surface desc, hr %#x.\n", hr); - goto err; - } - - render_target->desc.pixelFormat = desc->pixelFormat; - render_target->pixel_size.width = surface_desc.Width; - render_target->pixel_size.height = surface_desc.Height; render_target->drawing_state.transform = identity;
if (!d2d_clip_stack_init(&render_target->clip_stack)) @@ -3653,16 +3671,14 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, goto err; }
- render_target->desc.dpiX = dpi_x; - render_target->desc.dpiY = dpi_y; + render_target->desc.dpiX = 96.0f; + render_target->desc.dpiY = 96.0f;
return S_OK;
err: if (render_target->default_text_rendering_params) IDWriteRenderingParams_Release(render_target->default_text_rendering_params); - if (render_target->bs) - ID3D10BlendState_Release(render_target->bs); if (render_target->rs) ID3D10RasterizerState_Release(render_target->rs); if (render_target->vb) @@ -3680,8 +3696,6 @@ err: } if (render_target->stateblock) render_target->stateblock->lpVtbl->Release(render_target->stateblock); - if (render_target->view) - ID3D10RenderTargetView_Release(render_target->view); if (render_target->d3d_device) ID3D10Device_Release(render_target->d3d_device); ID2D1Device_Release(render_target->device); @@ -3692,65 +3706,62 @@ err: HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, IUnknown *outer_unknown, const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target) { + D2D1_BITMAP_PROPERTIES1 bitmap_desc; struct d2d_device_context *object; + ID2D1Bitmap1 *bitmap; HRESULT hr;
+ if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE) + WARN("Ignoring render target type %#x.\n", desc->type); + if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE) + FIXME("Ignoring render target usage %#x.\n", desc->usage); + if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT) + WARN("Ignoring feature level %#x.\n", desc->minLevel); + + bitmap_desc.dpiX = desc->dpiX; + bitmap_desc.dpiY = desc->dpiY; + + if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f) + { + bitmap_desc.dpiX = 96.0f; + bitmap_desc.dpiY = 96.0f; + } + else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f) + return E_INVALIDARG; + if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY;
- if (FAILED(hr = d2d_device_context_init(object, device, surface, outer_unknown, ops, desc))) + if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops))) { WARN("Failed to initialize render target, hr %#x.\n", hr); heap_free(object); return hr; }
- TRACE("Created render target %p.\n", object); - *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext_iface; - - return S_OK; -} - -HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *iface, IDXGISurface1 *surface) -{ - struct d2d_device_context *render_target = impl_from_ID2D1RenderTarget(iface); - DXGI_SURFACE_DESC surface_desc; - ID3D10RenderTargetView *view; - ID3D10Resource *resource; - HRESULT hr; - - if (!surface) + if (surface) { - ID3D10RenderTargetView_Release(render_target->view); - render_target->view = NULL; - return S_OK; - } - - if (FAILED(hr = IDXGISurface1_GetDesc(surface, &surface_desc))) - { - WARN("Failed to get surface desc, hr %#x.\n", hr); - return hr; - } + bitmap_desc.pixelFormat = desc->pixelFormat; + bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; + bitmap_desc.colorContext = NULL;
- if (FAILED(hr = IDXGISurface1_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource))) - { - WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr); - return hr; - } + if (FAILED(hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext_iface, surface, + &bitmap_desc, &bitmap))) + { + WARN("Failed to create target bitmap, hr %#x.\n", hr); + ID2D1DeviceContext_Release(&object->ID2D1DeviceContext_iface); + heap_free(object); + return hr; + }
- hr = ID3D10Device_CreateRenderTargetView(render_target->d3d_device, resource, NULL, &view); - ID3D10Resource_Release(resource); - if (FAILED(hr)) - { - WARN("Failed to create rendertarget view, hr %#x.\n", hr); - return hr; + ID2D1DeviceContext_SetTarget(&object->ID2D1DeviceContext_iface, (ID2D1Image *)bitmap); + ID2D1Bitmap1_Release(bitmap); } + else + object->desc.pixelFormat = desc->pixelFormat;
- render_target->pixel_size.width = surface_desc.Width; - render_target->pixel_size.height = surface_desc.Height; - if (render_target->view) - ID3D10RenderTargetView_Release(render_target->view); - render_target->view = view; + TRACE("Created render target %p.\n", object); + *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext_iface;
return S_OK; } @@ -3861,6 +3872,14 @@ static const struct ID2D1DeviceVtbl d2d_device_vtbl = d2d_device_ClearResources, };
+static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface) +{ + if (!iface) + return NULL; + assert(iface->lpVtbl == &d2d_device_vtbl); + return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface); +} + void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device) { device->ID2D1Device_iface.lpVtbl = &d2d_device_vtbl; diff --git a/dlls/d2d1/hwnd_render_target.c b/dlls/d2d1/hwnd_render_target.c index 9b8771f895..d0b9695933 100644 --- a/dlls/d2d1/hwnd_render_target.c +++ b/dlls/d2d1/hwnd_render_target.c @@ -675,11 +675,14 @@ static HRESULT STDMETHODCALLTYPE d2d_hwnd_render_target_Resize(ID2D1HwndRenderTa { struct d2d_hwnd_render_target *render_target = impl_from_ID2D1HwndRenderTarget(iface); IDXGISurface1 *dxgi_surface; + ID2D1DeviceContext *context; + ID2D1Bitmap1 *bitmap; HRESULT hr;
TRACE("iface %p, width %u, height %u.\n", iface, size->width, size->height);
- d2d_d3d_render_target_create_rtv(render_target->dxgi_target, NULL); + ID2D1RenderTarget_QueryInterface(render_target->dxgi_target, &IID_ID2D1DeviceContext, (void **)&context); + ID2D1DeviceContext_SetTarget(context, NULL);
if (SUCCEEDED(hr = IDXGISwapChain_ResizeBuffers(render_target->swapchain, 1, size->width, size->height, DXGI_FORMAT_UNKNOWN, 0))) @@ -688,13 +691,25 @@ static HRESULT STDMETHODCALLTYPE d2d_hwnd_render_target_Resize(ID2D1HwndRenderTa (void **)&dxgi_surface))) { WARN("Failed to get buffer, hr %#x.\n", hr); + ID2D1DeviceContext_Release(context); return hr; }
- hr = d2d_d3d_render_target_create_rtv(render_target->dxgi_target, dxgi_surface); + hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(context, (IDXGISurface *)dxgi_surface, NULL, &bitmap); IDXGISurface1_Release(dxgi_surface); + if (FAILED(hr)) + { + WARN("Failed to create target bitmap, hr %#x.\n", hr); + ID2D1DeviceContext_Release(context); + return hr; + } + + ID2D1DeviceContext_SetTarget(context, (ID2D1Image *)bitmap); + ID2D1Bitmap1_Release(bitmap); }
+ ID2D1DeviceContext_Release(context); + return hr; }
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index f4e2f1c39d..fd9b4de1af 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -821,6 +821,7 @@ static void check_bitmap_surface_(unsigned int line, ID2D1Bitmap *bitmap, BOOL h break; }
+ todo_wine_if(options == D2D1_BITMAP_OPTIONS_TARGET) ok_(__FILE__, line)(desc.BindFlags == bind_flags, "Unexpected bind flags %#x, bitmap options %#x.\n", desc.BindFlags, options); ok_(__FILE__, line)(desc.CPUAccessFlags == 0, "Unexpected cpu access flags %#x.\n", desc.CPUAccessFlags); @@ -5289,10 +5290,7 @@ static void test_compatible_target_size(ID2D1RenderTarget *rt) { hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, size_tests[i].size, size_tests[i].pixel_size, NULL, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &bitmap_rt); - todo_wine - ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr); - if (FAILED(hr)) - return; + ok(SUCCEEDED(hr), "%u: failed to create render target, hr %#x.\n", i, hr);
if (size_tests[i].pixel_size) expected_size = *size_tests[i].pixel_size; @@ -5521,13 +5519,11 @@ static void test_bitmap_target(void) ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(rt); -todo_wine ok(pixel_size.width == 0 && pixel_size.height == 0, "Got wrong size\n");
hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap); ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr); pixel_size = ID2D1Bitmap_GetPixelSize(bitmap); -todo_wine ok(pixel_size.width == 0 && pixel_size.height == 0, "Got wrong size\n"); ID2D1Bitmap_Release(bitmap);
@@ -6990,15 +6986,10 @@ static void check_rt_bitmap_surface_(unsigned int line, ID2D1RenderTarget *rt, B
bitmap2 = NULL; ID2D1DeviceContext_GetTarget(context2, (ID2D1Image **)&bitmap2); - todo_wine ok_(__FILE__, line)(bitmap2 == bitmap, "Unexpected bitmap.\n");
- if (bitmap2) - { - check_bitmap_surface_(line, bitmap, has_surface, D2D1_BITMAP_OPTIONS_TARGET); - - ID2D1Bitmap_Release(bitmap2); - } + check_bitmap_surface_(line, bitmap, has_surface, D2D1_BITMAP_OPTIONS_TARGET); + ID2D1Bitmap_Release(bitmap2); ID2D1Bitmap_Release(bitmap);
ID2D1BitmapRenderTarget_Release(compatible_rt); @@ -7095,6 +7086,8 @@ static void test_bitmap_surface(void) ID2D1Bitmap1 *bitmap; ID2D1Device *device; ID2D1Image *target; + D2D1_SIZE_U size; + D2D1_TAG t1, t2; unsigned int i; HWND window; HRESULT hr; @@ -7128,14 +7121,10 @@ static void test_bitmap_surface(void)
bitmap = NULL; ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap); -todo_wine ok(!!bitmap, "Unexpected target.\n"); - -if (bitmap) -{ check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW); ID2D1Bitmap1_Release(bitmap); -} + check_rt_bitmap_surface(rt, TRUE, D2D1_BITMAP_OPTIONS_NONE);
ID2D1DeviceContext_Release(device_context); @@ -7213,8 +7202,45 @@ if (SUCCEEDED(hr))
check_rt_bitmap_surface((ID2D1RenderTarget *)device_context, TRUE, D2D1_BITMAP_OPTIONS_NONE);
- ID2D1DeviceContext_Release(device_context); ID2D1Bitmap1_Release(bitmap); + + /* Without D2D1_BITMAP_OPTIONS_TARGET. */ + memset(&bitmap_desc, 0, sizeof(bitmap_desc)); + bitmap_desc.pixelFormat = ID2D1DeviceContext_GetPixelFormat(device_context); + size.width = size.height = 4; + hr = ID2D1DeviceContext_CreateBitmap(device_context, size, NULL, 0, &bitmap_desc, &bitmap); + ok(SUCCEEDED(hr), "Failed to create a bitmap, hr %#x.\n", hr); + check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_NONE); + ID2D1DeviceContext_SetTags(device_context, 1, 2); + + ID2D1DeviceContext_BeginDraw(device_context); + ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap); + hr = ID2D1DeviceContext_EndDraw(device_context, &t1, &t2); + ok(hr == D2DERR_INVALID_TARGET, "Unexpected hr %#x.\n", hr); + ok(t1 == 1 && t2 == 2, "Unexpected tags.\n"); + + ID2D1Bitmap1_Release(bitmap); + + ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap); + ok(!!bitmap, "Expected target bitmap.\n"); + ID2D1Bitmap1_Release(bitmap); + + bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET; + hr = ID2D1DeviceContext_CreateBitmap(device_context, size, NULL, 0, &bitmap_desc, &bitmap); + ok(SUCCEEDED(hr), "Failed to create a bitmap, hr %#x.\n", hr); + check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_TARGET); + ID2D1DeviceContext_SetTarget(device_context, NULL); + ID2D1DeviceContext_SetTags(device_context, 3, 4); + + ID2D1DeviceContext_BeginDraw(device_context); + ID2D1DeviceContext_SetTarget(device_context, (ID2D1Image *)bitmap); + hr = ID2D1DeviceContext_EndDraw(device_context, &t1, &t2); + ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr); + ok(t1 == 0 && t2 == 0, "Unexpected tags.\n"); + + ID2D1Bitmap1_Release(bitmap); + + ID2D1DeviceContext_Release(device_context); } ID2D1Device_Release(device); IDXGIDevice_Release(dxgi_device);