From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru Signed-off-by: Nikolay Sivov nsivov@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);