d2d1/tests: Add some tests for opacity brushes.
[wine.git] / dlls / d2d1 / tests / d2d1.c
blobb721c2684cdfd7125a6bd1f747837764b42e8637
1 /*
2 * Copyright 2014 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
20 #include <math.h>
21 #include "d2d1.h"
22 #include "wincrypt.h"
23 #include "wine/test.h"
24 #include "initguid.h"
25 #include "dwrite.h"
26 #include "wincodec.h"
28 struct figure
30 unsigned int *spans;
31 unsigned int spans_size;
32 unsigned int span_count;
35 static void set_point(D2D1_POINT_2F *point, float x, float y)
37 point->x = x;
38 point->y = y;
41 static void set_quadratic(D2D1_QUADRATIC_BEZIER_SEGMENT *quadratic, float x1, float y1, float x2, float y2)
43 quadratic->point1.x = x1;
44 quadratic->point1.y = y1;
45 quadratic->point2.x = x2;
46 quadratic->point2.y = y2;
49 static void set_rect(D2D1_RECT_F *rect, float left, float top, float right, float bottom)
51 rect->left = left;
52 rect->top = top;
53 rect->right = right;
54 rect->bottom = bottom;
57 static void set_rect_u(D2D1_RECT_U *rect, UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
59 rect->left = left;
60 rect->top = top;
61 rect->right = right;
62 rect->bottom = bottom;
65 static void set_color(D2D1_COLOR_F *color, float r, float g, float b, float a)
67 color->r = r;
68 color->g = g;
69 color->b = b;
70 color->a = a;
73 static void set_size_u(D2D1_SIZE_U *size, unsigned int w, unsigned int h)
75 size->width = w;
76 size->height = h;
79 static void set_matrix_identity(D2D1_MATRIX_3X2_F *matrix)
81 matrix->_11 = 1.0f;
82 matrix->_12 = 0.0f;
83 matrix->_21 = 0.0f;
84 matrix->_22 = 1.0f;
85 matrix->_31 = 0.0f;
86 matrix->_32 = 0.0f;
89 static void rotate_matrix(D2D1_MATRIX_3X2_F *matrix, float theta)
91 float sin_theta, cos_theta, tmp_11, tmp_12;
93 sin_theta = sinf(theta);
94 cos_theta = cosf(theta);
95 tmp_11 = matrix->_11;
96 tmp_12 = matrix->_12;
98 matrix->_11 = cos_theta * tmp_11 + sin_theta * matrix->_21;
99 matrix->_12 = cos_theta * tmp_12 + sin_theta * matrix->_22;
100 matrix->_21 = -sin_theta * tmp_11 + cos_theta * matrix->_21;
101 matrix->_22 = -sin_theta * tmp_12 + cos_theta * matrix->_22;
104 static void scale_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
106 matrix->_11 *= x;
107 matrix->_12 *= x;
108 matrix->_21 *= y;
109 matrix->_22 *= y;
112 static void translate_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
114 matrix->_31 += x * matrix->_11 + y * matrix->_21;
115 matrix->_32 += x * matrix->_12 + y * matrix->_22;
118 static BOOL compare_sha1(void *data, unsigned int pitch, unsigned int bpp,
119 unsigned int w, unsigned int h, const char *ref_sha1)
121 static const char hex_chars[] = "0123456789abcdef";
122 HCRYPTPROV provider;
123 BYTE hash_data[20];
124 HCRYPTHASH hash;
125 unsigned int i;
126 char sha1[41];
127 BOOL ret;
129 ret = CryptAcquireContextW(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
130 ok(ret, "Failed to acquire crypt context.\n");
131 ret = CryptCreateHash(provider, CALG_SHA1, 0, 0, &hash);
132 ok(ret, "Failed to create hash.\n");
134 for (i = 0; i < h; ++i)
136 if (!(ret = CryptHashData(hash, (BYTE *)data + pitch * i, w * bpp, 0)))
137 break;
139 ok(ret, "Failed to hash data.\n");
141 i = sizeof(hash_data);
142 ret = CryptGetHashParam(hash, HP_HASHVAL, hash_data, &i, 0);
143 ok(ret, "Failed to get hash value.\n");
144 ok(i == sizeof(hash_data), "Got unexpected hash size %u.\n", i);
146 ret = CryptDestroyHash(hash);
147 ok(ret, "Failed to destroy hash.\n");
148 ret = CryptReleaseContext(provider, 0);
149 ok(ret, "Failed to release crypt context.\n");
151 for (i = 0; i < 20; ++i)
153 sha1[i * 2] = hex_chars[hash_data[i] >> 4];
154 sha1[i * 2 + 1] = hex_chars[hash_data[i] & 0xf];
156 sha1[40] = 0;
158 return !strcmp(ref_sha1, (char *)sha1);
161 static BOOL compare_surface(IDXGISurface *surface, const char *ref_sha1)
163 D3D10_MAPPED_TEXTURE2D mapped_texture;
164 D3D10_TEXTURE2D_DESC texture_desc;
165 DXGI_SURFACE_DESC surface_desc;
166 ID3D10Resource *src_resource;
167 ID3D10Texture2D *texture;
168 ID3D10Device *device;
169 HRESULT hr;
170 BOOL ret;
172 hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&device);
173 ok(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
174 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&src_resource);
175 ok(SUCCEEDED(hr), "Failed to query resource interface, hr %#x.\n", hr);
177 hr = IDXGISurface_GetDesc(surface, &surface_desc);
178 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
179 texture_desc.Width = surface_desc.Width;
180 texture_desc.Height = surface_desc.Height;
181 texture_desc.MipLevels = 1;
182 texture_desc.ArraySize = 1;
183 texture_desc.Format = surface_desc.Format;
184 texture_desc.SampleDesc = surface_desc.SampleDesc;
185 texture_desc.Usage = D3D10_USAGE_STAGING;
186 texture_desc.BindFlags = 0;
187 texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
188 texture_desc.MiscFlags = 0;
189 hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, &texture);
190 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
192 ID3D10Device_CopyResource(device, (ID3D10Resource *)texture, src_resource);
193 hr = ID3D10Texture2D_Map(texture, 0, D3D10_MAP_READ, 0, &mapped_texture);
194 ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr);
195 ret = compare_sha1(mapped_texture.pData, mapped_texture.RowPitch, 4,
196 texture_desc.Width, texture_desc.Height, ref_sha1);
197 ID3D10Texture2D_Unmap(texture, 0);
199 ID3D10Texture2D_Release(texture);
200 ID3D10Resource_Release(src_resource);
201 ID3D10Device_Release(device);
203 return ret;
206 static void serialize_figure(struct figure *figure)
208 static const char lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
209 unsigned int i, j, k, span;
210 char output[76];
211 char t[3];
212 char *p;
214 for (i = 0, j = 0, k = 0, p = output; i < figure->span_count; ++i)
216 span = figure->spans[i];
217 while (span)
219 t[j] = span & 0x7f;
220 if (span > 0x7f)
221 t[j] |= 0x80;
222 span >>= 7;
223 if (++j == 3)
225 p[0] = lookup[(t[0] & 0xfc) >> 2];
226 p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
227 p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
228 p[3] = lookup[t[2] & 0x3f];
229 p += 4;
230 if (++k == 19)
232 trace("%.76s\n", output);
233 p = output;
234 k = 0;
236 j = 0;
240 if (j)
242 for (i = j; i < 3; ++i)
243 t[i] = 0;
244 p[0] = lookup[(t[0] & 0xfc) >> 2];
245 p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
246 p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
247 p[3] = lookup[t[2] & 0x3f];
248 ++k;
250 if (k)
251 trace("%.*s\n", k * 4, output);
254 static void figure_add_span(struct figure *figure, unsigned int span)
256 if (figure->span_count == figure->spans_size)
258 figure->spans_size *= 2;
259 figure->spans = HeapReAlloc(GetProcessHeap(), 0, figure->spans,
260 figure->spans_size * sizeof(*figure->spans));
263 figure->spans[figure->span_count++] = span;
266 static void deserialize_span(struct figure *figure, unsigned int *current, unsigned int *shift, unsigned int c)
268 *current |= (c & 0x7f) << *shift;
269 if (c & 0x80)
271 *shift += 7;
272 return;
275 if (*current)
276 figure_add_span(figure, *current);
277 *current = 0;
278 *shift = 0;
281 static void deserialize_figure(struct figure *figure, const BYTE *s)
283 static const BYTE lookup[] =
285 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
286 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
287 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
288 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
289 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
290 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
291 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
292 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
294 unsigned int current = 0, shift = 0;
295 const BYTE *ptr;
296 BYTE x, y;
298 figure->span_count = 0;
299 figure->spans_size = 64;
300 figure->spans = HeapAlloc(GetProcessHeap(), 0, figure->spans_size * sizeof(*figure->spans));
302 for (ptr = s; *ptr; ptr += 4)
304 x = lookup[ptr[0]];
305 y = lookup[ptr[1]];
306 deserialize_span(figure, &current, &shift, ((x & 0x3f) << 2) | ((y & 0x3f) >> 4));
307 x = lookup[ptr[2]];
308 deserialize_span(figure, &current, &shift, ((y & 0x0f) << 4) | ((x & 0x3f) >> 2));
309 y = lookup[ptr[3]];
310 deserialize_span(figure, &current, &shift, ((x & 0x03) << 6) | (y & 0x3f));
314 static BOOL compare_figure(IDXGISurface *surface, unsigned int x, unsigned int y,
315 unsigned int w, unsigned int h, DWORD prev, unsigned int max_diff, const char *ref)
317 D3D10_MAPPED_TEXTURE2D mapped_texture;
318 D3D10_TEXTURE2D_DESC texture_desc;
319 struct figure ref_figure, figure;
320 DXGI_SURFACE_DESC surface_desc;
321 unsigned int i, j, span, diff;
322 ID3D10Resource *src_resource;
323 ID3D10Texture2D *texture;
324 ID3D10Device *device;
325 HRESULT hr;
327 hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&device);
328 ok(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
329 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&src_resource);
330 ok(SUCCEEDED(hr), "Failed to query resource interface, hr %#x.\n", hr);
332 hr = IDXGISurface_GetDesc(surface, &surface_desc);
333 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
334 texture_desc.Width = surface_desc.Width;
335 texture_desc.Height = surface_desc.Height;
336 texture_desc.MipLevels = 1;
337 texture_desc.ArraySize = 1;
338 texture_desc.Format = surface_desc.Format;
339 texture_desc.SampleDesc = surface_desc.SampleDesc;
340 texture_desc.Usage = D3D10_USAGE_STAGING;
341 texture_desc.BindFlags = 0;
342 texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
343 texture_desc.MiscFlags = 0;
344 hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, &texture);
345 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
347 ID3D10Device_CopyResource(device, (ID3D10Resource *)texture, src_resource);
348 hr = ID3D10Texture2D_Map(texture, 0, D3D10_MAP_READ, 0, &mapped_texture);
349 ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr);
351 figure.span_count = 0;
352 figure.spans_size = 64;
353 figure.spans = HeapAlloc(GetProcessHeap(), 0, figure.spans_size * sizeof(*figure.spans));
355 for (i = 0, span = 0; i < h; ++i)
357 const DWORD *row = (DWORD *)((BYTE *)mapped_texture.pData + (y + i) * mapped_texture.RowPitch + x * 4);
358 for (j = 0; j < w; ++j, ++span)
360 if ((i || j) && prev != row[j])
362 figure_add_span(&figure, span);
363 prev = row[j];
364 span = 0;
368 if (span)
369 figure_add_span(&figure, span);
371 deserialize_figure(&ref_figure, (BYTE *)ref);
372 span = w * h;
373 for (i = 0; i < ref_figure.span_count; ++i)
375 span -= ref_figure.spans[i];
377 if (span)
378 figure_add_span(&ref_figure, span);
380 for (i = 0, j = 0, diff = 0; i < figure.span_count && j < ref_figure.span_count;)
382 if (figure.spans[i] == ref_figure.spans[j])
384 if ((i ^ j) & 1)
385 diff += ref_figure.spans[j];
386 ++i;
387 ++j;
389 else if (figure.spans[i] > ref_figure.spans[j])
391 if ((i ^ j) & 1)
392 diff += ref_figure.spans[j];
393 figure.spans[i] -= ref_figure.spans[j];
394 ++j;
396 else
398 if ((i ^ j) & 1)
399 diff += figure.spans[i];
400 ref_figure.spans[j] -= figure.spans[i];
401 ++i;
404 if (diff > max_diff)
405 serialize_figure(&figure);
407 HeapFree(GetProcessHeap(), 0, ref_figure.spans);
408 HeapFree(GetProcessHeap(), 0, figure.spans);
409 ID3D10Texture2D_Unmap(texture, 0);
411 ID3D10Texture2D_Release(texture);
412 ID3D10Resource_Release(src_resource);
413 ID3D10Device_Release(device);
415 return diff <= max_diff;
418 static ID3D10Device1 *create_device(void)
420 ID3D10Device1 *device;
422 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL,
423 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
424 return device;
425 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_WARP, NULL,
426 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
427 return device;
428 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL,
429 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
430 return device;
432 return NULL;
435 static IDXGISwapChain *create_swapchain(ID3D10Device1 *device, HWND window, BOOL windowed)
437 IDXGISwapChain *swapchain;
438 DXGI_SWAP_CHAIN_DESC desc;
439 IDXGIDevice *dxgi_device;
440 IDXGIAdapter *adapter;
441 IDXGIFactory *factory;
442 HRESULT hr;
444 hr = ID3D10Device1_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
445 ok(SUCCEEDED(hr), "Failed to get DXGI device, hr %#x.\n", hr);
446 hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter);
447 ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr);
448 IDXGIDevice_Release(dxgi_device);
449 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
450 ok(SUCCEEDED(hr), "Failed to get factory, hr %#x.\n", hr);
451 IDXGIAdapter_Release(adapter);
453 desc.BufferDesc.Width = 640;
454 desc.BufferDesc.Height = 480;
455 desc.BufferDesc.RefreshRate.Numerator = 60;
456 desc.BufferDesc.RefreshRate.Denominator = 1;
457 desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
458 desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
459 desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
460 desc.SampleDesc.Count = 1;
461 desc.SampleDesc.Quality = 0;
462 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
463 desc.BufferCount = 1;
464 desc.OutputWindow = window;
465 desc.Windowed = windowed;
466 desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
467 desc.Flags = 0;
469 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &desc, &swapchain);
470 ok(SUCCEEDED(hr), "Failed to create swapchain, hr %#x.\n", hr);
471 IDXGIFactory_Release(factory);
473 return swapchain;
476 static ID2D1RenderTarget *create_render_target_desc(IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
478 ID2D1RenderTarget *render_target;
479 ID2D1Factory *factory;
480 HRESULT hr;
482 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
483 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
484 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, desc, &render_target);
485 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
486 ID2D1Factory_Release(factory);
488 return render_target;
491 static ID2D1RenderTarget *create_render_target(IDXGISurface *surface)
493 D2D1_RENDER_TARGET_PROPERTIES desc;
495 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
496 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
497 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
498 desc.dpiX = 0.0f;
499 desc.dpiY = 0.0f;
500 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
501 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
503 return create_render_target_desc(surface, &desc);
506 static void test_clip(void)
508 IDXGISwapChain *swapchain;
509 D2D1_MATRIX_3X2_F matrix;
510 D2D1_SIZE_U pixel_size;
511 ID2D1RenderTarget *rt;
512 ID3D10Device1 *device;
513 IDXGISurface *surface;
514 D2D1_POINT_2F point;
515 D2D1_COLOR_F color;
516 float dpi_x, dpi_y;
517 D2D1_RECT_F rect;
518 D2D1_SIZE_F size;
519 HWND window;
520 HRESULT hr;
521 BOOL match;
522 static const D2D1_MATRIX_3X2_F identity =
524 1.0f, 0.0f,
525 0.0f, 1.0f,
526 0.0f, 0.0f,
529 if (!(device = create_device()))
531 skip("Failed to create device, skipping tests.\n");
532 return;
534 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
535 0, 0, 640, 480, NULL, NULL, NULL, NULL);
536 swapchain = create_swapchain(device, window, TRUE);
537 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
538 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
539 rt = create_render_target(surface);
540 ok(!!rt, "Failed to create render target.\n");
542 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
543 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
544 ok(dpi_y == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
545 size = ID2D1RenderTarget_GetSize(rt);
546 ok(size.width == 640.0f, "Got unexpected width %.8e.\n", size.width);
547 ok(size.height == 480.0f, "Got unexpected height %.8e.\n", size.height);
548 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
549 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
550 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
552 ID2D1RenderTarget_GetTransform(rt, &matrix);
553 ok(!memcmp(&matrix, &identity, sizeof(matrix)),
554 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
555 matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32);
557 ID2D1RenderTarget_BeginDraw(rt);
559 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
560 ID2D1RenderTarget_Clear(rt, &color);
562 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
563 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
564 ok(dpi_x == 48.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
565 ok(dpi_y == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
566 size = ID2D1RenderTarget_GetSize(rt);
567 ok(size.width == 1280.0f, "Got unexpected width %.8e.\n", size.width);
568 ok(size.height == 240.0f, "Got unexpected height %.8e.\n", size.height);
569 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
570 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
571 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
573 /* The effective clip rect is the intersection of all currently pushed
574 * clip rects. Clip rects are in DIPs. */
575 set_rect(&rect, 0.0f, 0.0f, 1280.0f, 80.0f);
576 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
577 set_rect(&rect, 0.0f, 0.0f, 426.0f, 240.0f);
578 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
580 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
581 ID2D1RenderTarget_Clear(rt, &color);
582 ID2D1RenderTarget_PopAxisAlignedClip(rt);
583 ID2D1RenderTarget_PopAxisAlignedClip(rt);
585 ID2D1RenderTarget_SetDpi(rt, 0.0f, 0.0f);
586 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
587 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
588 ok(dpi_y == 96.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
590 /* Transformations apply to clip rects, the effective clip rect is the
591 * (axis-aligned) bounding box of the transformed clip rect. */
592 set_point(&point, 320.0f, 240.0f);
593 D2D1MakeRotateMatrix(30.0f, point, &matrix);
594 ID2D1RenderTarget_SetTransform(rt, &matrix);
595 set_rect(&rect, 215.0f, 208.0f, 425.0f, 272.0f);
596 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
597 set_color(&color, 1.0f, 1.0f, 1.0f, 1.0f);
598 ID2D1RenderTarget_Clear(rt, &color);
599 ID2D1RenderTarget_PopAxisAlignedClip(rt);
601 /* Transformations are applied when pushing the clip rect, transformations
602 * set afterwards have no effect on the current clip rect. This includes
603 * SetDpi(). */
604 ID2D1RenderTarget_SetTransform(rt, &identity);
605 set_rect(&rect, 427.0f, 320.0f, 640.0f, 480.0f);
606 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
607 ID2D1RenderTarget_SetTransform(rt, &matrix);
608 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
609 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
610 ID2D1RenderTarget_Clear(rt, &color);
611 ID2D1RenderTarget_PopAxisAlignedClip(rt);
613 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
614 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
615 match = compare_surface(surface, "035a44d4198d6e422e9de6185b5b2c2bac5e33c9");
616 ok(match, "Surface does not match.\n");
618 ID2D1RenderTarget_Release(rt);
619 IDXGISurface_Release(surface);
620 IDXGISwapChain_Release(swapchain);
621 ID3D10Device1_Release(device);
622 DestroyWindow(window);
625 static void test_state_block(void)
627 IDWriteRenderingParams *text_rendering_params1, *text_rendering_params2;
628 D2D1_DRAWING_STATE_DESCRIPTION drawing_state;
629 ID2D1DrawingStateBlock *state_block;
630 IDWriteFactory *dwrite_factory;
631 IDXGISwapChain *swapchain;
632 ID2D1RenderTarget *rt;
633 ID3D10Device1 *device;
634 IDXGISurface *surface;
635 ID2D1Factory *factory;
636 ULONG refcount;
637 HWND window;
638 HRESULT hr;
639 static const D2D1_MATRIX_3X2_F identity =
641 1.0f, 0.0f,
642 0.0f, 1.0f,
643 0.0f, 0.0f,
645 static const D2D1_MATRIX_3X2_F transform1 =
647 1.0f, 2.0f,
648 3.0f, 4.0f,
649 5.0f, 6.0f,
651 static const D2D1_MATRIX_3X2_F transform2 =
653 7.0f, 8.0f,
654 9.0f, 10.0f,
655 11.0f, 12.0f,
658 if (!(device = create_device()))
660 skip("Failed to create device, skipping tests.\n");
661 return;
663 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
664 0, 0, 640, 480, NULL, NULL, NULL, NULL);
665 swapchain = create_swapchain(device, window, TRUE);
666 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
667 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
668 rt = create_render_target(surface);
669 ok(!!rt, "Failed to create render target.\n");
670 ID2D1RenderTarget_GetFactory(rt, &factory);
671 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
672 ok(SUCCEEDED(hr), "Failed to create dwrite factory, hr %#x.\n", hr);
673 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &text_rendering_params1);
674 ok(SUCCEEDED(hr), "Failed to create dwrite rendering params, hr %#x.\n", hr);
675 IDWriteFactory_Release(dwrite_factory);
677 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
678 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
679 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
680 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
681 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
682 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
683 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
684 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %08x%08x:%08x%08x.\n",
685 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
686 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
687 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
688 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
689 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
690 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
691 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
692 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
693 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
695 hr = ID2D1Factory_CreateDrawingStateBlock(factory, NULL, NULL, &state_block);
696 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
697 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
698 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
699 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
700 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
701 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
702 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %08x%08x:%08x%08x.\n",
703 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
704 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
705 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
706 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
707 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
708 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
709 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
710 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
711 ID2D1DrawingStateBlock_Release(state_block);
713 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
714 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
715 drawing_state.tag1 = 0xdead;
716 drawing_state.tag2 = 0xbeef;
717 drawing_state.transform = transform1;
718 hr = ID2D1Factory_CreateDrawingStateBlock(factory, &drawing_state, text_rendering_params1, &state_block);
719 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
721 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
722 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
723 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
724 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
725 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
726 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %08x%08x:%08x%08x.\n",
727 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
728 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
729 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
730 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
731 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
732 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
733 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
734 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
735 text_rendering_params2, text_rendering_params1);
736 IDWriteRenderingParams_Release(text_rendering_params2);
738 ID2D1RenderTarget_RestoreDrawingState(rt, state_block);
740 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
741 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
742 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
743 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
744 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
745 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
746 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
747 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %08x%08x:%08x%08x.\n",
748 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
749 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
750 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
751 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
752 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
753 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
754 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
755 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
756 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
757 text_rendering_params2, text_rendering_params1);
758 IDWriteRenderingParams_Release(text_rendering_params2);
760 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
761 ID2D1RenderTarget_SetTextAntialiasMode(rt, D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
762 ID2D1RenderTarget_SetTags(rt, 1, 2);
763 ID2D1RenderTarget_SetTransform(rt, &transform2);
764 ID2D1RenderTarget_SetTextRenderingParams(rt, NULL);
766 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
767 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
768 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
769 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
770 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
771 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
772 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
773 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %08x%08x:%08x%08x.\n",
774 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
775 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
776 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
777 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
778 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
779 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
780 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
781 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
782 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
784 ID2D1RenderTarget_SaveDrawingState(rt, state_block);
786 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
787 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
788 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
789 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
790 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
791 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %08x%08x:%08x%08x.\n",
792 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
793 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
794 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
795 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
796 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
797 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
798 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
799 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
801 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
802 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
803 drawing_state.tag1 = 3;
804 drawing_state.tag2 = 4;
805 drawing_state.transform = transform1;
806 ID2D1DrawingStateBlock_SetDescription(state_block, &drawing_state);
807 ID2D1DrawingStateBlock_SetTextRenderingParams(state_block, text_rendering_params1);
809 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
810 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
811 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
812 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE,
813 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
814 ok(drawing_state.tag1 == 3 && drawing_state.tag2 == 4, "Got unexpected tags %08x%08x:%08x%08x.\n",
815 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
816 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
817 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
818 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
819 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
820 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
821 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
822 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
823 text_rendering_params2, text_rendering_params1);
824 IDWriteRenderingParams_Release(text_rendering_params2);
826 ID2D1DrawingStateBlock_Release(state_block);
828 refcount = IDWriteRenderingParams_Release(text_rendering_params1);
829 ok(!refcount, "Rendering params %u references left.\n", refcount);
830 ID2D1Factory_Release(factory);
831 ID2D1RenderTarget_Release(rt);
832 IDXGISurface_Release(surface);
833 IDXGISwapChain_Release(swapchain);
834 ID3D10Device1_Release(device);
835 DestroyWindow(window);
838 static void test_color_brush(void)
840 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
841 D2D1_BRUSH_PROPERTIES brush_desc;
842 D2D1_COLOR_F color, tmp_color;
843 ID2D1SolidColorBrush *brush;
844 IDXGISwapChain *swapchain;
845 ID2D1RenderTarget *rt;
846 ID3D10Device1 *device;
847 IDXGISurface *surface;
848 D2D1_RECT_F rect;
849 float opacity;
850 HWND window;
851 HRESULT hr;
852 BOOL match;
854 if (!(device = create_device()))
856 skip("Failed to create device, skipping tests.\n");
857 return;
859 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
860 0, 0, 640, 480, NULL, NULL, NULL, NULL);
861 swapchain = create_swapchain(device, window, TRUE);
862 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
863 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
864 rt = create_render_target(surface);
865 ok(!!rt, "Failed to create render target.\n");
867 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
868 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
870 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
871 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
872 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
873 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
874 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
875 set_matrix_identity(&matrix);
876 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
877 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
878 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
879 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
880 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
881 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
882 ok(!memcmp(&tmp_color, &color, sizeof(color)),
883 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
884 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
885 ID2D1SolidColorBrush_Release(brush);
887 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
888 brush_desc.opacity = 0.3f;
889 set_matrix_identity(&matrix);
890 scale_matrix(&matrix, 2.0f, 2.0f);
891 brush_desc.transform = matrix;
892 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, &brush_desc, &brush);
893 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
894 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
895 ok(opacity == 0.3f, "Got unexpected opacity %.8e.\n", opacity);
896 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
897 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
898 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
899 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
900 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
901 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
902 ok(!memcmp(&tmp_color, &color, sizeof(color)),
903 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
904 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
906 ID2D1RenderTarget_BeginDraw(rt);
908 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
909 ID2D1RenderTarget_Clear(rt, &color);
911 ID2D1SolidColorBrush_SetOpacity(brush, 1.0f);
912 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
913 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
915 set_matrix_identity(&matrix);
916 scale_matrix(&matrix, 0.5f, 2.0f);
917 translate_matrix(&matrix, 320.0f, 240.0f);
918 rotate_matrix(&matrix, M_PI / 4.0f);
919 ID2D1RenderTarget_SetTransform(rt, &matrix);
920 set_color(&color, 1.0f, 0.0f, 0.0f, 0.625f);
921 ID2D1SolidColorBrush_SetColor(brush, &color);
922 ID2D1SolidColorBrush_SetOpacity(brush, 0.75f);
923 set_rect(&rect, -80.0f, -60.0f, 80.0f, 60.0f);
924 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
926 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
927 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
928 match = compare_surface(surface, "6d1218fca5e21fb7e287b3a439d60dbc251f5ceb");
929 ok(match, "Surface does not match.\n");
931 ID2D1SolidColorBrush_Release(brush);
932 ID2D1RenderTarget_Release(rt);
933 IDXGISurface_Release(surface);
934 IDXGISwapChain_Release(swapchain);
935 ID3D10Device1_Release(device);
936 DestroyWindow(window);
939 static void test_bitmap_brush(void)
941 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode;
942 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
943 D2D1_BITMAP_PROPERTIES bitmap_desc;
944 ID2D1Bitmap *bitmap, *tmp_bitmap;
945 D2D1_RECT_F src_rect, dst_rect;
946 D2D1_EXTEND_MODE extend_mode;
947 IDXGISwapChain *swapchain;
948 ID2D1BitmapBrush *brush;
949 ID2D1RenderTarget *rt;
950 ID3D10Device1 *device;
951 IDXGISurface *surface;
952 D2D1_COLOR_F color;
953 D2D1_SIZE_U size;
954 unsigned int i;
955 ULONG refcount;
956 float opacity;
957 HWND window;
958 HRESULT hr;
959 BOOL match;
961 static const struct
963 D2D1_EXTEND_MODE extend_mode_x;
964 D2D1_EXTEND_MODE extend_mode_y;
965 float translate_x;
966 float translate_y;
967 D2D1_RECT_F rect;
969 extend_mode_tests[] =
971 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_MIRROR, -7.0f, 1.0f, {-4.0f, 0.0f, -8.0f, 4.0f}},
972 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_MIRROR, -3.0f, 1.0f, {-4.0f, 4.0f, 0.0f, 0.0f}},
973 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_MIRROR, 1.0f, 1.0f, { 4.0f, 0.0f, 0.0f, 4.0f}},
974 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_WRAP, -7.0f, 5.0f, {-8.0f, 8.0f, -4.0f, 4.0f}},
975 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP, -3.0f, 5.0f, { 0.0f, 4.0f, -4.0f, 8.0f}},
976 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_WRAP, 1.0f, 5.0f, { 0.0f, 8.0f, 4.0f, 4.0f}},
977 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_CLAMP, -7.0f, 9.0f, {-4.0f, 8.0f, -8.0f, 12.0f}},
978 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_CLAMP, -3.0f, 9.0f, {-4.0f, 12.0f, 0.0f, 8.0f}},
979 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_CLAMP, 1.0f, 9.0f, { 4.0f, 8.0f, 0.0f, 12.0f}},
981 static const DWORD bitmap_data[] =
983 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
984 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
985 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
986 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
989 if (!(device = create_device()))
991 skip("Failed to create device, skipping tests.\n");
992 return;
994 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
995 0, 0, 640, 480, NULL, NULL, NULL, NULL);
996 swapchain = create_swapchain(device, window, TRUE);
997 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
998 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
999 rt = create_render_target(surface);
1000 ok(!!rt, "Failed to create render target.\n");
1002 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1003 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1005 set_size_u(&size, 4, 4);
1006 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
1007 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1008 bitmap_desc.dpiX = 96.0f;
1009 bitmap_desc.dpiY = 96.0f;
1010 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1011 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1013 /* Creating a brush with a NULL bitmap crashes on Vista, but works fine on
1014 * Windows 7+. */
1015 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
1016 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1017 ID2D1BitmapBrush_GetBitmap(brush, &tmp_bitmap);
1018 ok(tmp_bitmap == bitmap, "Got unexpected bitmap %p, expected %p.\n", tmp_bitmap, bitmap);
1019 ID2D1Bitmap_Release(tmp_bitmap);
1020 opacity = ID2D1BitmapBrush_GetOpacity(brush);
1021 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
1022 set_matrix_identity(&matrix);
1023 ID2D1BitmapBrush_GetTransform(brush, &tmp_matrix);
1024 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1025 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1026 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1027 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1028 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
1029 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
1030 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
1031 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
1032 interpolation_mode = ID2D1BitmapBrush_GetInterpolationMode(brush);
1033 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
1034 "Got unexpected interpolation mode %#x.\n", interpolation_mode);
1035 ID2D1BitmapBrush_Release(brush);
1037 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
1038 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1039 set_matrix_identity(&matrix);
1040 translate_matrix(&matrix, 40.0f, 120.0f);
1041 scale_matrix(&matrix, 20.0f, 60.0f);
1042 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1043 ID2D1BitmapBrush_SetInterpolationMode(brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
1045 ID2D1RenderTarget_BeginDraw(rt);
1047 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1048 ID2D1RenderTarget_Clear(rt, &color);
1050 set_rect(&dst_rect, 40.0f, 120.0f, 120.0f, 360.0f);
1051 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1053 set_matrix_identity(&matrix);
1054 scale_matrix(&matrix, 0.5f, 2.0f);
1055 translate_matrix(&matrix, 320.0f, 240.0f);
1056 rotate_matrix(&matrix, M_PI / 4.0f);
1057 ID2D1RenderTarget_SetTransform(rt, &matrix);
1058 set_matrix_identity(&matrix);
1059 translate_matrix(&matrix, -80.0f, -60.0f);
1060 scale_matrix(&matrix, 40.0f, 30.0f);
1061 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1062 ID2D1BitmapBrush_SetOpacity(brush, 0.75f);
1063 set_rect(&dst_rect, -80.0f, -60.0f, 80.0f, 60.0f);
1064 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1066 set_matrix_identity(&matrix);
1067 translate_matrix(&matrix, 200.0f, 120.0f);
1068 scale_matrix(&matrix, 20.0f, 60.0f);
1069 ID2D1RenderTarget_SetTransform(rt, &matrix);
1070 ID2D1RenderTarget_DrawBitmap(rt, bitmap, NULL, 0.25f,
1071 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
1072 set_rect(&dst_rect, -4.0f, 12.0f, -8.0f, 8.0f);
1073 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 0.75f,
1074 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
1075 set_rect(&dst_rect, 0.0f, 8.0f, 4.0f, 12.0f);
1076 set_rect(&src_rect, 2.0f, 1.0f, 4.0f, 3.0f);
1077 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
1078 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
1080 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1081 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1082 match = compare_surface(surface, "393636185359a550d459e1e5f0e25411814f724c");
1083 ok(match, "Surface does not match.\n");
1085 ID2D1RenderTarget_BeginDraw(rt);
1087 ID2D1RenderTarget_Clear(rt, &color);
1089 ID2D1BitmapBrush_SetOpacity(brush, 1.0f);
1090 for (i = 0; i < sizeof(extend_mode_tests) / sizeof(*extend_mode_tests); ++i)
1092 ID2D1BitmapBrush_SetExtendModeX(brush, extend_mode_tests[i].extend_mode_x);
1093 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
1094 ok(extend_mode == extend_mode_tests[i].extend_mode_x,
1095 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
1096 i, extend_mode, extend_mode_tests[i].extend_mode_x);
1097 ID2D1BitmapBrush_SetExtendModeY(brush, extend_mode_tests[i].extend_mode_y);
1098 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
1099 ok(extend_mode == extend_mode_tests[i].extend_mode_y,
1100 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
1101 i, extend_mode, extend_mode_tests[i].extend_mode_y);
1102 set_matrix_identity(&matrix);
1103 translate_matrix(&matrix, extend_mode_tests[i].translate_x, extend_mode_tests[i].translate_y);
1104 scale_matrix(&matrix, 0.5f, 0.5f);
1105 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1106 ID2D1RenderTarget_FillRectangle(rt, &extend_mode_tests[i].rect, (ID2D1Brush *)brush);
1109 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1110 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1111 match = compare_surface(surface, "b4b775afecdae2d26642001f4faff73663bb8b31");
1112 ok(match, "Surface does not match.\n");
1114 ID2D1BitmapBrush_Release(brush);
1115 refcount = ID2D1Bitmap_Release(bitmap);
1116 ok(!refcount, "Bitmap has %u references left.\n", refcount);
1117 ID2D1RenderTarget_Release(rt);
1118 IDXGISurface_Release(surface);
1119 IDXGISwapChain_Release(swapchain);
1120 ID3D10Device1_Release(device);
1121 DestroyWindow(window);
1124 static void fill_geometry_sink(ID2D1GeometrySink *sink)
1126 D2D1_POINT_2F point;
1128 set_point(&point, 15.0f, 20.0f);
1129 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1130 set_point(&point, 55.0f, 20.0f);
1131 ID2D1GeometrySink_AddLine(sink, point);
1132 set_point(&point, 55.0f, 220.0f);
1133 ID2D1GeometrySink_AddLine(sink, point);
1134 set_point(&point, 25.0f, 220.0f);
1135 ID2D1GeometrySink_AddLine(sink, point);
1136 set_point(&point, 25.0f, 100.0f);
1137 ID2D1GeometrySink_AddLine(sink, point);
1138 set_point(&point, 75.0f, 100.0f);
1139 ID2D1GeometrySink_AddLine(sink, point);
1140 set_point(&point, 75.0f, 300.0f);
1141 ID2D1GeometrySink_AddLine(sink, point);
1142 set_point(&point, 5.0f, 300.0f);
1143 ID2D1GeometrySink_AddLine(sink, point);
1144 set_point(&point, 5.0f, 60.0f);
1145 ID2D1GeometrySink_AddLine(sink, point);
1146 set_point(&point, 45.0f, 60.0f);
1147 ID2D1GeometrySink_AddLine(sink, point);
1148 set_point(&point, 45.0f, 180.0f);
1149 ID2D1GeometrySink_AddLine(sink, point);
1150 set_point(&point, 35.0f, 180.0f);
1151 ID2D1GeometrySink_AddLine(sink, point);
1152 set_point(&point, 35.0f, 140.0f);
1153 ID2D1GeometrySink_AddLine(sink, point);
1154 set_point(&point, 65.0f, 140.0f);
1155 ID2D1GeometrySink_AddLine(sink, point);
1156 set_point(&point, 65.0f, 260.0f);
1157 ID2D1GeometrySink_AddLine(sink, point);
1158 set_point(&point, 15.0f, 260.0f);
1159 ID2D1GeometrySink_AddLine(sink, point);
1160 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1162 set_point(&point, 155.0f, 300.0f);
1163 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1164 set_point(&point, 155.0f, 160.0f);
1165 ID2D1GeometrySink_AddLine(sink, point);
1166 set_point(&point, 85.0f, 160.0f);
1167 ID2D1GeometrySink_AddLine(sink, point);
1168 set_point(&point, 85.0f, 300.0f);
1169 ID2D1GeometrySink_AddLine(sink, point);
1170 set_point(&point, 120.0f, 300.0f);
1171 ID2D1GeometrySink_AddLine(sink, point);
1172 set_point(&point, 120.0f, 20.0f);
1173 ID2D1GeometrySink_AddLine(sink, point);
1174 set_point(&point, 155.0f, 20.0f);
1175 ID2D1GeometrySink_AddLine(sink, point);
1176 set_point(&point, 155.0f, 160.0f);
1177 ID2D1GeometrySink_AddLine(sink, point);
1178 set_point(&point, 85.0f, 160.0f);
1179 ID2D1GeometrySink_AddLine(sink, point);
1180 set_point(&point, 85.0f, 20.0f);
1181 ID2D1GeometrySink_AddLine(sink, point);
1182 set_point(&point, 120.0f, 20.0f);
1183 ID2D1GeometrySink_AddLine(sink, point);
1184 set_point(&point, 120.0f, 300.0f);
1185 ID2D1GeometrySink_AddLine(sink, point);
1186 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1188 set_point(&point, 165.0f, 20.0f);
1189 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1190 set_point(&point, 165.0f, 300.0f);
1191 ID2D1GeometrySink_AddLine(sink, point);
1192 set_point(&point, 235.0f, 300.0f);
1193 ID2D1GeometrySink_AddLine(sink, point);
1194 set_point(&point, 235.0f, 20.0f);
1195 ID2D1GeometrySink_AddLine(sink, point);
1196 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1197 set_point(&point, 225.0f, 60.0f);
1198 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1199 set_point(&point, 225.0f, 260.0f);
1200 ID2D1GeometrySink_AddLine(sink, point);
1201 set_point(&point, 175.0f, 260.0f);
1202 ID2D1GeometrySink_AddLine(sink, point);
1203 set_point(&point, 175.0f, 60.0f);
1204 ID2D1GeometrySink_AddLine(sink, point);
1205 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1206 set_point(&point, 215.0f, 220.0f);
1207 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1208 set_point(&point, 185.0f, 220.0f);
1209 ID2D1GeometrySink_AddLine(sink, point);
1210 set_point(&point, 185.0f, 100.0f);
1211 ID2D1GeometrySink_AddLine(sink, point);
1212 set_point(&point, 215.0f, 100.0f);
1213 ID2D1GeometrySink_AddLine(sink, point);
1214 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1215 set_point(&point, 195.0f, 180.0f);
1216 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1217 set_point(&point, 205.0f, 180.0f);
1218 ID2D1GeometrySink_AddLine(sink, point);
1219 set_point(&point, 205.0f, 140.0f);
1220 ID2D1GeometrySink_AddLine(sink, point);
1221 set_point(&point, 195.0f, 140.0f);
1222 ID2D1GeometrySink_AddLine(sink, point);
1223 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1226 static void fill_geometry_sink_bezier(ID2D1GeometrySink *sink)
1228 D2D1_QUADRATIC_BEZIER_SEGMENT quadratic;
1229 D2D1_POINT_2F point;
1231 set_point(&point, 5.0f, 160.0f);
1232 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1233 set_quadratic(&quadratic, 40.0f, 160.0f, 40.0f, 20.0f);
1234 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1235 set_quadratic(&quadratic, 40.0f, 160.0f, 75.0f, 160.0f);
1236 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1237 set_quadratic(&quadratic, 40.0f, 160.0f, 40.0f, 300.0f);
1238 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1239 set_quadratic(&quadratic, 40.0f, 160.0f, 5.0f, 160.0f);
1240 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1241 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1243 set_point(&point, 20.0f, 160.0f);
1244 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1245 set_quadratic(&quadratic, 20.0f, 80.0f, 40.0f, 80.0f);
1246 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1247 set_quadratic(&quadratic, 60.0f, 80.0f, 60.0f, 160.0f);
1248 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1249 set_quadratic(&quadratic, 60.0f, 240.0f, 40.0f, 240.0f);
1250 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1251 set_quadratic(&quadratic, 20.0f, 240.0f, 20.0f, 160.0f);
1252 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1253 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1256 static void test_path_geometry(void)
1258 ID2D1TransformedGeometry *transformed_geometry;
1259 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
1260 ID2D1GeometrySink *sink, *tmp_sink;
1261 D2D1_POINT_2F point = {0.0f, 0.0f};
1262 ID2D1SolidColorBrush *brush;
1263 ID2D1PathGeometry *geometry;
1264 ID2D1Geometry *tmp_geometry;
1265 IDXGISwapChain *swapchain;
1266 ID2D1RenderTarget *rt;
1267 ID3D10Device1 *device;
1268 IDXGISurface *surface;
1269 ID2D1Factory *factory;
1270 D2D1_COLOR_F color;
1271 ULONG refcount;
1272 UINT32 count;
1273 HWND window;
1274 HRESULT hr;
1275 BOOL match;
1277 if (!(device = create_device()))
1279 skip("Failed to create device, skipping tests.\n");
1280 return;
1282 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1283 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1284 swapchain = create_swapchain(device, window, TRUE);
1285 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1286 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1287 rt = create_render_target(surface);
1288 ok(!!rt, "Failed to create render target.\n");
1289 ID2D1RenderTarget_GetFactory(rt, &factory);
1291 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1292 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1293 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
1294 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
1295 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1297 /* Close() when closed. */
1298 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1299 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1300 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1301 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1302 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1303 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1304 hr = ID2D1PathGeometry_Open(geometry, &sink);
1305 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1306 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1307 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1308 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1309 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1310 hr = ID2D1GeometrySink_Close(sink);
1311 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1312 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1313 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1314 ok(!count, "Got unexpected figure count %u.\n", count);
1315 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1316 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1317 ok(!count, "Got unexpected segment count %u.\n", count);
1318 hr = ID2D1GeometrySink_Close(sink);
1319 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1320 ID2D1GeometrySink_Release(sink);
1321 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1322 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1323 ok(!count, "Got unexpected figure count %u.\n", count);
1324 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1325 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1326 ok(!count, "Got unexpected segment count %u.\n", count);
1327 ID2D1PathGeometry_Release(geometry);
1329 /* Open() when closed. */
1330 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1331 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1332 hr = ID2D1PathGeometry_Open(geometry, &sink);
1333 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1334 hr = ID2D1GeometrySink_Close(sink);
1335 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1336 ID2D1GeometrySink_Release(sink);
1337 hr = ID2D1PathGeometry_Open(geometry, &sink);
1338 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1339 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1340 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1341 ok(!count, "Got unexpected figure count %u.\n", count);
1342 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1343 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1344 ok(!count, "Got unexpected segment count %u.\n", count);
1345 ID2D1PathGeometry_Release(geometry);
1347 /* Open() when open. */
1348 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1349 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1350 hr = ID2D1PathGeometry_Open(geometry, &sink);
1351 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1352 hr = ID2D1PathGeometry_Open(geometry, &tmp_sink);
1353 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1354 hr = ID2D1GeometrySink_Close(sink);
1355 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1356 ID2D1GeometrySink_Release(sink);
1357 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1358 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1359 ok(!count, "Got unexpected figure count %u.\n", count);
1360 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1361 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1362 ok(!count, "Got unexpected segment count %u.\n", count);
1363 ID2D1PathGeometry_Release(geometry);
1365 /* BeginFigure() without EndFigure(). */
1366 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1367 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1368 hr = ID2D1PathGeometry_Open(geometry, &sink);
1369 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1370 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1371 hr = ID2D1GeometrySink_Close(sink);
1372 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1373 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1374 hr = ID2D1GeometrySink_Close(sink);
1375 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1376 ID2D1GeometrySink_Release(sink);
1377 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1378 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1379 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1380 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1381 ID2D1PathGeometry_Release(geometry);
1383 /* EndFigure() without BeginFigure(). */
1384 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1385 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1386 hr = ID2D1PathGeometry_Open(geometry, &sink);
1387 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1388 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1389 hr = ID2D1GeometrySink_Close(sink);
1390 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1391 ID2D1GeometrySink_Release(sink);
1392 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1393 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1394 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1395 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1396 ID2D1PathGeometry_Release(geometry);
1398 /* BeginFigure()/EndFigure() mismatch. */
1399 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1400 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1401 hr = ID2D1PathGeometry_Open(geometry, &sink);
1402 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1403 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1404 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1405 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1406 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1407 hr = ID2D1GeometrySink_Close(sink);
1408 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1409 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1410 hr = ID2D1GeometrySink_Close(sink);
1411 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1412 ID2D1GeometrySink_Release(sink);
1413 ID2D1PathGeometry_Release(geometry);
1415 /* AddLine() outside BeginFigure()/EndFigure(). */
1416 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1417 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1418 hr = ID2D1PathGeometry_Open(geometry, &sink);
1419 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1420 ID2D1GeometrySink_AddLine(sink, point);
1421 hr = ID2D1GeometrySink_Close(sink);
1422 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1423 ID2D1GeometrySink_AddLine(sink, point);
1424 ID2D1GeometrySink_Release(sink);
1425 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1426 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1427 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1428 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1429 ID2D1PathGeometry_Release(geometry);
1431 /* Empty figure. */
1432 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1433 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1434 hr = ID2D1PathGeometry_Open(geometry, &sink);
1435 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1436 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1437 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1438 hr = ID2D1GeometrySink_Close(sink);
1439 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1440 ID2D1GeometrySink_Release(sink);
1441 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1442 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1443 ok(count == 1, "Got unexpected figure count %u.\n", count);
1444 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1445 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1446 ok(count == 1, "Got unexpected segment count %u.\n", count);
1447 ID2D1PathGeometry_Release(geometry);
1449 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1450 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1451 hr = ID2D1PathGeometry_Open(geometry, &sink);
1452 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1453 /* The fillmode that's used is the last one set before the sink is closed. */
1454 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
1455 fill_geometry_sink(sink);
1456 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
1457 hr = ID2D1GeometrySink_Close(sink);
1458 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1459 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1460 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1461 ok(count == 6, "Got unexpected figure count %u.\n", count);
1462 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1463 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1464 /* Intersections don't create extra segments. */
1465 ok(count == 44, "Got unexpected segment count %u.\n", count);
1466 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
1467 ID2D1GeometrySink_Release(sink);
1469 set_matrix_identity(&matrix);
1470 translate_matrix(&matrix, 80.0f, 640.0f);
1471 scale_matrix(&matrix, 1.0f, -1.0f);
1472 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
1473 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
1475 ID2D1TransformedGeometry_GetSourceGeometry(transformed_geometry, &tmp_geometry);
1476 ok(tmp_geometry == (ID2D1Geometry *)geometry,
1477 "Got unexpected source geometry %p, expected %p.\n", tmp_geometry, geometry);
1478 ID2D1Geometry_Release(tmp_geometry);
1479 ID2D1TransformedGeometry_GetTransform(transformed_geometry, &tmp_matrix);
1480 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1481 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1482 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1483 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1485 ID2D1RenderTarget_BeginDraw(rt);
1486 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
1487 ID2D1RenderTarget_Clear(rt, &color);
1488 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1489 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1490 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1491 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1492 match = compare_surface(surface, "3aace1b22aae111cb577614fed16e4eb1650dba5");
1493 ok(match, "Surface does not match.\n");
1494 ID2D1TransformedGeometry_Release(transformed_geometry);
1495 ID2D1PathGeometry_Release(geometry);
1497 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1498 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1499 hr = ID2D1PathGeometry_Open(geometry, &sink);
1500 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1501 fill_geometry_sink(sink);
1502 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
1503 hr = ID2D1GeometrySink_Close(sink);
1504 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1505 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1506 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1507 ok(count == 6, "Got unexpected figure count %u.\n", count);
1508 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1509 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1510 ok(count == 44, "Got unexpected segment count %u.\n", count);
1511 ID2D1GeometrySink_Release(sink);
1513 set_matrix_identity(&matrix);
1514 translate_matrix(&matrix, 320.0f, 320.0f);
1515 scale_matrix(&matrix, -1.0f, 1.0f);
1516 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
1517 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
1519 ID2D1RenderTarget_BeginDraw(rt);
1520 ID2D1RenderTarget_Clear(rt, &color);
1521 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1522 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1523 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1524 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1525 match = compare_surface(surface, "bfb40a1f007694fa07dbd3b854f3f5d9c3e1d76b");
1526 ok(match, "Surface does not match.\n");
1527 ID2D1TransformedGeometry_Release(transformed_geometry);
1528 ID2D1PathGeometry_Release(geometry);
1530 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1531 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1532 hr = ID2D1PathGeometry_Open(geometry, &sink);
1533 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1534 fill_geometry_sink_bezier(sink);
1535 hr = ID2D1GeometrySink_Close(sink);
1536 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1537 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1538 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1539 ok(count == 2, "Got unexpected figure count %u.\n", count);
1540 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1541 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1542 ok(count == 10, "Got unexpected segment count %u.\n", count);
1543 ID2D1GeometrySink_Release(sink);
1545 set_matrix_identity(&matrix);
1546 scale_matrix(&matrix, 0.5f, 2.0f);
1547 translate_matrix(&matrix, 240.0f, -33.0f);
1548 rotate_matrix(&matrix, M_PI / 4.0f);
1549 scale_matrix(&matrix, 2.0f, 0.5f);
1550 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
1551 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
1553 ID2D1RenderTarget_BeginDraw(rt);
1554 ID2D1RenderTarget_Clear(rt, &color);
1555 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1556 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1557 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1558 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1559 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
1560 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
1561 "lAEECASLAQgKCIEBDQoMew8KD3YQDBByEgwSbhMOEmwUDhRpFBAUZxUQFWUVEhVjFhIWYRYUFl8X"
1562 "FBddFxYWXRYYFlsXGBdaFhoWWRYcFlgVHhVXFSAVVhQiFFUUIxRVEyYTVBIoElQRKhFUECwQUxAu"
1563 "EFIOMg5SDTQNUgs4C1IJPAlRCEAIUAZEBlAESARQAU4BTgJQAkgGUAY/C1ALMhNQEyoTUBMyC1AL"
1564 "PwZQBkgCUAJOAU4BUARIBFAGRAZQCEAIUQk8CVILOAtSDTQNUg4yDlIQLhBTECwQVBEqEVQSKBJU"
1565 "EyYTVBQjFFYUIhRWFSAVVxUeFVgWHBZZFhoWWhcYF1sWGBZcFxYWXhcUF18WFBZhFhIWYxUSFWUV"
1566 "EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
1567 "BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
1568 todo_wine ok(match, "Figure does not match.\n");
1569 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
1570 "4VIBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQEjDCMB7AECHhQeAu0BAxoYGgPvAQMWHhYD8QEDFCAU"
1571 "A/MBBBAkEAT0AQUOJw0F9QEGCioKBvcBBggsCAb4AQgFLgUI+QEJATIBCfsBCAIwAgj8AQcFLAUH"
1572 "/QEFCCgIBf4BBAwiDAT/AQIQHBAClwISlwIBPgGAAgI8Av8BAzwD/QEEPAT7AQY6BvkBBzoH+AEI"
1573 "OAj3AQk4CfYBCTgK9AELNgvzAQw2DPIBDDYM8QEONA7wAQ40DvABDjQO7wEPNA/uAQ80D+4BEDIQ"
1574 "7QERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewB"
1575 "ETIR7AERMhHsAREyEe0BEDIQ7gEQMw/uAQ80D+4BDzQP7wEONA7wAQ40DvEBDDYM8gEMNgzzAQs2"
1576 "C/QBCzcK9QEJOAn3AQg4CfcBBzoH+QEGOgb7AQU6BfwBBDwE/QEDPAP/AQE+AZkCDpkCAhIYEgKA"
1577 "AgMNIA0D/wEFCSYJBf4BBgYqBgf8AQgDLgMI+wFG+gEIAzADCPkBBwYuBgf3AQYKKgoG9gEFDCgM"
1578 "BfUBBBAlDwTzAQQSIhIE8QEDFh4WA/ABAhkaGQLvAQIcFhwC7QECIBAgAusBASgEKAHpAQFWAecB"
1579 "AVgB5QEBWgHAAgEA");
1580 todo_wine ok(match, "Figure does not match.\n");
1581 ID2D1TransformedGeometry_Release(transformed_geometry);
1582 ID2D1PathGeometry_Release(geometry);
1584 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1585 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1586 hr = ID2D1PathGeometry_Open(geometry, &sink);
1587 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1588 fill_geometry_sink_bezier(sink);
1589 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
1590 hr = ID2D1GeometrySink_Close(sink);
1591 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1592 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1593 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1594 ok(count == 2, "Got unexpected figure count %u.\n", count);
1595 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1596 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1597 ok(count == 10, "Got unexpected segment count %u.\n", count);
1598 ID2D1GeometrySink_Release(sink);
1600 set_matrix_identity(&matrix);
1601 scale_matrix(&matrix, 0.5f, 2.0f);
1602 translate_matrix(&matrix, 127.0f, 80.0f);
1603 rotate_matrix(&matrix, M_PI / -4.0f);
1604 scale_matrix(&matrix, 2.0f, 0.5f);
1605 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
1606 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
1608 ID2D1RenderTarget_BeginDraw(rt);
1609 ID2D1RenderTarget_Clear(rt, &color);
1610 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1611 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1612 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1613 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1614 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
1615 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
1616 "lAEQiwEagQEjeyh2LHIwbjNsNmk4ZzplPGM+YUBfQl1DXURbRlpGWUhYSFdKVkpVS1VMVExUTFRM"
1617 "U05STlJOUk5STlFQUFBQUFBQTlRIXD9mMnYqdjJmP1xIVE5QUFBQUFBQUU5STlJOUk5STlNMVExU"
1618 "TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
1619 "mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
1620 ok(match, "Figure does not match.\n");
1621 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
1622 "4VIBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQIhDiIB7QECHRUdAu4BAhkaGQPvAQMWHhYD8QEEEyET"
1623 "A/MBBBAkEAT1AQUMKA0F9QEGCioKBvcBBwctBwb5AQgELwQI+QEJATIBCfsBRP0BQ/0BQv8BQf8B"
1624 "QIECP4ACQIACQf4BQ/wBRPsBRvoBR/gBSPcBSvYBS/QBTPMBTvIBTvIBT/ABUPABUe4BUu4BUu4B"
1625 "U+0BU+wBVOwBVOwBVOwBVOwBVesBVesBVesBVesBVOwBVOwBVOwBVO0BU+0BU+0BUu4BUu8BUe8B"
1626 "UPEBT/EBTvIBTvMBTPUBS/UBSvcBSfcBSPkBRvsBRP0BQ/4BQf8BQIECP4ACQIACQf4BQv4BQ/wB"
1627 "RPsBCQEyAQn6AQgELwQI+AEHBy0GB/cBBgoqCgb2AQUMKA0F9AEEECUPBPMBBBIiEwPxAQMWHhYD"
1628 "8AECGRoZA+4BAh0VHQLsAQIhDiIB6wEBVAHpAQFWAecBAVgB5QEBWgHAAgEA");
1629 ok(match, "Figure does not match.\n");
1630 ID2D1TransformedGeometry_Release(transformed_geometry);
1631 ID2D1PathGeometry_Release(geometry);
1633 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1634 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1635 hr = ID2D1PathGeometry_Open(geometry, &sink);
1636 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1638 set_point(&point, 40.0f, 20.0f);
1639 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1640 set_point(&point, 75.0f, 300.0f);
1641 ID2D1GeometrySink_AddLine(sink, point);
1642 set_point(&point, 5.0f, 300.0f);
1643 ID2D1GeometrySink_AddLine(sink, point);
1644 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1646 set_point(&point, 40.0f, 290.0f);
1647 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1648 set_point(&point, 55.0f, 160.0f);
1649 ID2D1GeometrySink_AddLine(sink, point);
1650 set_point(&point, 25.0f, 160.0f);
1651 ID2D1GeometrySink_AddLine(sink, point);
1652 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1654 hr = ID2D1GeometrySink_Close(sink);
1655 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1656 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1657 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1658 ok(count == 2, "Got unexpected figure count %u.\n", count);
1659 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1660 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1661 ok(count == 6, "Got unexpected segment count %u.\n", count);
1662 ID2D1GeometrySink_Release(sink);
1664 ID2D1RenderTarget_BeginDraw(rt);
1665 ID2D1RenderTarget_Clear(rt, &color);
1666 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1667 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1668 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1669 match = compare_surface(surface, "a875e68e0cb9c055927b1b50b879f90b24e38470");
1670 ok(match, "Surface does not match.\n");
1671 ID2D1PathGeometry_Release(geometry);
1673 ID2D1SolidColorBrush_Release(brush);
1674 ID2D1RenderTarget_Release(rt);
1675 refcount = ID2D1Factory_Release(factory);
1676 ok(!refcount, "Factory has %u references left.\n", refcount);
1677 IDXGISurface_Release(surface);
1678 IDXGISwapChain_Release(swapchain);
1679 ID3D10Device1_Release(device);
1680 DestroyWindow(window);
1683 static void test_bitmap_formats(void)
1685 D2D1_BITMAP_PROPERTIES bitmap_desc;
1686 IDXGISwapChain *swapchain;
1687 D2D1_SIZE_U size = {4, 4};
1688 ID2D1RenderTarget *rt;
1689 ID3D10Device1 *device;
1690 IDXGISurface *surface;
1691 ID2D1Bitmap *bitmap;
1692 unsigned int i, j;
1693 HWND window;
1694 HRESULT hr;
1696 static const struct
1698 DXGI_FORMAT format;
1699 DWORD mask;
1701 bitmap_formats[] =
1703 {DXGI_FORMAT_R32G32B32A32_FLOAT, 0x8a},
1704 {DXGI_FORMAT_R16G16B16A16_FLOAT, 0x8a},
1705 {DXGI_FORMAT_R16G16B16A16_UNORM, 0x8a},
1706 {DXGI_FORMAT_R8G8B8A8_TYPELESS, 0x00},
1707 {DXGI_FORMAT_R8G8B8A8_UNORM, 0x0a},
1708 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0x8a},
1709 {DXGI_FORMAT_R8G8B8A8_UINT, 0x00},
1710 {DXGI_FORMAT_R8G8B8A8_SNORM, 0x00},
1711 {DXGI_FORMAT_R8G8B8A8_SINT, 0x00},
1712 {DXGI_FORMAT_A8_UNORM, 0x06},
1713 {DXGI_FORMAT_B8G8R8A8_UNORM, 0x0a},
1714 {DXGI_FORMAT_B8G8R8X8_UNORM, 0x88},
1715 {DXGI_FORMAT_B8G8R8A8_TYPELESS, 0x00},
1716 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, 0x8a},
1719 if (!(device = create_device()))
1721 skip("Failed to create device, skipping tests.\n");
1722 return;
1724 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1725 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1726 swapchain = create_swapchain(device, window, TRUE);
1727 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1728 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1729 rt = create_render_target(surface);
1730 ok(!!rt, "Failed to create render target.\n");
1732 bitmap_desc.dpiX = 96.0f;
1733 bitmap_desc.dpiY = 96.0f;
1734 for (i = 0; i < sizeof(bitmap_formats) / sizeof(*bitmap_formats); ++i)
1736 for (j = 0; j < 4; ++j)
1738 if ((bitmap_formats[i].mask & (0x80 | (1u << j))) == (0x80 | (1u << j)))
1739 continue;
1741 bitmap_desc.pixelFormat.format = bitmap_formats[i].format;
1742 bitmap_desc.pixelFormat.alphaMode = j;
1743 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
1744 if (bitmap_formats[i].mask & (1u << j))
1745 ok(hr == S_OK, "Got unexpected hr %#x, for format %#x/%#x.\n",
1746 hr, bitmap_formats[i].format, j);
1747 else
1748 ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "Got unexpected hr %#x, for format %#x/%#x.\n",
1749 hr, bitmap_formats[i].format, j);
1750 if (SUCCEEDED(hr))
1751 ID2D1Bitmap_Release(bitmap);
1755 ID2D1RenderTarget_Release(rt);
1756 IDXGISurface_Release(surface);
1757 IDXGISwapChain_Release(swapchain);
1758 ID3D10Device1_Release(device);
1759 DestroyWindow(window);
1762 static void test_alpha_mode(void)
1764 D2D1_RENDER_TARGET_PROPERTIES rt_desc;
1765 D2D1_BITMAP_PROPERTIES bitmap_desc;
1766 ID2D1SolidColorBrush *color_brush;
1767 ID2D1BitmapBrush *bitmap_brush;
1768 IDXGISwapChain *swapchain;
1769 ID2D1RenderTarget *rt;
1770 ID3D10Device1 *device;
1771 IDXGISurface *surface;
1772 ID2D1Bitmap *bitmap;
1773 D2D1_COLOR_F color;
1774 D2D1_RECT_F rect;
1775 D2D1_SIZE_U size;
1776 ULONG refcount;
1777 HWND window;
1778 HRESULT hr;
1779 BOOL match;
1781 static const DWORD bitmap_data[] =
1783 0x7f7f0000, 0x7f7f7f00, 0x7f007f00, 0x7f007f7f,
1784 0x7f00007f, 0x7f7f007f, 0x7f000000, 0x7f404040,
1785 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f000000,
1786 0x7f7f7f7f, 0x7f000000, 0x7f000000, 0x7f000000,
1789 if (!(device = create_device()))
1791 skip("Failed to create device, skipping tests.\n");
1792 return;
1794 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1795 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1796 swapchain = create_swapchain(device, window, TRUE);
1797 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1798 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1799 rt = create_render_target(surface);
1800 ok(!!rt, "Failed to create render target.\n");
1802 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1804 set_size_u(&size, 4, 4);
1805 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
1806 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1807 bitmap_desc.dpiX = 96.0f / 40.0f;
1808 bitmap_desc.dpiY = 96.0f / 30.0f;
1809 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1810 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1812 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
1813 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1814 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
1815 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
1816 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
1818 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
1819 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
1820 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1822 ID2D1RenderTarget_BeginDraw(rt);
1823 ID2D1RenderTarget_Clear(rt, NULL);
1824 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1825 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1826 match = compare_surface(surface, "48c41aff3a130a17ee210866b2ab7d36763934d5");
1827 ok(match, "Surface does not match.\n");
1829 ID2D1RenderTarget_BeginDraw(rt);
1830 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
1831 ID2D1RenderTarget_Clear(rt, &color);
1832 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1833 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1834 match = compare_surface(surface, "6487e683730fb5a77c1911388d00b04664c5c4e4");
1835 ok(match, "Surface does not match.\n");
1837 ID2D1RenderTarget_BeginDraw(rt);
1838 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
1839 ID2D1RenderTarget_Clear(rt, &color);
1840 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1841 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1842 match = compare_surface(surface, "7a35ba09e43cbaf591388ff1ef8de56157630c98");
1843 ok(match, "Surface does not match.\n");
1845 ID2D1RenderTarget_BeginDraw(rt);
1847 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
1848 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1849 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
1850 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
1851 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1852 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
1853 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
1854 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1856 ID2D1Bitmap_Release(bitmap);
1857 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1858 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1859 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1860 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
1862 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
1863 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
1864 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1865 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
1866 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
1867 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1868 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
1869 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
1870 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1872 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
1873 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1874 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
1875 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
1876 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1877 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
1878 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
1879 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1881 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1882 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1883 match = compare_surface(surface, "14f8ac64b70966c7c3c6281c59aaecdb17c3b16a");
1884 ok(match, "Surface does not match.\n");
1886 ID2D1RenderTarget_Release(rt);
1887 rt_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
1888 rt_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
1889 rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1890 rt_desc.dpiX = 0.0f;
1891 rt_desc.dpiY = 0.0f;
1892 rt_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
1893 rt_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
1894 rt = create_render_target_desc(surface, &rt_desc);
1895 ok(!!rt, "Failed to create render target.\n");
1897 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1899 ID2D1Bitmap_Release(bitmap);
1900 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1901 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1902 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1903 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
1905 ID2D1BitmapBrush_Release(bitmap_brush);
1906 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
1907 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1908 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
1909 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
1910 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
1912 ID2D1SolidColorBrush_Release(color_brush);
1913 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
1914 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
1915 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1917 ID2D1RenderTarget_BeginDraw(rt);
1918 ID2D1RenderTarget_Clear(rt, NULL);
1919 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1920 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1921 match = compare_surface(surface, "b44510bf2d2e61a8d7c0ad862de49a471f1fd13f");
1922 ok(match, "Surface does not match.\n");
1924 ID2D1RenderTarget_BeginDraw(rt);
1925 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
1926 ID2D1RenderTarget_Clear(rt, &color);
1927 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1928 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1929 match = compare_surface(surface, "2184f4a9198fc1de09ac85301b7a03eebadd9b81");
1930 ok(match, "Surface does not match.\n");
1932 ID2D1RenderTarget_BeginDraw(rt);
1933 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
1934 ID2D1RenderTarget_Clear(rt, &color);
1935 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1936 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1937 match = compare_surface(surface, "6527ec83b4039c895b50f9b3e144fe0cf90d1889");
1938 ok(match, "Surface does not match.\n");
1940 ID2D1RenderTarget_BeginDraw(rt);
1942 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
1943 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1944 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
1945 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
1946 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1947 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
1948 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
1949 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1951 ID2D1Bitmap_Release(bitmap);
1952 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1953 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1954 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1955 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
1957 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
1958 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
1959 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1960 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
1961 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
1962 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1963 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
1964 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
1965 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1967 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
1968 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1969 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
1970 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
1971 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1972 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
1973 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
1974 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1976 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1977 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1978 match = compare_surface(surface, "465f5a3190d7bde408b3206b4be939fb22f8a3d6");
1979 ok(match, "Surface does not match.\n");
1981 refcount = ID2D1Bitmap_Release(bitmap);
1982 ok(refcount == 1, "Bitmap has %u references left.\n", refcount);
1983 ID2D1SolidColorBrush_Release(color_brush);
1984 ID2D1BitmapBrush_Release(bitmap_brush);
1985 ID2D1RenderTarget_Release(rt);
1986 IDXGISurface_Release(surface);
1987 IDXGISwapChain_Release(swapchain);
1988 ID3D10Device1_Release(device);
1989 DestroyWindow(window);
1992 static void test_shared_bitmap(void)
1994 IDXGISwapChain *swapchain1, *swapchain2;
1995 IWICBitmap *wic_bitmap1, *wic_bitmap2;
1996 D2D1_RENDER_TARGET_PROPERTIES desc;
1997 D2D1_BITMAP_PROPERTIES bitmap_desc;
1998 IDXGISurface *surface1, *surface2;
1999 ID2D1Factory *factory1, *factory2;
2000 ID3D10Device1 *device1, *device2;
2001 IWICImagingFactory *wic_factory;
2002 ID2D1Bitmap *bitmap1, *bitmap2;
2003 ID2D1RenderTarget *rt1, *rt2;
2004 D2D1_SIZE_U size = {4, 4};
2005 HWND window1, window2;
2006 HRESULT hr;
2008 if (!(device1 = create_device()))
2010 skip("Failed to create device, skipping tests.\n");
2011 return;
2014 window1 = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2015 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2016 window2 = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2017 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2018 swapchain1 = create_swapchain(device1, window1, TRUE);
2019 swapchain2 = create_swapchain(device1, window2, TRUE);
2020 hr = IDXGISwapChain_GetBuffer(swapchain1, 0, &IID_IDXGISurface, (void **)&surface1);
2021 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2022 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
2023 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2025 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2026 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
2027 &IID_IWICImagingFactory, (void **)&wic_factory);
2028 ok(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
2029 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
2030 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap1);
2031 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2032 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
2033 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap2);
2034 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2035 IWICImagingFactory_Release(wic_factory);
2037 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
2038 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
2039 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2040 desc.dpiX = 0.0f;
2041 desc.dpiY = 0.0f;
2042 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
2043 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
2045 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2046 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2047 bitmap_desc.dpiX = 96.0f;
2048 bitmap_desc.dpiY = 96.0f;
2050 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory1);
2051 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2052 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
2053 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2055 /* DXGI surface render targets with the same device and factory. */
2056 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface1, &desc, &rt1);
2057 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2058 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
2059 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2061 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
2062 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2063 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2064 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2065 ID2D1Bitmap_Release(bitmap2);
2066 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IUnknown, bitmap1, NULL, &bitmap2);
2067 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2068 ID2D1RenderTarget_Release(rt2);
2070 /* DXGI surface render targets with the same device but different factories. */
2071 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
2072 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2073 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2074 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
2075 ID2D1RenderTarget_Release(rt2);
2077 /* DXGI surface render targets with different devices but the same factory. */
2078 IDXGISurface_Release(surface2);
2079 IDXGISwapChain_Release(swapchain2);
2080 device2 = create_device();
2081 ok(!!device2, "Failed to create device.\n");
2082 swapchain2 = create_swapchain(device2, window2, TRUE);
2083 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
2084 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2086 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
2087 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2088 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2089 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
2090 ID2D1RenderTarget_Release(rt2);
2092 /* DXGI surface render targets with different devices and different factories. */
2093 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
2094 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2095 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2096 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
2097 ID2D1RenderTarget_Release(rt2);
2099 /* DXGI surface render target and WIC bitmap render target, same factory. */
2100 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
2101 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2102 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2103 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
2104 ID2D1RenderTarget_Release(rt2);
2106 /* WIC bitmap render targets on different D2D factories. */
2107 ID2D1Bitmap_Release(bitmap1);
2108 ID2D1RenderTarget_Release(rt1);
2109 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap1, &desc, &rt1);
2110 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2111 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
2112 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2114 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory2, wic_bitmap2, &desc, &rt2);
2115 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2116 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2117 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
2118 ID2D1RenderTarget_Release(rt2);
2120 /* WIC bitmap render targets on the same D2D factory. */
2121 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
2122 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2123 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2124 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2125 ID2D1Bitmap_Release(bitmap2);
2126 ID2D1RenderTarget_Release(rt2);
2128 ID2D1Bitmap_Release(bitmap1);
2129 ID2D1RenderTarget_Release(rt1);
2130 ID2D1Factory_Release(factory2);
2131 ID2D1Factory_Release(factory1);
2132 IWICBitmap_Release(wic_bitmap2);
2133 IWICBitmap_Release(wic_bitmap1);
2134 IDXGISurface_Release(surface2);
2135 IDXGISurface_Release(surface1);
2136 IDXGISwapChain_Release(swapchain2);
2137 IDXGISwapChain_Release(swapchain1);
2138 ID3D10Device1_Release(device2);
2139 ID3D10Device1_Release(device1);
2140 DestroyWindow(window2);
2141 DestroyWindow(window1);
2142 CoUninitialize();
2145 static void test_bitmap_updates(void)
2147 D2D1_BITMAP_PROPERTIES bitmap_desc;
2148 IDXGISwapChain *swapchain;
2149 ID2D1RenderTarget *rt;
2150 ID3D10Device1 *device;
2151 IDXGISurface *surface;
2152 D2D1_RECT_U dst_rect;
2153 ID2D1Bitmap *bitmap;
2154 D2D1_COLOR_F color;
2155 D2D1_RECT_F rect;
2156 D2D1_SIZE_U size;
2157 HWND window;
2158 HRESULT hr;
2159 BOOL match;
2161 static const DWORD bitmap_data[] =
2163 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
2164 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
2165 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
2166 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
2169 if (!(device = create_device()))
2171 skip("Failed to create device, skipping tests.\n");
2172 return;
2174 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2175 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2176 swapchain = create_swapchain(device, window, TRUE);
2177 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2178 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2179 rt = create_render_target(surface);
2180 ok(!!rt, "Failed to create render target.\n");
2182 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2184 ID2D1RenderTarget_BeginDraw(rt);
2185 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
2186 ID2D1RenderTarget_Clear(rt, &color);
2188 set_size_u(&size, 4, 4);
2189 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2190 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2191 bitmap_desc.dpiX = 96.0f;
2192 bitmap_desc.dpiY = 96.0f;
2193 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
2194 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2196 set_rect(&rect, 0.0f, 0.0f, 320.0f, 240.0f);
2197 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2198 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2200 ID2D1Bitmap_Release(bitmap);
2202 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
2203 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
2204 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2206 set_rect(&rect, 0.0f, 240.0f, 320.0f, 480.0f);
2207 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2208 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2210 set_rect_u(&dst_rect, 1, 1, 3, 3);
2211 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, 4 * sizeof(*bitmap_data));
2212 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2213 set_rect_u(&dst_rect, 0, 3, 3, 4);
2214 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[6], 4 * sizeof(*bitmap_data));
2215 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2216 set_rect_u(&dst_rect, 0, 0, 4, 1);
2217 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[10], 4 * sizeof(*bitmap_data));
2218 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2219 set_rect_u(&dst_rect, 0, 1, 1, 3);
2220 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[2], sizeof(*bitmap_data));
2221 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2222 set_rect_u(&dst_rect, 4, 4, 3, 1);
2223 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, sizeof(*bitmap_data));
2224 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2225 set_rect(&rect, 320.0f, 240.0f, 640.0f, 480.0f);
2226 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2227 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2229 hr = ID2D1Bitmap_CopyFromMemory(bitmap, NULL, bitmap_data, 4 * sizeof(*bitmap_data));
2230 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2231 set_rect(&rect, 320.0f, 0.0f, 640.0f, 240.0f);
2232 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2233 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2235 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2236 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2238 match = compare_surface(surface, "cb8136c91fbbdc76bb83b8c09edc1907b0a5d0a6");
2239 ok(match, "Surface does not match.\n");
2241 ID2D1Bitmap_Release(bitmap);
2242 ID2D1RenderTarget_Release(rt);
2243 IDXGISurface_Release(surface);
2244 IDXGISwapChain_Release(swapchain);
2245 ID3D10Device1_Release(device);
2246 DestroyWindow(window);
2249 static void test_opacity_brush(void)
2251 ID2D1BitmapBrush *bitmap_brush, *opacity_brush;
2252 D2D1_BITMAP_PROPERTIES bitmap_desc;
2253 ID2D1RectangleGeometry *geometry;
2254 ID2D1SolidColorBrush *color_brush;
2255 IDXGISwapChain *swapchain;
2256 D2D1_MATRIX_3X2_F matrix;
2257 ID2D1RenderTarget *rt;
2258 ID3D10Device1 *device;
2259 IDXGISurface *surface;
2260 ID2D1Factory *factory;
2261 ID2D1Bitmap *bitmap;
2262 D2D1_COLOR_F color;
2263 D2D1_RECT_F rect;
2264 D2D1_SIZE_U size;
2265 ULONG refcount;
2266 HWND window;
2267 HRESULT hr;
2268 BOOL match;
2270 static const DWORD bitmap_data[] =
2272 0xffff0000, 0x40ffff00, 0x4000ff00, 0xff00ffff,
2273 0x7f0000ff, 0x00ff00ff, 0x00000000, 0x7f7f7f7f,
2274 0x7fffffff, 0x00ffffff, 0x00ffffff, 0x7f000000,
2275 0xffffffff, 0x40000000, 0x40000000, 0xff000000,
2278 if (!(device = create_device()))
2280 skip("Failed to create device, skipping tests.\n");
2281 return;
2283 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2284 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2285 swapchain = create_swapchain(device, window, TRUE);
2286 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2287 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2288 rt = create_render_target(surface);
2289 ok(!!rt, "Failed to create render target.\n");
2290 ID2D1RenderTarget_GetFactory(rt, &factory);
2292 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
2293 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2295 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
2296 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
2297 ok(SUCCEEDED(hr), "Failed to create color brush, hr %#x.\n", hr);
2299 set_size_u(&size, 4, 4);
2300 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2301 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2302 bitmap_desc.dpiX = 96.0f;
2303 bitmap_desc.dpiY = 96.0f;
2304 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
2305 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2306 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &opacity_brush);
2307 ok(SUCCEEDED(hr), "Failed to create bitmap brush, hr %#x.\n", hr);
2308 ID2D1BitmapBrush_SetInterpolationMode(opacity_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
2309 refcount = ID2D1Bitmap_Release(bitmap);
2310 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
2312 set_size_u(&size, 1, 1);
2313 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2314 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
2315 bitmap_desc.dpiX = 96.0f;
2316 bitmap_desc.dpiY = 96.0f;
2317 hr = ID2D1RenderTarget_CreateBitmap(rt, size, &bitmap_data[2], sizeof(*bitmap_data), &bitmap_desc, &bitmap);
2318 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2319 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
2320 ok(SUCCEEDED(hr), "Failed to create bitmap brush, hr %#x.\n", hr);
2321 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
2322 refcount = ID2D1Bitmap_Release(bitmap);
2323 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
2325 ID2D1RenderTarget_BeginDraw(rt);
2327 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
2328 ID2D1RenderTarget_Clear(rt, &color);
2330 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
2331 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
2333 set_matrix_identity(&matrix);
2334 translate_matrix(&matrix, 120.0f, 120.0f);
2335 scale_matrix(&matrix, 20.0f, 60.0f);
2336 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2337 set_rect(&rect, 120.0f, 120.0f, 200.0f, 360.0f);
2338 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)opacity_brush);
2340 set_rect(&rect, 200.0f, 120.0f, 280.0f, 360.0f);
2341 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2343 set_matrix_identity(&matrix);
2344 translate_matrix(&matrix, 40.0f, 360.0f);
2345 scale_matrix(&matrix, 20.0f, 60.0f);
2346 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2347 set_rect(&rect, 40.0f, 360.0f, 120.0f, 600.0f);
2348 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2349 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2350 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
2351 ID2D1RectangleGeometry_Release(geometry);
2353 set_matrix_identity(&matrix);
2354 translate_matrix(&matrix, 120.0f, 360.0f);
2355 scale_matrix(&matrix, 20.0f, 60.0f);
2356 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2357 set_rect(&rect, 120.0f, 360.0f, 200.0f, 600.0f);
2358 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2359 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2360 (ID2D1Brush *)color_brush, (ID2D1Brush *)opacity_brush);
2361 ID2D1RectangleGeometry_Release(geometry);
2363 set_matrix_identity(&matrix);
2364 translate_matrix(&matrix, 200.0f, 360.0f);
2365 scale_matrix(&matrix, 20.0f, 60.0f);
2366 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2367 set_rect(&rect, 200.0f, 360.0f, 280.0f, 600.0f);
2368 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2369 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2370 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
2372 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2373 ok(hr == D2DERR_INCOMPATIBLE_BRUSH_TYPES, "Got unexpected hr %#x.\n", hr);
2374 match = compare_surface(surface, "7141c6c7b3decb91196428efb1856bcbf9872935");
2375 ok(match, "Surface does not match.\n");
2376 ID2D1RenderTarget_BeginDraw(rt);
2378 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2379 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
2380 ID2D1RectangleGeometry_Release(geometry);
2382 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.5f);
2383 set_matrix_identity(&matrix);
2384 translate_matrix(&matrix, 40.0f, 600.0f);
2385 scale_matrix(&matrix, 20.0f, 60.0f);
2386 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2387 set_rect(&rect, 40.0f, 600.0f, 120.0f, 840.0f);
2388 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2389 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2390 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
2391 ID2D1RectangleGeometry_Release(geometry);
2393 ID2D1BitmapBrush_SetOpacity(opacity_brush, 0.8f);
2394 set_matrix_identity(&matrix);
2395 translate_matrix(&matrix, 120.0f, 600.0f);
2396 scale_matrix(&matrix, 20.0f, 60.0f);
2397 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2398 set_rect(&rect, 120.0f, 600.0f, 200.0f, 840.0f);
2399 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2400 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2401 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)bitmap_brush);
2402 ID2D1RectangleGeometry_Release(geometry);
2404 set_matrix_identity(&matrix);
2405 translate_matrix(&matrix, 200.0f, 600.0f);
2406 scale_matrix(&matrix, 20.0f, 60.0f);
2407 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2408 set_rect(&rect, 200.0f, 600.0f, 280.0f, 840.0f);
2409 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2410 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2411 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
2412 ID2D1RectangleGeometry_Release(geometry);
2414 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2415 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2416 match = compare_surface(surface, "c3a5802d1750efa3e9122c1a92f6064df3872732");
2417 ok(match, "Surface does not match.\n");
2419 ID2D1BitmapBrush_Release(bitmap_brush);
2420 ID2D1BitmapBrush_Release(opacity_brush);
2421 ID2D1SolidColorBrush_Release(color_brush);
2422 ID2D1RenderTarget_Release(rt);
2423 refcount = ID2D1Factory_Release(factory);
2424 ok(!refcount, "Factory has %u references left.\n", refcount);
2425 IDXGISurface_Release(surface);
2426 IDXGISwapChain_Release(swapchain);
2427 ID3D10Device1_Release(device);
2428 DestroyWindow(window);
2431 START_TEST(d2d1)
2433 test_clip();
2434 test_state_block();
2435 test_color_brush();
2436 test_bitmap_brush();
2437 test_path_geometry();
2438 test_bitmap_formats();
2439 test_alpha_mode();
2440 test_shared_bitmap();
2441 test_bitmap_updates();
2442 test_opacity_brush();