d2d1: Implement d2d_device_context_SetTarget() for bitmap targets.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2018-09-29 02:32:06 +03:30 committed by Alexandre Julliard
parent f60455be90
commit 86f1ab36a9
7 changed files with 296 additions and 264 deletions

View File

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

View File

@ -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;
bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET;
bitmap_desc.colorContext = NULL;
hr = ID2D1RenderTarget_CreateSharedBitmap(render_target->dxgi_target, &IID_IDXGISurface, dxgi_surface,
&bitmap_desc, &render_target->bitmap);
IDXGISurface_Release(dxgi_surface);
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;

View File

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

View File

@ -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;
}

View File

@ -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,15 @@ 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 +3648,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 +3663,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 +3672,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 +3697,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,69 +3707,66 @@ 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;
}
if (surface)
{
bitmap_desc.pixelFormat = desc->pixelFormat;
bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
bitmap_desc.colorContext = NULL;
if (FAILED(hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext_iface,
surface, &bitmap_desc, &bitmap)))
{
WARN("Failed to create target bitmap, hr %#x.\n", hr);
IUnknown_Release(&object->IUnknown_iface);
heap_free(object);
return hr;
}
ID2D1DeviceContext_SetTarget(&object->ID2D1DeviceContext_iface, (ID2D1Image *)bitmap);
ID2D1Bitmap1_Release(bitmap);
}
else
object->desc.pixelFormat = desc->pixelFormat;
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)
{
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;
}
if (FAILED(hr = IDXGISurface1_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
{
WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
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;
}
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;
return S_OK;
}
static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device *iface, REFIID iid, void **out)
{
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
@ -3861,6 +3873,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;

View File

@ -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;
}

View File

@ -813,8 +813,9 @@ static void check_bitmap_surface_(unsigned int line, ID2D1Bitmap *bitmap, BOOL h
if (!(options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW))
bind_flags |= D3D10_BIND_SHADER_RESOURCE;
ok_(__FILE__, line)(desc.BindFlags == bind_flags, "Unexpected bind flags %#x for bitmap options %#x.\n",
desc.BindFlags, options);
todo_wine_if (options == D2D1_BITMAP_OPTIONS_TARGET)
ok_(__FILE__, line)(desc.BindFlags == bind_flags, "Unexpected bind flags %#x for bitmap options %#x.\n",
desc.BindFlags, options);
ok_(__FILE__, line)(!desc.CPUAccessFlags, "Unexpected cpu access flags %#x.\n", desc.CPUAccessFlags);
ok_(__FILE__, line)(!desc.MiscFlags, "Unexpected misc flags %#x.\n", desc.MiscFlags);
@ -5283,9 +5284,7 @@ static void test_compatible_target_size_(unsigned int line, ID2D1RenderTarget *r
{
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_(__FILE__, line)(SUCCEEDED(hr), "%u: Failed to create render target, hr %#x.\n", i, hr);
if (FAILED(hr))
return;
ok_(__FILE__, line)(SUCCEEDED(hr), "%u: Failed to create render target, hr %#x.\n", i, hr);
if (size_tests[i].pixel_size)
{
@ -5519,13 +5518,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);
@ -6989,14 +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");
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);
@ -7093,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;
@ -7126,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 +7204,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 %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
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), "Failed to end draw, hr %#x.\n", hr);
ok(!t1 && !t2, "Unexpected tags %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
ID2D1Bitmap1_Release(bitmap);
ID2D1DeviceContext_Release(device_context);
}
ID2D1Device_Release(device);
IDXGIDevice_Release(dxgi_device);