From: Dmitry Timoshkov <dmitry(a)baikal.ru>
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
v3: simplified helpers a bit.
dlls/d2d1/brush.c | 68 +++++++++++++++++++++++++++++++++++-------
dlls/d2d1/tests/d2d1.c | 46 ++++++++++++++++++++++++++++
2 files changed, 103 insertions(+), 11 deletions(-)
diff --git a/dlls/d2d1/brush.c b/dlls/d2d1/brush.c
index b9a673fe54c..22116759b10 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 *image_bitmap = NULL;
+
+ if (brush->type == D2D_BRUSH_TYPE_BITMAP)
+ bitmap = brush->u.bitmap.bitmap;
+ else
+ {
+ if (FAILED(ID2D1Image_QueryInterface(brush->u.image.image, &IID_ID2D1Bitmap, (void **)&image_bitmap)))
+ {
+ FIXME("Only image brushes with bitmaps are supported.\n");
+ return FALSE;
+ }
+
+ bitmap = unsafe_impl_from_ID2D1Bitmap(image_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 (image_bitmap)
+ ID2D1Bitmap_Release(image_bitmap);
+
return TRUE;
+ }
default:
FIXME("Unhandled brush type %#x.\n", brush->type);
@@ -1485,31 +1505,32 @@ 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_bitmap(struct d2d_bitmap *bitmap, struct d2d_device_context *context,
+ D2D1_EXTEND_MODE extend_mode_x, D2D1_EXTEND_MODE extend_mode_y,
+ D2D1_INTERPOLATION_MODE interpolation_mode, 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];
+ [interpolation_mode % D2D_SAMPLER_INTERPOLATION_MODE_COUNT]
+ [extend_mode_x % D2D_SAMPLER_EXTEND_MODE_COUNT]
+ [extend_mode_y % 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 (interpolation_mode == 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(extend_mode_x);
+ sampler_desc.AddressV = texture_address_mode_from_extend_mode(extend_mode_y);
sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
sampler_desc.MipLODBias = 0.0f;
sampler_desc.MaxAnisotropy = 0;
@@ -1529,6 +1550,26 @@ static void d2d_brush_bind_bitmap(struct d2d_brush *brush, struct d2d_device_con
ID3D11DeviceContext_Release(d3d_context);
}
+static void d2d_brush_bind_image(struct d2d_brush *brush, struct d2d_device_context *context,
+ unsigned int brush_idx)
+{
+ ID2D1Bitmap *image_bitmap;
+ struct d2d_bitmap *bitmap;
+
+ if (FAILED(ID2D1Image_QueryInterface(brush->u.image.image, &IID_ID2D1Bitmap, (void **)&image_bitmap)))
+ {
+ FIXME("Only image brushes with bitmaps are supported.\n");
+ return;
+ }
+
+ bitmap = unsafe_impl_from_ID2D1Bitmap(image_bitmap);
+
+ d2d_brush_bind_bitmap(bitmap, context, brush->u.image.extend_mode_x, brush->u.image.extend_mode_y,
+ brush->u.image.interpolation_mode, brush_idx);
+
+ ID2D1Bitmap_Release(image_bitmap);
+}
+
void d2d_brush_bind_resources(struct d2d_brush *brush, struct d2d_device_context *context, unsigned int brush_idx)
{
switch (brush->type)
@@ -1545,7 +1586,12 @@ void d2d_brush_bind_resources(struct d2d_brush *brush, struct d2d_device_context
break;
case D2D_BRUSH_TYPE_BITMAP:
- d2d_brush_bind_bitmap(brush, context, brush_idx);
+ d2d_brush_bind_bitmap(brush->u.bitmap.bitmap, context, brush->u.bitmap.extend_mode_x,
+ brush->u.bitmap.extend_mode_y, brush->u.bitmap.interpolation_mode, brush_idx);
+ break;
+
+ case D2D_BRUSH_TYPE_IMAGE:
+ d2d_brush_bind_image(brush, context, brush_idx);
break;
default:
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index bc662b4f8ae..752e34bf4da 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -2509,11 +2509,13 @@ static void test_image_brush(BOOL d3d11)
D2D1_BITMAP_PROPERTIES bitmap_desc;
D2D1_BRUSH_PROPERTIES brush_desc;
ID2D1Image *image, *tmp_image;
+ D2D1_RECT_F dst_rect;
struct d2d1_test_context ctx;
D2D1_EXTEND_MODE extend_mode;
D2D1_MATRIX_3X2_F matrix;
ID2D1ImageBrush *brush;
ID2D1Bitmap *bitmap;
+ D2D1_COLOR_F color;
D2D1_SIZE_U size;
D2D1_RECT_F rect;
ULONG refcount;
@@ -2585,6 +2587,50 @@ static void test_image_brush(BOOL d3d11)
ID2D1ImageBrush_Release(brush);
+ /* FillRectangle */
+ set_rect(&image_brush_desc.sourceRectangle, 0.0f, 0.0f, 4.0f, 4.0f);
+ hr = ID2D1DeviceContext_CreateImageBrush(device_context, image, &image_brush_desc, NULL, &brush);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ ID2D1ImageBrush_SetInterpolationMode(brush, D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
+
+ ID2D1RenderTarget_BeginDraw(ctx.rt);
+
+ set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
+ ID2D1RenderTarget_Clear(ctx.rt, &color);
+
+ set_rect(&dst_rect, 40.0f, 120.0f, 120.0f, 360.0f);
+ ID2D1RenderTarget_FillRectangle(ctx.rt, &dst_rect, (ID2D1Brush *)brush);
+
+ hr = ID2D1RenderTarget_EndDraw(ctx.rt, NULL, NULL);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ match = compare_surface(&ctx, "89917481db82e6d683a75f068d3984fe2703cce5");
+ ok(match, "Surface does not match.\n");
+
+ ID2D1ImageBrush_Release(brush);
+
+ set_rect(&image_brush_desc.sourceRectangle, 0.0f, 0.0f, 1.0f, 1.0f);
+ hr = ID2D1DeviceContext_CreateImageBrush(device_context, image, &image_brush_desc, NULL, &brush);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ ID2D1ImageBrush_SetInterpolationMode(brush, D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
+
+ ID2D1RenderTarget_BeginDraw(ctx.rt);
+
+ set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
+ ID2D1RenderTarget_Clear(ctx.rt, &color);
+
+ set_rect(&dst_rect, 40.0f, 120.0f, 120.0f, 360.0f);
+ ID2D1RenderTarget_FillRectangle(ctx.rt, &dst_rect, (ID2D1Brush *)brush);
+
+ hr = ID2D1RenderTarget_EndDraw(ctx.rt, NULL, NULL);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ match = compare_surface(&ctx, "23544adf9695a51428c194a1cffd531be3416e65");
+ todo_wine
+ ok(match, "Surface does not match.\n");
+
+ ID2D1ImageBrush_Release(brush);
+
/* Custom brush description and image pointer. */
brush_desc.opacity = 2.0f;
set_matrix_identity(&brush_desc.transform);
--
2.35.1