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);