d2d1: Implement retrieving dash pattern data for stroke styles.
[wine.git] / dlls / d2d1 / tests / d2d1.c
blob7fcda6418a59cde171612d7a3b3d645c754149e8
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 <limits.h>
21 #include <math.h>
22 #include "d2d1.h"
23 #include "wincrypt.h"
24 #include "wine/test.h"
25 #include "initguid.h"
26 #include "dwrite.h"
27 #include "wincodec.h"
29 struct figure
31 unsigned int *spans;
32 unsigned int spans_size;
33 unsigned int span_count;
36 static void set_point(D2D1_POINT_2F *point, float x, float y)
38 point->x = x;
39 point->y = y;
42 static void set_quadratic(D2D1_QUADRATIC_BEZIER_SEGMENT *quadratic, float x1, float y1, float x2, float y2)
44 quadratic->point1.x = x1;
45 quadratic->point1.y = y1;
46 quadratic->point2.x = x2;
47 quadratic->point2.y = y2;
50 static void set_rect(D2D1_RECT_F *rect, float left, float top, float right, float bottom)
52 rect->left = left;
53 rect->top = top;
54 rect->right = right;
55 rect->bottom = bottom;
58 static void set_rounded_rect(D2D1_ROUNDED_RECT *rect, float left, float top, float right, float bottom,
59 float radius_x, float radius_y)
61 set_rect(&rect->rect, left, top, right, bottom);
62 rect->radiusX = radius_x;
63 rect->radiusY = radius_y;
66 static void set_rect_u(D2D1_RECT_U *rect, UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
68 rect->left = left;
69 rect->top = top;
70 rect->right = right;
71 rect->bottom = bottom;
74 static void set_color(D2D1_COLOR_F *color, float r, float g, float b, float a)
76 color->r = r;
77 color->g = g;
78 color->b = b;
79 color->a = a;
82 static void set_size_u(D2D1_SIZE_U *size, unsigned int w, unsigned int h)
84 size->width = w;
85 size->height = h;
88 static void set_size_f(D2D1_SIZE_F *size, float w, float h)
90 size->width = w;
91 size->height = h;
94 static void set_matrix_identity(D2D1_MATRIX_3X2_F *matrix)
96 matrix->_11 = 1.0f;
97 matrix->_12 = 0.0f;
98 matrix->_21 = 0.0f;
99 matrix->_22 = 1.0f;
100 matrix->_31 = 0.0f;
101 matrix->_32 = 0.0f;
104 static void rotate_matrix(D2D1_MATRIX_3X2_F *matrix, float theta)
106 float sin_theta, cos_theta, tmp_11, tmp_12;
108 sin_theta = sinf(theta);
109 cos_theta = cosf(theta);
110 tmp_11 = matrix->_11;
111 tmp_12 = matrix->_12;
113 matrix->_11 = cos_theta * tmp_11 + sin_theta * matrix->_21;
114 matrix->_12 = cos_theta * tmp_12 + sin_theta * matrix->_22;
115 matrix->_21 = -sin_theta * tmp_11 + cos_theta * matrix->_21;
116 matrix->_22 = -sin_theta * tmp_12 + cos_theta * matrix->_22;
119 static void scale_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
121 matrix->_11 *= x;
122 matrix->_12 *= x;
123 matrix->_21 *= y;
124 matrix->_22 *= y;
127 static void translate_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
129 matrix->_31 += x * matrix->_11 + y * matrix->_21;
130 matrix->_32 += x * matrix->_12 + y * matrix->_22;
133 static BOOL compare_float(float f, float g, unsigned int ulps)
135 int x = *(int *)&f;
136 int y = *(int *)&g;
138 if (x < 0)
139 x = INT_MIN - x;
140 if (y < 0)
141 y = INT_MIN - y;
143 if (abs(x - y) > ulps)
144 return FALSE;
146 return TRUE;
149 static BOOL compare_sha1(void *data, unsigned int pitch, unsigned int bpp,
150 unsigned int w, unsigned int h, const char *ref_sha1)
152 static const char hex_chars[] = "0123456789abcdef";
153 HCRYPTPROV provider;
154 BYTE hash_data[20];
155 HCRYPTHASH hash;
156 unsigned int i;
157 char sha1[41];
158 BOOL ret;
160 ret = CryptAcquireContextW(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
161 ok(ret, "Failed to acquire crypt context.\n");
162 ret = CryptCreateHash(provider, CALG_SHA1, 0, 0, &hash);
163 ok(ret, "Failed to create hash.\n");
165 for (i = 0; i < h; ++i)
167 if (!(ret = CryptHashData(hash, (BYTE *)data + pitch * i, w * bpp, 0)))
168 break;
170 ok(ret, "Failed to hash data.\n");
172 i = sizeof(hash_data);
173 ret = CryptGetHashParam(hash, HP_HASHVAL, hash_data, &i, 0);
174 ok(ret, "Failed to get hash value.\n");
175 ok(i == sizeof(hash_data), "Got unexpected hash size %u.\n", i);
177 ret = CryptDestroyHash(hash);
178 ok(ret, "Failed to destroy hash.\n");
179 ret = CryptReleaseContext(provider, 0);
180 ok(ret, "Failed to release crypt context.\n");
182 for (i = 0; i < 20; ++i)
184 sha1[i * 2] = hex_chars[hash_data[i] >> 4];
185 sha1[i * 2 + 1] = hex_chars[hash_data[i] & 0xf];
187 sha1[40] = 0;
189 return !strcmp(ref_sha1, (char *)sha1);
192 static BOOL compare_surface(IDXGISurface *surface, const char *ref_sha1)
194 D3D10_MAPPED_TEXTURE2D mapped_texture;
195 D3D10_TEXTURE2D_DESC texture_desc;
196 DXGI_SURFACE_DESC surface_desc;
197 ID3D10Resource *src_resource;
198 ID3D10Texture2D *texture;
199 ID3D10Device *device;
200 HRESULT hr;
201 BOOL ret;
203 hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&device);
204 ok(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
205 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&src_resource);
206 ok(SUCCEEDED(hr), "Failed to query resource interface, hr %#x.\n", hr);
208 hr = IDXGISurface_GetDesc(surface, &surface_desc);
209 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
210 texture_desc.Width = surface_desc.Width;
211 texture_desc.Height = surface_desc.Height;
212 texture_desc.MipLevels = 1;
213 texture_desc.ArraySize = 1;
214 texture_desc.Format = surface_desc.Format;
215 texture_desc.SampleDesc = surface_desc.SampleDesc;
216 texture_desc.Usage = D3D10_USAGE_STAGING;
217 texture_desc.BindFlags = 0;
218 texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
219 texture_desc.MiscFlags = 0;
220 hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, &texture);
221 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
223 ID3D10Device_CopyResource(device, (ID3D10Resource *)texture, src_resource);
224 hr = ID3D10Texture2D_Map(texture, 0, D3D10_MAP_READ, 0, &mapped_texture);
225 ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr);
226 ret = compare_sha1(mapped_texture.pData, mapped_texture.RowPitch, 4,
227 texture_desc.Width, texture_desc.Height, ref_sha1);
228 ID3D10Texture2D_Unmap(texture, 0);
230 ID3D10Texture2D_Release(texture);
231 ID3D10Resource_Release(src_resource);
232 ID3D10Device_Release(device);
234 return ret;
237 static void serialize_figure(struct figure *figure)
239 static const char lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
240 unsigned int i, j, k, span;
241 char output[76];
242 char t[3];
243 char *p;
245 for (i = 0, j = 0, k = 0, p = output; i < figure->span_count; ++i)
247 span = figure->spans[i];
248 while (span)
250 t[j] = span & 0x7f;
251 if (span > 0x7f)
252 t[j] |= 0x80;
253 span >>= 7;
254 if (++j == 3)
256 p[0] = lookup[(t[0] & 0xfc) >> 2];
257 p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
258 p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
259 p[3] = lookup[t[2] & 0x3f];
260 p += 4;
261 if (++k == 19)
263 trace("%.76s\n", output);
264 p = output;
265 k = 0;
267 j = 0;
271 if (j)
273 for (i = j; i < 3; ++i)
274 t[i] = 0;
275 p[0] = lookup[(t[0] & 0xfc) >> 2];
276 p[1] = lookup[((t[0] & 0x03) << 4) | ((t[1] & 0xf0) >> 4)];
277 p[2] = lookup[((t[1] & 0x0f) << 2) | ((t[2] & 0xc0) >> 6)];
278 p[3] = lookup[t[2] & 0x3f];
279 ++k;
281 if (k)
282 trace("%.*s\n", k * 4, output);
285 static void figure_add_span(struct figure *figure, unsigned int span)
287 if (figure->span_count == figure->spans_size)
289 figure->spans_size *= 2;
290 figure->spans = HeapReAlloc(GetProcessHeap(), 0, figure->spans,
291 figure->spans_size * sizeof(*figure->spans));
294 figure->spans[figure->span_count++] = span;
297 static void deserialize_span(struct figure *figure, unsigned int *current, unsigned int *shift, unsigned int c)
299 *current |= (c & 0x7f) << *shift;
300 if (c & 0x80)
302 *shift += 7;
303 return;
306 if (*current)
307 figure_add_span(figure, *current);
308 *current = 0;
309 *shift = 0;
312 static void deserialize_figure(struct figure *figure, const BYTE *s)
314 static const BYTE lookup[] =
316 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
317 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
318 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
319 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
320 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
321 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
322 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
323 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
325 unsigned int current = 0, shift = 0;
326 const BYTE *ptr;
327 BYTE x, y;
329 figure->span_count = 0;
330 figure->spans_size = 64;
331 figure->spans = HeapAlloc(GetProcessHeap(), 0, figure->spans_size * sizeof(*figure->spans));
333 for (ptr = s; *ptr; ptr += 4)
335 x = lookup[ptr[0]];
336 y = lookup[ptr[1]];
337 deserialize_span(figure, &current, &shift, ((x & 0x3f) << 2) | ((y & 0x3f) >> 4));
338 x = lookup[ptr[2]];
339 deserialize_span(figure, &current, &shift, ((y & 0x0f) << 4) | ((x & 0x3f) >> 2));
340 y = lookup[ptr[3]];
341 deserialize_span(figure, &current, &shift, ((x & 0x03) << 6) | (y & 0x3f));
345 static BOOL compare_figure(IDXGISurface *surface, unsigned int x, unsigned int y,
346 unsigned int w, unsigned int h, DWORD prev, unsigned int max_diff, const char *ref)
348 D3D10_MAPPED_TEXTURE2D mapped_texture;
349 D3D10_TEXTURE2D_DESC texture_desc;
350 struct figure ref_figure, figure;
351 DXGI_SURFACE_DESC surface_desc;
352 unsigned int i, j, span, diff;
353 ID3D10Resource *src_resource;
354 ID3D10Texture2D *texture;
355 ID3D10Device *device;
356 HRESULT hr;
358 hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&device);
359 ok(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
360 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&src_resource);
361 ok(SUCCEEDED(hr), "Failed to query resource interface, hr %#x.\n", hr);
363 hr = IDXGISurface_GetDesc(surface, &surface_desc);
364 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
365 texture_desc.Width = surface_desc.Width;
366 texture_desc.Height = surface_desc.Height;
367 texture_desc.MipLevels = 1;
368 texture_desc.ArraySize = 1;
369 texture_desc.Format = surface_desc.Format;
370 texture_desc.SampleDesc = surface_desc.SampleDesc;
371 texture_desc.Usage = D3D10_USAGE_STAGING;
372 texture_desc.BindFlags = 0;
373 texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
374 texture_desc.MiscFlags = 0;
375 hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, &texture);
376 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
378 ID3D10Device_CopyResource(device, (ID3D10Resource *)texture, src_resource);
379 hr = ID3D10Texture2D_Map(texture, 0, D3D10_MAP_READ, 0, &mapped_texture);
380 ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr);
382 figure.span_count = 0;
383 figure.spans_size = 64;
384 figure.spans = HeapAlloc(GetProcessHeap(), 0, figure.spans_size * sizeof(*figure.spans));
386 for (i = 0, span = 0; i < h; ++i)
388 const DWORD *row = (DWORD *)((BYTE *)mapped_texture.pData + (y + i) * mapped_texture.RowPitch + x * 4);
389 for (j = 0; j < w; ++j, ++span)
391 if ((i || j) && prev != row[j])
393 figure_add_span(&figure, span);
394 prev = row[j];
395 span = 0;
399 if (span)
400 figure_add_span(&figure, span);
402 deserialize_figure(&ref_figure, (BYTE *)ref);
403 span = w * h;
404 for (i = 0; i < ref_figure.span_count; ++i)
406 span -= ref_figure.spans[i];
408 if (span)
409 figure_add_span(&ref_figure, span);
411 for (i = 0, j = 0, diff = 0; i < figure.span_count && j < ref_figure.span_count;)
413 if (figure.spans[i] == ref_figure.spans[j])
415 if ((i ^ j) & 1)
416 diff += ref_figure.spans[j];
417 ++i;
418 ++j;
420 else if (figure.spans[i] > ref_figure.spans[j])
422 if ((i ^ j) & 1)
423 diff += ref_figure.spans[j];
424 figure.spans[i] -= ref_figure.spans[j];
425 ++j;
427 else
429 if ((i ^ j) & 1)
430 diff += figure.spans[i];
431 ref_figure.spans[j] -= figure.spans[i];
432 ++i;
435 if (diff > max_diff)
436 serialize_figure(&figure);
438 HeapFree(GetProcessHeap(), 0, ref_figure.spans);
439 HeapFree(GetProcessHeap(), 0, figure.spans);
440 ID3D10Texture2D_Unmap(texture, 0);
442 ID3D10Texture2D_Release(texture);
443 ID3D10Resource_Release(src_resource);
444 ID3D10Device_Release(device);
446 return diff <= max_diff;
449 static ID3D10Device1 *create_device(void)
451 ID3D10Device1 *device;
453 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL,
454 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
455 return device;
456 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_WARP, NULL,
457 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
458 return device;
459 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL,
460 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
461 return device;
463 return NULL;
466 static IDXGISwapChain *create_swapchain(ID3D10Device1 *device, HWND window, BOOL windowed)
468 IDXGISwapChain *swapchain;
469 DXGI_SWAP_CHAIN_DESC desc;
470 IDXGIDevice *dxgi_device;
471 IDXGIAdapter *adapter;
472 IDXGIFactory *factory;
473 HRESULT hr;
475 hr = ID3D10Device1_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
476 ok(SUCCEEDED(hr), "Failed to get DXGI device, hr %#x.\n", hr);
477 hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter);
478 ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr);
479 IDXGIDevice_Release(dxgi_device);
480 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
481 ok(SUCCEEDED(hr), "Failed to get factory, hr %#x.\n", hr);
482 IDXGIAdapter_Release(adapter);
484 desc.BufferDesc.Width = 640;
485 desc.BufferDesc.Height = 480;
486 desc.BufferDesc.RefreshRate.Numerator = 60;
487 desc.BufferDesc.RefreshRate.Denominator = 1;
488 desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
489 desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
490 desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
491 desc.SampleDesc.Count = 1;
492 desc.SampleDesc.Quality = 0;
493 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
494 desc.BufferCount = 1;
495 desc.OutputWindow = window;
496 desc.Windowed = windowed;
497 desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
498 desc.Flags = 0;
500 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &desc, &swapchain);
501 ok(SUCCEEDED(hr), "Failed to create swapchain, hr %#x.\n", hr);
502 IDXGIFactory_Release(factory);
504 return swapchain;
507 static ID2D1RenderTarget *create_render_target_desc(IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
509 ID2D1RenderTarget *render_target;
510 ID2D1Factory *factory;
511 HRESULT hr;
513 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
514 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
515 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, desc, &render_target);
516 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
517 ID2D1Factory_Release(factory);
519 return render_target;
522 static ID2D1RenderTarget *create_render_target(IDXGISurface *surface)
524 D2D1_RENDER_TARGET_PROPERTIES desc;
526 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
527 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
528 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
529 desc.dpiX = 0.0f;
530 desc.dpiY = 0.0f;
531 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
532 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
534 return create_render_target_desc(surface, &desc);
537 static void test_clip(void)
539 IDXGISwapChain *swapchain;
540 D2D1_MATRIX_3X2_F matrix;
541 D2D1_SIZE_U pixel_size;
542 ID2D1RenderTarget *rt;
543 ID3D10Device1 *device;
544 IDXGISurface *surface;
545 D2D1_POINT_2F point;
546 D2D1_COLOR_F color;
547 float dpi_x, dpi_y;
548 D2D1_RECT_F rect;
549 D2D1_SIZE_F size;
550 HWND window;
551 HRESULT hr;
552 BOOL match;
553 static const D2D1_MATRIX_3X2_F identity =
555 1.0f, 0.0f,
556 0.0f, 1.0f,
557 0.0f, 0.0f,
560 if (!(device = create_device()))
562 skip("Failed to create device, skipping tests.\n");
563 return;
565 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
566 0, 0, 640, 480, NULL, NULL, NULL, NULL);
567 swapchain = create_swapchain(device, window, TRUE);
568 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
569 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
570 rt = create_render_target(surface);
571 ok(!!rt, "Failed to create render target.\n");
573 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
574 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
575 ok(dpi_y == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
576 size = ID2D1RenderTarget_GetSize(rt);
577 ok(size.width == 640.0f, "Got unexpected width %.8e.\n", size.width);
578 ok(size.height == 480.0f, "Got unexpected height %.8e.\n", size.height);
579 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
580 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
581 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
583 ID2D1RenderTarget_GetTransform(rt, &matrix);
584 ok(!memcmp(&matrix, &identity, sizeof(matrix)),
585 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
586 matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32);
588 ID2D1RenderTarget_BeginDraw(rt);
590 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
591 ID2D1RenderTarget_Clear(rt, &color);
593 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
594 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
595 ok(dpi_x == 48.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
596 ok(dpi_y == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
597 size = ID2D1RenderTarget_GetSize(rt);
598 ok(size.width == 1280.0f, "Got unexpected width %.8e.\n", size.width);
599 ok(size.height == 240.0f, "Got unexpected height %.8e.\n", size.height);
600 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
601 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
602 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
604 /* The effective clip rect is the intersection of all currently pushed
605 * clip rects. Clip rects are in DIPs. */
606 set_rect(&rect, 0.0f, 0.0f, 1280.0f, 80.0f);
607 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
608 set_rect(&rect, 0.0f, 0.0f, 426.0f, 240.0f);
609 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
611 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
612 ID2D1RenderTarget_Clear(rt, &color);
613 ID2D1RenderTarget_PopAxisAlignedClip(rt);
614 ID2D1RenderTarget_PopAxisAlignedClip(rt);
616 ID2D1RenderTarget_SetDpi(rt, 0.0f, 0.0f);
617 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
618 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
619 ok(dpi_y == 96.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
621 ID2D1RenderTarget_SetDpi(rt, 192.0f, 192.0f);
622 ID2D1RenderTarget_SetDpi(rt, 0.0f, 96.0f);
623 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
624 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
625 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
627 ID2D1RenderTarget_SetDpi(rt, -10.0f, 96.0f);
628 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
629 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
630 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
632 ID2D1RenderTarget_SetDpi(rt, 96.0f, -10.0f);
633 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
634 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
635 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
637 ID2D1RenderTarget_SetDpi(rt, 96.0f, 0.0f);
638 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
639 ok(dpi_x == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
640 ok(dpi_y == 192.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
642 ID2D1RenderTarget_SetDpi(rt, 96.0f, 96.0f);
644 /* Transformations apply to clip rects, the effective clip rect is the
645 * (axis-aligned) bounding box of the transformed clip rect. */
646 set_point(&point, 320.0f, 240.0f);
647 D2D1MakeRotateMatrix(30.0f, point, &matrix);
648 ID2D1RenderTarget_SetTransform(rt, &matrix);
649 set_rect(&rect, 215.0f, 208.0f, 425.0f, 272.0f);
650 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
651 set_color(&color, 1.0f, 1.0f, 1.0f, 1.0f);
652 ID2D1RenderTarget_Clear(rt, &color);
653 ID2D1RenderTarget_PopAxisAlignedClip(rt);
655 /* Transformations are applied when pushing the clip rect, transformations
656 * set afterwards have no effect on the current clip rect. This includes
657 * SetDpi(). */
658 ID2D1RenderTarget_SetTransform(rt, &identity);
659 set_rect(&rect, 427.0f, 320.0f, 640.0f, 480.0f);
660 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
661 ID2D1RenderTarget_SetTransform(rt, &matrix);
662 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
663 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
664 ID2D1RenderTarget_Clear(rt, &color);
665 ID2D1RenderTarget_PopAxisAlignedClip(rt);
667 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
668 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
669 match = compare_surface(surface, "035a44d4198d6e422e9de6185b5b2c2bac5e33c9");
670 ok(match, "Surface does not match.\n");
672 ID2D1RenderTarget_Release(rt);
673 IDXGISurface_Release(surface);
674 IDXGISwapChain_Release(swapchain);
675 ID3D10Device1_Release(device);
676 DestroyWindow(window);
679 static void test_state_block(void)
681 IDWriteRenderingParams *text_rendering_params1, *text_rendering_params2;
682 D2D1_DRAWING_STATE_DESCRIPTION drawing_state;
683 ID2D1DrawingStateBlock *state_block;
684 IDWriteFactory *dwrite_factory;
685 IDXGISwapChain *swapchain;
686 ID2D1RenderTarget *rt;
687 ID3D10Device1 *device;
688 IDXGISurface *surface;
689 ID2D1Factory *factory;
690 ULONG refcount;
691 HWND window;
692 HRESULT hr;
693 static const D2D1_MATRIX_3X2_F identity =
695 1.0f, 0.0f,
696 0.0f, 1.0f,
697 0.0f, 0.0f,
699 static const D2D1_MATRIX_3X2_F transform1 =
701 1.0f, 2.0f,
702 3.0f, 4.0f,
703 5.0f, 6.0f,
705 static const D2D1_MATRIX_3X2_F transform2 =
707 7.0f, 8.0f,
708 9.0f, 10.0f,
709 11.0f, 12.0f,
712 if (!(device = create_device()))
714 skip("Failed to create device, skipping tests.\n");
715 return;
717 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
718 0, 0, 640, 480, NULL, NULL, NULL, NULL);
719 swapchain = create_swapchain(device, window, TRUE);
720 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
721 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
722 rt = create_render_target(surface);
723 ok(!!rt, "Failed to create render target.\n");
724 ID2D1RenderTarget_GetFactory(rt, &factory);
725 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
726 ok(SUCCEEDED(hr), "Failed to create dwrite factory, hr %#x.\n", hr);
727 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &text_rendering_params1);
728 ok(SUCCEEDED(hr), "Failed to create dwrite rendering params, hr %#x.\n", hr);
729 IDWriteFactory_Release(dwrite_factory);
731 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
732 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
733 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
734 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
735 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
736 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
737 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
738 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %08x%08x:%08x%08x.\n",
739 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
740 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
741 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
742 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
743 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
744 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
745 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
746 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
747 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
749 hr = ID2D1Factory_CreateDrawingStateBlock(factory, NULL, NULL, &state_block);
750 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
751 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
752 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
753 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
754 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
755 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
756 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %08x%08x:%08x%08x.\n",
757 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
758 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
759 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
760 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
761 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
762 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
763 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
764 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
765 ID2D1DrawingStateBlock_Release(state_block);
767 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
768 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
769 drawing_state.tag1 = 0xdead;
770 drawing_state.tag2 = 0xbeef;
771 drawing_state.transform = transform1;
772 hr = ID2D1Factory_CreateDrawingStateBlock(factory, &drawing_state, text_rendering_params1, &state_block);
773 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
775 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
776 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
777 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
778 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
779 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
780 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %08x%08x:%08x%08x.\n",
781 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
782 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
783 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
784 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
785 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
786 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
787 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
788 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
789 text_rendering_params2, text_rendering_params1);
790 IDWriteRenderingParams_Release(text_rendering_params2);
792 ID2D1RenderTarget_RestoreDrawingState(rt, state_block);
794 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
795 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
796 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
797 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
798 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
799 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
800 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
801 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %08x%08x:%08x%08x.\n",
802 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
803 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
804 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
805 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
806 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
807 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
808 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
809 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
810 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
811 text_rendering_params2, text_rendering_params1);
812 IDWriteRenderingParams_Release(text_rendering_params2);
814 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
815 ID2D1RenderTarget_SetTextAntialiasMode(rt, D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
816 ID2D1RenderTarget_SetTags(rt, 1, 2);
817 ID2D1RenderTarget_SetTransform(rt, &transform2);
818 ID2D1RenderTarget_SetTextRenderingParams(rt, NULL);
820 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
821 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
822 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
823 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
824 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
825 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
826 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
827 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %08x%08x:%08x%08x.\n",
828 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
829 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
830 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
831 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
832 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
833 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
834 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
835 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
836 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
838 ID2D1RenderTarget_SaveDrawingState(rt, state_block);
840 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
841 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
842 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
843 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
844 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
845 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %08x%08x:%08x%08x.\n",
846 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
847 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
848 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
849 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
850 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
851 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
852 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
853 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
855 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
856 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
857 drawing_state.tag1 = 3;
858 drawing_state.tag2 = 4;
859 drawing_state.transform = transform1;
860 ID2D1DrawingStateBlock_SetDescription(state_block, &drawing_state);
861 ID2D1DrawingStateBlock_SetTextRenderingParams(state_block, text_rendering_params1);
863 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
864 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
865 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
866 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE,
867 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
868 ok(drawing_state.tag1 == 3 && drawing_state.tag2 == 4, "Got unexpected tags %08x%08x:%08x%08x.\n",
869 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
870 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
871 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
872 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
873 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
874 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
875 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
876 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
877 text_rendering_params2, text_rendering_params1);
878 IDWriteRenderingParams_Release(text_rendering_params2);
880 ID2D1DrawingStateBlock_Release(state_block);
882 refcount = IDWriteRenderingParams_Release(text_rendering_params1);
883 ok(!refcount, "Rendering params %u references left.\n", refcount);
884 ID2D1Factory_Release(factory);
885 ID2D1RenderTarget_Release(rt);
886 IDXGISurface_Release(surface);
887 IDXGISwapChain_Release(swapchain);
888 ID3D10Device1_Release(device);
889 DestroyWindow(window);
892 static void test_color_brush(void)
894 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
895 D2D1_BRUSH_PROPERTIES brush_desc;
896 D2D1_COLOR_F color, tmp_color;
897 ID2D1SolidColorBrush *brush;
898 IDXGISwapChain *swapchain;
899 ID2D1RenderTarget *rt;
900 ID3D10Device1 *device;
901 IDXGISurface *surface;
902 D2D1_RECT_F rect;
903 float opacity;
904 HWND window;
905 HRESULT hr;
906 BOOL match;
908 if (!(device = create_device()))
910 skip("Failed to create device, skipping tests.\n");
911 return;
913 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
914 0, 0, 640, 480, NULL, NULL, NULL, NULL);
915 swapchain = create_swapchain(device, window, TRUE);
916 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
917 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
918 rt = create_render_target(surface);
919 ok(!!rt, "Failed to create render target.\n");
921 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
922 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
924 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
925 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
926 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
927 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
928 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
929 set_matrix_identity(&matrix);
930 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
931 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
932 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
933 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
934 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
935 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
936 ok(!memcmp(&tmp_color, &color, sizeof(color)),
937 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
938 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
939 ID2D1SolidColorBrush_Release(brush);
941 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
942 brush_desc.opacity = 0.3f;
943 set_matrix_identity(&matrix);
944 scale_matrix(&matrix, 2.0f, 2.0f);
945 brush_desc.transform = matrix;
946 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, &brush_desc, &brush);
947 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
948 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
949 ok(opacity == 0.3f, "Got unexpected opacity %.8e.\n", opacity);
950 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
951 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
952 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
953 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
954 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
955 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
956 ok(!memcmp(&tmp_color, &color, sizeof(color)),
957 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
958 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
960 ID2D1RenderTarget_BeginDraw(rt);
962 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
963 ID2D1RenderTarget_Clear(rt, &color);
965 ID2D1SolidColorBrush_SetOpacity(brush, 1.0f);
966 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
967 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
969 set_matrix_identity(&matrix);
970 scale_matrix(&matrix, 0.5f, 2.0f);
971 translate_matrix(&matrix, 320.0f, 240.0f);
972 rotate_matrix(&matrix, M_PI / 4.0f);
973 ID2D1RenderTarget_SetTransform(rt, &matrix);
974 set_color(&color, 1.0f, 0.0f, 0.0f, 0.625f);
975 ID2D1SolidColorBrush_SetColor(brush, &color);
976 ID2D1SolidColorBrush_SetOpacity(brush, 0.75f);
977 set_rect(&rect, -80.0f, -60.0f, 80.0f, 60.0f);
978 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
980 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
981 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
982 match = compare_surface(surface, "6d1218fca5e21fb7e287b3a439d60dbc251f5ceb");
983 ok(match, "Surface does not match.\n");
985 ID2D1SolidColorBrush_Release(brush);
986 ID2D1RenderTarget_Release(rt);
987 IDXGISurface_Release(surface);
988 IDXGISwapChain_Release(swapchain);
989 ID3D10Device1_Release(device);
990 DestroyWindow(window);
993 static void test_bitmap_brush(void)
995 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode;
996 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
997 D2D1_BITMAP_PROPERTIES bitmap_desc;
998 ID2D1Bitmap *bitmap, *tmp_bitmap;
999 D2D1_RECT_F src_rect, dst_rect;
1000 D2D1_EXTEND_MODE extend_mode;
1001 IDXGISwapChain *swapchain;
1002 ID2D1BitmapBrush *brush;
1003 ID2D1RenderTarget *rt;
1004 ID3D10Device1 *device;
1005 IDXGISurface *surface;
1006 D2D1_COLOR_F color;
1007 D2D1_SIZE_U size;
1008 unsigned int i;
1009 ULONG refcount;
1010 float opacity;
1011 HWND window;
1012 HRESULT hr;
1013 BOOL match;
1015 static const struct
1017 D2D1_EXTEND_MODE extend_mode_x;
1018 D2D1_EXTEND_MODE extend_mode_y;
1019 float translate_x;
1020 float translate_y;
1021 D2D1_RECT_F rect;
1023 extend_mode_tests[] =
1025 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_MIRROR, -7.0f, 1.0f, {-4.0f, 0.0f, -8.0f, 4.0f}},
1026 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_MIRROR, -3.0f, 1.0f, {-4.0f, 4.0f, 0.0f, 0.0f}},
1027 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_MIRROR, 1.0f, 1.0f, { 4.0f, 0.0f, 0.0f, 4.0f}},
1028 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_WRAP, -7.0f, 5.0f, {-8.0f, 8.0f, -4.0f, 4.0f}},
1029 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP, -3.0f, 5.0f, { 0.0f, 4.0f, -4.0f, 8.0f}},
1030 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_WRAP, 1.0f, 5.0f, { 0.0f, 8.0f, 4.0f, 4.0f}},
1031 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_CLAMP, -7.0f, 9.0f, {-4.0f, 8.0f, -8.0f, 12.0f}},
1032 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_CLAMP, -3.0f, 9.0f, {-4.0f, 12.0f, 0.0f, 8.0f}},
1033 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_CLAMP, 1.0f, 9.0f, { 4.0f, 8.0f, 0.0f, 12.0f}},
1035 static const DWORD bitmap_data[] =
1037 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
1038 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
1039 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
1040 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
1043 if (!(device = create_device()))
1045 skip("Failed to create device, skipping tests.\n");
1046 return;
1048 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1049 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1050 swapchain = create_swapchain(device, window, TRUE);
1051 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1052 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1053 rt = create_render_target(surface);
1054 ok(!!rt, "Failed to create render target.\n");
1056 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1057 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1059 set_size_u(&size, 4, 4);
1060 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
1061 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
1062 bitmap_desc.dpiX = 96.0f;
1063 bitmap_desc.dpiY = 96.0f;
1064 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
1065 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
1067 /* Creating a brush with a NULL bitmap crashes on Vista, but works fine on
1068 * Windows 7+. */
1069 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
1070 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1071 ID2D1BitmapBrush_GetBitmap(brush, &tmp_bitmap);
1072 ok(tmp_bitmap == bitmap, "Got unexpected bitmap %p, expected %p.\n", tmp_bitmap, bitmap);
1073 ID2D1Bitmap_Release(tmp_bitmap);
1074 opacity = ID2D1BitmapBrush_GetOpacity(brush);
1075 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
1076 set_matrix_identity(&matrix);
1077 ID2D1BitmapBrush_GetTransform(brush, &tmp_matrix);
1078 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1079 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1080 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1081 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1082 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
1083 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
1084 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
1085 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
1086 interpolation_mode = ID2D1BitmapBrush_GetInterpolationMode(brush);
1087 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
1088 "Got unexpected interpolation mode %#x.\n", interpolation_mode);
1089 ID2D1BitmapBrush_Release(brush);
1091 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
1092 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1093 set_matrix_identity(&matrix);
1094 translate_matrix(&matrix, 40.0f, 120.0f);
1095 scale_matrix(&matrix, 20.0f, 60.0f);
1096 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1097 ID2D1BitmapBrush_SetInterpolationMode(brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
1099 ID2D1RenderTarget_BeginDraw(rt);
1101 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
1102 ID2D1RenderTarget_Clear(rt, &color);
1104 set_rect(&dst_rect, 40.0f, 120.0f, 120.0f, 360.0f);
1105 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1107 set_matrix_identity(&matrix);
1108 scale_matrix(&matrix, 0.5f, 2.0f);
1109 translate_matrix(&matrix, 320.0f, 240.0f);
1110 rotate_matrix(&matrix, M_PI / 4.0f);
1111 ID2D1RenderTarget_SetTransform(rt, &matrix);
1112 set_matrix_identity(&matrix);
1113 translate_matrix(&matrix, -80.0f, -60.0f);
1114 scale_matrix(&matrix, 40.0f, 30.0f);
1115 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1116 ID2D1BitmapBrush_SetOpacity(brush, 0.75f);
1117 set_rect(&dst_rect, -80.0f, -60.0f, 80.0f, 60.0f);
1118 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
1120 set_matrix_identity(&matrix);
1121 translate_matrix(&matrix, 200.0f, 120.0f);
1122 scale_matrix(&matrix, 20.0f, 60.0f);
1123 ID2D1RenderTarget_SetTransform(rt, &matrix);
1124 ID2D1RenderTarget_DrawBitmap(rt, bitmap, NULL, 0.25f,
1125 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
1126 set_rect(&dst_rect, -4.0f, 12.0f, -8.0f, 8.0f);
1127 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 0.75f,
1128 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
1129 set_rect(&dst_rect, 0.0f, 8.0f, 4.0f, 12.0f);
1130 set_rect(&src_rect, 2.0f, 1.0f, 4.0f, 3.0f);
1131 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
1132 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
1134 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1135 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1136 match = compare_surface(surface, "393636185359a550d459e1e5f0e25411814f724c");
1137 ok(match, "Surface does not match.\n");
1139 ID2D1RenderTarget_BeginDraw(rt);
1141 ID2D1RenderTarget_Clear(rt, &color);
1143 ID2D1BitmapBrush_SetOpacity(brush, 1.0f);
1144 for (i = 0; i < sizeof(extend_mode_tests) / sizeof(*extend_mode_tests); ++i)
1146 ID2D1BitmapBrush_SetExtendModeX(brush, extend_mode_tests[i].extend_mode_x);
1147 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
1148 ok(extend_mode == extend_mode_tests[i].extend_mode_x,
1149 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
1150 i, extend_mode, extend_mode_tests[i].extend_mode_x);
1151 ID2D1BitmapBrush_SetExtendModeY(brush, extend_mode_tests[i].extend_mode_y);
1152 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
1153 ok(extend_mode == extend_mode_tests[i].extend_mode_y,
1154 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
1155 i, extend_mode, extend_mode_tests[i].extend_mode_y);
1156 set_matrix_identity(&matrix);
1157 translate_matrix(&matrix, extend_mode_tests[i].translate_x, extend_mode_tests[i].translate_y);
1158 scale_matrix(&matrix, 0.5f, 0.5f);
1159 ID2D1BitmapBrush_SetTransform(brush, &matrix);
1160 ID2D1RenderTarget_FillRectangle(rt, &extend_mode_tests[i].rect, (ID2D1Brush *)brush);
1163 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1164 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1165 match = compare_surface(surface, "b4b775afecdae2d26642001f4faff73663bb8b31");
1166 ok(match, "Surface does not match.\n");
1168 ID2D1BitmapBrush_Release(brush);
1169 refcount = ID2D1Bitmap_Release(bitmap);
1170 ok(!refcount, "Bitmap has %u references left.\n", refcount);
1171 ID2D1RenderTarget_Release(rt);
1172 IDXGISurface_Release(surface);
1173 IDXGISwapChain_Release(swapchain);
1174 ID3D10Device1_Release(device);
1175 DestroyWindow(window);
1178 static void fill_geometry_sink(ID2D1GeometrySink *sink)
1180 D2D1_POINT_2F point;
1182 set_point(&point, 15.0f, 20.0f);
1183 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1184 set_point(&point, 55.0f, 20.0f);
1185 ID2D1GeometrySink_AddLine(sink, point);
1186 set_point(&point, 55.0f, 220.0f);
1187 ID2D1GeometrySink_AddLine(sink, point);
1188 set_point(&point, 25.0f, 220.0f);
1189 ID2D1GeometrySink_AddLine(sink, point);
1190 set_point(&point, 25.0f, 100.0f);
1191 ID2D1GeometrySink_AddLine(sink, point);
1192 set_point(&point, 75.0f, 100.0f);
1193 ID2D1GeometrySink_AddLine(sink, point);
1194 set_point(&point, 75.0f, 300.0f);
1195 ID2D1GeometrySink_AddLine(sink, point);
1196 set_point(&point, 5.0f, 300.0f);
1197 ID2D1GeometrySink_AddLine(sink, point);
1198 set_point(&point, 5.0f, 60.0f);
1199 ID2D1GeometrySink_AddLine(sink, point);
1200 set_point(&point, 45.0f, 60.0f);
1201 ID2D1GeometrySink_AddLine(sink, point);
1202 set_point(&point, 45.0f, 180.0f);
1203 ID2D1GeometrySink_AddLine(sink, point);
1204 set_point(&point, 35.0f, 180.0f);
1205 ID2D1GeometrySink_AddLine(sink, point);
1206 set_point(&point, 35.0f, 140.0f);
1207 ID2D1GeometrySink_AddLine(sink, point);
1208 set_point(&point, 65.0f, 140.0f);
1209 ID2D1GeometrySink_AddLine(sink, point);
1210 set_point(&point, 65.0f, 260.0f);
1211 ID2D1GeometrySink_AddLine(sink, point);
1212 set_point(&point, 15.0f, 260.0f);
1213 ID2D1GeometrySink_AddLine(sink, point);
1214 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1216 set_point(&point, 155.0f, 300.0f);
1217 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1218 set_point(&point, 155.0f, 160.0f);
1219 ID2D1GeometrySink_AddLine(sink, point);
1220 set_point(&point, 85.0f, 160.0f);
1221 ID2D1GeometrySink_AddLine(sink, point);
1222 set_point(&point, 85.0f, 300.0f);
1223 ID2D1GeometrySink_AddLine(sink, point);
1224 set_point(&point, 120.0f, 300.0f);
1225 ID2D1GeometrySink_AddLine(sink, point);
1226 set_point(&point, 120.0f, 20.0f);
1227 ID2D1GeometrySink_AddLine(sink, point);
1228 set_point(&point, 155.0f, 20.0f);
1229 ID2D1GeometrySink_AddLine(sink, point);
1230 set_point(&point, 155.0f, 160.0f);
1231 ID2D1GeometrySink_AddLine(sink, point);
1232 set_point(&point, 85.0f, 160.0f);
1233 ID2D1GeometrySink_AddLine(sink, point);
1234 set_point(&point, 85.0f, 20.0f);
1235 ID2D1GeometrySink_AddLine(sink, point);
1236 set_point(&point, 120.0f, 20.0f);
1237 ID2D1GeometrySink_AddLine(sink, point);
1238 set_point(&point, 120.0f, 300.0f);
1239 ID2D1GeometrySink_AddLine(sink, point);
1240 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1242 set_point(&point, 165.0f, 20.0f);
1243 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1244 set_point(&point, 165.0f, 300.0f);
1245 ID2D1GeometrySink_AddLine(sink, point);
1246 set_point(&point, 235.0f, 300.0f);
1247 ID2D1GeometrySink_AddLine(sink, point);
1248 set_point(&point, 235.0f, 20.0f);
1249 ID2D1GeometrySink_AddLine(sink, point);
1250 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1251 set_point(&point, 225.0f, 60.0f);
1252 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1253 set_point(&point, 225.0f, 260.0f);
1254 ID2D1GeometrySink_AddLine(sink, point);
1255 set_point(&point, 175.0f, 260.0f);
1256 ID2D1GeometrySink_AddLine(sink, point);
1257 set_point(&point, 175.0f, 60.0f);
1258 ID2D1GeometrySink_AddLine(sink, point);
1259 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1260 set_point(&point, 215.0f, 220.0f);
1261 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1262 set_point(&point, 185.0f, 220.0f);
1263 ID2D1GeometrySink_AddLine(sink, point);
1264 set_point(&point, 185.0f, 100.0f);
1265 ID2D1GeometrySink_AddLine(sink, point);
1266 set_point(&point, 215.0f, 100.0f);
1267 ID2D1GeometrySink_AddLine(sink, point);
1268 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1269 set_point(&point, 195.0f, 180.0f);
1270 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1271 set_point(&point, 205.0f, 180.0f);
1272 ID2D1GeometrySink_AddLine(sink, point);
1273 set_point(&point, 205.0f, 140.0f);
1274 ID2D1GeometrySink_AddLine(sink, point);
1275 set_point(&point, 195.0f, 140.0f);
1276 ID2D1GeometrySink_AddLine(sink, point);
1277 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1280 static void fill_geometry_sink_bezier(ID2D1GeometrySink *sink)
1282 D2D1_QUADRATIC_BEZIER_SEGMENT quadratic;
1283 D2D1_POINT_2F point;
1285 set_point(&point, 5.0f, 160.0f);
1286 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1287 set_quadratic(&quadratic, 40.0f, 160.0f, 40.0f, 20.0f);
1288 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1289 set_quadratic(&quadratic, 40.0f, 160.0f, 75.0f, 160.0f);
1290 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1291 set_quadratic(&quadratic, 40.0f, 160.0f, 40.0f, 300.0f);
1292 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1293 set_quadratic(&quadratic, 40.0f, 160.0f, 5.0f, 160.0f);
1294 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1295 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1297 set_point(&point, 20.0f, 160.0f);
1298 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1299 set_quadratic(&quadratic, 20.0f, 80.0f, 40.0f, 80.0f);
1300 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1301 set_quadratic(&quadratic, 60.0f, 80.0f, 60.0f, 160.0f);
1302 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1303 set_quadratic(&quadratic, 60.0f, 240.0f, 40.0f, 240.0f);
1304 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1305 set_quadratic(&quadratic, 20.0f, 240.0f, 20.0f, 160.0f);
1306 ID2D1GeometrySink_AddQuadraticBezier(sink, &quadratic);
1307 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1310 static void test_path_geometry(void)
1312 ID2D1TransformedGeometry *transformed_geometry;
1313 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
1314 ID2D1GeometrySink *sink, *tmp_sink;
1315 D2D1_POINT_2F point = {0.0f, 0.0f};
1316 ID2D1SolidColorBrush *brush;
1317 ID2D1PathGeometry *geometry;
1318 ID2D1Geometry *tmp_geometry;
1319 IDXGISwapChain *swapchain;
1320 ID2D1RenderTarget *rt;
1321 ID3D10Device1 *device;
1322 IDXGISurface *surface;
1323 ID2D1Factory *factory;
1324 BOOL match, contains;
1325 D2D1_COLOR_F color;
1326 ULONG refcount;
1327 UINT32 count;
1328 HWND window;
1329 HRESULT hr;
1331 if (!(device = create_device()))
1333 skip("Failed to create device, skipping tests.\n");
1334 return;
1336 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1337 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1338 swapchain = create_swapchain(device, window, TRUE);
1339 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1340 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1341 rt = create_render_target(surface);
1342 ok(!!rt, "Failed to create render target.\n");
1343 ID2D1RenderTarget_GetFactory(rt, &factory);
1345 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
1346 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
1347 set_color(&color, 0.890f, 0.851f, 0.600f, 1.0f);
1348 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
1349 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
1351 /* Close() when closed. */
1352 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1353 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1354 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1355 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1356 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1357 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1358 hr = ID2D1PathGeometry_Open(geometry, &sink);
1359 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1360 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1361 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1362 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1363 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1364 hr = ID2D1GeometrySink_Close(sink);
1365 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1366 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1367 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1368 ok(!count, "Got unexpected figure count %u.\n", count);
1369 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1370 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1371 ok(!count, "Got unexpected segment count %u.\n", count);
1372 hr = ID2D1GeometrySink_Close(sink);
1373 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1374 ID2D1GeometrySink_Release(sink);
1375 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1376 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1377 ok(!count, "Got unexpected figure count %u.\n", count);
1378 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1379 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1380 ok(!count, "Got unexpected segment count %u.\n", count);
1381 ID2D1PathGeometry_Release(geometry);
1383 /* Open() when closed. */
1384 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1385 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1386 hr = ID2D1PathGeometry_Open(geometry, &sink);
1387 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1388 hr = ID2D1GeometrySink_Close(sink);
1389 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1390 ID2D1GeometrySink_Release(sink);
1391 hr = ID2D1PathGeometry_Open(geometry, &sink);
1392 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1393 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1394 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1395 ok(!count, "Got unexpected figure count %u.\n", count);
1396 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1397 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1398 ok(!count, "Got unexpected segment count %u.\n", count);
1399 ID2D1PathGeometry_Release(geometry);
1401 /* Open() when open. */
1402 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1403 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1404 hr = ID2D1PathGeometry_Open(geometry, &sink);
1405 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1406 hr = ID2D1PathGeometry_Open(geometry, &tmp_sink);
1407 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1408 hr = ID2D1GeometrySink_Close(sink);
1409 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1410 ID2D1GeometrySink_Release(sink);
1411 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1412 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1413 ok(!count, "Got unexpected figure count %u.\n", count);
1414 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1415 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1416 ok(!count, "Got unexpected segment count %u.\n", count);
1417 ID2D1PathGeometry_Release(geometry);
1419 /* BeginFigure() without EndFigure(). */
1420 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1421 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1422 hr = ID2D1PathGeometry_Open(geometry, &sink);
1423 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1424 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1425 hr = ID2D1GeometrySink_Close(sink);
1426 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1427 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1428 hr = ID2D1GeometrySink_Close(sink);
1429 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1430 ID2D1GeometrySink_Release(sink);
1431 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1432 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1433 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1434 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1435 ID2D1PathGeometry_Release(geometry);
1437 /* EndFigure() without BeginFigure(). */
1438 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1439 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1440 hr = ID2D1PathGeometry_Open(geometry, &sink);
1441 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1442 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1443 hr = ID2D1GeometrySink_Close(sink);
1444 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1445 ID2D1GeometrySink_Release(sink);
1446 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1447 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1448 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1449 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1450 ID2D1PathGeometry_Release(geometry);
1452 /* BeginFigure()/EndFigure() mismatch. */
1453 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1454 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1455 hr = ID2D1PathGeometry_Open(geometry, &sink);
1456 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1457 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1458 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1459 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1460 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1461 hr = ID2D1GeometrySink_Close(sink);
1462 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1463 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1464 hr = ID2D1GeometrySink_Close(sink);
1465 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1466 ID2D1GeometrySink_Release(sink);
1467 ID2D1PathGeometry_Release(geometry);
1469 /* AddLine() outside BeginFigure()/EndFigure(). */
1470 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1471 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1472 hr = ID2D1PathGeometry_Open(geometry, &sink);
1473 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1474 ID2D1GeometrySink_AddLine(sink, point);
1475 hr = ID2D1GeometrySink_Close(sink);
1476 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1477 ID2D1GeometrySink_AddLine(sink, point);
1478 ID2D1GeometrySink_Release(sink);
1479 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1480 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1481 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1482 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
1483 ID2D1PathGeometry_Release(geometry);
1485 /* Empty figure. */
1486 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1487 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1488 hr = ID2D1PathGeometry_Open(geometry, &sink);
1489 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1490 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1491 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1492 hr = ID2D1GeometrySink_Close(sink);
1493 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1494 ID2D1GeometrySink_Release(sink);
1495 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1496 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1497 ok(count == 1, "Got unexpected figure count %u.\n", count);
1498 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1499 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1500 ok(count == 1, "Got unexpected segment count %u.\n", count);
1501 ID2D1PathGeometry_Release(geometry);
1503 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1504 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1505 hr = ID2D1PathGeometry_Open(geometry, &sink);
1506 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1507 /* The fillmode that's used is the last one set before the sink is closed. */
1508 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
1509 fill_geometry_sink(sink);
1510 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
1511 hr = ID2D1GeometrySink_Close(sink);
1512 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1513 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1514 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1515 ok(count == 6, "Got unexpected figure count %u.\n", count);
1516 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1517 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1518 /* Intersections don't create extra segments. */
1519 ok(count == 44, "Got unexpected segment count %u.\n", count);
1520 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
1521 ID2D1GeometrySink_Release(sink);
1523 set_matrix_identity(&matrix);
1524 translate_matrix(&matrix, 80.0f, 640.0f);
1525 scale_matrix(&matrix, 1.0f, -1.0f);
1526 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
1527 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
1529 ID2D1TransformedGeometry_GetSourceGeometry(transformed_geometry, &tmp_geometry);
1530 ok(tmp_geometry == (ID2D1Geometry *)geometry,
1531 "Got unexpected source geometry %p, expected %p.\n", tmp_geometry, geometry);
1532 ID2D1Geometry_Release(tmp_geometry);
1533 ID2D1TransformedGeometry_GetTransform(transformed_geometry, &tmp_matrix);
1534 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
1535 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1536 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
1537 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
1539 ID2D1RenderTarget_BeginDraw(rt);
1540 set_color(&color, 0.396f, 0.180f, 0.537f, 1.0f);
1541 ID2D1RenderTarget_Clear(rt, &color);
1542 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1543 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1544 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1545 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1546 match = compare_surface(surface, "3aace1b22aae111cb577614fed16e4eb1650dba5");
1547 ok(match, "Surface does not match.\n");
1549 /* Edge test. */
1550 set_point(&point, 94.0f, 620.0f);
1551 contains = TRUE;
1552 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, NULL, 0.0f, &contains);
1553 ok(hr == S_OK, "FillContainsPoint failed, hr %#x.\n", hr);
1554 ok(!contains, "Got unexpected contains %#x.\n", contains);
1556 set_point(&point, 95.0f, 620.0f);
1557 contains = FALSE;
1558 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, NULL, 0.0f, &contains);
1559 ok(hr == S_OK, "FillContainsPoint failed, hr %#x.\n", hr);
1560 ok(contains == TRUE, "Got unexpected contains %#x.\n", contains);
1562 /* With transformation matrix. */
1563 set_matrix_identity(&matrix);
1564 translate_matrix(&matrix, -10.0f, 0.0f);
1565 set_point(&point, 85.0f, 620.0f);
1566 contains = FALSE;
1567 hr = ID2D1TransformedGeometry_FillContainsPoint(transformed_geometry, point, &matrix, 0.0f, &contains);
1568 ok(hr == S_OK, "FillContainsPoint failed, hr %#x.\n", hr);
1569 ok(contains == TRUE, "Got unexpected contains %#x.\n", contains);
1571 ID2D1TransformedGeometry_Release(transformed_geometry);
1572 ID2D1PathGeometry_Release(geometry);
1574 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1575 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1576 hr = ID2D1PathGeometry_Open(geometry, &sink);
1577 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1578 fill_geometry_sink(sink);
1579 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
1580 hr = ID2D1GeometrySink_Close(sink);
1581 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1582 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1583 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1584 ok(count == 6, "Got unexpected figure count %u.\n", count);
1585 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1586 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1587 ok(count == 44, "Got unexpected segment count %u.\n", count);
1588 ID2D1GeometrySink_Release(sink);
1590 set_matrix_identity(&matrix);
1591 translate_matrix(&matrix, 320.0f, 320.0f);
1592 scale_matrix(&matrix, -1.0f, 1.0f);
1593 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
1594 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
1596 ID2D1RenderTarget_BeginDraw(rt);
1597 ID2D1RenderTarget_Clear(rt, &color);
1598 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1599 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1600 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1601 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1602 match = compare_surface(surface, "bfb40a1f007694fa07dbd3b854f3f5d9c3e1d76b");
1603 ok(match, "Surface 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 hr = ID2D1GeometrySink_Close(sink);
1613 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1614 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1615 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1616 ok(count == 2, "Got unexpected figure count %u.\n", count);
1617 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1618 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1619 ok(count == 10, "Got unexpected segment count %u.\n", count);
1620 ID2D1GeometrySink_Release(sink);
1622 set_matrix_identity(&matrix);
1623 scale_matrix(&matrix, 0.5f, 2.0f);
1624 translate_matrix(&matrix, 240.0f, -33.0f);
1625 rotate_matrix(&matrix, M_PI / 4.0f);
1626 scale_matrix(&matrix, 2.0f, 0.5f);
1627 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
1628 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
1630 ID2D1RenderTarget_BeginDraw(rt);
1631 ID2D1RenderTarget_Clear(rt, &color);
1632 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1633 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1634 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1635 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1636 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
1637 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
1638 "lAEECASLAQgKCIEBDQoMew8KD3YQDBByEgwSbhMOEmwUDhRpFBAUZxUQFWUVEhVjFhIWYRYUFl8X"
1639 "FBddFxYWXRYYFlsXGBdaFhoWWRYcFlgVHhVXFSAVVhQiFFUUIxRVEyYTVBIoElQRKhFUECwQUxAu"
1640 "EFIOMg5SDTQNUgs4C1IJPAlRCEAIUAZEBlAESARQAU4BTgJQAkgGUAY/C1ALMhNQEyoTUBMyC1AL"
1641 "PwZQBkgCUAJOAU4BUARIBFAGRAZQCEAIUQk8CVILOAtSDTQNUg4yDlIQLhBTECwQVBEqEVQSKBJU"
1642 "EyYTVBQjFFYUIhRWFSAVVxUeFVgWHBZZFhoWWhcYF1sWGBZcFxYWXhcUF18WFBZhFhIWYxUSFWUV"
1643 "EBVnFBAUaRQOFGsTDhJvEgwSchAMEHYPCg96DQoMggEICgiLAQQIBJQBCJgBCJkBBpoBBpoBBpoB"
1644 "BpsBBJwBBJwBBJwBBJwBBJ0BAp4BAp4BAp4BAp4BAp4BAp4BAp4BAgAA");
1645 todo_wine ok(match, "Figure does not match.\n");
1646 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
1647 "4VIBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQEjDCMB7AECHhQeAu0BAxoYGgPvAQMWHhYD8QEDFCAU"
1648 "A/MBBBAkEAT0AQUOJw0F9QEGCioKBvcBBggsCAb4AQgFLgUI+QEJATIBCfsBCAIwAgj8AQcFLAUH"
1649 "/QEFCCgIBf4BBAwiDAT/AQIQHBAClwISlwIBPgGAAgI8Av8BAzwD/QEEPAT7AQY6BvkBBzoH+AEI"
1650 "OAj3AQk4CfYBCTgK9AELNgvzAQw2DPIBDDYM8QEONA7wAQ40DvABDjQO7wEPNA/uAQ80D+4BEDIQ"
1651 "7QERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewBETIR7AERMhHsAREyEewB"
1652 "ETIR7AERMhHsAREyEe0BEDIQ7gEQMw/uAQ80D+4BDzQP7wEONA7wAQ40DvEBDDYM8gEMNgzzAQs2"
1653 "C/QBCzcK9QEJOAn3AQg4CfcBBzoH+QEGOgb7AQU6BfwBBDwE/QEDPAP/AQE+AZkCDpkCAhIYEgKA"
1654 "AgMNIA0D/wEFCSYJBf4BBgYqBgf8AQgDLgMI+wFG+gEIAzADCPkBBwYuBgf3AQYKKgoG9gEFDCgM"
1655 "BfUBBBAlDwTzAQQSIhIE8QEDFh4WA/ABAhkaGQLvAQIcFhwC7QECIBAgAusBASgEKAHpAQFWAecB"
1656 "AVgB5QEBWgHAAgEA");
1657 todo_wine ok(match, "Figure does not match.\n");
1658 ID2D1TransformedGeometry_Release(transformed_geometry);
1659 ID2D1PathGeometry_Release(geometry);
1661 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1662 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1663 hr = ID2D1PathGeometry_Open(geometry, &sink);
1664 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1665 fill_geometry_sink_bezier(sink);
1666 ID2D1GeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
1667 hr = ID2D1GeometrySink_Close(sink);
1668 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1669 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1670 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1671 ok(count == 2, "Got unexpected figure count %u.\n", count);
1672 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1673 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1674 ok(count == 10, "Got unexpected segment count %u.\n", count);
1675 ID2D1GeometrySink_Release(sink);
1677 set_matrix_identity(&matrix);
1678 scale_matrix(&matrix, 0.5f, 2.0f);
1679 translate_matrix(&matrix, 127.0f, 80.0f);
1680 rotate_matrix(&matrix, M_PI / -4.0f);
1681 scale_matrix(&matrix, 2.0f, 0.5f);
1682 hr = ID2D1Factory_CreateTransformedGeometry(factory, (ID2D1Geometry *)geometry, &matrix, &transformed_geometry);
1683 ok(SUCCEEDED(hr), "Failed to create transformed geometry, hr %#x.\n", hr);
1685 ID2D1RenderTarget_BeginDraw(rt);
1686 ID2D1RenderTarget_Clear(rt, &color);
1687 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1688 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)transformed_geometry, (ID2D1Brush *)brush, NULL);
1689 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1690 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1691 match = compare_figure(surface, 0, 0, 160, 160, 0xff652e89, 64,
1692 "7xoCngECngECngECngECngECngECngECnQEEnAEEnAEEnAEEnAEEmwEGmgEGmgEGmgEGmQEImAEI"
1693 "lAEQiwEagQEjeyh2LHIwbjNsNmk4ZzplPGM+YUBfQl1DXURbRlpGWUhYSFdKVkpVS1VMVExUTFRM"
1694 "U05STlJOUk5STlFQUFBQUFBQTlRIXD9mMnYqdjJmP1xIVE5QUFBQUFBQUU5STlJOUk5STlNMVExU"
1695 "TFRMVEtWSlZKV0hYSFlGWkZbRFxDXkJfQGE+YzxlOmc4aTZrM28wcix2KHojggEaiwEQlAEImAEI"
1696 "mQEGmgEGmgEGmgEGmwEEnAEEnAEEnAEEnAEEnQECngECngECngECngECngECngECngEC");
1697 ok(match, "Figure does not match.\n");
1698 match = compare_figure(surface, 160, 0, 320, 160, 0xff652e89, 64,
1699 "4VIBwAIBWgHlAQFYAecBAVYB6QEBVAHrAQIhDiIB7QECHRUdAu4BAhkaGQPvAQMWHhYD8QEEEyET"
1700 "A/MBBBAkEAT1AQUMKA0F9QEGCioKBvcBBwctBwb5AQgELwQI+QEJATIBCfsBRP0BQ/0BQv8BQf8B"
1701 "QIECP4ACQIACQf4BQ/wBRPsBRvoBR/gBSPcBSvYBS/QBTPMBTvIBTvIBT/ABUPABUe4BUu4BUu4B"
1702 "U+0BU+wBVOwBVOwBVOwBVOwBVesBVesBVesBVesBVOwBVOwBVOwBVO0BU+0BU+0BUu4BUu8BUe8B"
1703 "UPEBT/EBTvIBTvMBTPUBS/UBSvcBSfcBSPkBRvsBRP0BQ/4BQf8BQIECP4ACQIACQf4BQv4BQ/wB"
1704 "RPsBCQEyAQn6AQgELwQI+AEHBy0GB/cBBgoqCgb2AQUMKA0F9AEEECUPBPMBBBIiEwPxAQMWHhYD"
1705 "8AECGRoZA+4BAh0VHQLsAQIhDiIB6wEBVAHpAQFWAecBAVgB5QEBWgHAAgEA");
1706 ok(match, "Figure does not match.\n");
1707 ID2D1TransformedGeometry_Release(transformed_geometry);
1708 ID2D1PathGeometry_Release(geometry);
1710 hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
1711 ok(SUCCEEDED(hr), "Failed to create path geometry, hr %#x.\n", hr);
1712 hr = ID2D1PathGeometry_Open(geometry, &sink);
1713 ok(SUCCEEDED(hr), "Failed to open geometry sink, hr %#x.\n", hr);
1715 set_point(&point, 40.0f, 20.0f);
1716 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1717 set_point(&point, 75.0f, 300.0f);
1718 ID2D1GeometrySink_AddLine(sink, point);
1719 set_point(&point, 5.0f, 300.0f);
1720 ID2D1GeometrySink_AddLine(sink, point);
1721 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1723 set_point(&point, 40.0f, 290.0f);
1724 ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
1725 set_point(&point, 55.0f, 160.0f);
1726 ID2D1GeometrySink_AddLine(sink, point);
1727 set_point(&point, 25.0f, 160.0f);
1728 ID2D1GeometrySink_AddLine(sink, point);
1729 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
1731 hr = ID2D1GeometrySink_Close(sink);
1732 ok(SUCCEEDED(hr), "Failed to close geometry sink, hr %#x.\n", hr);
1733 hr = ID2D1PathGeometry_GetFigureCount(geometry, &count);
1734 ok(SUCCEEDED(hr), "Failed to get figure count, hr %#x.\n", hr);
1735 ok(count == 2, "Got unexpected figure count %u.\n", count);
1736 hr = ID2D1PathGeometry_GetSegmentCount(geometry, &count);
1737 ok(SUCCEEDED(hr), "Failed to get segment count, hr %#x.\n", hr);
1738 ok(count == 6, "Got unexpected segment count %u.\n", count);
1739 ID2D1GeometrySink_Release(sink);
1741 ID2D1RenderTarget_BeginDraw(rt);
1742 ID2D1RenderTarget_Clear(rt, &color);
1743 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry, (ID2D1Brush *)brush, NULL);
1744 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
1745 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
1746 match = compare_surface(surface, "a875e68e0cb9c055927b1b50b879f90b24e38470");
1747 ok(match, "Surface does not match.\n");
1748 ID2D1PathGeometry_Release(geometry);
1750 ID2D1SolidColorBrush_Release(brush);
1751 ID2D1RenderTarget_Release(rt);
1752 refcount = ID2D1Factory_Release(factory);
1753 ok(!refcount, "Factory has %u references left.\n", refcount);
1754 IDXGISurface_Release(surface);
1755 IDXGISwapChain_Release(swapchain);
1756 ID3D10Device1_Release(device);
1757 DestroyWindow(window);
1760 static void test_rectangle_geometry(void)
1762 ID2D1RectangleGeometry *geometry;
1763 D2D1_RECT_F rect, rect2;
1764 ID2D1Factory *factory;
1765 D2D1_POINT_2F point;
1766 BOOL contains;
1767 HRESULT hr;
1769 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
1770 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
1772 set_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f);
1773 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
1774 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
1775 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
1776 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
1777 rect2.left, rect2.top, rect2.right, rect2.bottom);
1778 ID2D1RectangleGeometry_Release(geometry);
1780 set_rect(&rect, 50.0f, 0.0f, 40.0f, 100.0f);
1781 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
1782 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
1783 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
1784 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
1785 rect2.left, rect2.top, rect2.right, rect2.bottom);
1786 ID2D1RectangleGeometry_Release(geometry);
1788 set_rect(&rect, 0.0f, 100.0f, 40.0f, 50.0f);
1789 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
1790 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
1791 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
1792 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
1793 rect2.left, rect2.top, rect2.right, rect2.bottom);
1794 ID2D1RectangleGeometry_Release(geometry);
1796 set_rect(&rect, 50.0f, 100.0f, 40.0f, 50.0f);
1797 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
1798 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
1799 ID2D1RectangleGeometry_GetRect(geometry, &rect2);
1800 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e}.\n",
1801 rect2.left, rect2.top, rect2.right, rect2.bottom);
1802 ID2D1RectangleGeometry_Release(geometry);
1804 set_rect(&rect, 0.0f, 0.0f, 10.0f, 20.0f);
1805 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
1806 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
1808 /* Edge. */
1809 contains = FALSE;
1810 set_point(&point, 0.0f, 0.0f);
1811 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
1812 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
1813 ok(!!contains, "Got wrong hit test result %d.\n", contains);
1815 /* Within tolerance limit around corner. */
1816 contains = TRUE;
1817 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE, 0.0f);
1818 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
1819 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
1820 ok(!contains, "Got wrong hit test result %d.\n", contains);
1822 contains = FALSE;
1823 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE + 0.01f, 0.0f);
1824 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
1825 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
1826 ok(!!contains, "Got wrong hit test result %d.\n", contains);
1828 contains = TRUE;
1829 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE - 0.01f, 0.0f);
1830 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
1831 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
1832 ok(!contains, "Got wrong hit test result %d.\n", contains);
1834 contains = TRUE;
1835 set_point(&point, -D2D1_DEFAULT_FLATTENING_TOLERANCE, -D2D1_DEFAULT_FLATTENING_TOLERANCE);
1836 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
1837 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
1838 ok(!contains, "Got wrong hit test result %d.\n", contains);
1840 /* Inside. */
1841 contains = FALSE;
1842 set_point(&point, 5.0f, 5.0f);
1843 hr = ID2D1RectangleGeometry_FillContainsPoint(geometry, point, NULL, 0.0f, &contains);
1844 ok(SUCCEEDED(hr), "FillContainsPoint() failed, hr %#x.\n", hr);
1845 ok(!!contains, "Got wrong hit test result %d.\n", contains);
1847 ID2D1RectangleGeometry_Release(geometry);
1849 ID2D1Factory_Release(factory);
1852 static void test_rounded_rectangle_geometry(void)
1854 ID2D1RoundedRectangleGeometry *geometry;
1855 D2D1_ROUNDED_RECT rect, rect2;
1856 ID2D1Factory *factory;
1857 HRESULT hr;
1859 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
1860 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
1862 set_rounded_rect(&rect, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
1863 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
1864 todo_wine
1865 ok(SUCCEEDED(hr), "Failed to create geometry, hr %#x.\n", hr);
1866 if (FAILED(hr))
1868 ID2D1Factory_Release(factory);
1869 return;
1872 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
1873 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1874 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
1875 ID2D1RoundedRectangleGeometry_Release(geometry);
1877 /* X radius larger than half width. */
1878 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 30.0f, 5.0f);
1879 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
1880 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
1881 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1882 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
1883 ID2D1RoundedRectangleGeometry_Release(geometry);
1885 /* Y radius larger than half height. */
1886 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 5.0f, 30.0f);
1887 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
1888 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
1889 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1890 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
1891 ID2D1RoundedRectangleGeometry_Release(geometry);
1893 /* Both exceed rectangle size. */
1894 set_rounded_rect(&rect, 0.0f, 0.0f, 50.0f, 40.0f, 30.0f, 25.0f);
1895 hr = ID2D1Factory_CreateRoundedRectangleGeometry(factory, &rect, &geometry);
1896 ID2D1RoundedRectangleGeometry_GetRoundedRect(geometry, &rect2);
1897 ok(!memcmp(&rect, &rect2, sizeof(rect)), "Got unexpected rectangle {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
1898 rect2.rect.left, rect2.rect.top, rect2.rect.right, rect2.rect.bottom, rect2.radiusX, rect2.radiusY);
1899 ID2D1RoundedRectangleGeometry_Release(geometry);
1901 ID2D1Factory_Release(factory);
1904 static void test_bitmap_formats(void)
1906 D2D1_BITMAP_PROPERTIES bitmap_desc;
1907 IDXGISwapChain *swapchain;
1908 D2D1_SIZE_U size = {4, 4};
1909 ID2D1RenderTarget *rt;
1910 ID3D10Device1 *device;
1911 IDXGISurface *surface;
1912 ID2D1Bitmap *bitmap;
1913 unsigned int i, j;
1914 HWND window;
1915 HRESULT hr;
1917 static const struct
1919 DXGI_FORMAT format;
1920 DWORD mask;
1922 bitmap_formats[] =
1924 {DXGI_FORMAT_R32G32B32A32_FLOAT, 0x8a},
1925 {DXGI_FORMAT_R16G16B16A16_FLOAT, 0x8a},
1926 {DXGI_FORMAT_R16G16B16A16_UNORM, 0x8a},
1927 {DXGI_FORMAT_R8G8B8A8_TYPELESS, 0x00},
1928 {DXGI_FORMAT_R8G8B8A8_UNORM, 0x0a},
1929 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0x8a},
1930 {DXGI_FORMAT_R8G8B8A8_UINT, 0x00},
1931 {DXGI_FORMAT_R8G8B8A8_SNORM, 0x00},
1932 {DXGI_FORMAT_R8G8B8A8_SINT, 0x00},
1933 {DXGI_FORMAT_A8_UNORM, 0x06},
1934 {DXGI_FORMAT_B8G8R8A8_UNORM, 0x0a},
1935 {DXGI_FORMAT_B8G8R8X8_UNORM, 0x88},
1936 {DXGI_FORMAT_B8G8R8A8_TYPELESS, 0x00},
1937 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, 0x8a},
1940 if (!(device = create_device()))
1942 skip("Failed to create device, skipping tests.\n");
1943 return;
1945 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1946 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1947 swapchain = create_swapchain(device, window, TRUE);
1948 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
1949 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
1950 rt = create_render_target(surface);
1951 ok(!!rt, "Failed to create render target.\n");
1953 bitmap_desc.dpiX = 96.0f;
1954 bitmap_desc.dpiY = 96.0f;
1955 for (i = 0; i < sizeof(bitmap_formats) / sizeof(*bitmap_formats); ++i)
1957 for (j = 0; j < 4; ++j)
1959 if ((bitmap_formats[i].mask & (0x80 | (1u << j))) == (0x80 | (1u << j)))
1960 continue;
1962 bitmap_desc.pixelFormat.format = bitmap_formats[i].format;
1963 bitmap_desc.pixelFormat.alphaMode = j;
1964 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
1965 if (bitmap_formats[i].mask & (1u << j))
1966 ok(hr == S_OK, "Got unexpected hr %#x, for format %#x/%#x.\n",
1967 hr, bitmap_formats[i].format, j);
1968 else
1969 ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "Got unexpected hr %#x, for format %#x/%#x.\n",
1970 hr, bitmap_formats[i].format, j);
1971 if (SUCCEEDED(hr))
1972 ID2D1Bitmap_Release(bitmap);
1976 ID2D1RenderTarget_Release(rt);
1977 IDXGISurface_Release(surface);
1978 IDXGISwapChain_Release(swapchain);
1979 ID3D10Device1_Release(device);
1980 DestroyWindow(window);
1983 static void test_alpha_mode(void)
1985 D2D1_RENDER_TARGET_PROPERTIES rt_desc;
1986 D2D1_BITMAP_PROPERTIES bitmap_desc;
1987 ID2D1SolidColorBrush *color_brush;
1988 ID2D1BitmapBrush *bitmap_brush;
1989 IDXGISwapChain *swapchain;
1990 ID2D1RenderTarget *rt;
1991 ID3D10Device1 *device;
1992 IDXGISurface *surface;
1993 ID2D1Bitmap *bitmap;
1994 D2D1_COLOR_F color;
1995 D2D1_RECT_F rect;
1996 D2D1_SIZE_U size;
1997 ULONG refcount;
1998 HWND window;
1999 HRESULT hr;
2000 BOOL match;
2002 static const DWORD bitmap_data[] =
2004 0x7f7f0000, 0x7f7f7f00, 0x7f007f00, 0x7f007f7f,
2005 0x7f00007f, 0x7f7f007f, 0x7f000000, 0x7f404040,
2006 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f000000,
2007 0x7f7f7f7f, 0x7f000000, 0x7f000000, 0x7f000000,
2010 if (!(device = create_device()))
2012 skip("Failed to create device, skipping tests.\n");
2013 return;
2015 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2016 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2017 swapchain = create_swapchain(device, window, TRUE);
2018 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2019 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2020 rt = create_render_target(surface);
2021 ok(!!rt, "Failed to create render target.\n");
2023 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2025 set_size_u(&size, 4, 4);
2026 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2027 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
2028 bitmap_desc.dpiX = 96.0f / 40.0f;
2029 bitmap_desc.dpiY = 96.0f / 30.0f;
2030 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
2031 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2033 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
2034 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
2035 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
2036 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
2037 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
2039 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
2040 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
2041 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
2043 ID2D1RenderTarget_BeginDraw(rt);
2044 ID2D1RenderTarget_Clear(rt, NULL);
2045 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2046 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2047 match = compare_surface(surface, "48c41aff3a130a17ee210866b2ab7d36763934d5");
2048 ok(match, "Surface does not match.\n");
2050 ID2D1RenderTarget_BeginDraw(rt);
2051 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
2052 ID2D1RenderTarget_Clear(rt, &color);
2053 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2054 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2055 match = compare_surface(surface, "6487e683730fb5a77c1911388d00b04664c5c4e4");
2056 ok(match, "Surface does not match.\n");
2058 ID2D1RenderTarget_BeginDraw(rt);
2059 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
2060 ID2D1RenderTarget_Clear(rt, &color);
2061 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2062 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2063 match = compare_surface(surface, "7a35ba09e43cbaf591388ff1ef8de56157630c98");
2064 ok(match, "Surface does not match.\n");
2066 ID2D1RenderTarget_BeginDraw(rt);
2068 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
2069 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2070 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
2071 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
2072 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2073 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
2074 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
2075 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2077 ID2D1Bitmap_Release(bitmap);
2078 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2079 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
2080 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2081 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
2083 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
2084 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
2085 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2086 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
2087 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
2088 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2089 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
2090 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
2091 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2093 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
2094 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
2095 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
2096 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
2097 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
2098 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
2099 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
2100 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
2102 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2103 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2104 match = compare_surface(surface, "14f8ac64b70966c7c3c6281c59aaecdb17c3b16a");
2105 ok(match, "Surface does not match.\n");
2107 ID2D1RenderTarget_Release(rt);
2108 rt_desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
2109 rt_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
2110 rt_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
2111 rt_desc.dpiX = 0.0f;
2112 rt_desc.dpiY = 0.0f;
2113 rt_desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
2114 rt_desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
2115 rt = create_render_target_desc(surface, &rt_desc);
2116 ok(!!rt, "Failed to create render target.\n");
2118 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2120 ID2D1Bitmap_Release(bitmap);
2121 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
2122 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
2123 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2124 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
2126 ID2D1BitmapBrush_Release(bitmap_brush);
2127 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
2128 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
2129 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
2130 ID2D1BitmapBrush_SetExtendModeX(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
2131 ID2D1BitmapBrush_SetExtendModeY(bitmap_brush, D2D1_EXTEND_MODE_WRAP);
2133 ID2D1SolidColorBrush_Release(color_brush);
2134 set_color(&color, 0.0f, 1.0f, 0.0f, 0.75f);
2135 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
2136 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
2138 ID2D1RenderTarget_BeginDraw(rt);
2139 ID2D1RenderTarget_Clear(rt, NULL);
2140 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2141 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2142 match = compare_surface(surface, "b44510bf2d2e61a8d7c0ad862de49a471f1fd13f");
2143 ok(match, "Surface does not match.\n");
2145 ID2D1RenderTarget_BeginDraw(rt);
2146 set_color(&color, 1.0f, 0.0f, 0.0f, 0.25f);
2147 ID2D1RenderTarget_Clear(rt, &color);
2148 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2149 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2150 match = compare_surface(surface, "2184f4a9198fc1de09ac85301b7a03eebadd9b81");
2151 ok(match, "Surface does not match.\n");
2153 ID2D1RenderTarget_BeginDraw(rt);
2154 set_color(&color, 0.0f, 0.0f, 1.0f, 0.75f);
2155 ID2D1RenderTarget_Clear(rt, &color);
2156 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2157 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2158 match = compare_surface(surface, "6527ec83b4039c895b50f9b3e144fe0cf90d1889");
2159 ok(match, "Surface does not match.\n");
2161 ID2D1RenderTarget_BeginDraw(rt);
2163 set_rect(&rect, 0.0f, 0.0f, 160.0f, 120.0f);
2164 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2165 set_rect(&rect, 160.0f, 0.0f, 320.0f, 120.0f);
2166 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
2167 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2168 set_rect(&rect, 320.0f, 0.0f, 480.0f, 120.0f);
2169 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
2170 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2172 ID2D1Bitmap_Release(bitmap);
2173 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2174 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
2175 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2176 ID2D1BitmapBrush_SetBitmap(bitmap_brush, bitmap);
2178 set_rect(&rect, 0.0f, 120.0f, 160.0f, 240.0f);
2179 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 1.0f);
2180 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2181 set_rect(&rect, 160.0f, 120.0f, 320.0f, 240.0f);
2182 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.75f);
2183 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2184 set_rect(&rect, 320.0f, 120.0f, 480.0f, 240.0f);
2185 ID2D1BitmapBrush_SetOpacity(bitmap_brush, 0.25f);
2186 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2188 set_rect(&rect, 0.0f, 240.0f, 160.0f, 360.0f);
2189 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
2190 set_rect(&rect, 160.0f, 240.0f, 320.0f, 360.0f);
2191 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.75f);
2192 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
2193 set_rect(&rect, 320.0f, 240.0f, 480.0f, 360.0f);
2194 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.25f);
2195 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
2197 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2198 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2199 match = compare_surface(surface, "465f5a3190d7bde408b3206b4be939fb22f8a3d6");
2200 ok(match, "Surface does not match.\n");
2202 refcount = ID2D1Bitmap_Release(bitmap);
2203 ok(refcount == 1, "Bitmap has %u references left.\n", refcount);
2204 ID2D1SolidColorBrush_Release(color_brush);
2205 ID2D1BitmapBrush_Release(bitmap_brush);
2206 ID2D1RenderTarget_Release(rt);
2207 IDXGISurface_Release(surface);
2208 IDXGISwapChain_Release(swapchain);
2209 ID3D10Device1_Release(device);
2210 DestroyWindow(window);
2213 static void test_shared_bitmap(void)
2215 IDXGISwapChain *swapchain1, *swapchain2;
2216 IWICBitmap *wic_bitmap1, *wic_bitmap2;
2217 D2D1_RENDER_TARGET_PROPERTIES desc;
2218 D2D1_BITMAP_PROPERTIES bitmap_desc;
2219 IDXGISurface *surface1, *surface2;
2220 ID2D1Factory *factory1, *factory2;
2221 ID3D10Device1 *device1, *device2;
2222 IWICImagingFactory *wic_factory;
2223 ID2D1Bitmap *bitmap1, *bitmap2;
2224 DXGI_SURFACE_DESC surface_desc;
2225 ID2D1RenderTarget *rt1, *rt2;
2226 D2D1_SIZE_U size = {4, 4};
2227 IDXGISurface1 *surface3;
2228 HWND window1, window2;
2229 HRESULT hr;
2231 if (!(device1 = create_device()))
2233 skip("Failed to create device, skipping tests.\n");
2234 return;
2237 window1 = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2238 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2239 window2 = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2240 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2241 swapchain1 = create_swapchain(device1, window1, TRUE);
2242 swapchain2 = create_swapchain(device1, window2, TRUE);
2243 hr = IDXGISwapChain_GetBuffer(swapchain1, 0, &IID_IDXGISurface, (void **)&surface1);
2244 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2245 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
2246 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2248 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2249 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
2250 &IID_IWICImagingFactory, (void **)&wic_factory);
2251 ok(SUCCEEDED(hr), "Failed to create WIC imaging factory, hr %#x.\n", hr);
2252 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
2253 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap1);
2254 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2255 hr = IWICImagingFactory_CreateBitmap(wic_factory, 640, 480,
2256 &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &wic_bitmap2);
2257 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2258 IWICImagingFactory_Release(wic_factory);
2260 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
2261 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
2262 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2263 desc.dpiX = 0.0f;
2264 desc.dpiY = 0.0f;
2265 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
2266 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
2268 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2269 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2270 bitmap_desc.dpiX = 96.0f;
2271 bitmap_desc.dpiY = 96.0f;
2273 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory1);
2274 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2275 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
2276 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2278 /* DXGI surface render targets with the same device and factory. */
2279 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface1, &desc, &rt1);
2280 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2281 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
2282 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2284 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
2285 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2286 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2287 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2288 ID2D1Bitmap_Release(bitmap2);
2289 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IUnknown, bitmap1, NULL, &bitmap2);
2290 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2291 ID2D1RenderTarget_Release(rt2);
2293 /* DXGI surface render targets with the same device but different factories. */
2294 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
2295 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2296 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2297 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
2298 ID2D1RenderTarget_Release(rt2);
2300 /* DXGI surface render targets with different devices but the same factory. */
2301 IDXGISurface_Release(surface2);
2302 IDXGISwapChain_Release(swapchain2);
2303 device2 = create_device();
2304 ok(!!device2, "Failed to create device.\n");
2305 swapchain2 = create_swapchain(device2, window2, TRUE);
2306 hr = IDXGISwapChain_GetBuffer(swapchain2, 0, &IID_IDXGISurface, (void **)&surface2);
2307 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2309 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
2310 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2311 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2312 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
2313 ID2D1RenderTarget_Release(rt2);
2315 /* DXGI surface render targets with different devices and different factories. */
2316 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface2, &desc, &rt2);
2317 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2318 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2319 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
2320 ID2D1RenderTarget_Release(rt2);
2322 /* DXGI surface render target and WIC bitmap render target, same factory. */
2323 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
2324 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2325 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2326 ok(hr == D2DERR_UNSUPPORTED_OPERATION, "Got unexpected hr %#x.\n", hr);
2327 ID2D1RenderTarget_Release(rt2);
2329 /* WIC bitmap render targets on different D2D factories. */
2330 ID2D1Bitmap_Release(bitmap1);
2331 ID2D1RenderTarget_Release(rt1);
2332 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap1, &desc, &rt1);
2333 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2334 hr = ID2D1RenderTarget_CreateBitmap(rt1, size, NULL, 0, &bitmap_desc, &bitmap1);
2335 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2337 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory2, wic_bitmap2, &desc, &rt2);
2338 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2339 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2340 ok(hr == D2DERR_WRONG_FACTORY, "Got unexpected hr %#x.\n", hr);
2341 ID2D1RenderTarget_Release(rt2);
2343 /* WIC bitmap render targets on the same D2D factory. */
2344 hr = ID2D1Factory_CreateWicBitmapRenderTarget(factory1, wic_bitmap2, &desc, &rt2);
2345 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2346 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_ID2D1Bitmap, bitmap1, NULL, &bitmap2);
2347 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2348 ID2D1Bitmap_Release(bitmap2);
2349 ID2D1RenderTarget_Release(rt2);
2351 /* Shared DXGI surface. */
2352 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
2353 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2354 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2355 desc.dpiX = 0.0f;
2356 desc.dpiY = 0.0f;
2357 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
2358 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
2360 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory1, surface2, &desc, &rt2);
2361 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2363 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2364 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2365 bitmap_desc.dpiX = 0.0f;
2366 bitmap_desc.dpiY = 0.0f;
2368 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface, surface2, &bitmap_desc, &bitmap2);
2369 ok(SUCCEEDED(hr) || broken(hr == E_INVALIDARG) /* vista */, "Failed to create bitmap, hr %#x.\n", hr);
2371 if (SUCCEEDED(hr))
2373 size = ID2D1Bitmap_GetPixelSize(bitmap2);
2374 hr = IDXGISurface_GetDesc(surface2, &surface_desc);
2375 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
2376 ok(size.width == surface_desc.Width && size.height == surface_desc.Height, "Got wrong bitmap size.\n");
2378 ID2D1Bitmap_Release(bitmap2);
2380 /* IDXGISurface1 is supported too. */
2381 if (IDXGISurface_QueryInterface(surface2, &IID_IDXGISurface1, (void **)&surface3) == S_OK)
2383 hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface1, surface3, &bitmap_desc, &bitmap2);
2384 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2386 ID2D1Bitmap_Release(bitmap2);
2387 IDXGISurface1_Release(surface3);
2391 ID2D1RenderTarget_Release(rt2);
2393 ID2D1Bitmap_Release(bitmap1);
2394 ID2D1RenderTarget_Release(rt1);
2395 ID2D1Factory_Release(factory2);
2396 ID2D1Factory_Release(factory1);
2397 IWICBitmap_Release(wic_bitmap2);
2398 IWICBitmap_Release(wic_bitmap1);
2399 IDXGISurface_Release(surface2);
2400 IDXGISurface_Release(surface1);
2401 IDXGISwapChain_Release(swapchain2);
2402 IDXGISwapChain_Release(swapchain1);
2403 ID3D10Device1_Release(device2);
2404 ID3D10Device1_Release(device1);
2405 DestroyWindow(window2);
2406 DestroyWindow(window1);
2407 CoUninitialize();
2410 static void test_bitmap_updates(void)
2412 D2D1_BITMAP_PROPERTIES bitmap_desc;
2413 IDXGISwapChain *swapchain;
2414 ID2D1RenderTarget *rt;
2415 ID3D10Device1 *device;
2416 IDXGISurface *surface;
2417 D2D1_RECT_U dst_rect;
2418 ID2D1Bitmap *bitmap;
2419 D2D1_COLOR_F color;
2420 D2D1_RECT_F rect;
2421 D2D1_SIZE_U size;
2422 HWND window;
2423 HRESULT hr;
2424 BOOL match;
2426 static const DWORD bitmap_data[] =
2428 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
2429 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
2430 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
2431 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
2434 if (!(device = create_device()))
2436 skip("Failed to create device, skipping tests.\n");
2437 return;
2439 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2440 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2441 swapchain = create_swapchain(device, window, TRUE);
2442 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2443 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2444 rt = create_render_target(surface);
2445 ok(!!rt, "Failed to create render target.\n");
2447 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2449 ID2D1RenderTarget_BeginDraw(rt);
2450 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
2451 ID2D1RenderTarget_Clear(rt, &color);
2453 set_size_u(&size, 4, 4);
2454 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2455 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2456 bitmap_desc.dpiX = 96.0f;
2457 bitmap_desc.dpiY = 96.0f;
2458 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
2459 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2461 set_rect(&rect, 0.0f, 0.0f, 320.0f, 240.0f);
2462 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2463 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2465 ID2D1Bitmap_Release(bitmap);
2467 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
2468 hr = ID2D1RenderTarget_CreateBitmap(rt, size, NULL, 0, &bitmap_desc, &bitmap);
2469 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2471 set_rect(&rect, 0.0f, 240.0f, 320.0f, 480.0f);
2472 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2473 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2475 set_rect_u(&dst_rect, 1, 1, 3, 3);
2476 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, 4 * sizeof(*bitmap_data));
2477 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2478 set_rect_u(&dst_rect, 0, 3, 3, 4);
2479 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[6], 4 * sizeof(*bitmap_data));
2480 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2481 set_rect_u(&dst_rect, 0, 0, 4, 1);
2482 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[10], 4 * sizeof(*bitmap_data));
2483 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2484 set_rect_u(&dst_rect, 0, 1, 1, 3);
2485 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, &bitmap_data[2], sizeof(*bitmap_data));
2486 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2487 set_rect_u(&dst_rect, 4, 4, 3, 1);
2488 hr = ID2D1Bitmap_CopyFromMemory(bitmap, &dst_rect, bitmap_data, sizeof(*bitmap_data));
2489 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2490 set_rect(&rect, 320.0f, 240.0f, 640.0f, 480.0f);
2491 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2492 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2494 hr = ID2D1Bitmap_CopyFromMemory(bitmap, NULL, bitmap_data, 4 * sizeof(*bitmap_data));
2495 ok(SUCCEEDED(hr), "Failed to update bitmap, hr %#x.\n", hr);
2496 set_rect(&rect, 320.0f, 0.0f, 640.0f, 240.0f);
2497 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &rect, 1.0f,
2498 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
2500 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2501 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2503 match = compare_surface(surface, "cb8136c91fbbdc76bb83b8c09edc1907b0a5d0a6");
2504 ok(match, "Surface does not match.\n");
2506 ID2D1Bitmap_Release(bitmap);
2507 ID2D1RenderTarget_Release(rt);
2508 IDXGISurface_Release(surface);
2509 IDXGISwapChain_Release(swapchain);
2510 ID3D10Device1_Release(device);
2511 DestroyWindow(window);
2514 static void test_opacity_brush(void)
2516 ID2D1BitmapBrush *bitmap_brush, *opacity_brush;
2517 D2D1_BITMAP_PROPERTIES bitmap_desc;
2518 ID2D1RectangleGeometry *geometry;
2519 ID2D1SolidColorBrush *color_brush;
2520 IDXGISwapChain *swapchain;
2521 D2D1_MATRIX_3X2_F matrix;
2522 ID2D1RenderTarget *rt;
2523 ID3D10Device1 *device;
2524 IDXGISurface *surface;
2525 ID2D1Factory *factory;
2526 ID2D1Bitmap *bitmap;
2527 D2D1_COLOR_F color;
2528 D2D1_RECT_F rect;
2529 D2D1_SIZE_U size;
2530 ULONG refcount;
2531 HWND window;
2532 HRESULT hr;
2533 BOOL match;
2535 static const DWORD bitmap_data[] =
2537 0xffff0000, 0x40ffff00, 0x4000ff00, 0xff00ffff,
2538 0x7f0000ff, 0x00ff00ff, 0x00000000, 0x7f7f7f7f,
2539 0x7fffffff, 0x00ffffff, 0x00ffffff, 0x7f000000,
2540 0xffffffff, 0x40000000, 0x40000000, 0xff000000,
2543 if (!(device = create_device()))
2545 skip("Failed to create device, skipping tests.\n");
2546 return;
2548 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2549 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2550 swapchain = create_swapchain(device, window, TRUE);
2551 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2552 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2553 rt = create_render_target(surface);
2554 ok(!!rt, "Failed to create render target.\n");
2555 ID2D1RenderTarget_GetFactory(rt, &factory);
2557 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
2558 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
2560 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
2561 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &color_brush);
2562 ok(SUCCEEDED(hr), "Failed to create color brush, hr %#x.\n", hr);
2564 set_size_u(&size, 4, 4);
2565 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2566 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2567 bitmap_desc.dpiX = 96.0f;
2568 bitmap_desc.dpiY = 96.0f;
2569 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
2570 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2571 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &opacity_brush);
2572 ok(SUCCEEDED(hr), "Failed to create bitmap brush, hr %#x.\n", hr);
2573 ID2D1BitmapBrush_SetInterpolationMode(opacity_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
2574 refcount = ID2D1Bitmap_Release(bitmap);
2575 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
2577 set_size_u(&size, 1, 1);
2578 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2579 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
2580 bitmap_desc.dpiX = 96.0f;
2581 bitmap_desc.dpiY = 96.0f;
2582 hr = ID2D1RenderTarget_CreateBitmap(rt, size, &bitmap_data[2], sizeof(*bitmap_data), &bitmap_desc, &bitmap);
2583 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
2584 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &bitmap_brush);
2585 ok(SUCCEEDED(hr), "Failed to create bitmap brush, hr %#x.\n", hr);
2586 ID2D1BitmapBrush_SetInterpolationMode(bitmap_brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
2587 refcount = ID2D1Bitmap_Release(bitmap);
2588 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
2590 ID2D1RenderTarget_BeginDraw(rt);
2592 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
2593 ID2D1RenderTarget_Clear(rt, &color);
2595 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
2596 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)color_brush);
2598 set_matrix_identity(&matrix);
2599 translate_matrix(&matrix, 120.0f, 120.0f);
2600 scale_matrix(&matrix, 20.0f, 60.0f);
2601 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2602 set_rect(&rect, 120.0f, 120.0f, 200.0f, 360.0f);
2603 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)opacity_brush);
2605 set_rect(&rect, 200.0f, 120.0f, 280.0f, 360.0f);
2606 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)bitmap_brush);
2608 set_matrix_identity(&matrix);
2609 translate_matrix(&matrix, 40.0f, 360.0f);
2610 scale_matrix(&matrix, 20.0f, 60.0f);
2611 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2612 set_rect(&rect, 40.0f, 360.0f, 120.0f, 600.0f);
2613 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2614 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2615 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
2616 ID2D1RectangleGeometry_Release(geometry);
2618 set_matrix_identity(&matrix);
2619 translate_matrix(&matrix, 120.0f, 360.0f);
2620 scale_matrix(&matrix, 20.0f, 60.0f);
2621 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2622 set_rect(&rect, 120.0f, 360.0f, 200.0f, 600.0f);
2623 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2624 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2625 (ID2D1Brush *)color_brush, (ID2D1Brush *)opacity_brush);
2626 ID2D1RectangleGeometry_Release(geometry);
2628 set_matrix_identity(&matrix);
2629 translate_matrix(&matrix, 200.0f, 360.0f);
2630 scale_matrix(&matrix, 20.0f, 60.0f);
2631 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2632 set_rect(&rect, 200.0f, 360.0f, 280.0f, 600.0f);
2633 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2634 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2635 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
2637 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2638 ok(hr == D2DERR_INCOMPATIBLE_BRUSH_TYPES, "Got unexpected hr %#x.\n", hr);
2639 match = compare_surface(surface, "7141c6c7b3decb91196428efb1856bcbf9872935");
2640 ok(match, "Surface does not match.\n");
2641 ID2D1RenderTarget_BeginDraw(rt);
2643 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2644 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
2645 ID2D1RectangleGeometry_Release(geometry);
2647 ID2D1SolidColorBrush_SetOpacity(color_brush, 0.5f);
2648 set_matrix_identity(&matrix);
2649 translate_matrix(&matrix, 40.0f, 600.0f);
2650 scale_matrix(&matrix, 20.0f, 60.0f);
2651 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2652 set_rect(&rect, 40.0f, 600.0f, 120.0f, 840.0f);
2653 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2654 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2655 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)color_brush);
2656 ID2D1RectangleGeometry_Release(geometry);
2658 ID2D1BitmapBrush_SetOpacity(opacity_brush, 0.8f);
2659 set_matrix_identity(&matrix);
2660 translate_matrix(&matrix, 120.0f, 600.0f);
2661 scale_matrix(&matrix, 20.0f, 60.0f);
2662 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2663 set_rect(&rect, 120.0f, 600.0f, 200.0f, 840.0f);
2664 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2665 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2666 (ID2D1Brush *)opacity_brush, (ID2D1Brush *)bitmap_brush);
2667 ID2D1RectangleGeometry_Release(geometry);
2669 set_matrix_identity(&matrix);
2670 translate_matrix(&matrix, 200.0f, 600.0f);
2671 scale_matrix(&matrix, 20.0f, 60.0f);
2672 ID2D1BitmapBrush_SetTransform(opacity_brush, &matrix);
2673 set_rect(&rect, 200.0f, 600.0f, 280.0f, 840.0f);
2674 ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2675 ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry,
2676 (ID2D1Brush *)bitmap_brush, (ID2D1Brush *)opacity_brush);
2677 ID2D1RectangleGeometry_Release(geometry);
2679 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2680 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
2681 match = compare_surface(surface, "c3a5802d1750efa3e9122c1a92f6064df3872732");
2682 ok(match, "Surface does not match.\n");
2684 ID2D1BitmapBrush_Release(bitmap_brush);
2685 ID2D1BitmapBrush_Release(opacity_brush);
2686 ID2D1SolidColorBrush_Release(color_brush);
2687 ID2D1RenderTarget_Release(rt);
2688 refcount = ID2D1Factory_Release(factory);
2689 ok(!refcount, "Factory has %u references left.\n", refcount);
2690 IDXGISurface_Release(surface);
2691 IDXGISwapChain_Release(swapchain);
2692 ID3D10Device1_Release(device);
2693 DestroyWindow(window);
2696 static void test_create_target(void)
2698 IDXGISwapChain *swapchain;
2699 ID2D1Factory *factory;
2700 ID2D1RenderTarget *rt;
2701 ID3D10Device1 *device;
2702 IDXGISurface *surface;
2703 HWND window;
2704 HRESULT hr;
2705 static const struct
2707 float dpi_x, dpi_y;
2708 float rt_dpi_x, rt_dpi_y;
2709 HRESULT hr;
2711 create_dpi_tests[] =
2713 { 0.0f, 0.0f, 96.0f, 96.0f, S_OK },
2714 { 192.0f, 0.0f, 96.0f, 96.0f, E_INVALIDARG },
2715 { 0.0f, 192.0f, 96.0f, 96.0f, E_INVALIDARG },
2716 { 192.0f, -10.0f, 96.0f, 96.0f, E_INVALIDARG },
2717 { -10.0f, 192.0f, 96.0f, 96.0f, E_INVALIDARG },
2718 { 48.0f, 96.0f, 48.0f, 96.0f, S_OK },
2720 unsigned int i;
2722 if (!(device = create_device()))
2724 skip("Failed to create device, skipping tests.\n");
2725 return;
2727 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2728 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2729 swapchain = create_swapchain(device, window, TRUE);
2730 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2731 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2733 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
2734 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2736 for (i = 0; i < sizeof(create_dpi_tests) / sizeof(*create_dpi_tests); ++i)
2738 D2D1_RENDER_TARGET_PROPERTIES desc;
2739 float dpi_x, dpi_y;
2741 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
2742 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
2743 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2744 desc.dpiX = create_dpi_tests[i].dpi_x;
2745 desc.dpiY = create_dpi_tests[i].dpi_y;
2746 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
2747 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
2749 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt);
2750 ok(hr == create_dpi_tests[i].hr, "Wrong return code, hr %#x, expected %#x, test %u.\n", hr,
2751 create_dpi_tests[i].hr, i);
2753 if (FAILED(hr))
2754 continue;
2756 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
2757 ok(dpi_x == create_dpi_tests[i].rt_dpi_x, "Wrong dpi_x %.8e, expected %.8e, test %u\n",
2758 dpi_x, create_dpi_tests[i].rt_dpi_x, i);
2759 ok(dpi_y == create_dpi_tests[i].rt_dpi_y, "Wrong dpi_y %.8e, expected %.8e, test %u\n",
2760 dpi_y, create_dpi_tests[i].rt_dpi_y, i);
2762 ID2D1RenderTarget_Release(rt);
2765 ID2D1Factory_Release(factory);
2766 IDXGISurface_Release(surface);
2767 IDXGISwapChain_Release(swapchain);
2768 ID3D10Device1_Release(device);
2769 DestroyWindow(window);
2772 static void test_draw_text_layout(void)
2774 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
2775 static const WCHAR textW[] = {'t','e','x','t',0};
2776 static const WCHAR emptyW[] = {0};
2777 D2D1_RENDER_TARGET_PROPERTIES desc;
2778 IDXGISwapChain *swapchain;
2779 ID2D1Factory *factory, *factory2;
2780 ID2D1RenderTarget *rt, *rt2;
2781 ID3D10Device1 *device;
2782 IDXGISurface *surface;
2783 HWND window;
2784 HRESULT hr;
2785 IDWriteFactory *dwrite_factory;
2786 IDWriteTextFormat *text_format;
2787 IDWriteTextLayout *text_layout;
2788 D2D1_POINT_2F origin;
2789 DWRITE_TEXT_RANGE range;
2790 D2D1_COLOR_F color;
2791 ID2D1SolidColorBrush *brush, *brush2;
2792 ID2D1RectangleGeometry *geometry;
2793 D2D1_RECT_F rect;
2795 if (!(device = create_device()))
2797 skip("Failed to create device, skipping tests.\n");
2798 return;
2800 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2801 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2802 swapchain = create_swapchain(device, window, TRUE);
2803 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2804 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2806 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
2807 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2809 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory2);
2810 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2811 ok(factory != factory2, "got same factory\n");
2813 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
2814 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
2815 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2816 desc.dpiX = 0.0f;
2817 desc.dpiY = 0.0f;
2818 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
2819 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
2821 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &rt);
2822 ok(SUCCEEDED(hr), "Failed to create a target, hr %#x.\n", hr);
2824 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory2, surface, &desc, &rt2);
2825 ok(SUCCEEDED(hr), "Failed to create a target, hr %#x.\n", hr);
2827 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
2828 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2830 hr = IDWriteFactory_CreateTextFormat(dwrite_factory, tahomaW, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
2831 DWRITE_FONT_STRETCH_NORMAL, 10.0f, emptyW, &text_format);
2832 ok(SUCCEEDED(hr), "Failed to create text format, hr %#x.\n", hr);
2834 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, textW, 4, text_format, 100.0f, 100.0f, &text_layout);
2835 ok(SUCCEEDED(hr), "Failed to create text layout, hr %#x.\n", hr);
2837 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
2838 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
2839 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
2841 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt2, &color, NULL, &brush2);
2842 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
2844 /* effect brush is created from different factory */
2845 range.startPosition = 0;
2846 range.length = 4;
2847 hr = IDWriteTextLayout_SetDrawingEffect(text_layout, (IUnknown*)brush2, range);
2848 ok(SUCCEEDED(hr), "Failed to set drawing effect, hr %#x.\n", hr);
2850 ID2D1RenderTarget_BeginDraw(rt);
2852 origin.x = origin.y = 0.0f;
2853 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush*)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
2855 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2856 todo_wine
2857 ok(hr == D2DERR_WRONG_FACTORY, "EndDraw failure expected, hr %#x.\n", hr);
2859 /* Effect is d2d resource, but not a brush. */
2860 set_rect(&rect, 0.0f, 0.0f, 10.0f, 10.0f);
2861 hr = ID2D1Factory_CreateRectangleGeometry(factory, &rect, &geometry);
2862 ok(SUCCEEDED(hr), "Failed to geometry, hr %#x.\n", hr);
2864 range.startPosition = 0;
2865 range.length = 4;
2866 hr = IDWriteTextLayout_SetDrawingEffect(text_layout, (IUnknown*)geometry, range);
2867 ok(SUCCEEDED(hr), "Failed to set drawing effect, hr %#x.\n", hr);
2868 ID2D1RectangleGeometry_Release(geometry);
2870 ID2D1RenderTarget_BeginDraw(rt);
2872 origin.x = origin.y = 0.0f;
2873 ID2D1RenderTarget_DrawTextLayout(rt, origin, text_layout, (ID2D1Brush*)brush, D2D1_DRAW_TEXT_OPTIONS_NONE);
2875 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
2876 ok(hr == S_OK, "EndDraw failure expected, hr %#x.\n", hr);
2878 IDWriteTextFormat_Release(text_format);
2879 IDWriteTextLayout_Release(text_layout);
2880 IDWriteFactory_Release(dwrite_factory);
2881 ID2D1RenderTarget_Release(rt);
2882 ID2D1RenderTarget_Release(rt2);
2884 ID2D1Factory_Release(factory);
2885 ID2D1Factory_Release(factory2);
2886 IDXGISurface_Release(surface);
2887 IDXGISwapChain_Release(swapchain);
2888 ID3D10Device1_Release(device);
2889 DestroyWindow(window);
2892 static void create_target_dibsection(HDC hdc, UINT32 width, UINT32 height)
2894 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
2895 BITMAPINFO *bmi = (BITMAPINFO*)bmibuf;
2896 HBITMAP hbm;
2898 memset(bmi, 0, sizeof(bmibuf));
2899 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2900 bmi->bmiHeader.biHeight = -height;
2901 bmi->bmiHeader.biWidth = width;
2902 bmi->bmiHeader.biBitCount = 32;
2903 bmi->bmiHeader.biPlanes = 1;
2904 bmi->bmiHeader.biCompression = BI_RGB;
2906 hbm = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2907 ok(hbm != NULL, "Failed to create a dib section.\n");
2909 DeleteObject(SelectObject(hdc, hbm));
2912 static void test_dc_target(void)
2914 static const D2D1_PIXEL_FORMAT invalid_formats[] =
2916 { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED },
2917 { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_UNKNOWN },
2918 { DXGI_FORMAT_R8G8B8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED },
2920 D2D1_TEXT_ANTIALIAS_MODE text_aa_mode;
2921 D2D1_RENDER_TARGET_PROPERTIES desc;
2922 D2D1_MATRIX_3X2_F matrix, matrix2;
2923 D2D1_ANTIALIAS_MODE aa_mode;
2924 ID2D1SolidColorBrush *brush;
2925 ID2D1DCRenderTarget *rt;
2926 ID2D1Factory *factory;
2927 ID3D10Device1 *device;
2928 FLOAT dpi_x, dpi_y;
2929 D2D1_COLOR_F color;
2930 D2D1_SIZE_U sizeu;
2931 D2D1_SIZE_F size;
2932 D2D1_TAG t1, t2;
2933 unsigned int i;
2934 HDC hdc, hdc2;
2935 D2D_RECT_F r;
2936 COLORREF clr;
2937 HRESULT hr;
2938 RECT rect;
2940 if (!(device = create_device()))
2942 skip("Failed to create device, skipping tests.\n");
2943 return;
2945 ID3D10Device1_Release(device);
2947 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
2948 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
2950 for (i = 0; i < sizeof(invalid_formats) / sizeof(*invalid_formats); ++i)
2952 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
2953 desc.pixelFormat = invalid_formats[i];
2954 desc.dpiX = 96.0f;
2955 desc.dpiY = 96.0f;
2956 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
2957 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
2959 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
2960 ok(hr == D2DERR_UNSUPPORTED_PIXEL_FORMAT, "Got unexpected hr %#x.\n", hr);
2963 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
2964 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
2965 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2966 desc.dpiX = 96.0f;
2967 desc.dpiY = 96.0f;
2968 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
2969 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
2970 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
2971 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
2973 size = ID2D1DCRenderTarget_GetSize(rt);
2974 ok(size.width == 0.0f, "got width %.08e.\n", size.width);
2975 ok(size.height == 0.0f, "got height %.08e.\n", size.height);
2977 sizeu = ID2D1DCRenderTarget_GetPixelSize(rt);
2978 ok(sizeu.width == 0, "got width %u.\n", sizeu.width);
2979 ok(sizeu.height == 0, "got height %u.\n", sizeu.height);
2981 /* object creation methods work without BindDC() */
2982 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
2983 hr = ID2D1DCRenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
2984 ok(SUCCEEDED(hr), "Failed to create a brush, hr %#x.\n", hr);
2985 ID2D1SolidColorBrush_Release(brush);
2987 ID2D1DCRenderTarget_BeginDraw(rt);
2988 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
2989 ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#x.\n", hr);
2991 ID2D1DCRenderTarget_Release(rt);
2993 /* BindDC() */
2994 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &rt);
2995 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
2997 aa_mode = ID2D1DCRenderTarget_GetAntialiasMode(rt);
2998 ok(aa_mode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, "Got wrong default aa mode %d.\n", aa_mode);
2999 text_aa_mode = ID2D1DCRenderTarget_GetTextAntialiasMode(rt);
3000 ok(text_aa_mode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT, "Got wrong default text aa mode %d.\n", text_aa_mode);
3002 ID2D1DCRenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
3003 ok(dpi_x == 96.0f && dpi_y == 96.0f, "Got dpi_x %f, dpi_y %f.\n", dpi_x, dpi_y);
3005 hdc = CreateCompatibleDC(NULL);
3006 ok(hdc != NULL, "Failed to create an HDC.\n");
3008 create_target_dibsection(hdc, 16, 16);
3010 SetRect(&rect, 0, 0, 32, 32);
3011 hr = ID2D1DCRenderTarget_BindDC(rt, NULL, &rect);
3012 ok(hr == E_INVALIDARG, "BindDC() returned %#x.\n", hr);
3014 /* Target properties are retained during BindDC() */
3015 ID2D1DCRenderTarget_SetTags(rt, 1, 2);
3016 ID2D1DCRenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
3017 ID2D1DCRenderTarget_SetTextAntialiasMode(rt, D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
3019 set_matrix_identity(&matrix);
3020 translate_matrix(&matrix, 200.0f, 600.0f);
3021 ID2D1DCRenderTarget_SetTransform(rt, &matrix);
3023 hr = ID2D1DCRenderTarget_BindDC(rt, hdc, &rect);
3024 ok(hr == S_OK, "BindDC() returned %#x.\n", hr);
3026 ID2D1DCRenderTarget_GetTags(rt, &t1, &t2);
3027 ok(t1 == 1 && t2 == 2, "Got wrong tags.\n");
3029 aa_mode = ID2D1DCRenderTarget_GetAntialiasMode(rt);
3030 ok(aa_mode == D2D1_ANTIALIAS_MODE_ALIASED, "Got wrong aa mode %d.\n", aa_mode);
3032 text_aa_mode = ID2D1DCRenderTarget_GetTextAntialiasMode(rt);
3033 ok(text_aa_mode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE, "Got wrong text aa mode %d.\n", text_aa_mode);
3035 ID2D1DCRenderTarget_GetTransform(rt, &matrix2);
3036 ok(!memcmp(&matrix, &matrix2, sizeof(matrix)), "Got wrong target transform.\n");
3038 set_matrix_identity(&matrix);
3039 ID2D1DCRenderTarget_SetTransform(rt, &matrix);
3041 /* target size comes from specified dimensions, not from selected bitmap size */
3042 size = ID2D1DCRenderTarget_GetSize(rt);
3043 ok(size.width == 32.0f, "got width %.08e.\n", size.width);
3044 ok(size.height == 32.0f, "got height %.08e.\n", size.height);
3046 /* clear one HDC to red, switch to another one, partially fill it and test contents */
3047 ID2D1DCRenderTarget_BeginDraw(rt);
3049 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
3050 ID2D1DCRenderTarget_Clear(rt, &color);
3052 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
3053 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
3055 clr = GetPixel(hdc, 0, 0);
3056 ok(clr == RGB(255, 0, 0), "Got color %#x\n", clr);
3058 hdc2 = CreateCompatibleDC(NULL);
3059 ok(hdc2 != NULL, "Failed to create an HDC.\n");
3061 create_target_dibsection(hdc2, 16, 16);
3063 hr = ID2D1DCRenderTarget_BindDC(rt, hdc2, &rect);
3064 ok(hr == S_OK, "BindDC() returned %#x.\n", hr);
3066 clr = GetPixel(hdc2, 0, 0);
3067 ok(clr == 0, "Got color %#x\n", clr);
3069 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
3070 hr = ID2D1DCRenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
3071 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
3073 ID2D1DCRenderTarget_BeginDraw(rt);
3075 r.left = r.top = 0.0f;
3076 r.bottom = 16.0f;
3077 r.right = 8.0f;
3078 ID2D1DCRenderTarget_FillRectangle(rt, &r, (ID2D1Brush*)brush);
3080 hr = ID2D1DCRenderTarget_EndDraw(rt, NULL, NULL);
3081 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
3083 ID2D1SolidColorBrush_Release(brush);
3085 clr = GetPixel(hdc2, 0, 0);
3086 ok(clr == RGB(0, 255, 0), "Got color %#x\n", clr);
3088 clr = GetPixel(hdc2, 10, 0);
3089 ok(clr == 0, "Got color %#x\n", clr);
3091 DeleteDC(hdc);
3092 DeleteDC(hdc2);
3093 ID2D1DCRenderTarget_Release(rt);
3094 ID2D1Factory_Release(factory);
3097 static void test_hwnd_target(void)
3099 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
3100 D2D1_RENDER_TARGET_PROPERTIES desc;
3101 ID2D1HwndRenderTarget *rt;
3102 ID2D1Factory *factory;
3103 ID3D10Device1 *device;
3104 HRESULT hr;
3106 if (!(device = create_device()))
3108 skip("Failed to create device, skipping tests.\n");
3109 return;
3111 ID3D10Device1_Release(device);
3113 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
3114 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3116 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
3117 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3118 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3119 desc.dpiX = 0.0f;
3120 desc.dpiY = 0.0f;
3121 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
3122 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
3124 hwnd_rt_desc.hwnd = NULL;
3125 hwnd_rt_desc.pixelSize.width = 64;
3126 hwnd_rt_desc.pixelSize.height = 64;
3127 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
3129 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
3130 ok(FAILED(hr), "Target creation should fail, hr %#x.\n", hr);
3132 hwnd_rt_desc.hwnd = (HWND)0xdeadbeef;
3133 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
3134 ok(FAILED(hr), "Target creation should fail, hr %#x.\n", hr);
3136 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
3137 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
3138 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &rt);
3139 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3141 ID2D1HwndRenderTarget_Release(rt);
3143 DestroyWindow(hwnd_rt_desc.hwnd);
3144 ID2D1Factory_Release(factory);
3147 static void test_bitmap_target(void)
3149 D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
3150 D2D1_SIZE_U pixel_size, pixel_size2;
3151 D2D1_RENDER_TARGET_PROPERTIES desc;
3152 ID2D1HwndRenderTarget *hwnd_rt;
3153 ID2D1Bitmap *bitmap, *bitmap2;
3154 ID2D1BitmapRenderTarget *rt;
3155 ID2D1DCRenderTarget *dc_rt;
3156 D2D1_SIZE_F size, size2;
3157 ID2D1Factory *factory;
3158 ID3D10Device1 *device;
3159 float dpi[2], dpi2[2];
3160 D2D1_COLOR_F color;
3161 ULONG refcount;
3162 HRESULT hr;
3164 if (!(device = create_device()))
3166 skip("Failed to create device, skipping tests.\n");
3167 return;
3169 ID3D10Device1_Release(device);
3171 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
3172 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3174 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
3175 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3176 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3177 desc.dpiX = 96.0f;
3178 desc.dpiY = 192.0f;
3179 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
3180 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
3182 hwnd_rt_desc.hwnd = CreateWindowA("static", "d2d_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
3183 ok(!!hwnd_rt_desc.hwnd, "Failed to create target window.\n");
3184 hwnd_rt_desc.pixelSize.width = 64;
3185 hwnd_rt_desc.pixelSize.height = 64;
3186 hwnd_rt_desc.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
3188 hr = ID2D1Factory_CreateHwndRenderTarget(factory, &desc, &hwnd_rt_desc, &hwnd_rt);
3189 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3191 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, NULL, NULL, NULL,
3192 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
3193 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3195 /* See if parent target is referenced. */
3196 ID2D1HwndRenderTarget_AddRef(hwnd_rt);
3197 refcount = ID2D1HwndRenderTarget_Release(hwnd_rt);
3198 ok(refcount == 1, "Target should not have been referenced, got %u.\n", refcount);
3200 /* Size was not specified, should match parent. */
3201 pixel_size = ID2D1HwndRenderTarget_GetPixelSize(hwnd_rt);
3202 pixel_size2 = ID2D1BitmapRenderTarget_GetPixelSize(rt);
3203 ok(!memcmp(&pixel_size, &pixel_size2, sizeof(pixel_size)), "Got target pixel size mismatch.\n");
3205 size = ID2D1HwndRenderTarget_GetSize(hwnd_rt);
3206 size2 = ID2D1BitmapRenderTarget_GetSize(rt);
3207 ok(!memcmp(&size, &size2, sizeof(size)), "Got target DIP size mismatch.\n");
3209 ID2D1HwndRenderTarget_GetDpi(hwnd_rt, dpi, dpi + 1);
3210 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
3211 ok(!memcmp(dpi, dpi2, sizeof(dpi)), "Got dpi mismatch.\n");
3213 ID2D1BitmapRenderTarget_Release(rt);
3215 /* Pixel size specified. */
3216 set_size_u(&pixel_size, 32, 32);
3217 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, NULL, &pixel_size, NULL,
3218 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
3219 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3221 pixel_size2 = ID2D1BitmapRenderTarget_GetPixelSize(rt);
3222 ok(!memcmp(&pixel_size, &pixel_size2, sizeof(pixel_size)), "Got target pixel size mismatch.\n");
3224 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
3225 ok(!memcmp(dpi, dpi2, sizeof(dpi)), "Got dpi mismatch.\n");
3227 ID2D1BitmapRenderTarget_Release(rt);
3229 /* Both pixel size and DIP size are specified. */
3230 set_size_u(&pixel_size, 128, 128);
3231 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, &size, &pixel_size, NULL,
3232 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
3233 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3235 /* Doubled pixel size dimensions with the same DIP size give doubled dpi. */
3236 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
3237 ok(dpi[0] == dpi2[0] / 2.0f && dpi[1] == dpi2[1] / 2.0f, "Got dpi mismatch.\n");
3239 ID2D1BitmapRenderTarget_Release(rt);
3241 /* DIP size is specified, fractional. */
3242 set_size_f(&size, 70.1f, 70.4f);
3243 hr = ID2D1HwndRenderTarget_CreateCompatibleRenderTarget(hwnd_rt, &size, NULL, NULL,
3244 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
3245 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3247 ID2D1BitmapRenderTarget_GetDpi(rt, dpi2, dpi2 + 1);
3249 pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(rt);
3250 ok(pixel_size.width == ceilf(size.width * dpi[0] / 96.0f)
3251 && pixel_size.height == ceilf(size.height * dpi[1] / 96.0f), "Wrong pixel size %ux%u\n",
3252 pixel_size.width, pixel_size.height);
3254 dpi[0] *= (pixel_size.width / size.width) * (96.0f / dpi[0]);
3255 dpi[1] *= (pixel_size.height / size.height) * (96.0f / dpi[1]);
3257 ok(compare_float(dpi[0], dpi2[0], 1) && compare_float(dpi[1], dpi2[1], 1), "Got dpi mismatch.\n");
3259 ID2D1HwndRenderTarget_Release(hwnd_rt);
3261 /* Check if GetBitmap() returns same instance. */
3262 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap);
3263 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
3264 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap2);
3265 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
3266 ok(bitmap == bitmap2, "Got different bitmap instances.\n");
3268 /* Draw something, see if bitmap instance is retained. */
3269 ID2D1BitmapRenderTarget_BeginDraw(rt);
3270 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
3271 ID2D1BitmapRenderTarget_Clear(rt, &color);
3272 hr = ID2D1BitmapRenderTarget_EndDraw(rt, NULL, NULL);
3273 ok(SUCCEEDED(hr), "EndDraw() failed, hr %#x.\n", hr);
3275 ID2D1Bitmap_Release(bitmap2);
3276 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap2);
3277 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
3278 ok(bitmap == bitmap2, "Got different bitmap instances.\n");
3280 ID2D1Bitmap_Release(bitmap);
3281 ID2D1Bitmap_Release(bitmap2);
3283 refcount = ID2D1BitmapRenderTarget_Release(rt);
3284 ok(!refcount, "Target should be released, got %u.\n", refcount);
3286 DestroyWindow(hwnd_rt_desc.hwnd);
3288 /* Compatible target created from a DC target without associated HDC */
3289 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
3290 desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
3291 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
3292 desc.dpiX = 96.0f;
3293 desc.dpiY = 96.0f;
3294 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
3295 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
3296 hr = ID2D1Factory_CreateDCRenderTarget(factory, &desc, &dc_rt);
3297 ok(SUCCEEDED(hr), "Failed to create target, hr %#x.\n", hr);
3299 hr = ID2D1DCRenderTarget_CreateCompatibleRenderTarget(dc_rt, NULL, NULL, NULL,
3300 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &rt);
3301 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3303 pixel_size = ID2D1BitmapRenderTarget_GetPixelSize(rt);
3304 todo_wine
3305 ok(pixel_size.width == 0 && pixel_size.height == 0, "Got wrong size\n");
3307 hr = ID2D1BitmapRenderTarget_GetBitmap(rt, &bitmap);
3308 ok(SUCCEEDED(hr), "GetBitmap() failed, hr %#x.\n", hr);
3309 pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
3310 todo_wine
3311 ok(pixel_size.width == 0 && pixel_size.height == 0, "Got wrong size\n");
3312 ID2D1Bitmap_Release(bitmap);
3314 ID2D1BitmapRenderTarget_Release(rt);
3315 ID2D1DCRenderTarget_Release(dc_rt);
3317 ID2D1Factory_Release(factory);
3320 static void test_desktop_dpi(void)
3322 ID2D1Factory *factory;
3323 float dpi_x, dpi_y;
3324 HRESULT hr;
3326 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
3327 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3329 dpi_x = dpi_y = 0.0f;
3330 ID2D1Factory_GetDesktopDpi(factory, &dpi_x, &dpi_y);
3331 ok(dpi_x > 0.0f && dpi_y > 0.0f, "Got wrong dpi %f x %f.\n", dpi_x, dpi_y);
3333 ID2D1Factory_Release(factory);
3336 static void test_stroke_style(void)
3338 static const struct
3340 D2D1_DASH_STYLE dash_style;
3341 UINT32 dash_count;
3342 float dashes[6];
3344 dash_style_tests[] =
3346 {D2D1_DASH_STYLE_SOLID, 0},
3347 {D2D1_DASH_STYLE_DASH, 2, {2.0f, 2.0f}},
3348 {D2D1_DASH_STYLE_DOT, 2, {0.0f, 2.0f}},
3349 {D2D1_DASH_STYLE_DASH_DOT, 4, {2.0f, 2.0f, 0.0f, 2.0f}},
3350 {D2D1_DASH_STYLE_DASH_DOT_DOT, 6, {2.0f, 2.0f, 0.0f, 2.0f, 0.0f, 2.0f}},
3352 D2D1_STROKE_STYLE_PROPERTIES desc;
3353 ID2D1StrokeStyle *style;
3354 ID2D1Factory *factory;
3355 UINT32 count;
3356 HRESULT hr;
3357 D2D1_CAP_STYLE cap_style;
3358 D2D1_LINE_JOIN line_join;
3359 float miter_limit, dash_offset;
3360 D2D1_DASH_STYLE dash_style;
3361 unsigned int i;
3362 float dashes[2];
3364 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
3365 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
3367 desc.startCap = D2D1_CAP_STYLE_SQUARE;
3368 desc.endCap = D2D1_CAP_STYLE_ROUND;
3369 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
3370 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
3371 desc.miterLimit = 1.5f;
3372 desc.dashStyle = D2D1_DASH_STYLE_DOT;
3373 desc.dashOffset = -1.0f;
3375 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
3376 ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
3378 cap_style = ID2D1StrokeStyle_GetStartCap(style);
3379 ok(cap_style == D2D1_CAP_STYLE_SQUARE, "Unexpected cap style %d.\n", cap_style);
3380 cap_style = ID2D1StrokeStyle_GetEndCap(style);
3381 ok(cap_style == D2D1_CAP_STYLE_ROUND, "Unexpected cap style %d.\n", cap_style);
3382 cap_style = ID2D1StrokeStyle_GetDashCap(style);
3383 ok(cap_style == D2D1_CAP_STYLE_TRIANGLE, "Unexpected cap style %d.\n", cap_style);
3384 line_join = ID2D1StrokeStyle_GetLineJoin(style);
3385 ok(line_join == D2D1_LINE_JOIN_BEVEL, "Unexpected line joind %d.\n", line_join);
3386 miter_limit = ID2D1StrokeStyle_GetMiterLimit(style);
3387 ok(miter_limit == 1.5f, "Unexpected miter limit %f.\n", miter_limit);
3388 dash_style = ID2D1StrokeStyle_GetDashStyle(style);
3389 ok(dash_style == D2D1_DASH_STYLE_DOT, "Unexpected dash style %d.\n", dash_style);
3390 dash_offset = ID2D1StrokeStyle_GetDashOffset(style);
3391 ok(dash_offset == -1.0f, "Unexpected dash offset %f.\n", dash_offset);
3393 /* Custom dash pattern, no dashes data specified. */
3394 desc.startCap = D2D1_CAP_STYLE_SQUARE;
3395 desc.endCap = D2D1_CAP_STYLE_ROUND;
3396 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
3397 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
3398 desc.miterLimit = 1.5f;
3399 desc.dashStyle = D2D1_DASH_STYLE_CUSTOM;
3400 desc.dashOffset = 0.0f;
3402 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
3403 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
3405 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 0, &style);
3406 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
3408 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 1, &style);
3409 ok(hr == S_OK, "Unexpected return value, %#x.\n", hr);
3410 ID2D1StrokeStyle_Release(style);
3412 /* Builtin style, dashes are specified. */
3413 desc.dashStyle = D2D1_DASH_STYLE_DOT;
3414 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 1, &style);
3415 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
3417 /* Invalid style. */
3418 desc.dashStyle = 100;
3419 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
3420 ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
3422 /* Test returned dash pattern for builtin styles. */
3423 desc.startCap = D2D1_CAP_STYLE_SQUARE;
3424 desc.endCap = D2D1_CAP_STYLE_ROUND;
3425 desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
3426 desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
3427 desc.miterLimit = 1.5f;
3428 desc.dashOffset = 0.0f;
3430 for (i = 0; i < sizeof(dash_style_tests)/sizeof(dash_style_tests[0]); i++)
3432 float dashes[10];
3433 UINT dash_count;
3435 desc.dashStyle = dash_style_tests[i].dash_style;
3437 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
3438 ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
3440 dash_count = ID2D1StrokeStyle_GetDashesCount(style);
3441 ok(dash_count == dash_style_tests[i].dash_count, "%u: unexpected dash count %u, expected %u.\n",
3442 i, dash_count, dash_style_tests[i].dash_count);
3443 ok(dash_count < sizeof(dashes)/sizeof(dashes[0]), "%u: unexpectedly large dash count %u.\n", i, dash_count);
3444 if (dash_count == dash_style_tests[i].dash_count)
3446 unsigned int j;
3448 ID2D1StrokeStyle_GetDashes(style, dashes, dash_count);
3449 ok(!memcmp(dashes, dash_style_tests[i].dashes, sizeof(*dashes) * dash_count),
3450 "%u: unexpected dash array.\n", i);
3452 /* Ask for more dashes than style actually has. */
3453 memset(dashes, 0xcc, sizeof(dashes));
3454 ID2D1StrokeStyle_GetDashes(style, dashes, sizeof(dashes)/sizeof(dashes[0]));
3455 ok(!memcmp(dashes, dash_style_tests[i].dashes, sizeof(*dashes) * dash_count),
3456 "%u: unexpected dash array.\n", i);
3458 for (j = dash_count; j < sizeof(dashes)/sizeof(dashes[0]); j++)
3459 ok(dashes[j] == 0.0f, "%u: unexpected dash value at %u.\n", i, j);
3462 ID2D1StrokeStyle_Release(style);
3465 /* NULL dashes array, non-zero length. */
3466 memset(&desc, 0, sizeof(desc));
3467 hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 1, &style);
3468 ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
3470 count = ID2D1StrokeStyle_GetDashesCount(style);
3471 ok(count == 0, "Unexpected dashes count %u.\n", count);
3473 ID2D1StrokeStyle_Release(style);
3475 ID2D1Factory_Release(factory);
3478 START_TEST(d2d1)
3480 test_clip();
3481 test_state_block();
3482 test_color_brush();
3483 test_bitmap_brush();
3484 test_path_geometry();
3485 test_rectangle_geometry();
3486 test_rounded_rectangle_geometry();
3487 test_bitmap_formats();
3488 test_alpha_mode();
3489 test_shared_bitmap();
3490 test_bitmap_updates();
3491 test_opacity_brush();
3492 test_create_target();
3493 test_draw_text_layout();
3494 test_dc_target();
3495 test_hwnd_target();
3496 test_bitmap_target();
3497 test_desktop_dpi();
3498 test_stroke_style();