d2d1: Bitmap values are always premultiplied in practice.

Since creating bitmaps with D2D1_ALPHA_MODE_UNKNOWN or
D2D1_ALPHA_MODE_STRAIGHT is not possible, and D2D1_ALPHA_MODE_IGNORE
behaves as if alpha == 1.0f.
This commit is contained in:
Henri Verbeet 2015-07-30 11:10:55 +02:00 committed by Alexandre Julliard
parent 905bf79337
commit 52c412492f
3 changed files with 145 additions and 9 deletions

View file

@ -746,6 +746,9 @@ HRESULT d2d_brush_get_ps_cb(struct d2d_brush *brush, struct d2d_d3d_render_targe
{
color = brush->u.solid.color;
color.a *= brush->opacity;
color.r *= color.a;
color.g *= color.a;
color.b *= color.a;
buffer_desc.ByteWidth = sizeof(color);
buffer_data.pSysMem = &color;

View file

@ -1580,16 +1580,14 @@ HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target,
texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
ret = t.Sample(s, texcoord);
ret = t.Sample(s, texcoord) * opacity;
if (ignore_alpha)
ret.a = opacity;
else
ret.a *= opacity;
return ret;
}
#endif
0x43425844, 0xf2e9967c, 0xad1d1ac2, 0x865274b8, 0x6ab4c5ca, 0x00000001, 0x000001fc, 0x00000003,
0x43425844, 0xf5bb1e01, 0xe3386963, 0xcaa095bd, 0xea2887de, 0x00000001, 0x000001fc, 0x00000003,
0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
@ -1601,10 +1599,10 @@ HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target,
0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x00100082,
0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x05000036, 0x00102072,
0x00000000, 0x00100246, 0x00000000, 0x0b000037, 0x00102082, 0x00000000, 0x0020800a, 0x00000000,
0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a, 0x00000000, 0x0100003e,
0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00102082,
0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x0100003e,
};
/* The basic idea here is to evaluate the implicit form of the curve in
* texture space. "t.z" determines which side of the curve is shaded. */
@ -1793,7 +1791,7 @@ HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target,
memset(&blend_desc, 0, sizeof(blend_desc));
blend_desc.BlendEnable[0] = TRUE;
blend_desc.SrcBlend = D3D10_BLEND_SRC_ALPHA;
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;

View file

@ -1609,6 +1609,140 @@ static void test_bitmap_formats(void)
DestroyWindow(window);
}
static void test_alpha_mode(void)
{
D2D1_BITMAP_PROPERTIES bitmap_desc;
ID2D1SolidColorBrush *color_brush;
ID2D1BitmapBrush *bitmap_brush;
IDXGISwapChain *swapchain;
ID2D1RenderTarget *rt;
ID3D10Device1 *device;
IDXGISurface *surface;
ID2D1Bitmap *bitmap;
D2D1_COLOR_F color;
D2D1_RECT_F rect;
D2D1_SIZE_U size;
ULONG refcount;
HWND window;
HRESULT hr;
BOOL match;
static const DWORD bitmap_data[] =
{
0x7f7f0000, 0x7f7f7f00, 0x7f007f00, 0x7f007f7f,
0x7f00007f, 0x7f7f007f, 0x7f000000, 0x7f404040,
0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f000000,
0x7f7f7f7f, 0x7f000000, 0x7f000000, 0x7f000000,
};
if (!(device = create_device()))
{
skip("Failed to create device, skipping tests.\n");
return;
}
window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 640, 480, NULL, NULL, NULL, NULL);
swapchain = create_swapchain(device, window, TRUE);
hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
rt = create_render_target(surface);
ok(!!rt, "Failed to create render target.\n");
ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
set_size_u(&size, 4, 4);
bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
bitmap_desc.dpiX = 96.0f / 40.0f;
bitmap_desc.dpiY = 96.0f / 30.0f;
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);
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);
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");
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, "2184f4a9198fc1de09ac85301b7a03eebadd9b81");
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, "6527ec83b4039c895b50f9b3e144fe0cf90d1889");
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, "465f5a3190d7bde408b3206b4be939fb22f8a3d6");
ok(match, "Surface does not match.\n");
refcount = ID2D1Bitmap_Release(bitmap);
ok(refcount == 1, "Bitmap has %u references left.\n", refcount);
ID2D1SolidColorBrush_Release(color_brush);
ID2D1BitmapBrush_Release(bitmap_brush);
ID2D1RenderTarget_Release(rt);
IDXGISurface_Release(surface);
IDXGISwapChain_Release(swapchain);
ID3D10Device1_Release(device);
DestroyWindow(window);
}
START_TEST(d2d1)
{
test_clip();
@ -1617,4 +1751,5 @@ START_TEST(d2d1)
test_bitmap_brush();
test_path_geometry();
test_bitmap_formats();
test_alpha_mode();
}