>From b9333913d37045f2e2a15212f69fe121dd109ced Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Fri, 3 Jun 2022 15:36:19 +0300 Subject: [PATCH] d2d1: Add support for painting image brush as a bitmap. Content-Type: text/plain; charset=UTF-8 To: wine-devel@winehq.org Signed-off-by: Dmitry Timoshkov --- dlls/d2d1/brush.c | 85 ++++++++++++++++++++++++++++++++++++++++------ dlls/d2d1/device.c | 2 +- 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/dlls/d2d1/brush.c b/dlls/d2d1/brush.c index b9a673fe54c..7febafc375c 100644 --- a/dlls/d2d1/brush.c +++ b/dlls/d2d1/brush.c @@ -1450,7 +1450,23 @@ BOOL d2d_brush_fill_cb(const struct d2d_brush *brush, struct d2d_brush_cb *cb) return TRUE; case D2D_BRUSH_TYPE_BITMAP: - bitmap = brush->u.bitmap.bitmap; + case D2D_BRUSH_TYPE_IMAGE: + { + ID2D1Bitmap *src_bitmap; + + if (brush->type == D2D_BRUSH_TYPE_BITMAP) + bitmap = brush->u.bitmap.bitmap; + else + { + if (FAILED(ID2D1Image_QueryInterface(brush->u.image.image, &IID_ID2D1Bitmap, (void **)&src_bitmap))) + { + FIXME("ID2D1Image doesn't support ID2D1Bitmap interface.\n"); + return FALSE; + } + + bitmap = unsafe_impl_from_ID2D1Bitmap(src_bitmap); + cb->type = D2D_BRUSH_TYPE_BITMAP; + } /* Scale for bitmap size and dpi. */ b = brush->transform; @@ -1477,7 +1493,11 @@ BOOL d2d_brush_fill_cb(const struct d2d_brush *brush, struct d2d_brush_cb *cb) cb->u.bitmap.ignore_alpha = bitmap->format.alphaMode == D2D1_ALPHA_MODE_IGNORE; + if (brush->type == D2D_BRUSH_TYPE_IMAGE) + ID2D1Bitmap_Release(src_bitmap); + return TRUE; + } default: FIXME("Unhandled brush type %#x.\n", brush->type); @@ -1485,31 +1505,31 @@ BOOL d2d_brush_fill_cb(const struct d2d_brush *brush, struct d2d_brush_cb *cb) } } -static void d2d_brush_bind_bitmap(struct d2d_brush *brush, struct d2d_device_context *context, - unsigned int brush_idx) +static void d2d_brush_bind(struct d2d_bitmap *bitmap, struct d2d_device_context *context, + const D2D1_IMAGE_BRUSH_PROPERTIES *image_brush_desc, unsigned int brush_idx) { ID3D11SamplerState **sampler_state; ID3D11DeviceContext *d3d_context; HRESULT hr; ID3D11Device1_GetImmediateContext(context->d3d_device, &d3d_context); - ID3D11DeviceContext_PSSetShaderResources(d3d_context, brush_idx, 1, &brush->u.bitmap.bitmap->srv); + ID3D11DeviceContext_PSSetShaderResources(d3d_context, brush_idx, 1, &bitmap->srv); sampler_state = &context->sampler_states - [brush->u.bitmap.interpolation_mode % D2D_SAMPLER_INTERPOLATION_MODE_COUNT] - [brush->u.bitmap.extend_mode_x % D2D_SAMPLER_EXTEND_MODE_COUNT] - [brush->u.bitmap.extend_mode_y % D2D_SAMPLER_EXTEND_MODE_COUNT]; + [image_brush_desc->interpolationMode % D2D_SAMPLER_INTERPOLATION_MODE_COUNT] + [image_brush_desc->extendModeX % D2D_SAMPLER_EXTEND_MODE_COUNT] + [image_brush_desc->extendModeY % D2D_SAMPLER_EXTEND_MODE_COUNT]; if (!*sampler_state) { D3D11_SAMPLER_DESC sampler_desc; - if (brush->u.bitmap.interpolation_mode == D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR) + if (image_brush_desc->interpolationMode == D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR) sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; else sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - sampler_desc.AddressU = texture_address_mode_from_extend_mode(brush->u.bitmap.extend_mode_x); - sampler_desc.AddressV = texture_address_mode_from_extend_mode(brush->u.bitmap.extend_mode_y); + sampler_desc.AddressU = texture_address_mode_from_extend_mode(image_brush_desc->extendModeX); + sampler_desc.AddressV = texture_address_mode_from_extend_mode(image_brush_desc->extendModeY); sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampler_desc.MipLODBias = 0.0f; sampler_desc.MaxAnisotropy = 0; @@ -1529,6 +1549,47 @@ static void d2d_brush_bind_bitmap(struct d2d_brush *brush, struct d2d_device_con ID3D11DeviceContext_Release(d3d_context); } +static void d2d_brush_bind_bitmap(struct d2d_brush *brush, struct d2d_device_context *context, + unsigned int brush_idx) +{ + D2D1_IMAGE_BRUSH_PROPERTIES image_brush_desc; + + image_brush_desc.sourceRectangle.left = 0.0f; + image_brush_desc.sourceRectangle.top = 0.0f; + image_brush_desc.sourceRectangle.right = brush->u.bitmap.bitmap->pixel_size.width; + image_brush_desc.sourceRectangle.bottom = brush->u.bitmap.bitmap->pixel_size.height; + image_brush_desc.extendModeX = brush->u.bitmap.extend_mode_x; + image_brush_desc.extendModeY = brush->u.bitmap.extend_mode_y; + image_brush_desc.interpolationMode = brush->u.bitmap.interpolation_mode; + + d2d_brush_bind(brush->u.bitmap.bitmap, context, &image_brush_desc, brush_idx); +} + +static void d2d_brush_bind_image(struct d2d_brush *brush, struct d2d_device_context *context, + unsigned int brush_idx) +{ + ID2D1Bitmap *src_bitmap; + struct d2d_bitmap *bitmap; + D2D1_IMAGE_BRUSH_PROPERTIES image_brush_desc; + + if (FAILED(ID2D1Image_QueryInterface(brush->u.image.image, &IID_ID2D1Bitmap, (void **)&src_bitmap))) + { + FIXME("ID2D1Image doesn't support ID2D1Bitmap interface.\n"); + return; + } + + bitmap = unsafe_impl_from_ID2D1Bitmap(src_bitmap); + + image_brush_desc.sourceRectangle = brush->u.image.source_rect; + image_brush_desc.extendModeX = brush->u.bitmap.extend_mode_x; + image_brush_desc.extendModeY = brush->u.bitmap.extend_mode_y; + image_brush_desc.interpolationMode = brush->u.bitmap.interpolation_mode; + + d2d_brush_bind(bitmap, context, &image_brush_desc, brush_idx); + + ID2D1Bitmap_Release(src_bitmap); +} + void d2d_brush_bind_resources(struct d2d_brush *brush, struct d2d_device_context *context, unsigned int brush_idx) { switch (brush->type) @@ -1548,6 +1609,10 @@ void d2d_brush_bind_resources(struct d2d_brush *brush, struct d2d_device_context d2d_brush_bind_bitmap(brush, context, brush_idx); break; + case D2D_BRUSH_TYPE_IMAGE: + d2d_brush_bind_image(brush, context, brush_idx); + break; + default: FIXME("Unhandled brush type %#x.\n", brush->type); break; diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index 12aa2acc331..a619c006885 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -1043,7 +1043,7 @@ static void STDMETHODCALLTYPE d2d_device_context_FillGeometry(ID2D1DeviceContext if (FAILED(context->error.code)) return; - if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP) + if (opacity_brush && !(brush_impl->type == D2D_BRUSH_TYPE_BITMAP || brush_impl->type == D2D_BRUSH_TYPE_IMAGE)) { d2d_device_context_set_error(context, D2DERR_INCOMPATIBLE_BRUSH_TYPES); return; -- 2.36.1