From: Zhiyi Zhang <zzhang@codeweavers.com> --- dlls/d2d1/tests/d2d1.c | 313 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 313 insertions(+) diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 012f3005d09..f85c65ad9c3 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -2516,17 +2516,244 @@ static void test_color_brush(BOOL d3d11) release_test_context(&ctx); } +struct opacity_command_sink +{ + ID2D1CommandSink ID2D1CommandSink_iface; + unsigned int draw_bitmap_count; +}; + +static inline struct opacity_command_sink *impl_from_ID2D1CommandSink(ID2D1CommandSink *iface) +{ + return CONTAINING_RECORD(iface, struct opacity_command_sink, ID2D1CommandSink_iface); +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_QueryInterface(ID2D1CommandSink *iface, + REFIID iid, void **out) +{ + if (IsEqualGUID(iid, &IID_ID2D1CommandSink) || IsEqualGUID(iid, &IID_IUnknown)) + { + ID2D1CommandSink_AddRef(iface); + *out = iface; + return S_OK; + } + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE opacity_command_sink_AddRef(ID2D1CommandSink *iface) +{ + return 2; +} + +static ULONG STDMETHODCALLTYPE opacity_command_sink_Release(ID2D1CommandSink *iface) +{ + return 1; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_BeginDraw(ID2D1CommandSink *iface) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_EndDraw(ID2D1CommandSink *iface) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_SetAntialiasMode(ID2D1CommandSink *iface, + D2D1_ANTIALIAS_MODE antialias_mode) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_SetTags(ID2D1CommandSink *iface, + D2D1_TAG tag1, D2D1_TAG tag2) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_SetTextAntialiasMode(ID2D1CommandSink *iface, + D2D1_TEXT_ANTIALIAS_MODE antialias_mode) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_SetTextRenderingParams(ID2D1CommandSink *iface, + IDWriteRenderingParams *text_rendering_params) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_SetTransform(ID2D1CommandSink *iface, + const D2D1_MATRIX_3X2_F *transform) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_SetPrimitiveBlend(ID2D1CommandSink *iface, + D2D1_PRIMITIVE_BLEND primitive_blend) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_SetUnitMode(ID2D1CommandSink *iface, + D2D1_UNIT_MODE unit_mode) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_Clear(ID2D1CommandSink *iface, + const D2D1_COLOR_F *color) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_DrawGlyphRun(ID2D1CommandSink *iface, + D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, + const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, + DWRITE_MEASURING_MODE measuring_mode) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_DrawLine(ID2D1CommandSink *iface, + D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, + ID2D1StrokeStyle *stroke_style) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_DrawGeometry(ID2D1CommandSink *iface, + ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, + ID2D1StrokeStyle *stroke_style) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_DrawRectangle(ID2D1CommandSink *iface, + const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, + ID2D1StrokeStyle *stroke_style) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_DrawBitmap(ID2D1CommandSink *iface, ID2D1Bitmap *bitmap, + const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode, + const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform) +{ + struct opacity_command_sink *sink = impl_from_ID2D1CommandSink(iface); + ok(opacity == 255.0f || opacity == -255.0f, "Got unexpected opacity %.8e.\n", opacity); + sink->draw_bitmap_count++; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_DrawImage(ID2D1CommandSink *iface, + ID2D1Image *image, const D2D1_POINT_2F *target_offset, const D2D1_RECT_F *image_rect, + D2D1_INTERPOLATION_MODE interpolation_mode, D2D1_COMPOSITE_MODE composite_mode) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_DrawGdiMetafile(ID2D1CommandSink *iface, + ID2D1GdiMetafile *metafile, const D2D1_POINT_2F *target_offset) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_FillMesh(ID2D1CommandSink *iface, + ID2D1Mesh *mesh, ID2D1Brush *brush) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_FillOpacityMask(ID2D1CommandSink *iface, + ID2D1Bitmap *opacity_mask, ID2D1Brush *brush, const D2D1_RECT_F *dst_rect, + const D2D1_RECT_F *src_rect) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_FillGeometry(ID2D1CommandSink *iface, + ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_FillRectangle(ID2D1CommandSink *iface, + const D2D1_RECT_F *rect, ID2D1Brush *brush) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_PushAxisAlignedClip(ID2D1CommandSink *iface, + const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_PushLayer(ID2D1CommandSink *iface, + const D2D1_LAYER_PARAMETERS1 *layer_parameters, ID2D1Layer *layer) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_PopAxisAlignedClip(ID2D1CommandSink *iface) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE opacity_command_sink_PopLayer(ID2D1CommandSink *iface) +{ + return S_OK; +} + +static const ID2D1CommandSinkVtbl opacity_command_sink_vtbl = +{ + opacity_command_sink_QueryInterface, + opacity_command_sink_AddRef, + opacity_command_sink_Release, + opacity_command_sink_BeginDraw, + opacity_command_sink_EndDraw, + opacity_command_sink_SetAntialiasMode, + opacity_command_sink_SetTags, + opacity_command_sink_SetTextAntialiasMode, + opacity_command_sink_SetTextRenderingParams, + opacity_command_sink_SetTransform, + opacity_command_sink_SetPrimitiveBlend, + opacity_command_sink_SetUnitMode, + opacity_command_sink_Clear, + opacity_command_sink_DrawGlyphRun, + opacity_command_sink_DrawLine, + opacity_command_sink_DrawGeometry, + opacity_command_sink_DrawRectangle, + opacity_command_sink_DrawBitmap, + opacity_command_sink_DrawImage, + opacity_command_sink_DrawGdiMetafile, + opacity_command_sink_FillMesh, + opacity_command_sink_FillOpacityMask, + opacity_command_sink_FillGeometry, + opacity_command_sink_FillRectangle, + opacity_command_sink_PushAxisAlignedClip, + opacity_command_sink_PushLayer, + opacity_command_sink_PopAxisAlignedClip, + opacity_command_sink_PopLayer, +}; + static void test_bitmap_brush(BOOL d3d11) { D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode; + struct opacity_command_sink opacity_command_sink; ID2D1TransformedGeometry *transformed_geometry; ID2D1RectangleGeometry *rectangle_geometry; D2D1_MATRIX_3X2_F matrix, tmp_matrix; D2D1_BITMAP_PROPERTIES bitmap_desc; ID2D1Bitmap *bitmap, *tmp_bitmap; D2D1_RECT_F src_rect, dst_rect; + ID2D1CommandList *command_list; struct d2d1_test_context ctx; D2D1_EXTEND_MODE extend_mode; + struct resource_readback rb; ID2D1BitmapBrush1 *brush1; ID2D1BitmapBrush *brush; D2D1_SIZE_F image_size; @@ -2538,6 +2765,7 @@ static void test_bitmap_brush(BOOL d3d11) unsigned int i; ULONG refcount; float opacity; + DWORD colour; HRESULT hr; BOOL match; @@ -2568,6 +2796,10 @@ static void test_bitmap_brush(BOOL d3d11) 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, }; + static const DWORD opacity_test_bitmap_data[] = + { + 0xff7f0000 + }; if (!init_test_context(&ctx, d3d11)) return; @@ -2900,6 +3132,87 @@ static void test_bitmap_brush(BOOL d3d11) ID2D1BitmapBrush_Release(brush); refcount = ID2D1Bitmap_Release(bitmap); ok(!refcount, "Bitmap has %lu references left.\n", refcount); + + /* Test ID2D1RenderTarget_DrawBitmap() with out of range opacity values */ + set_size_u(&size, 1, 1); + bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; + bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; + bitmap_desc.dpiX = 96.0f; + bitmap_desc.dpiY = 96.0f; + hr = ID2D1RenderTarget_CreateBitmap(rt, size, opacity_test_bitmap_data, + sizeof(*bitmap_data), &bitmap_desc, &bitmap); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + ID2D1RenderTarget_SetDpi(rt, 96.0f, 96.0f); + ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); + ID2D1RenderTarget_BeginDraw(rt); + set_color(&color, 0.0f, 0.0f, 0.0f, 1.0f); + ID2D1RenderTarget_Clear(rt, &color); + set_rect(&dst_rect, 0.0f, 0.0f, 1.0f, 1.0f); + ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 255.0f, + D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL); + set_rect(&dst_rect, 1.0f, 0.0f, 2.0f, 1.0f); + ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, -255.0f, + D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL); + hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + get_surface_readback(&ctx, &rb); + colour = get_readback_colour(&rb, 0, 0); + todo_wine + ok(compare_colour(colour, 0xff7f0000, 1), "Got unexpected colour 0x%08lx.\n", colour); + colour = get_readback_colour(&rb, 1, 0); + ok(compare_colour(colour, 0xff010000, 1), "Got unexpected colour 0x%08lx.\n", colour); + release_resource_readback(&rb); + + /* Test ID2D1DeviceContext_DrawBitmap() with out of range opacity values */ + ID2D1DeviceContext_BeginDraw(ctx.context); + set_color(&color, 0.0f, 0.0f, 0.0f, 1.0f); + ID2D1DeviceContext_Clear(ctx.context, &color); + set_rect(&dst_rect, 0.0f, 0.0f, 1.0f, 1.0f); + ID2D1DeviceContext_DrawBitmap(ctx.context, bitmap, &dst_rect, 255.0f, + D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL, NULL); + set_rect(&dst_rect, 1.0f, 0.0f, 2.0f, 1.0f); + ID2D1DeviceContext_DrawBitmap(ctx.context, bitmap, &dst_rect, -255.0f, + D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL, NULL); + hr = ID2D1DeviceContext_EndDraw(ctx.context, NULL, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + get_surface_readback(&ctx, &rb); + colour = get_readback_colour(&rb, 0, 0); + todo_wine + ok(compare_colour(colour, 0xff7f0000, 1), "Got unexpected colour 0x%08lx.\n", colour); + colour = get_readback_colour(&rb, 1, 0); + ok(compare_colour(colour, 0xff010000, 1), "Got unexpected colour 0x%08lx.\n", colour); + release_resource_readback(&rb); + + /* Test ID2D1DeviceContext_DrawBitmap() with a command list and out of range opacity values */ + hr = ID2D1DeviceContext_CreateCommandList(ctx.context, &command_list); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ID2D1DeviceContext_SetTarget(ctx.context, (ID2D1Image *)command_list); + ID2D1DeviceContext_BeginDraw(ctx.context); + ID2D1DeviceContext_DrawBitmap(ctx.context, bitmap, NULL, 255.0f, + D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL, NULL); + ID2D1DeviceContext_DrawBitmap(ctx.context, bitmap, NULL, -255.0f, + D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL, NULL); + hr = ID2D1DeviceContext_EndDraw(ctx.context, NULL, NULL); + todo_wine + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ID2D1CommandList_Close(command_list); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + opacity_command_sink.ID2D1CommandSink_iface.lpVtbl = &opacity_command_sink_vtbl; + opacity_command_sink.draw_bitmap_count = 0; + + hr = ID2D1CommandList_Stream(command_list, &opacity_command_sink.ID2D1CommandSink_iface); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(opacity_command_sink.draw_bitmap_count == 2, "Got unexpected count %u.\n", opacity_command_sink.draw_bitmap_count); + + ID2D1DeviceContext_SetTarget(ctx.context, NULL); + ID2D1CommandList_Release(command_list); + + ID2D1Bitmap_Release(bitmap); release_test_context(&ctx); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10162