wined3d: Store sub-resource locations in the sub-resource structure.
[wine.git] / dlls / d2d1 / tests / d2d1.c
blob2a78d2c712331b6e630bcf7ca5a7a8151d30636b
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 ID2D1RenderTarget_SetDpi(rt, 192.0f, 192.0f);
591 ID2D1RenderTarget_SetDpi(rt, 0.0f, 96.0f);
592 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
593 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
594 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
596 ID2D1RenderTarget_SetDpi(rt, -10.0f, 96.0f);
597 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
598 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
599 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
601 ID2D1RenderTarget_SetDpi(rt, 96.0f, -10.0f);
602 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
603 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
604 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
606 ID2D1RenderTarget_SetDpi(rt, 96.0f, 0.0f);
607 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
608 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
609 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
611 ID2D1RenderTarget_SetDpi(rt, 96.0f, 96.0f);
613 /* Transformations apply to clip rects, the effective clip rect is the
614 * (axis-aligned) bounding box of the transformed clip rect. */
615 set_point(&point, 320.0f, 240.0f);
616 D2D1MakeRotateMatrix(30.0f, point, &matrix);
617 ID2D1RenderTarget_SetTransform(rt, &matrix);
618 set_rect(&rect, 215.0f, 208.0f, 425.0f, 272.0f);
619 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
620 set_color(&color, 1.0f, 1.0f, 1.0f, 1.0f);
621 ID2D1RenderTarget_Clear(rt, &color);
622 ID2D1RenderTarget_PopAxisAlignedClip(rt);
624 /* Transformations are applied when pushing the clip rect, transformations
625 * set afterwards have no effect on the current clip rect. This includes
626 * SetDpi(). */
627 ID2D1RenderTarget_SetTransform(rt, &identity);
628 set_rect(&rect, 427.0f, 320.0f, 640.0f, 480.0f);
629 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
630 ID2D1RenderTarget_SetTransform(rt, &matrix);
631 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
632 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
633 ID2D1RenderTarget_Clear(rt, &color);
634 ID2D1RenderTarget_PopAxisAlignedClip(rt);
636 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
637 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
638 match = compare_surface(surface, "035a44d4198d6e422e9de6185b5b2c2bac5e33c9");
639 ok(match, "Surface does not match.\n");
641 ID2D1RenderTarget_Release(rt);
642 IDXGISurface_Release(surface);
643 IDXGISwapChain_Release(swapchain);
644 ID3D10Device1_Release(device);
645 DestroyWindow(window);
648 static void test_state_block(void)
650 IDWriteRenderingParams *text_rendering_params1, *text_rendering_params2;
651 D2D1_DRAWING_STATE_DESCRIPTION drawing_state;
652 ID2D1DrawingStateBlock *state_block;
653 IDWriteFactory *dwrite_factory;
654 IDXGISwapChain *swapchain;
655 ID2D1RenderTarget *rt;
656 ID3D10Device1 *device;
657 IDXGISurface *surface;
658 ID2D1Factory *factory;
659 ULONG refcount;
660 HWND window;
661 HRESULT hr;
662 static const D2D1_MATRIX_3X2_F identity =
664 1.0f, 0.0f,
665 0.0f, 1.0f,
666 0.0f, 0.0f,
668 static const D2D1_MATRIX_3X2_F transform1 =
670 1.0f, 2.0f,
671 3.0f, 4.0f,
672 5.0f, 6.0f,
674 static const D2D1_MATRIX_3X2_F transform2 =
676 7.0f, 8.0f,
677 9.0f, 10.0f,
678 11.0f, 12.0f,
681 if (!(device = create_device()))
683 skip("Failed to create device, skipping tests.\n");
684 return;
686 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
687 0, 0, 640, 480, NULL, NULL, NULL, NULL);
688 swapchain = create_swapchain(device, window, TRUE);
689 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
690 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
691 rt = create_render_target(surface);
692 ok(!!rt, "Failed to create render target.\n");
693 ID2D1RenderTarget_GetFactory(rt, &factory);
694 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
695 ok(SUCCEEDED(hr), "Failed to create dwrite factory, hr %#x.\n", hr);
696 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &text_rendering_params1);
697 ok(SUCCEEDED(hr), "Failed to create dwrite rendering params, hr %#x.\n", hr);
698 IDWriteFactory_Release(dwrite_factory);
700 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
701 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
702 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
703 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
704 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
705 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
706 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
707 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %08x%08x:%08x%08x.\n",
708 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
709 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
710 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
711 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
712 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
713 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
714 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
715 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
716 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
718 hr = ID2D1Factory_CreateDrawingStateBlock(factory, NULL, NULL, &state_block);
719 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
720 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
721 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
722 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
723 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
724 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
725 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %08x%08x:%08x%08x.\n",
726 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
727 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
728 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
729 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
730 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
731 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
732 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
733 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
734 ID2D1DrawingStateBlock_Release(state_block);
736 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
737 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
738 drawing_state.tag1 = 0xdead;
739 drawing_state.tag2 = 0xbeef;
740 drawing_state.transform = transform1;
741 hr = ID2D1Factory_CreateDrawingStateBlock(factory, &drawing_state, text_rendering_params1, &state_block);
742 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
744 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
745 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
746 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
747 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
748 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
749 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %08x%08x:%08x%08x.\n",
750 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
751 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
752 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
753 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
754 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
755 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
756 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
757 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
758 text_rendering_params2, text_rendering_params1);
759 IDWriteRenderingParams_Release(text_rendering_params2);
761 ID2D1RenderTarget_RestoreDrawingState(rt, state_block);
763 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
764 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
765 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
766 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
767 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
768 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
769 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
770 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %08x%08x:%08x%08x.\n",
771 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
772 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
773 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
774 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
775 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
776 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
777 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
778 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
779 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
780 text_rendering_params2, text_rendering_params1);
781 IDWriteRenderingParams_Release(text_rendering_params2);
783 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
784 ID2D1RenderTarget_SetTextAntialiasMode(rt, D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
785 ID2D1RenderTarget_SetTags(rt, 1, 2);
786 ID2D1RenderTarget_SetTransform(rt, &transform2);
787 ID2D1RenderTarget_SetTextRenderingParams(rt, NULL);
789 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
790 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
791 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
792 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
793 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
794 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
795 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
796 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %08x%08x:%08x%08x.\n",
797 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
798 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
799 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
800 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
801 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
802 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
803 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
804 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
805 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
807 ID2D1RenderTarget_SaveDrawingState(rt, state_block);
809 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
810 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
811 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
812 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
813 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
814 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "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, &transform2, 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, "Got unexpected text rendering params %p.\n", text_rendering_params2);
824 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
825 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
826 drawing_state.tag1 = 3;
827 drawing_state.tag2 = 4;
828 drawing_state.transform = transform1;
829 ID2D1DrawingStateBlock_SetDescription(state_block, &drawing_state);
830 ID2D1DrawingStateBlock_SetTextRenderingParams(state_block, text_rendering_params1);
832 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
833 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
834 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
835 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE,
836 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
837 ok(drawing_state.tag1 == 3 && drawing_state.tag2 == 4, "Got unexpected tags %08x%08x:%08x%08x.\n",
838 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
839 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
840 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
841 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
842 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
843 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
844 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
845 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
846 text_rendering_params2, text_rendering_params1);
847 IDWriteRenderingParams_Release(text_rendering_params2);
849 ID2D1DrawingStateBlock_Release(state_block);
851 refcount = IDWriteRenderingParams_Release(text_rendering_params1);
852 ok(!refcount, "Rendering params %u references left.\n", refcount);
853 ID2D1Factory_Release(factory);
854 ID2D1RenderTarget_Release(rt);
855 IDXGISurface_Release(surface);
856 IDXGISwapChain_Release(swapchain);
857 ID3D10Device1_Release(device);
858 DestroyWindow(window);
861 static void test_color_brush(void)
863 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
864 D2D1_BRUSH_PROPERTIES brush_desc;
865 D2D1_COLOR_F color, tmp_color;
866 ID2D1SolidColorBrush *brush;
867 IDXGISwapChain *swapchain;
868 ID2D1RenderTarget *rt;
869 ID3D10Device1 *device;
870 IDXGISurface *surface;
871 D2D1_RECT_F rect;
872 float opacity;
873 HWND window;
874 HRESULT hr;
875 BOOL match;
877 if (!(device = create_device()))
879 skip("Failed to create device, skipping tests.\n");
880 return;
882 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
883 0, 0, 640, 480, NULL, NULL, NULL, NULL);
884 swapchain = create_swapchain(device, window, TRUE);
885 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
886 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
887 rt = create_render_target(surface);
888 ok(!!rt, "Failed to create render target.\n");
890 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
891 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
893 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
894 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
895 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
896 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
897 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
898 set_matrix_identity(&matrix);
899 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
900 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
901 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
902 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
903 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
904 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
905 ok(!memcmp(&tmp_color, &color, sizeof(color)),
906 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
907 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
908 ID2D1SolidColorBrush_Release(brush);
910 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
911 brush_desc.opacity = 0.3f;
912 set_matrix_identity(&matrix);
913 scale_matrix(&matrix, 2.0f, 2.0f);
914 brush_desc.transform = matrix;
915 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, &brush_desc, &brush);
916 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
917 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
918 ok(opacity == 0.3f, "Got unexpected opacity %.8e.\n", opacity);
919 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
920 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
921 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
922 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
923 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
924 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
925 ok(!memcmp(&tmp_color, &color, sizeof(color)),
926 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
927 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
929 ID2D1RenderTarget_BeginDraw(rt);
931 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
932 ID2D1RenderTarget_Clear(rt, &color);
934 ID2D1SolidColorBrush_SetOpacity(brush, 1.0f);
935 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
936 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
938 set_matrix_identity(&matrix);
939 scale_matrix(&matrix, 0.5f, 2.0f);
940 translate_matrix(&matrix, 320.0f, 240.0f);
941 rotate_matrix(&matrix, M_PI / 4.0f);
942 ID2D1RenderTarget_SetTransform(rt, &matrix);
943 set_color(&color, 1.0f, 0.0f, 0.0f, 0.625f);
944 ID2D1SolidColorBrush_SetColor(brush, &color);
945 ID2D1SolidColorBrush_SetOpacity(brush, 0.75f);
946 set_rect(&rect, -80.0f, -60.0f, 80.0f, 60.0f);
947 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
949 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
950 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
951 match = compare_surface(surface, "6d1218fca5e21fb7e287b3a439d60dbc251f5ceb");
952 ok(match, "Surface does not match.\n");
954 ID2D1SolidColorBrush_Release(brush);
955 ID2D1RenderTarget_Release(rt);
956 IDXGISurface_Release(surface);
957 IDXGISwapChain_Release(swapchain);
958 ID3D10Device1_Release(device);
959 DestroyWindow(window);
962 static void test_bitmap_brush(void)
964 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode;
965 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
966 D2D1_BITMAP_PROPERTIES bitmap_desc;
967 ID2D1Bitmap *bitmap, *tmp_bitmap;
968 D2D1_RECT_F src_rect, dst_rect;
969 D2D1_EXTEND_MODE extend_mode;
970 IDXGISwapChain *swapchain;
971 ID2D1BitmapBrush *brush;
972 ID2D1RenderTarget *rt;
973 ID3D10Device1 *device;
974 IDXGISurface *surface;
975 D2D1_COLOR_F color;
976 D2D1_SIZE_U size;
977 unsigned int i;
978 ULONG refcount;
979 float opacity;
980 HWND window;
981 HRESULT hr;
982 BOOL match;
984 static const struct
986 D2D1_EXTEND_MODE extend_mode_x;
987 D2D1_EXTEND_MODE extend_mode_y;
988 float translate_x;
989 float translate_y;
990 D2D1_RECT_F rect;
992 extend_mode_tests[] =
994 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_MIRROR, -7.0f, 1.0f, {-4.0f, 0.0f, -8.0f, 4.0f}},
995 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_MIRROR, -3.0f, 1.0f, {-4.0f, 4.0f, 0.0f, 0.0f}},
996 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_MIRROR, 1.0f, 1.0f, { 4.0f, 0.0f, 0.0f, 4.0f}},
997 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_WRAP, -7.0f, 5.0f, {-8.0f, 8.0f, -4.0f, 4.0f}},
998 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP, -3.0f, 5.0f, { 0.0f, 4.0f, -4.0f, 8.0f}},
999 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_WRAP, 1.0f, 5.0f, { 0.0f, 8.0f, 4.0f, 4.0f}},
1000 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_CLAMP, -7.0f, 9.0f, {-4.0f, 8.0f, -8.0f, 12.0f}},
1001 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_CLAMP, -3.0f, 9.0f, {-4.0f, 12.0f, 0.0f, 8.0f}},
1002 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_CLAMP, 1.0f, 9.0f, { 4.0f, 8.0f, 0.0f, 12.0f}},
1004 static const DWORD bitmap_data[] =
1006 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
1007 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
1008 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
1009 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
1012 if (!(device = create_device()))
1014 skip("Failed to create device, skipping tests.\n");
1015 return;
1017 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1018 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1019 swapchain = create_swapchain(device, window, TRUE);
1020 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1021 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1022 rt = create_render_target(surface);
1023 ok(!!rt, "Failed to create render target.\n");
1025 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1026 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1028 set_size_u(&size, 4, 4);
1029 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
1030 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1031 bitmap_desc.dpiX = 96.0f;
1032 bitmap_desc.dpiY = 96.0f;
1033 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1034 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1036 /* Creating a brush with a NULL bitmap crashes on Vista, but works fine on
1037 * Windows 7+. */
1038 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
1039 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1040 ID2D1BitmapBrush_GetBitmap(brush, &tmp_bitmap);
1041 ok(tmp_bitmap == bitmap, "Got unexpected bitmap %p, expected %p.\n", tmp_bitmap, bitmap);
1042 ID2D1Bitmap_Release(tmp_bitmap);
1043 opacity = ID2D1BitmapBrush_GetOpacity(brush);
1044 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
1045 set_matrix_identity(&matrix);
1046 ID2D1BitmapBrush_GetTransform(brush, &tmp_matrix);
1047 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1048 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1049 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1050 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1051 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
1052 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
1053 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
1054 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
1055 interpolation_mode = ID2D1BitmapBrush_GetInterpolationMode(brush);
1056 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
1057 "Got unexpected interpolation mode %#x.\n", interpolation_mode);
1058 ID2D1BitmapBrush_Release(brush);
1060 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
1061 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1062 set_matrix_identity(&matrix);
1063 translate_matrix(&matrix, 40.0f, 120.0f);
1064 scale_matrix(&matrix, 20.0f, 60.0f);
1065 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1066 ID2D1BitmapBrush_SetInterpolationMode(brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
1068 ID2D1RenderTarget_BeginDraw(rt);
1070 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1071 ID2D1RenderTarget_Clear(rt, &color);
1073 set_rect(&dst_rect, 40.0f, 120.0f, 120.0f, 360.0f);
1074 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1076 set_matrix_identity(&matrix);
1077 scale_matrix(&matrix, 0.5f, 2.0f);
1078 translate_matrix(&matrix, 320.0f, 240.0f);
1079 rotate_matrix(&matrix, M_PI / 4.0f);
1080 ID2D1RenderTarget_SetTransform(rt, &matrix);
1081 set_matrix_identity(&matrix);
1082 translate_matrix(&matrix, -80.0f, -60.0f);
1083 scale_matrix(&matrix, 40.0f, 30.0f);
1084 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1085 ID2D1BitmapBrush_SetOpacity(brush, 0.75f);
1086 set_rect(&dst_rect, -80.0f, -60.0f, 80.0f, 60.0f);
1087 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1089 set_matrix_identity(&matrix);
1090 translate_matrix(&matrix, 200.0f, 120.0f);
1091 scale_matrix(&matrix, 20.0f, 60.0f);
1092 ID2D1RenderTarget_SetTransform(rt, &matrix);
1093 ID2D1RenderTarget_DrawBitmap(rt, bitmap, NULL, 0.25f,
1094 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
1095 set_rect(&dst_rect, -4.0f, 12.0f, -8.0f, 8.0f);
1096 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 0.75f,
1097 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
1098 set_rect(&dst_rect, 0.0f, 8.0f, 4.0f, 12.0f);
1099 set_rect(&src_rect, 2.0f, 1.0f, 4.0f, 3.0f);
1100 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
1101 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
1103 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1104 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1105 match = compare_surface(surface, "393636185359a550d459e1e5f0e25411814f724c");
1106 ok(match, "Surface does not match.\n");
1108 ID2D1RenderTarget_BeginDraw(rt);
1110 ID2D1RenderTarget_Clear(rt, &color);
1112 ID2D1BitmapBrush_SetOpacity(brush, 1.0f);
1113 for (i = 0; i < sizeof(extend_mode_tests) / sizeof(*extend_mode_tests); ++i)
1115 ID2D1BitmapBrush_SetExtendModeX(brush, extend_mode_tests[i].extend_mode_x);
1116 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
1117 ok(extend_mode == extend_mode_tests[i].extend_mode_x,
1118 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
1119 i, extend_mode, extend_mode_tests[i].extend_mode_x);
1120 ID2D1BitmapBrush_SetExtendModeY(brush, extend_mode_tests[i].extend_mode_y);
1121 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
1122 ok(extend_mode == extend_mode_tests[i].extend_mode_y,
1123 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
1124 i, extend_mode, extend_mode_tests[i].extend_mode_y);
1125 set_matrix_identity(&matrix);
1126 translate_matrix(&matrix, extend_mode_tests[i].translate_x, extend_mode_tests[i].translate_y);
1127 scale_matrix(&matrix, 0.5f, 0.5f);
1128 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1129 ID2D1RenderTarget_FillRectangle(rt, &extend_mode_tests[i].rect, (ID2D1Brush *)brush);
1132 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1133 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1134 match = compare_surface(surface, "b4b775afecdae2d26642001f4faff73663bb8b31");
1135 ok(match, "Surface does not match.\n");
1137 ID2D1BitmapBrush_Release(brush);
1138 refcount = ID2D1Bitmap_Release(bitmap);
1139 ok(!refcount, "Bitmap has %u references left.\n", refcount);
1140 ID2D1RenderTarget_Release(rt);
1141 IDXGISurface_Release(surface);
1142 IDXGISwapChain_Release(swapchain);
1143 ID3D10Device1_Release(device);
1144 DestroyWindow(window);
1147 static void fill_geometry_sink(ID2D1GeometrySink *sink)
1149 D2D1_POINT_2F point;
1151 set_point(&point, 15.0f, 20.0f);
1152 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1153 set_point(&point, 55.0f, 20.0f);
1154 ID2D1GeometrySink_AddLine(sink, point);
1155 set_point(&point, 55.0f, 220.0f);
1156 ID2D1GeometrySink_AddLine(sink, point);
1157 set_point(&point, 25.0f, 220.0f);
1158 ID2D1GeometrySink_AddLine(sink, point);
1159 set_point(&point, 25.0f, 100.0f);
1160 ID2D1GeometrySink_AddLine(sink, point);
1161 set_point(&point, 75.0f, 100.0f);
1162 ID2D1GeometrySink_AddLine(sink, point);
1163 set_point(&point, 75.0f, 300.0f);
1164 ID2D1GeometrySink_AddLine(sink, point);
1165 set_point(&point, 5.0f, 300.0f);
1166 ID2D1GeometrySink_AddLine(sink, point);
1167 set_point(&point, 5.0f, 60.0f);
1168 ID2D1GeometrySink_AddLine(sink, point);
1169 set_point(&point, 45.0f, 60.0f);
1170 ID2D1GeometrySink_AddLine(sink, point);
1171 set_point(&point, 45.0f, 180.0f);
1172 ID2D1GeometrySink_AddLine(sink, point);
1173 set_point(&point, 35.0f, 180.0f);
1174 ID2D1GeometrySink_AddLine(sink, point);
1175 set_point(&point, 35.0f, 140.0f);
1176 ID2D1GeometrySink_AddLine(sink, point);
1177 set_point(&point, 65.0f, 140.0f);
1178 ID2D1GeometrySink_AddLine(sink, point);
1179 set_point(&point, 65.0f, 260.0f);
1180 ID2D1GeometrySink_AddLine(sink, point);
1181 set_point(&point, 15.0f, 260.0f);
1182 ID2D1GeometrySink_AddLine(sink, point);
1183 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1185 set_point(&point, 155.0f, 300.0f);
1186 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1187 set_point(&point, 155.0f, 160.0f);
1188 ID2D1GeometrySink_AddLine(sink, point);
1189 set_point(&point, 85.0f, 160.0f);
1190 ID2D1GeometrySink_AddLine(sink, point);
1191 set_point(&point, 85.0f, 300.0f);
1192 ID2D1GeometrySink_AddLine(sink, point);
1193 set_point(&point, 120.0f, 300.0f);
1194 ID2D1GeometrySink_AddLine(sink, point);
1195 set_point(&point, 120.0f, 20.0f);
1196 ID2D1GeometrySink_AddLine(sink, point);
1197 set_point(&point, 155.0f, 20.0f);
1198 ID2D1GeometrySink_AddLine(sink, point);
1199 set_point(&point, 155.0f, 160.0f);
1200 ID2D1GeometrySink_AddLine(sink, point);
1201 set_point(&point, 85.0f, 160.0f);
1202 ID2D1GeometrySink_AddLine(sink, point);
1203 set_point(&point, 85.0f, 20.0f);
1204 ID2D1GeometrySink_AddLine(sink, point);
1205 set_point(&point, 120.0f, 20.0f);
1206 ID2D1GeometrySink_AddLine(sink, point);
1207 set_point(&point, 120.0f, 300.0f);
1208 ID2D1GeometrySink_AddLine(sink, point);
1209 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1211 set_point(&point, 165.0f, 20.0f);
1212 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1213 set_point(&point, 165.0f, 300.0f);
1214 ID2D1GeometrySink_AddLine(sink, point);
1215 set_point(&point, 235.0f, 300.0f);
1216 ID2D1GeometrySink_AddLine(sink, point);
1217 set_point(&point, 235.0f, 20.0f);
1218 ID2D1GeometrySink_AddLine(sink, point);
1219 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1220 set_point(&point, 225.0f, 60.0f);
1221 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1222 set_point(&point, 225.0f, 260.0f);
1223 ID2D1GeometrySink_AddLine(sink, point);
1224 set_point(&point, 175.0f, 260.0f);
1225 ID2D1GeometrySink_AddLine(sink, point);
1226 set_point(&point, 175.0f, 60.0f);
1227 ID2D1GeometrySink_AddLine(sink, point);
1228 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1229 set_point(&point, 215.0f, 220.0f);
1230 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1231 set_point(&point, 185.0f, 220.0f);
1232 ID2D1GeometrySink_AddLine(sink, point);
1233 set_point(&point, 185.0f, 100.0f);
1234 ID2D1GeometrySink_AddLine(sink, point);
1235 set_point(&point, 215.0f, 100.0f);
1236 ID2D1GeometrySink_AddLine(sink, point);
1237 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1238 set_point(&point, 195.0f, 180.0f);
1239 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1240 set_point(&point, 205.0f, 180.0f);
1241 ID2D1GeometrySink_AddLine(sink, point);
1242 set_point(&point, 205.0f, 140.0f);
1243 ID2D1GeometrySink_AddLine(sink, point);
1244 set_point(&point, 195.0f, 140.0f);
1245 ID2D1GeometrySink_AddLine(sink, point);
1246 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1249 static void fill_geometry_sink_bezier(ID2D1GeometrySink *sink)
1251 D2D1_QUADRATIC_BEZIER_SEGMENT quadratic;
1252 D2D1_POINT_2F point;
1254 set_point(&point, 5.0f, 160.0f);
1255 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1256 set_quadratic(&quadratic, 40.0f, 160.0f, 40.0f, 20.0f);
1257 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1258 set_quadratic(&quadratic, 40.0f, 160.0f, 75.0f, 160.0f);
1259 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1260 set_quadratic(&quadratic, 40.0f, 160.0f, 40.0f, 300.0f);
1261 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1262 set_quadratic(&quadratic, 40.0f, 160.0f, 5.0f, 160.0f);
1263 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1264 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1266 set_point(&point, 20.0f, 160.0f);
1267 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1268 set_quadratic(&quadratic, 20.0f, 80.0f, 40.0f, 80.0f);
1269 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1270 set_quadratic(&quadratic, 60.0f, 80.0f, 60.0f, 160.0f);
1271 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1272 set_quadratic(&quadratic, 60.0f, 240.0f, 40.0f, 240.0f);
1273 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1274 set_quadratic(&quadratic, 20.0f, 240.0f, 20.0f, 160.0f);
1275 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1276 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1279 static void test_path_geometry(void)
1281 ID2D1TransformedGeometry *transformed_geometry;
1282 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
1283 ID2D1GeometrySink *sink, *tmp_sink;
1284 D2D1_POINT_2F point = {0.0f, 0.0f};
1285 ID2D1SolidColorBrush *brush;
1286 ID2D1PathGeometry *geometry;
1287 ID2D1Geometry *tmp_geometry;
1288 IDXGISwapChain *swapchain;
1289 ID2D1RenderTarget *rt;
1290 ID3D10Device1 *device;
1291 IDXGISurface *surface;
1292 ID2D1Factory *factory;
1293 D2D1_COLOR_F color;
1294 ULONG refcount;
1295 UINT32 count;
1296 HWND window;
1297 HRESULT hr;
1298 BOOL match;
1300 if (!(device = create_device()))
1302 skip("Failed to create device, skipping tests.\n");
1303 return;
1305 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1306 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1307 swapchain = create_swapchain(device, window, TRUE);
1308 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1309 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1310 rt = create_render_target(surface);
1311 ok(!!rt, "Failed to create render target.\n");
1312 ID2D1RenderTarget_GetFactory(rt, &factory);
1314 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1315 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1316 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
1317 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
1318 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1320 /* Close() when closed. */
1321 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1322 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1323 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1324 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1325 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1326 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1327 hr = ID2D1PathGeometry_Open(geometry, &sink);
1328 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1329 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1330 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1331 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1332 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1333 hr = ID2D1GeometrySink_Close(sink);
1334 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1335 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1336 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1337 ok(!count, "Got unexpected figure count %u.\n", count);
1338 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1339 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1340 ok(!count, "Got unexpected segment count %u.\n", count);
1341 hr = ID2D1GeometrySink_Close(sink);
1342 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1343 ID2D1GeometrySink_Release(sink);
1344 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1345 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1346 ok(!count, "Got unexpected figure count %u.\n", count);
1347 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1348 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1349 ok(!count, "Got unexpected segment count %u.\n", count);
1350 ID2D1PathGeometry_Release(geometry);
1352 /* Open() when closed. */
1353 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1354 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1355 hr = ID2D1PathGeometry_Open(geometry, &sink);
1356 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1357 hr = ID2D1GeometrySink_Close(sink);
1358 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1359 ID2D1GeometrySink_Release(sink);
1360 hr = ID2D1PathGeometry_Open(geometry, &sink);
1361 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1362 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1363 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1364 ok(!count, "Got unexpected figure count %u.\n", count);
1365 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1366 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1367 ok(!count, "Got unexpected segment count %u.\n", count);
1368 ID2D1PathGeometry_Release(geometry);
1370 /* Open() when open. */
1371 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1372 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1373 hr = ID2D1PathGeometry_Open(geometry, &sink);
1374 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1375 hr = ID2D1PathGeometry_Open(geometry, &tmp_sink);
1376 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1377 hr = ID2D1GeometrySink_Close(sink);
1378 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1379 ID2D1GeometrySink_Release(sink);
1380 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1381 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1382 ok(!count, "Got unexpected figure count %u.\n", count);
1383 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1384 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1385 ok(!count, "Got unexpected segment count %u.\n", count);
1386 ID2D1PathGeometry_Release(geometry);
1388 /* BeginFigure() without EndFigure(). */
1389 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1390 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1391 hr = ID2D1PathGeometry_Open(geometry, &sink);
1392 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1393 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1394 hr = ID2D1GeometrySink_Close(sink);
1395 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1396 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1397 hr = ID2D1GeometrySink_Close(sink);
1398 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1399 ID2D1GeometrySink_Release(sink);
1400 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1401 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1402 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1403 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1404 ID2D1PathGeometry_Release(geometry);
1406 /* EndFigure() without BeginFigure(). */
1407 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1408 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1409 hr = ID2D1PathGeometry_Open(geometry, &sink);
1410 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1411 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1412 hr = ID2D1GeometrySink_Close(sink);
1413 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1414 ID2D1GeometrySink_Release(sink);
1415 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1416 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1417 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1418 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1419 ID2D1PathGeometry_Release(geometry);
1421 /* BeginFigure()/EndFigure() mismatch. */
1422 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1423 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1424 hr = ID2D1PathGeometry_Open(geometry, &sink);
1425 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1426 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1427 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1428 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1429 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1430 hr = ID2D1GeometrySink_Close(sink);
1431 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1432 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1433 hr = ID2D1GeometrySink_Close(sink);
1434 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1435 ID2D1GeometrySink_Release(sink);
1436 ID2D1PathGeometry_Release(geometry);
1438 /* AddLine() outside BeginFigure()/EndFigure(). */
1439 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1440 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1441 hr = ID2D1PathGeometry_Open(geometry, &sink);
1442 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1443 ID2D1GeometrySink_AddLine(sink, point);
1444 hr = ID2D1GeometrySink_Close(sink);
1445 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1446 ID2D1GeometrySink_AddLine(sink, point);
1447 ID2D1GeometrySink_Release(sink);
1448 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1449 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1450 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1451 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1452 ID2D1PathGeometry_Release(geometry);
1454 /* Empty figure. */
1455 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1456 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1457 hr = ID2D1PathGeometry_Open(geometry, &sink);
1458 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1459 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1460 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1461 hr = ID2D1GeometrySink_Close(sink);
1462 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1463 ID2D1GeometrySink_Release(sink);
1464 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1465 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1466 ok(count == 1, "Got unexpected figure count %u.\n", count);
1467 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1468 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1469 ok(count == 1, "Got unexpected segment count %u.\n", count);
1470 ID2D1PathGeometry_Release(geometry);
1472 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1473 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1474 hr = ID2D1PathGeometry_Open(geometry, &sink);
1475 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1476 /* The fillmode that's used is the last one set before the sink is closed. */
1477 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
1478 fill_geometry_sink(sink);
1479 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
1480 hr = ID2D1GeometrySink_Close(sink);
1481 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1482 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1483 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1484 ok(count == 6, "Got unexpected figure count %u.\n", count);
1485 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1486 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1487 /* Intersections don't create extra segments. */
1488 ok(count == 44, "Got unexpected segment count %u.\n", count);
1489 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
1490 ID2D1GeometrySink_Release(sink);
1492 set_matrix_identity(&matrix);
1493 translate_matrix(&matrix, 80.0f, 640.0f);
1494 scale_matrix(&matrix, 1.0f, -1.0f);
1495 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
1496 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
1498 ID2D1TransformedGeometry_GetSourceGeometry(transformed_geometry, &tmp_geometry);
1499 ok(tmp_geometry == (ID2D1Geometry *)geometry,
1500 "Got unexpected source geometry %p, expected %p.\n", tmp_geometry, geometry);
1501 ID2D1Geometry_Release(tmp_geometry);
1502 ID2D1TransformedGeometry_GetTransform(transformed_geometry, &tmp_matrix);
1503 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1504 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1505 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1506 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1508 ID2D1RenderTarget_BeginDraw(rt);
1509 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
1510 ID2D1RenderTarget_Clear(rt, &color);
1511 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1512 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1513 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1514 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1515 match = compare_surface(surface, "3aace1b22aae111cb577614fed16e4eb1650dba5");
1516 ok(match, "Surface does not match.\n");
1517 ID2D1TransformedGeometry_Release(transformed_geometry);
1518 ID2D1PathGeometry_Release(geometry);
1520 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1521 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1522 hr = ID2D1PathGeometry_Open(geometry, &sink);
1523 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1524 fill_geometry_sink(sink);
1525 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
1526 hr = ID2D1GeometrySink_Close(sink);
1527 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1528 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1529 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1530 ok(count == 6, "Got unexpected figure count %u.\n", count);
1531 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1532 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1533 ok(count == 44, "Got unexpected segment count %u.\n", count);
1534 ID2D1GeometrySink_Release(sink);
1536 set_matrix_identity(&matrix);
1537 translate_matrix(&matrix, 320.0f, 320.0f);
1538 scale_matrix(&matrix, -1.0f, 1.0f);
1539 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
1540 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
1542 ID2D1RenderTarget_BeginDraw(rt);
1543 ID2D1RenderTarget_Clear(rt, &color);
1544 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1545 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1546 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1547 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1548 match = compare_surface(surface, "bfb40a1f007694fa07dbd3b854f3f5d9c3e1d76b");
1549 ok(match, "Surface does not match.\n");
1550 ID2D1TransformedGeometry_Release(transformed_geometry);
1551 ID2D1PathGeometry_Release(geometry);
1553 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1554 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1555 hr = ID2D1PathGeometry_Open(geometry, &sink);
1556 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1557 fill_geometry_sink_bezier(sink);
1558 hr = ID2D1GeometrySink_Close(sink);
1559 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1560 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1561 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1562 ok(count == 2, "Got unexpected figure count %u.\n", count);
1563 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1564 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1565 ok(count == 10, "Got unexpected segment count %u.\n", count);
1566 ID2D1GeometrySink_Release(sink);
1568 set_matrix_identity(&matrix);
1569 scale_matrix(&matrix, 0.5f, 2.0f);
1570 translate_matrix(&matrix, 240.0f, -33.0f);
1571 rotate_matrix(&matrix, M_PI / 4.0f);
1572 scale_matrix(&matrix, 2.0f, 0.5f);
1573 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
1574 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
1576 ID2D1RenderTarget_BeginDraw(rt);
1577 ID2D1RenderTarget_Clear(rt, &color);
1578 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1579 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1580 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1581 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1582 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
1583 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
1584 "lAEECASLAQgKCIEBDQoMew8KD3YQDBByEgwSbhMOEmwUDhRpFBAUZxUQFWUVEhVjFhIWYRYUFl8X"
1585 "FBddFxYWXRYYFlsXGBdaFhoWWRYcFlgVHhVXFSAVVhQiFFUUIxRVEyYTVBIoElQRKhFUECwQUxAu"
1586 "EFIOMg5SDTQNUgs4C1IJPAlRCEAIUAZEBlAESARQAU4BTgJQAkgGUAY/C1ALMhNQEyoTUBMyC1AL"
1587 "PwZQBkgCUAJOAU4BUARIBFAGRAZQCEAIUQk8CVILOAtSDTQNUg4yDlIQLhBTECwQVBEqEVQSKBJU"
1588 "EyYTVBQjFFYUIhRWFSAVVxUeFVgWHBZZFhoWWhcYF1sWGBZcFxYWXhcUF18WFBZhFhIWYxUSFWUV"
1589 "EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
1590 "BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
1591 todo_wine ok(match, "Figure does not match.\n");
1592 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
1593 "4VIBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQEjDCMB7AECHhQeAu0BAxoYGgPvAQMWHhYD8QEDFCAU"
1594 "A/MBBBAkEAT0AQUOJw0F9QEGCioKBvcBBggsCAb4AQgFLgUI+QEJATIBCfsBCAIwAgj8AQcFLAUH"
1595 "/QEFCCgIBf4BBAwiDAT/AQIQHBAClwISlwIBPgGAAgI8Av8BAzwD/QEEPAT7AQY6BvkBBzoH+AEI"
1596 "OAj3AQk4CfYBCTgK9AELNgvzAQw2DPIBDDYM8QEONA7wAQ40DvABDjQO7wEPNA/uAQ80D+4BEDIQ"
1597 "7QERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewB"
1598 "ETIR7AERMhHsAREyEe0BEDIQ7gEQMw/uAQ80D+4BDzQP7wEONA7wAQ40DvEBDDYM8gEMNgzzAQs2"
1599 "C/QBCzcK9QEJOAn3AQg4CfcBBzoH+QEGOgb7AQU6BfwBBDwE/QEDPAP/AQE+AZkCDpkCAhIYEgKA"
1600 "AgMNIA0D/wEFCSYJBf4BBgYqBgf8AQgDLgMI+wFG+gEIAzADCPkBBwYuBgf3AQYKKgoG9gEFDCgM"
1601 "BfUBBBAlDwTzAQQSIhIE8QEDFh4WA/ABAhkaGQLvAQIcFhwC7QECIBAgAusBASgEKAHpAQFWAecB"
1602 "AVgB5QEBWgHAAgEA");
1603 todo_wine ok(match, "Figure does not match.\n");
1604 ID2D1TransformedGeometry_Release(transformed_geometry);
1605 ID2D1PathGeometry_Release(geometry);
1607 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1608 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1609 hr = ID2D1PathGeometry_Open(geometry, &sink);
1610 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1611 fill_geometry_sink_bezier(sink);
1612 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
1613 hr = ID2D1GeometrySink_Close(sink);
1614 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1615 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1616 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1617 ok(count == 2, "Got unexpected figure count %u.\n", count);
1618 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1619 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1620 ok(count == 10, "Got unexpected segment count %u.\n", count);
1621 ID2D1GeometrySink_Release(sink);
1623 set_matrix_identity(&matrix);
1624 scale_matrix(&matrix, 0.5f, 2.0f);
1625 translate_matrix(&matrix, 127.0f, 80.0f);
1626 rotate_matrix(&matrix, M_PI / -4.0f);
1627 scale_matrix(&matrix, 2.0f, 0.5f);
1628 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
1629 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
1631 ID2D1RenderTarget_BeginDraw(rt);
1632 ID2D1RenderTarget_Clear(rt, &color);
1633 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1634 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1635 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1636 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1637 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
1638 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
1639 "lAEQiwEagQEjeyh2LHIwbjNsNmk4ZzplPGM+YUBfQl1DXURbRlpGWUhYSFdKVkpVS1VMVExUTFRM"
1640 "U05STlJOUk5STlFQUFBQUFBQTlRIXD9mMnYqdjJmP1xIVE5QUFBQUFBQUU5STlJOUk5STlNMVExU"
1641 "TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
1642 "mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
1643 ok(match, "Figure does not match.\n");
1644 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
1645 "4VIBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQIhDiIB7QECHRUdAu4BAhkaGQPvAQMWHhYD8QEEEyET"
1646 "A/MBBBAkEAT1AQUMKA0F9QEGCioKBvcBBwctBwb5AQgELwQI+QEJATIBCfsBRP0BQ/0BQv8BQf8B"
1647 "QIECP4ACQIACQf4BQ/wBRPsBRvoBR/gBSPcBSvYBS/QBTPMBTvIBTvIBT/ABUPABUe4BUu4BUu4B"
1648 "U+0BU+wBVOwBVOwBVOwBVOwBVesBVesBVesBVesBVOwBVOwBVOwBVO0BU+0BU+0BUu4BUu8BUe8B"
1649 "UPEBT/EBTvIBTvMBTPUBS/UBSvcBSfcBSPkBRvsBRP0BQ/4BQf8BQIECP4ACQIACQf4BQv4BQ/wB"
1650 "RPsBCQEyAQn6AQgELwQI+AEHBy0GB/cBBgoqCgb2AQUMKA0F9AEEECUPBPMBBBIiEwPxAQMWHhYD"
1651 "8AECGRoZA+4BAh0VHQLsAQIhDiIB6wEBVAHpAQFWAecBAVgB5QEBWgHAAgEA");
1652 ok(match, "Figure does not match.\n");
1653 ID2D1TransformedGeometry_Release(transformed_geometry);
1654 ID2D1PathGeometry_Release(geometry);
1656 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1657 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1658 hr = ID2D1PathGeometry_Open(geometry, &sink);
1659 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1661 set_point(&point, 40.0f, 20.0f);
1662 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1663 set_point(&point, 75.0f, 300.0f);
1664 ID2D1GeometrySink_AddLine(sink, point);
1665 set_point(&point, 5.0f, 300.0f);
1666 ID2D1GeometrySink_AddLine(sink, point);
1667 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1669 set_point(&point, 40.0f, 290.0f);
1670 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1671 set_point(&point, 55.0f, 160.0f);
1672 ID2D1GeometrySink_AddLine(sink, point);
1673 set_point(&point, 25.0f, 160.0f);
1674 ID2D1GeometrySink_AddLine(sink, point);
1675 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1677 hr = ID2D1GeometrySink_Close(sink);
1678 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1679 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1680 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1681 ok(count == 2, "Got unexpected figure count %u.\n", count);
1682 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1683 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1684 ok(count == 6, "Got unexpected segment count %u.\n", count);
1685 ID2D1GeometrySink_Release(sink);
1687 ID2D1RenderTarget_BeginDraw(rt);
1688 ID2D1RenderTarget_Clear(rt, &color);
1689 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1690 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1691 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1692 match = compare_surface(surface, "a875e68e0cb9c055927b1b50b879f90b24e38470");
1693 ok(match, "Surface does not match.\n");
1694 ID2D1PathGeometry_Release(geometry);
1696 ID2D1SolidColorBrush_Release(brush);
1697 ID2D1RenderTarget_Release(rt);
1698 refcount = ID2D1Factory_Release(factory);
1699 ok(!refcount, "Factory has %u references left.\n", refcount);
1700 IDXGISurface_Release(surface);
1701 IDXGISwapChain_Release(swapchain);
1702 ID3D10Device1_Release(device);
1703 DestroyWindow(window);
1706 static void test_bitmap_formats(void)
1708 D2D1_BITMAP_PROPERTIES bitmap_desc;
1709 IDXGISwapChain *swapchain;
1710 D2D1_SIZE_U size = {4, 4};
1711 ID2D1RenderTarget *rt;
1712 ID3D10Device1 *device;
1713 IDXGISurface *surface;
1714 ID2D1Bitmap *bitmap;
1715 unsigned int i, j;
1716 HWND window;
1717 HRESULT hr;
1719 static const struct
1721 DXGI_FORMAT format;
1722 DWORD mask;
1724 bitmap_formats[] =
1726 {DXGI_FORMAT_R32G32B32A32_FLOAT, 0x8a},
1727 {DXGI_FORMAT_R16G16B16A16_FLOAT, 0x8a},
1728 {DXGI_FORMAT_R16G16B16A16_UNORM, 0x8a},
1729 {DXGI_FORMAT_R8G8B8A8_TYPELESS, 0x00},
1730 {DXGI_FORMAT_R8G8B8A8_UNORM, 0x0a},
1731 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0x8a},
1732 {DXGI_FORMAT_R8G8B8A8_UINT, 0x00},
1733 {DXGI_FORMAT_R8G8B8A8_SNORM, 0x00},
1734 {DXGI_FORMAT_R8G8B8A8_SINT, 0x00},
1735 {DXGI_FORMAT_A8_UNORM, 0x06},
1736 {DXGI_FORMAT_B8G8R8A8_UNORM, 0x0a},
1737 {DXGI_FORMAT_B8G8R8X8_UNORM, 0x88},
1738 {DXGI_FORMAT_B8G8R8A8_TYPELESS, 0x00},
1739 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, 0x8a},
1742 if (!(device = create_device()))
1744 skip("Failed to create device, skipping tests.\n");
1745 return;
1747 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1748 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1749 swapchain = create_swapchain(device, window, TRUE);
1750 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1751 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1752 rt = create_render_target(surface);
1753 ok(!!rt, "Failed to create render target.\n");
1755 bitmap_desc.dpiX = 96.0f;
1756 bitmap_desc.dpiY = 96.0f;
1757 for (i = 0; i < sizeof(bitmap_formats) / sizeof(*bitmap_formats); ++i)
1759 for (j = 0; j < 4; ++j)
1761 if ((bitmap_formats[i].mask & (0x80 | (1u << j))) == (0x80 | (1u << j)))
1762 continue;
1764 bitmap_desc.pixelFormat.format = bitmap_formats[i].format;
1765 bitmap_desc.pixelFormat.alphaMode = j;
1766 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
1767 if (bitmap_formats[i].mask & (1u << j))
1768 ok(hr == S_OK, "Got unexpected hr %#x, for format %#x/%#x.\n",
1769 hr, bitmap_formats[i].format, j);
1770 else
1771 ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "Got unexpected hr %#x, for format %#x/%#x.\n",
1772 hr, bitmap_formats[i].format, j);
1773 if (SUCCEEDED(hr))
1774 ID2D1Bitmap_Release(bitmap);
1778 ID2D1RenderTarget_Release(rt);
1779 IDXGISurface_Release(surface);
1780 IDXGISwapChain_Release(swapchain);
1781 ID3D10Device1_Release(device);
1782 DestroyWindow(window);
1785 static void test_alpha_mode(void)
1787 D2D1_RENDER_TARGET_PROPERTIES rt_desc;
1788 D2D1_BITMAP_PROPERTIES bitmap_desc;
1789 ID2D1SolidColorBrush *color_brush;
1790 ID2D1BitmapBrush *bitmap_brush;
1791 IDXGISwapChain *swapchain;
1792 ID2D1RenderTarget *rt;
1793 ID3D10Device1 *device;
1794 IDXGISurface *surface;
1795 ID2D1Bitmap *bitmap;
1796 D2D1_COLOR_F color;
1797 D2D1_RECT_F rect;
1798 D2D1_SIZE_U size;
1799 ULONG refcount;
1800 HWND window;
1801 HRESULT hr;
1802 BOOL match;
1804 static const DWORD bitmap_data[] =
1806 0x7f7f0000, 0x7f7f7f00, 0x7f007f00, 0x7f007f7f,
1807 0x7f00007f, 0x7f7f007f, 0x7f000000, 0x7f404040,
1808 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f000000,
1809 0x7f7f7f7f, 0x7f000000, 0x7f000000, 0x7f000000,
1812 if (!(device = create_device()))
1814 skip("Failed to create device, skipping tests.\n");
1815 return;
1817 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1818 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1819 swapchain = create_swapchain(device, window, TRUE);
1820 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1821 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1822 rt = create_render_target(surface);
1823 ok(!!rt, "Failed to create render target.\n");
1825 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1827 set_size_u(&size, 4, 4);
1828 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
1829 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1830 bitmap_desc.dpiX = 96.0f / 40.0f;
1831 bitmap_desc.dpiY = 96.0f / 30.0f;
1832 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1833 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1835 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
1836 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1837 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
1838 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
1839 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
1841 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
1842 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
1843 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1845 ID2D1RenderTarget_BeginDraw(rt);
1846 ID2D1RenderTarget_Clear(rt, NULL);
1847 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1848 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1849 match = compare_surface(surface, "48c41aff3a130a17ee210866b2ab7d36763934d5");
1850 ok(match, "Surface does not match.\n");
1852 ID2D1RenderTarget_BeginDraw(rt);
1853 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
1854 ID2D1RenderTarget_Clear(rt, &color);
1855 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1856 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1857 match = compare_surface(surface, "6487e683730fb5a77c1911388d00b04664c5c4e4");
1858 ok(match, "Surface does not match.\n");
1860 ID2D1RenderTarget_BeginDraw(rt);
1861 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
1862 ID2D1RenderTarget_Clear(rt, &color);
1863 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1864 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1865 match = compare_surface(surface, "7a35ba09e43cbaf591388ff1ef8de56157630c98");
1866 ok(match, "Surface does not match.\n");
1868 ID2D1RenderTarget_BeginDraw(rt);
1870 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
1871 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1872 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
1873 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
1874 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1875 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
1876 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
1877 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1879 ID2D1Bitmap_Release(bitmap);
1880 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1881 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1882 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1883 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
1885 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
1886 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
1887 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1888 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
1889 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
1890 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1891 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
1892 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
1893 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1895 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
1896 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1897 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
1898 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
1899 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1900 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
1901 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
1902 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1904 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1905 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1906 match = compare_surface(surface, "14f8ac64b70966c7c3c6281c59aaecdb17c3b16a");
1907 ok(match, "Surface does not match.\n");
1909 ID2D1RenderTarget_Release(rt);
1910 rt_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
1911 rt_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
1912 rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1913 rt_desc.dpiX = 0.0f;
1914 rt_desc.dpiY = 0.0f;
1915 rt_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
1916 rt_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
1917 rt = create_render_target_desc(surface, &rt_desc);
1918 ok(!!rt, "Failed to create render target.\n");
1920 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1922 ID2D1Bitmap_Release(bitmap);
1923 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1924 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1925 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1926 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
1928 ID2D1BitmapBrush_Release(bitmap_brush);
1929 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
1930 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1931 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
1932 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
1933 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
1935 ID2D1SolidColorBrush_Release(color_brush);
1936 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
1937 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
1938 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1940 ID2D1RenderTarget_BeginDraw(rt);
1941 ID2D1RenderTarget_Clear(rt, NULL);
1942 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1943 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1944 match = compare_surface(surface, "b44510bf2d2e61a8d7c0ad862de49a471f1fd13f");
1945 ok(match, "Surface does not match.\n");
1947 ID2D1RenderTarget_BeginDraw(rt);
1948 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
1949 ID2D1RenderTarget_Clear(rt, &color);
1950 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1951 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1952 match = compare_surface(surface, "2184f4a9198fc1de09ac85301b7a03eebadd9b81");
1953 ok(match, "Surface does not match.\n");
1955 ID2D1RenderTarget_BeginDraw(rt);
1956 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
1957 ID2D1RenderTarget_Clear(rt, &color);
1958 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1959 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1960 match = compare_surface(surface, "6527ec83b4039c895b50f9b3e144fe0cf90d1889");
1961 ok(match, "Surface does not match.\n");
1963 ID2D1RenderTarget_BeginDraw(rt);
1965 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
1966 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1967 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
1968 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
1969 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1970 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
1971 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
1972 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1974 ID2D1Bitmap_Release(bitmap);
1975 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1976 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1977 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1978 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
1980 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
1981 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
1982 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1983 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
1984 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
1985 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1986 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
1987 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
1988 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
1990 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
1991 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1992 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
1993 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
1994 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1995 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
1996 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
1997 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
1999 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2000 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2001 match = compare_surface(surface, "465f5a3190d7bde408b3206b4be939fb22f8a3d6");
2002 ok(match, "Surface does not match.\n");
2004 refcount = ID2D1Bitmap_Release(bitmap);
2005 ok(refcount == 1, "Bitmap has %u references left.\n", refcount);
2006 ID2D1SolidColorBrush_Release(color_brush);
2007 ID2D1BitmapBrush_Release(bitmap_brush);
2008 ID2D1RenderTarget_Release(rt);
2009 IDXGISurface_Release(surface);
2010 IDXGISwapChain_Release(swapchain);
2011 ID3D10Device1_Release(device);
2012 DestroyWindow(window);
2015 static void test_shared_bitmap(void)
2017 IDXGISwapChain *swapchain1, *swapchain2;
2018 IWICBitmap *wic_bitmap1, *wic_bitmap2;
2019 D2D1_RENDER_TARGET_PROPERTIES desc;
2020 D2D1_BITMAP_PROPERTIES bitmap_desc;
2021 IDXGISurface *surface1, *surface2;
2022 ID2D1Factory *factory1, *factory2;
2023 ID3D10Device1 *device1, *device2;
2024 IWICImagingFactory *wic_factory;
2025 ID2D1Bitmap *bitmap1, *bitmap2;
2026 ID2D1RenderTarget *rt1, *rt2;
2027 D2D1_SIZE_U size = {4, 4};
2028 HWND window1, window2;
2029 HRESULT hr;
2031 if (!(device1 = create_device()))
2033 skip("Failed to create device, skipping tests.\n");
2034 return;
2037 window1 = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2038 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2039 window2 = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2040 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2041 swapchain1 = create_swapchain(device1, window1, TRUE);
2042 swapchain2 = create_swapchain(device1, window2, TRUE);
2043 hr = IDXGISwapChain_GetBuffer(swapchain1, 0, &IID_IDXGISurface, (void **)&surface1);
2044 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2045 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
2046 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2048 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2049 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
2050 &IID_IWICImagingFactory, (void **)&wic_factory);
2051 ok(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
2052 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
2053 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap1);
2054 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2055 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
2056 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap2);
2057 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2058 IWICImagingFactory_Release(wic_factory);
2060 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
2061 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
2062 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2063 desc.dpiX = 0.0f;
2064 desc.dpiY = 0.0f;
2065 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
2066 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
2068 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2069 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2070 bitmap_desc.dpiX = 96.0f;
2071 bitmap_desc.dpiY = 96.0f;
2073 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory1);
2074 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2075 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
2076 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2078 /* DXGI surface render targets with the same device and factory. */
2079 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface1, &desc, &rt1);
2080 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2081 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
2082 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2084 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
2085 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2086 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2087 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2088 ID2D1Bitmap_Release(bitmap2);
2089 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IUnknown, bitmap1, NULL, &bitmap2);
2090 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2091 ID2D1RenderTarget_Release(rt2);
2093 /* DXGI surface render targets with the same device but different factories. */
2094 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
2095 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2096 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2097 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
2098 ID2D1RenderTarget_Release(rt2);
2100 /* DXGI surface render targets with different devices but the same factory. */
2101 IDXGISurface_Release(surface2);
2102 IDXGISwapChain_Release(swapchain2);
2103 device2 = create_device();
2104 ok(!!device2, "Failed to create device.\n");
2105 swapchain2 = create_swapchain(device2, window2, TRUE);
2106 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
2107 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2109 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
2110 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2111 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2112 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
2113 ID2D1RenderTarget_Release(rt2);
2115 /* DXGI surface render targets with different devices and different factories. */
2116 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
2117 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2118 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2119 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
2120 ID2D1RenderTarget_Release(rt2);
2122 /* DXGI surface render target and WIC bitmap render target, same factory. */
2123 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
2124 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2125 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2126 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
2127 ID2D1RenderTarget_Release(rt2);
2129 /* WIC bitmap render targets on different D2D factories. */
2130 ID2D1Bitmap_Release(bitmap1);
2131 ID2D1RenderTarget_Release(rt1);
2132 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap1, &desc, &rt1);
2133 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2134 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
2135 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2137 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory2, wic_bitmap2, &desc, &rt2);
2138 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2139 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2140 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
2141 ID2D1RenderTarget_Release(rt2);
2143 /* WIC bitmap render targets on the same D2D factory. */
2144 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
2145 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2146 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2147 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2148 ID2D1Bitmap_Release(bitmap2);
2149 ID2D1RenderTarget_Release(rt2);
2151 ID2D1Bitmap_Release(bitmap1);
2152 ID2D1RenderTarget_Release(rt1);
2153 ID2D1Factory_Release(factory2);
2154 ID2D1Factory_Release(factory1);
2155 IWICBitmap_Release(wic_bitmap2);
2156 IWICBitmap_Release(wic_bitmap1);
2157 IDXGISurface_Release(surface2);
2158 IDXGISurface_Release(surface1);
2159 IDXGISwapChain_Release(swapchain2);
2160 IDXGISwapChain_Release(swapchain1);
2161 ID3D10Device1_Release(device2);
2162 ID3D10Device1_Release(device1);
2163 DestroyWindow(window2);
2164 DestroyWindow(window1);
2165 CoUninitialize();
2168 static void test_bitmap_updates(void)
2170 D2D1_BITMAP_PROPERTIES bitmap_desc;
2171 IDXGISwapChain *swapchain;
2172 ID2D1RenderTarget *rt;
2173 ID3D10Device1 *device;
2174 IDXGISurface *surface;
2175 D2D1_RECT_U dst_rect;
2176 ID2D1Bitmap *bitmap;
2177 D2D1_COLOR_F color;
2178 D2D1_RECT_F rect;
2179 D2D1_SIZE_U size;
2180 HWND window;
2181 HRESULT hr;
2182 BOOL match;
2184 static const DWORD bitmap_data[] =
2186 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
2187 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
2188 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
2189 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
2192 if (!(device = create_device()))
2194 skip("Failed to create device, skipping tests.\n");
2195 return;
2197 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2198 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2199 swapchain = create_swapchain(device, window, TRUE);
2200 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2201 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2202 rt = create_render_target(surface);
2203 ok(!!rt, "Failed to create render target.\n");
2205 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2207 ID2D1RenderTarget_BeginDraw(rt);
2208 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
2209 ID2D1RenderTarget_Clear(rt, &color);
2211 set_size_u(&size, 4, 4);
2212 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2213 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2214 bitmap_desc.dpiX = 96.0f;
2215 bitmap_desc.dpiY = 96.0f;
2216 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
2217 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2219 set_rect(&rect, 0.0f, 0.0f, 320.0f, 240.0f);
2220 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2221 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2223 ID2D1Bitmap_Release(bitmap);
2225 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
2226 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
2227 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2229 set_rect(&rect, 0.0f, 240.0f, 320.0f, 480.0f);
2230 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2231 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2233 set_rect_u(&dst_rect, 1, 1, 3, 3);
2234 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, 4 * sizeof(*bitmap_data));
2235 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2236 set_rect_u(&dst_rect, 0, 3, 3, 4);
2237 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[6], 4 * sizeof(*bitmap_data));
2238 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2239 set_rect_u(&dst_rect, 0, 0, 4, 1);
2240 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[10], 4 * sizeof(*bitmap_data));
2241 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2242 set_rect_u(&dst_rect, 0, 1, 1, 3);
2243 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[2], sizeof(*bitmap_data));
2244 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2245 set_rect_u(&dst_rect, 4, 4, 3, 1);
2246 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, sizeof(*bitmap_data));
2247 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2248 set_rect(&rect, 320.0f, 240.0f, 640.0f, 480.0f);
2249 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2250 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2252 hr = ID2D1Bitmap_CopyFromMemory(bitmap, NULL, bitmap_data, 4 * sizeof(*bitmap_data));
2253 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2254 set_rect(&rect, 320.0f, 0.0f, 640.0f, 240.0f);
2255 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2256 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2258 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2259 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2261 match = compare_surface(surface, "cb8136c91fbbdc76bb83b8c09edc1907b0a5d0a6");
2262 ok(match, "Surface does not match.\n");
2264 ID2D1Bitmap_Release(bitmap);
2265 ID2D1RenderTarget_Release(rt);
2266 IDXGISurface_Release(surface);
2267 IDXGISwapChain_Release(swapchain);
2268 ID3D10Device1_Release(device);
2269 DestroyWindow(window);
2272 static void test_opacity_brush(void)
2274 ID2D1BitmapBrush *bitmap_brush, *opacity_brush;
2275 D2D1_BITMAP_PROPERTIES bitmap_desc;
2276 ID2D1RectangleGeometry *geometry;
2277 ID2D1SolidColorBrush *color_brush;
2278 IDXGISwapChain *swapchain;
2279 D2D1_MATRIX_3X2_F matrix;
2280 ID2D1RenderTarget *rt;
2281 ID3D10Device1 *device;
2282 IDXGISurface *surface;
2283 ID2D1Factory *factory;
2284 ID2D1Bitmap *bitmap;
2285 D2D1_COLOR_F color;
2286 D2D1_RECT_F rect;
2287 D2D1_SIZE_U size;
2288 ULONG refcount;
2289 HWND window;
2290 HRESULT hr;
2291 BOOL match;
2293 static const DWORD bitmap_data[] =
2295 0xffff0000, 0x40ffff00, 0x4000ff00, 0xff00ffff,
2296 0x7f0000ff, 0x00ff00ff, 0x00000000, 0x7f7f7f7f,
2297 0x7fffffff, 0x00ffffff, 0x00ffffff, 0x7f000000,
2298 0xffffffff, 0x40000000, 0x40000000, 0xff000000,
2301 if (!(device = create_device()))
2303 skip("Failed to create device, skipping tests.\n");
2304 return;
2306 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2307 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2308 swapchain = create_swapchain(device, window, TRUE);
2309 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2310 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2311 rt = create_render_target(surface);
2312 ok(!!rt, "Failed to create render target.\n");
2313 ID2D1RenderTarget_GetFactory(rt, &factory);
2315 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
2316 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2318 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
2319 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
2320 ok(SUCCEEDED(hr), "Failed to create color brush, hr %#x.\n", hr);
2322 set_size_u(&size, 4, 4);
2323 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2324 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2325 bitmap_desc.dpiX = 96.0f;
2326 bitmap_desc.dpiY = 96.0f;
2327 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
2328 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2329 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &opacity_brush);
2330 ok(SUCCEEDED(hr), "Failed to create bitmap brush, hr %#x.\n", hr);
2331 ID2D1BitmapBrush_SetInterpolationMode(opacity_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
2332 refcount = ID2D1Bitmap_Release(bitmap);
2333 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
2335 set_size_u(&size, 1, 1);
2336 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2337 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
2338 bitmap_desc.dpiX = 96.0f;
2339 bitmap_desc.dpiY = 96.0f;
2340 hr = ID2D1RenderTarget_CreateBitmap(rt, size, &bitmap_data[2], sizeof(*bitmap_data), &bitmap_desc, &bitmap);
2341 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2342 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
2343 ok(SUCCEEDED(hr), "Failed to create bitmap brush, hr %#x.\n", hr);
2344 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
2345 refcount = ID2D1Bitmap_Release(bitmap);
2346 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
2348 ID2D1RenderTarget_BeginDraw(rt);
2350 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
2351 ID2D1RenderTarget_Clear(rt, &color);
2353 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
2354 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
2356 set_matrix_identity(&matrix);
2357 translate_matrix(&matrix, 120.0f, 120.0f);
2358 scale_matrix(&matrix, 20.0f, 60.0f);
2359 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2360 set_rect(&rect, 120.0f, 120.0f, 200.0f, 360.0f);
2361 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)opacity_brush);
2363 set_rect(&rect, 200.0f, 120.0f, 280.0f, 360.0f);
2364 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2366 set_matrix_identity(&matrix);
2367 translate_matrix(&matrix, 40.0f, 360.0f);
2368 scale_matrix(&matrix, 20.0f, 60.0f);
2369 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2370 set_rect(&rect, 40.0f, 360.0f, 120.0f, 600.0f);
2371 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2372 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2373 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
2374 ID2D1RectangleGeometry_Release(geometry);
2376 set_matrix_identity(&matrix);
2377 translate_matrix(&matrix, 120.0f, 360.0f);
2378 scale_matrix(&matrix, 20.0f, 60.0f);
2379 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2380 set_rect(&rect, 120.0f, 360.0f, 200.0f, 600.0f);
2381 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2382 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2383 (ID2D1Brush *)color_brush, (ID2D1Brush *)opacity_brush);
2384 ID2D1RectangleGeometry_Release(geometry);
2386 set_matrix_identity(&matrix);
2387 translate_matrix(&matrix, 200.0f, 360.0f);
2388 scale_matrix(&matrix, 20.0f, 60.0f);
2389 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2390 set_rect(&rect, 200.0f, 360.0f, 280.0f, 600.0f);
2391 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2392 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2393 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
2395 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2396 ok(hr == D2DERR_INCOMPATIBLE_BRUSH_TYPES, "Got unexpected hr %#x.\n", hr);
2397 match = compare_surface(surface, "7141c6c7b3decb91196428efb1856bcbf9872935");
2398 ok(match, "Surface does not match.\n");
2399 ID2D1RenderTarget_BeginDraw(rt);
2401 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2402 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
2403 ID2D1RectangleGeometry_Release(geometry);
2405 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.5f);
2406 set_matrix_identity(&matrix);
2407 translate_matrix(&matrix, 40.0f, 600.0f);
2408 scale_matrix(&matrix, 20.0f, 60.0f);
2409 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2410 set_rect(&rect, 40.0f, 600.0f, 120.0f, 840.0f);
2411 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2412 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2413 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
2414 ID2D1RectangleGeometry_Release(geometry);
2416 ID2D1BitmapBrush_SetOpacity(opacity_brush, 0.8f);
2417 set_matrix_identity(&matrix);
2418 translate_matrix(&matrix, 120.0f, 600.0f);
2419 scale_matrix(&matrix, 20.0f, 60.0f);
2420 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2421 set_rect(&rect, 120.0f, 600.0f, 200.0f, 840.0f);
2422 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2423 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2424 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)bitmap_brush);
2425 ID2D1RectangleGeometry_Release(geometry);
2427 set_matrix_identity(&matrix);
2428 translate_matrix(&matrix, 200.0f, 600.0f);
2429 scale_matrix(&matrix, 20.0f, 60.0f);
2430 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2431 set_rect(&rect, 200.0f, 600.0f, 280.0f, 840.0f);
2432 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2433 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2434 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
2435 ID2D1RectangleGeometry_Release(geometry);
2437 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2438 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2439 match = compare_surface(surface, "c3a5802d1750efa3e9122c1a92f6064df3872732");
2440 ok(match, "Surface does not match.\n");
2442 ID2D1BitmapBrush_Release(bitmap_brush);
2443 ID2D1BitmapBrush_Release(opacity_brush);
2444 ID2D1SolidColorBrush_Release(color_brush);
2445 ID2D1RenderTarget_Release(rt);
2446 refcount = ID2D1Factory_Release(factory);
2447 ok(!refcount, "Factory has %u references left.\n", refcount);
2448 IDXGISurface_Release(surface);
2449 IDXGISwapChain_Release(swapchain);
2450 ID3D10Device1_Release(device);
2451 DestroyWindow(window);
2454 static void test_create_target(void)
2456 IDXGISwapChain *swapchain;
2457 ID2D1Factory *factory;
2458 ID2D1RenderTarget *rt;
2459 ID3D10Device1 *device;
2460 IDXGISurface *surface;
2461 HWND window;
2462 HRESULT hr;
2463 static const struct
2465 float dpi_x, dpi_y;
2466 float rt_dpi_x, rt_dpi_y;
2467 HRESULT hr;
2469 create_dpi_tests[] =
2471 { 0.0f, 0.0f, 96.0f, 96.0f, S_OK },
2472 { 192.0f, 0.0f, 96.0f, 96.0f, E_INVALIDARG },
2473 { 0.0f, 192.0f, 96.0f, 96.0f, E_INVALIDARG },
2474 { 192.0f, -10.0f, 96.0f, 96.0f, E_INVALIDARG },
2475 { -10.0f, 192.0f, 96.0f, 96.0f, E_INVALIDARG },
2476 { 48.0f, 96.0f, 48.0f, 96.0f, S_OK },
2478 unsigned int i;
2480 if (!(device = create_device()))
2482 skip("Failed to create device, skipping tests.\n");
2483 return;
2485 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2486 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2487 swapchain = create_swapchain(device, window, TRUE);
2488 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2489 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2491 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
2492 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2494 for (i = 0; i < sizeof(create_dpi_tests) / sizeof(*create_dpi_tests); ++i)
2496 D2D1_RENDER_TARGET_PROPERTIES desc;
2497 float dpi_x, dpi_y;
2499 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
2500 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
2501 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2502 desc.dpiX = create_dpi_tests[i].dpi_x;
2503 desc.dpiY = create_dpi_tests[i].dpi_y;
2504 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
2505 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
2507 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt);
2508 ok(hr == create_dpi_tests[i].hr, "Wrong return code, hr %#x, expected %#x, test %u.\n", hr,
2509 create_dpi_tests[i].hr, i);
2511 if (FAILED(hr))
2512 continue;
2514 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
2515 ok(dpi_x == create_dpi_tests[i].rt_dpi_x, "Wrong dpi_x %.8e, expected %.8e, test %u\n",
2516 dpi_x, create_dpi_tests[i].rt_dpi_x, i);
2517 ok(dpi_y == create_dpi_tests[i].rt_dpi_y, "Wrong dpi_y %.8e, expected %.8e, test %u\n",
2518 dpi_y, create_dpi_tests[i].rt_dpi_y, i);
2520 ID2D1RenderTarget_Release(rt);
2523 ID2D1Factory_Release(factory);
2524 IDXGISurface_Release(surface);
2525 IDXGISwapChain_Release(swapchain);
2526 ID3D10Device1_Release(device);
2527 DestroyWindow(window);
2530 static void test_draw_text_layout(void)
2532 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
2533 static const WCHAR textW[] = {'t','e','x','t',0};
2534 static const WCHAR emptyW[] = {0};
2535 D2D1_RENDER_TARGET_PROPERTIES desc;
2536 IDXGISwapChain *swapchain;
2537 ID2D1Factory *factory, *factory2;
2538 ID2D1RenderTarget *rt, *rt2;
2539 ID3D10Device1 *device;
2540 IDXGISurface *surface;
2541 HWND window;
2542 HRESULT hr;
2543 IDWriteFactory *dwrite_factory;
2544 IDWriteTextFormat *text_format;
2545 IDWriteTextLayout *text_layout;
2546 D2D1_POINT_2F origin;
2547 DWRITE_TEXT_RANGE range;
2548 D2D1_COLOR_F color;
2549 ID2D1SolidColorBrush *brush, *brush2;
2551 if (!(device = create_device()))
2553 skip("Failed to create device, skipping tests.\n");
2554 return;
2556 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2557 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2558 swapchain = create_swapchain(device, window, TRUE);
2559 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2560 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2562 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
2563 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2565 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
2566 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2567 ok(factory != factory2, "got same factory\n");
2569 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
2570 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
2571 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2572 desc.dpiX = 0.0f;
2573 desc.dpiY = 0.0f;
2574 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
2575 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
2577 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt);
2578 ok(SUCCEEDED(hr), "Failed to create a target, hr %#x.\n", hr);
2580 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface, &desc, &rt2);
2581 ok(SUCCEEDED(hr), "Failed to create a target, hr %#x.\n", hr);
2583 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
2584 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2586 hr = IDWriteFactory_CreateTextFormat(dwrite_factory, tahomaW, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
2587 DWRITE_FONT_STRETCH_NORMAL, 10.0f, emptyW, &text_format);
2588 ok(SUCCEEDED(hr), "Failed to create text format, hr %#x.\n", hr);
2590 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, textW, 4, text_format, 100.0f, 100.0f, &text_layout);
2591 ok(SUCCEEDED(hr), "Failed to create text layout, hr %#x.\n", hr);
2593 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
2594 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
2595 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
2597 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt2, &color, NULL, &brush2);
2598 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
2600 /* effect brush is created from different factory */
2601 range.startPosition = 0;
2602 range.length = 4;
2603 hr = IDWriteTextLayout_SetDrawingEffect(text_layout, (IUnknown*)brush2, range);
2604 ok(SUCCEEDED(hr), "Failed to set drawing effect, hr %#x.\n", hr);
2606 ID2D1RenderTarget_BeginDraw(rt);
2608 origin.x = origin.y = 0.0f;
2609 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush*)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
2611 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2612 todo_wine
2613 ok(hr == D2DERR_WRONG_FACTORY, "EndDraw failure expected, hr %#x.\n", hr);
2615 IDWriteTextFormat_Release(text_format);
2616 IDWriteTextLayout_Release(text_layout);
2617 IDWriteFactory_Release(dwrite_factory);
2618 ID2D1RenderTarget_Release(rt);
2619 ID2D1RenderTarget_Release(rt2);
2621 ID2D1Factory_Release(factory);
2622 ID2D1Factory_Release(factory2);
2623 IDXGISurface_Release(surface);
2624 IDXGISwapChain_Release(swapchain);
2625 ID3D10Device1_Release(device);
2626 DestroyWindow(window);
2629 START_TEST(d2d1)
2631 test_clip();
2632 test_state_block();
2633 test_color_brush();
2634 test_bitmap_brush();
2635 test_path_geometry();
2636 test_bitmap_formats();
2637 test_alpha_mode();
2638 test_shared_bitmap();
2639 test_bitmap_updates();
2640 test_opacity_brush();
2641 test_create_target();
2642 test_draw_text_layout();