d2d1: Implement d2d_factory_CreateTransformedGeometry().
[wine.git] / dlls / d2d1 / tests / d2d1.c
blobdfc560f9bf9a16275911f4b854828042cc3eaf3b
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 ID2D1SolidColorBrush_Release(brush);
1634 ID2D1RenderTarget_Release(rt);
1635 refcount = ID2D1Factory_Release(factory);
1636 ok(!refcount, "Factory has %u references left.\n", refcount);
1637 IDXGISurface_Release(surface);
1638 IDXGISwapChain_Release(swapchain);
1639 ID3D10Device1_Release(device);
1640 DestroyWindow(window);
1643 static void test_bitmap_formats(void)
1645 D2D1_BITMAP_PROPERTIES bitmap_desc;
1646 IDXGISwapChain *swapchain;
1647 D2D1_SIZE_U size = {4, 4};
1648 ID2D1RenderTarget *rt;
1649 ID3D10Device1 *device;
1650 IDXGISurface *surface;
1651 ID2D1Bitmap *bitmap;
1652 unsigned int i, j;
1653 HWND window;
1654 HRESULT hr;
1656 static const struct
1658 DXGI_FORMAT format;
1659 DWORD mask;
1661 bitmap_formats[] =
1663 {DXGI_FORMAT_R32G32B32A32_FLOAT, 0x8a},
1664 {DXGI_FORMAT_R16G16B16A16_FLOAT, 0x8a},
1665 {DXGI_FORMAT_R16G16B16A16_UNORM, 0x8a},
1666 {DXGI_FORMAT_R8G8B8A8_TYPELESS, 0x00},
1667 {DXGI_FORMAT_R8G8B8A8_UNORM, 0x0a},
1668 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0x8a},
1669 {DXGI_FORMAT_R8G8B8A8_UINT, 0x00},
1670 {DXGI_FORMAT_R8G8B8A8_SNORM, 0x00},
1671 {DXGI_FORMAT_R8G8B8A8_SINT, 0x00},
1672 {DXGI_FORMAT_A8_UNORM, 0x06},
1673 {DXGI_FORMAT_B8G8R8A8_UNORM, 0x0a},
1674 {DXGI_FORMAT_B8G8R8X8_UNORM, 0x88},
1675 {DXGI_FORMAT_B8G8R8A8_TYPELESS, 0x00},
1676 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, 0x8a},
1679 if (!(device = create_device()))
1681 skip("Failed to create device, skipping tests.\n");
1682 return;
1684 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1685 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1686 swapchain = create_swapchain(device, window, TRUE);
1687 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1688 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1689 rt = create_render_target(surface);
1690 ok(!!rt, "Failed to create render target.\n");
1692 bitmap_desc.dpiX = 96.0f;
1693 bitmap_desc.dpiY = 96.0f;
1694 for (i = 0; i < sizeof(bitmap_formats) / sizeof(*bitmap_formats); ++i)
1696 for (j = 0; j < 4; ++j)
1698 if ((bitmap_formats[i].mask & (0x80 | (1u << j))) == (0x80 | (1u << j)))
1699 continue;
1701 bitmap_desc.pixelFormat.format = bitmap_formats[i].format;
1702 bitmap_desc.pixelFormat.alphaMode = j;
1703 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
1704 if (bitmap_formats[i].mask & (1u << j))
1705 ok(hr == S_OK, "Got unexpected hr %#x, for format %#x/%#x.\n",
1706 hr, bitmap_formats[i].format, j);
1707 else
1708 ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "Got unexpected hr %#x, for format %#x/%#x.\n",
1709 hr, bitmap_formats[i].format, j);
1710 if (SUCCEEDED(hr))
1711 ID2D1Bitmap_Release(bitmap);
1715 ID2D1RenderTarget_Release(rt);
1716 IDXGISurface_Release(surface);
1717 IDXGISwapChain_Release(swapchain);
1718 ID3D10Device1_Release(device);
1719 DestroyWindow(window);
1722 static void test_alpha_mode(void)
1724 D2D1_RENDER_TARGET_PROPERTIES rt_desc;
1725 D2D1_BITMAP_PROPERTIES bitmap_desc;
1726 ID2D1SolidColorBrush *color_brush;
1727 ID2D1BitmapBrush *bitmap_brush;
1728 IDXGISwapChain *swapchain;
1729 ID2D1RenderTarget *rt;
1730 ID3D10Device1 *device;
1731 IDXGISurface *surface;
1732 ID2D1Bitmap *bitmap;
1733 D2D1_COLOR_F color;
1734 D2D1_RECT_F rect;
1735 D2D1_SIZE_U size;
1736 ULONG refcount;
1737 HWND window;
1738 HRESULT hr;
1739 BOOL match;
1741 static const DWORD bitmap_data[] =
1743 0x7f7f0000, 0x7f7f7f00, 0x7f007f00, 0x7f007f7f,
1744 0x7f00007f, 0x7f7f007f, 0x7f000000, 0x7f404040,
1745 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f000000,
1746 0x7f7f7f7f, 0x7f000000, 0x7f000000, 0x7f000000,
1749 if (!(device = create_device()))
1751 skip("Failed to create device, skipping tests.\n");
1752 return;
1754 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1755 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1756 swapchain = create_swapchain(device, window, TRUE);
1757 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1758 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1759 rt = create_render_target(surface);
1760 ok(!!rt, "Failed to create render target.\n");
1762 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1764 set_size_u(&size, 4, 4);
1765 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
1766 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1767 bitmap_desc.dpiX = 96.0f / 40.0f;
1768 bitmap_desc.dpiY = 96.0f / 30.0f;
1769 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1770 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1772 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
1773 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1774 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
1775 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
1776 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
1778 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
1779 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
1780 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1782 ID2D1RenderTarget_BeginDraw(rt);
1783 ID2D1RenderTarget_Clear(rt, NULL);
1784 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1785 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1786 match = compare_surface(surface, "48c41aff3a130a17ee210866b2ab7d36763934d5");
1787 ok(match, "Surface does not match.\n");
1789 ID2D1RenderTarget_BeginDraw(rt);
1790 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
1791 ID2D1RenderTarget_Clear(rt, &color);
1792 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1793 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1794 match = compare_surface(surface, "6487e683730fb5a77c1911388d00b04664c5c4e4");
1795 ok(match, "Surface does not match.\n");
1797 ID2D1RenderTarget_BeginDraw(rt);
1798 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
1799 ID2D1RenderTarget_Clear(rt, &color);
1800 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1801 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1802 match = compare_surface(surface, "7a35ba09e43cbaf591388ff1ef8de56157630c98");
1803 ok(match, "Surface does not match.\n");
1805 ID2D1RenderTarget_BeginDraw(rt);
1807 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
1808 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1809 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
1810 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
1811 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1812 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
1813 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
1814 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1816 ID2D1Bitmap_Release(bitmap);
1817 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1818 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1819 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1820 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
1822 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
1823 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
1824 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1825 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
1826 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
1827 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1828 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
1829 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
1830 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1832 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
1833 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1834 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
1835 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
1836 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1837 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
1838 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
1839 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1841 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1842 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1843 match = compare_surface(surface, "14f8ac64b70966c7c3c6281c59aaecdb17c3b16a");
1844 ok(match, "Surface does not match.\n");
1846 ID2D1RenderTarget_Release(rt);
1847 rt_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
1848 rt_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
1849 rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1850 rt_desc.dpiX = 0.0f;
1851 rt_desc.dpiY = 0.0f;
1852 rt_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
1853 rt_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
1854 rt = create_render_target_desc(surface, &rt_desc);
1855 ok(!!rt, "Failed to create render target.\n");
1857 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1859 ID2D1Bitmap_Release(bitmap);
1860 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1861 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1862 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1863 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
1865 ID2D1BitmapBrush_Release(bitmap_brush);
1866 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
1867 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1868 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
1869 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
1870 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
1872 ID2D1SolidColorBrush_Release(color_brush);
1873 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
1874 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
1875 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1877 ID2D1RenderTarget_BeginDraw(rt);
1878 ID2D1RenderTarget_Clear(rt, NULL);
1879 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1880 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1881 match = compare_surface(surface, "b44510bf2d2e61a8d7c0ad862de49a471f1fd13f");
1882 ok(match, "Surface does not match.\n");
1884 ID2D1RenderTarget_BeginDraw(rt);
1885 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
1886 ID2D1RenderTarget_Clear(rt, &color);
1887 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1888 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1889 match = compare_surface(surface, "2184f4a9198fc1de09ac85301b7a03eebadd9b81");
1890 ok(match, "Surface does not match.\n");
1892 ID2D1RenderTarget_BeginDraw(rt);
1893 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
1894 ID2D1RenderTarget_Clear(rt, &color);
1895 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1896 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1897 match = compare_surface(surface, "6527ec83b4039c895b50f9b3e144fe0cf90d1889");
1898 ok(match, "Surface does not match.\n");
1900 ID2D1RenderTarget_BeginDraw(rt);
1902 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
1903 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1904 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
1905 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
1906 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1907 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
1908 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
1909 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1911 ID2D1Bitmap_Release(bitmap);
1912 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1913 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1914 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1915 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
1917 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
1918 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
1919 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1920 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
1921 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
1922 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1923 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
1924 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
1925 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1927 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
1928 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1929 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
1930 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
1931 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1932 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
1933 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
1934 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1936 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1937 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1938 match = compare_surface(surface, "465f5a3190d7bde408b3206b4be939fb22f8a3d6");
1939 ok(match, "Surface does not match.\n");
1941 refcount = ID2D1Bitmap_Release(bitmap);
1942 ok(refcount == 1, "Bitmap has %u references left.\n", refcount);
1943 ID2D1SolidColorBrush_Release(color_brush);
1944 ID2D1BitmapBrush_Release(bitmap_brush);
1945 ID2D1RenderTarget_Release(rt);
1946 IDXGISurface_Release(surface);
1947 IDXGISwapChain_Release(swapchain);
1948 ID3D10Device1_Release(device);
1949 DestroyWindow(window);
1952 static void test_shared_bitmap(void)
1954 IDXGISwapChain *swapchain1, *swapchain2;
1955 IWICBitmap *wic_bitmap1, *wic_bitmap2;
1956 D2D1_RENDER_TARGET_PROPERTIES desc;
1957 D2D1_BITMAP_PROPERTIES bitmap_desc;
1958 IDXGISurface *surface1, *surface2;
1959 ID2D1Factory *factory1, *factory2;
1960 ID3D10Device1 *device1, *device2;
1961 IWICImagingFactory *wic_factory;
1962 ID2D1Bitmap *bitmap1, *bitmap2;
1963 ID2D1RenderTarget *rt1, *rt2;
1964 D2D1_SIZE_U size = {4, 4};
1965 HWND window1, window2;
1966 HRESULT hr;
1968 if (!(device1 = create_device()))
1970 skip("Failed to create device, skipping tests.\n");
1971 return;
1974 window1 = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1975 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1976 window2 = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1977 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1978 swapchain1 = create_swapchain(device1, window1, TRUE);
1979 swapchain2 = create_swapchain(device1, window2, TRUE);
1980 hr = IDXGISwapChain_GetBuffer(swapchain1, 0, &IID_IDXGISurface, (void **)&surface1);
1981 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1982 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
1983 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1985 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1986 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1987 &IID_IWICImagingFactory, (void **)&wic_factory);
1988 ok(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
1989 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
1990 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap1);
1991 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1992 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
1993 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap2);
1994 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1995 IWICImagingFactory_Release(wic_factory);
1997 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
1998 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
1999 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2000 desc.dpiX = 0.0f;
2001 desc.dpiY = 0.0f;
2002 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
2003 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
2005 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2006 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2007 bitmap_desc.dpiX = 96.0f;
2008 bitmap_desc.dpiY = 96.0f;
2010 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory1);
2011 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2012 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
2013 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2015 /* DXGI surface render targets with the same device and factory. */
2016 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface1, &desc, &rt1);
2017 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2018 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
2019 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2021 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
2022 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2023 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2024 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2025 ID2D1Bitmap_Release(bitmap2);
2026 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IUnknown, bitmap1, NULL, &bitmap2);
2027 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2028 ID2D1RenderTarget_Release(rt2);
2030 /* DXGI surface render targets with the same device but different factories. */
2031 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
2032 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2033 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2034 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
2035 ID2D1RenderTarget_Release(rt2);
2037 /* DXGI surface render targets with different devices but the same factory. */
2038 IDXGISurface_Release(surface2);
2039 IDXGISwapChain_Release(swapchain2);
2040 device2 = create_device();
2041 ok(!!device2, "Failed to create device.\n");
2042 swapchain2 = create_swapchain(device2, window2, TRUE);
2043 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
2044 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2046 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
2047 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2048 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2049 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
2050 ID2D1RenderTarget_Release(rt2);
2052 /* DXGI surface render targets with different devices and different factories. */
2053 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
2054 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2055 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2056 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
2057 ID2D1RenderTarget_Release(rt2);
2059 /* DXGI surface render target and WIC bitmap render target, same factory. */
2060 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
2061 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2062 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2063 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
2064 ID2D1RenderTarget_Release(rt2);
2066 /* WIC bitmap render targets on different D2D factories. */
2067 ID2D1Bitmap_Release(bitmap1);
2068 ID2D1RenderTarget_Release(rt1);
2069 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap1, &desc, &rt1);
2070 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2071 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
2072 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2074 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory2, wic_bitmap2, &desc, &rt2);
2075 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2076 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2077 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
2078 ID2D1RenderTarget_Release(rt2);
2080 /* WIC bitmap render targets on the same D2D factory. */
2081 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
2082 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2083 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2084 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2085 ID2D1Bitmap_Release(bitmap2);
2086 ID2D1RenderTarget_Release(rt2);
2088 ID2D1Bitmap_Release(bitmap1);
2089 ID2D1RenderTarget_Release(rt1);
2090 ID2D1Factory_Release(factory2);
2091 ID2D1Factory_Release(factory1);
2092 IWICBitmap_Release(wic_bitmap2);
2093 IWICBitmap_Release(wic_bitmap1);
2094 IDXGISurface_Release(surface2);
2095 IDXGISurface_Release(surface1);
2096 IDXGISwapChain_Release(swapchain2);
2097 IDXGISwapChain_Release(swapchain1);
2098 ID3D10Device1_Release(device2);
2099 ID3D10Device1_Release(device1);
2100 DestroyWindow(window2);
2101 DestroyWindow(window1);
2102 CoUninitialize();
2105 static void test_bitmap_updates(void)
2107 D2D1_BITMAP_PROPERTIES bitmap_desc;
2108 IDXGISwapChain *swapchain;
2109 ID2D1RenderTarget *rt;
2110 ID3D10Device1 *device;
2111 IDXGISurface *surface;
2112 D2D1_RECT_U dst_rect;
2113 ID2D1Bitmap *bitmap;
2114 D2D1_COLOR_F color;
2115 D2D1_RECT_F rect;
2116 D2D1_SIZE_U size;
2117 HWND window;
2118 HRESULT hr;
2119 BOOL match;
2121 static const DWORD bitmap_data[] =
2123 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
2124 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
2125 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
2126 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
2129 if (!(device = create_device()))
2131 skip("Failed to create device, skipping tests.\n");
2132 return;
2134 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2135 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2136 swapchain = create_swapchain(device, window, TRUE);
2137 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2138 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2139 rt = create_render_target(surface);
2140 ok(!!rt, "Failed to create render target.\n");
2142 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2144 ID2D1RenderTarget_BeginDraw(rt);
2145 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
2146 ID2D1RenderTarget_Clear(rt, &color);
2148 set_size_u(&size, 4, 4);
2149 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2150 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2151 bitmap_desc.dpiX = 96.0f;
2152 bitmap_desc.dpiY = 96.0f;
2153 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
2154 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2156 set_rect(&rect, 0.0f, 0.0f, 320.0f, 240.0f);
2157 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2158 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2160 ID2D1Bitmap_Release(bitmap);
2162 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
2163 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
2164 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2166 set_rect(&rect, 0.0f, 240.0f, 320.0f, 480.0f);
2167 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2168 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2170 set_rect_u(&dst_rect, 1, 1, 3, 3);
2171 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, 4 * sizeof(*bitmap_data));
2172 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2173 set_rect_u(&dst_rect, 0, 3, 3, 4);
2174 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[6], 4 * sizeof(*bitmap_data));
2175 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2176 set_rect_u(&dst_rect, 0, 0, 4, 1);
2177 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[10], 4 * sizeof(*bitmap_data));
2178 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2179 set_rect_u(&dst_rect, 0, 1, 1, 3);
2180 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[2], sizeof(*bitmap_data));
2181 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2182 set_rect_u(&dst_rect, 4, 4, 3, 1);
2183 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, sizeof(*bitmap_data));
2184 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2185 set_rect(&rect, 320.0f, 240.0f, 640.0f, 480.0f);
2186 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2187 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2189 hr = ID2D1Bitmap_CopyFromMemory(bitmap, NULL, bitmap_data, 4 * sizeof(*bitmap_data));
2190 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2191 set_rect(&rect, 320.0f, 0.0f, 640.0f, 240.0f);
2192 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2193 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2195 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2196 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2198 match = compare_surface(surface, "cb8136c91fbbdc76bb83b8c09edc1907b0a5d0a6");
2199 ok(match, "Surface does not match.\n");
2201 ID2D1Bitmap_Release(bitmap);
2202 ID2D1RenderTarget_Release(rt);
2203 IDXGISurface_Release(surface);
2204 IDXGISwapChain_Release(swapchain);
2205 ID3D10Device1_Release(device);
2206 DestroyWindow(window);
2209 START_TEST(d2d1)
2211 test_clip();
2212 test_state_block();
2213 test_color_brush();
2214 test_bitmap_brush();
2215 test_path_geometry();
2216 test_bitmap_formats();
2217 test_alpha_mode();
2218 test_shared_bitmap();
2219 test_bitmap_updates();