Henri Verbeet : d2d1: Properly handle D2D1_ALPHA_MODE_PREMULTIPLIED on render targets.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Jul 30 17:10:04 CDT 2015


Module: wine
Branch: master
Commit: c2135dd498dc729deb5ad9f525f7b52c87c7d9f9
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c2135dd498dc729deb5ad9f525f7b52c87c7d9f9

Author: Henri Verbeet <hverbeet at codeweavers.com>
Date:   Thu Jul 30 11:10:56 2015 +0200

d2d1: Properly handle D2D1_ALPHA_MODE_PREMULTIPLIED on render targets.

---

 dlls/d2d1/render_target.c |  18 +++++--
 dlls/d2d1/tests/d2d1.c    | 117 ++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 124 insertions(+), 11 deletions(-)

diff --git a/dlls/d2d1/render_target.c b/dlls/d2d1/render_target.c
index 925db33..a25b8ea 100644
--- a/dlls/d2d1/render_target.c
+++ b/dlls/d2d1/render_target.c
@@ -1165,7 +1165,11 @@ static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *ifa
 
     if (color)
         c = *color;
-    c.a = 1.0f;
+    if (render_target->format.alphaMode == D2D1_ALPHA_MODE_IGNORE)
+        c.a = 1.0f;
+    c.r *= c.a;
+    c.g *= c.a;
+    c.b *= c.a;
     buffer_desc.ByteWidth = sizeof(c);
     buffer_data.pSysMem = &c;
 
@@ -1794,8 +1798,16 @@ HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target,
     blend_desc.SrcBlend = D3D10_BLEND_ONE;
     blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
     blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
-    blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
-    blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
+    if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
+    {
+        blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
+        blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
+    }
+    else
+    {
+        blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
+        blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
+    }
     blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
     blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
     if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index a7c720b..a0c9b11 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -438,29 +438,34 @@ static IDXGISwapChain *create_swapchain(ID3D10Device1 *device, HWND window, BOOL
     return swapchain;
 }
 
-static ID2D1RenderTarget *create_render_target(IDXGISurface *surface)
+static ID2D1RenderTarget *create_render_target_desc(IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
 {
-    D2D1_RENDER_TARGET_PROPERTIES desc;
     ID2D1RenderTarget *render_target;
     ID2D1Factory *factory;
     HRESULT hr;
 
     hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
     ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
+    hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, desc, &render_target);
+    ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
+    ID2D1Factory_Release(factory);
+
+    return render_target;
+}
+
+static ID2D1RenderTarget *create_render_target(IDXGISurface *surface)
+{
+    D2D1_RENDER_TARGET_PROPERTIES desc;
 
     desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
     desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
-    desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
+    desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
     desc.dpiX = 0.0f;
     desc.dpiY = 0.0f;
     desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
     desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
-    hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &render_target);
-    ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
 
-    ID2D1Factory_Release(factory);
-
-    return render_target;
+    return create_render_target_desc(surface, &desc);
 }
 
 static void test_clip(void)
@@ -1611,6 +1616,7 @@ static void test_bitmap_formats(void)
 
 static void test_alpha_mode(void)
 {
+    D2D1_RENDER_TARGET_PROPERTIES rt_desc;
     D2D1_BITMAP_PROPERTIES bitmap_desc;
     ID2D1SolidColorBrush *color_brush;
     ID2D1BitmapBrush *bitmap_brush;
@@ -1672,6 +1678,101 @@ static void test_alpha_mode(void)
     ID2D1RenderTarget_Clear(rt, NULL);
     hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
     ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
+    match = compare_surface(surface, "48c41aff3a130a17ee210866b2ab7d36763934d5");
+    ok(match, "Surface does not match.\n");
+
+    ID2D1RenderTarget_BeginDraw(rt);
+    set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
+    ID2D1RenderTarget_Clear(rt, &color);
+    hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
+    ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
+    match = compare_surface(surface, "6487e683730fb5a77c1911388d00b04664c5c4e4");
+    ok(match, "Surface does not match.\n");
+
+    ID2D1RenderTarget_BeginDraw(rt);
+    set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
+    ID2D1RenderTarget_Clear(rt, &color);
+    hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
+    ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
+    match = compare_surface(surface, "7a35ba09e43cbaf591388ff1ef8de56157630c98");
+    ok(match, "Surface does not match.\n");
+
+    ID2D1RenderTarget_BeginDraw(rt);
+
+    set_rect(&rect,   0.0f,   0.0f, 160.0f, 120.0f);
+    ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
+    set_rect(&rect, 160.0f,   0.0f, 320.0f, 120.0f);
+    ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
+    ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
+    set_rect(&rect, 320.0f,   0.0f, 480.0f, 120.0f);
+    ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
+    ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
+
+    ID2D1Bitmap_Release(bitmap);
+    bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
+    hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
+    ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
+    ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
+
+    set_rect(&rect,   0.0f, 120.0f, 160.0f, 240.0f);
+    ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
+    ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
+    set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
+    ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
+    ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
+    set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
+    ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
+    ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
+
+    set_rect(&rect,   0.0f, 240.0f, 160.0f, 360.0f);
+    ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
+    set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
+    ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
+    ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
+    set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
+    ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
+    ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
+
+    hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
+    ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
+    match = compare_surface(surface, "14f8ac64b70966c7c3c6281c59aaecdb17c3b16a");
+    ok(match, "Surface does not match.\n");
+
+    ID2D1RenderTarget_Release(rt);
+    rt_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
+    rt_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
+    rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
+    rt_desc.dpiX = 0.0f;
+    rt_desc.dpiY = 0.0f;
+    rt_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
+    rt_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
+    rt = create_render_target_desc(surface, &rt_desc);
+    ok(!!rt, "Failed to create render target.\n");
+
+    ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
+
+    ID2D1Bitmap_Release(bitmap);
+    bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
+    hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
+    ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
+    ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
+
+    ID2D1BitmapBrush_Release(bitmap_brush);
+    hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
+    ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
+    ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
+    ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
+    ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
+
+    ID2D1SolidColorBrush_Release(color_brush);
+    set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
+    hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
+    ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
+
+    ID2D1RenderTarget_BeginDraw(rt);
+    ID2D1RenderTarget_Clear(rt, NULL);
+    hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
+    ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
     match = compare_surface(surface, "b44510bf2d2e61a8d7c0ad862de49a471f1fd13f");
     ok(match, "Surface does not match.\n");
 




More information about the wine-cvs mailing list