v2: Add a test for sourceRectangle, drop ::FillGeometry() change.
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/d2d1/brush.c | 85 +++++++++++++++++++++++++++++++++++++----- dlls/d2d1/tests/d2d1.c | 46 +++++++++++++++++++++++ 2 files changed, 121 insertions(+), 10 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/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);