d2d1/tests: Add some extend mode tests to test_bitmap_brush().
[wine.git] / dlls / d2d1 / tests / d2d1.c
blob29e1bc62a01d327f9272211d728359e3c0723b9a
1 /*
2 * Copyright 2014 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
20 #include <math.h>
21 #include "d2d1.h"
22 #include "wincrypt.h"
23 #include "wine/test.h"
24 #include "initguid.h"
25 #include "dwrite.h"
27 static void set_point(D2D1_POINT_2F *point, float x, float y)
29 point->x = x;
30 point->y = y;
33 static void set_rect(D2D1_RECT_F *rect, float left, float top, float right, float bottom)
35 rect->left = left;
36 rect->top = top;
37 rect->right = right;
38 rect->bottom = bottom;
41 static void set_color(D2D1_COLOR_F *color, float r, float g, float b, float a)
43 color->r = r;
44 color->g = g;
45 color->b = b;
46 color->a = a;
49 static void set_size_u(D2D1_SIZE_U *size, unsigned int w, unsigned int h)
51 size->width = w;
52 size->height = h;
55 static void set_matrix_identity(D2D1_MATRIX_3X2_F *matrix)
57 matrix->_11 = 1.0f;
58 matrix->_12 = 0.0f;
59 matrix->_21 = 0.0f;
60 matrix->_22 = 1.0f;
61 matrix->_31 = 0.0f;
62 matrix->_32 = 0.0f;
65 static void rotate_matrix(D2D1_MATRIX_3X2_F *matrix, float theta)
67 float sin_theta, cos_theta, tmp_11, tmp_12;
69 sin_theta = sinf(theta);
70 cos_theta = cosf(theta);
71 tmp_11 = matrix->_11;
72 tmp_12 = matrix->_12;
74 matrix->_11 = cos_theta * tmp_11 + sin_theta * matrix->_21;
75 matrix->_12 = cos_theta * tmp_12 + sin_theta * matrix->_22;
76 matrix->_21 = -sin_theta * tmp_11 + cos_theta * matrix->_21;
77 matrix->_22 = -sin_theta * tmp_12 + cos_theta * matrix->_22;
80 static void scale_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
82 matrix->_11 *= x;
83 matrix->_12 *= x;
84 matrix->_21 *= y;
85 matrix->_22 *= y;
88 static void translate_matrix(D2D1_MATRIX_3X2_F *matrix, float x, float y)
90 matrix->_31 += x * matrix->_11 + y * matrix->_21;
91 matrix->_32 += x * matrix->_12 + y * matrix->_22;
94 static BOOL compare_sha1(void *data, unsigned int pitch, unsigned int bpp,
95 unsigned int w, unsigned int h, const char *ref_sha1)
97 static const char hex_chars[] = "0123456789abcdef";
98 HCRYPTPROV provider;
99 BYTE hash_data[20];
100 HCRYPTHASH hash;
101 unsigned int i;
102 char sha1[41];
103 BOOL ret;
105 ret = CryptAcquireContextW(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
106 ok(ret, "Failed to acquire crypt context.\n");
107 ret = CryptCreateHash(provider, CALG_SHA1, 0, 0, &hash);
108 ok(ret, "Failed to create hash.\n");
110 for (i = 0; i < h; ++i)
112 if (!(ret = CryptHashData(hash, (BYTE *)data + pitch * i, w * bpp, 0)))
113 break;
115 ok(ret, "Failed to hash data.\n");
117 i = sizeof(hash_data);
118 ret = CryptGetHashParam(hash, HP_HASHVAL, hash_data, &i, 0);
119 ok(ret, "Failed to get hash value.\n");
120 ok(i == sizeof(hash_data), "Got unexpected hash size %u.\n", i);
122 ret = CryptDestroyHash(hash);
123 ok(ret, "Failed to destroy hash.\n");
124 ret = CryptReleaseContext(provider, 0);
125 ok(ret, "Failed to release crypt context.\n");
127 for (i = 0; i < 20; ++i)
129 sha1[i * 2] = hex_chars[hash_data[i] >> 4];
130 sha1[i * 2 + 1] = hex_chars[hash_data[i] & 0xf];
132 sha1[40] = 0;
134 return !strcmp(ref_sha1, (char *)sha1);
137 static BOOL compare_surface(IDXGISurface *surface, const char *ref_sha1)
139 D3D10_MAPPED_TEXTURE2D mapped_texture;
140 D3D10_TEXTURE2D_DESC texture_desc;
141 DXGI_SURFACE_DESC surface_desc;
142 ID3D10Resource *src_resource;
143 ID3D10Texture2D *texture;
144 ID3D10Device *device;
145 HRESULT hr;
146 BOOL ret;
148 hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&device);
149 ok(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
150 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&src_resource);
151 ok(SUCCEEDED(hr), "Failed to query resource interface, hr %#x.\n", hr);
153 hr = IDXGISurface_GetDesc(surface, &surface_desc);
154 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
155 texture_desc.Width = surface_desc.Width;
156 texture_desc.Height = surface_desc.Height;
157 texture_desc.MipLevels = 1;
158 texture_desc.ArraySize = 1;
159 texture_desc.Format = surface_desc.Format;
160 texture_desc.SampleDesc = surface_desc.SampleDesc;
161 texture_desc.Usage = D3D10_USAGE_STAGING;
162 texture_desc.BindFlags = 0;
163 texture_desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
164 texture_desc.MiscFlags = 0;
165 hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, &texture);
166 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
168 ID3D10Device_CopyResource(device, (ID3D10Resource *)texture, src_resource);
169 hr = ID3D10Texture2D_Map(texture, 0, D3D10_MAP_READ, 0, &mapped_texture);
170 ok(SUCCEEDED(hr), "Failed to map texture, hr %#x.\n", hr);
171 ret = compare_sha1(mapped_texture.pData, mapped_texture.RowPitch, 4,
172 texture_desc.Width, texture_desc.Height, ref_sha1);
173 ID3D10Texture2D_Unmap(texture, 0);
175 ID3D10Texture2D_Release(texture);
176 ID3D10Resource_Release(src_resource);
177 ID3D10Device_Release(device);
179 return ret;
182 static ID3D10Device1 *create_device(void)
184 ID3D10Device1 *device;
186 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL,
187 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
188 return device;
189 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_WARP, NULL,
190 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
191 return device;
192 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL,
193 D3D10_CREATE_DEVICE_BGRA_SUPPORT, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
194 return device;
196 return NULL;
199 static IDXGISwapChain *create_swapchain(ID3D10Device1 *device, HWND window, BOOL windowed)
201 IDXGISwapChain *swapchain;
202 DXGI_SWAP_CHAIN_DESC desc;
203 IDXGIDevice *dxgi_device;
204 IDXGIAdapter *adapter;
205 IDXGIFactory *factory;
206 HRESULT hr;
208 hr = ID3D10Device1_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
209 ok(SUCCEEDED(hr), "Failed to get DXGI device, hr %#x.\n", hr);
210 hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter);
211 ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr);
212 IDXGIDevice_Release(dxgi_device);
213 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
214 ok(SUCCEEDED(hr), "Failed to get factory, hr %#x.\n", hr);
215 IDXGIAdapter_Release(adapter);
217 desc.BufferDesc.Width = 640;
218 desc.BufferDesc.Height = 480;
219 desc.BufferDesc.RefreshRate.Numerator = 60;
220 desc.BufferDesc.RefreshRate.Denominator = 1;
221 desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
222 desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
223 desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
224 desc.SampleDesc.Count = 1;
225 desc.SampleDesc.Quality = 0;
226 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
227 desc.BufferCount = 1;
228 desc.OutputWindow = window;
229 desc.Windowed = windowed;
230 desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
231 desc.Flags = 0;
233 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &desc, &swapchain);
234 ok(SUCCEEDED(hr), "Failed to create swapchain, hr %#x.\n", hr);
235 IDXGIFactory_Release(factory);
237 return swapchain;
240 static ID2D1RenderTarget *create_render_target(IDXGISurface *surface)
242 D2D1_RENDER_TARGET_PROPERTIES desc;
243 ID2D1RenderTarget *render_target;
244 ID2D1Factory *factory;
245 HRESULT hr;
247 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
248 ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
250 desc.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
251 desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
252 desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
253 desc.dpiX = 0.0f;
254 desc.dpiY = 0.0f;
255 desc.usage = D2D1_RENDER_TARGET_USAGE_NONE;
256 desc.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
257 hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, &desc, &render_target);
258 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
260 ID2D1Factory_Release(factory);
262 return render_target;
265 static void test_clip(void)
267 IDXGISwapChain *swapchain;
268 D2D1_MATRIX_3X2_F matrix;
269 D2D1_SIZE_U pixel_size;
270 ID2D1RenderTarget *rt;
271 ID3D10Device1 *device;
272 IDXGISurface *surface;
273 D2D1_POINT_2F point;
274 D2D1_COLOR_F color;
275 float dpi_x, dpi_y;
276 D2D1_RECT_F rect;
277 D2D1_SIZE_F size;
278 HWND window;
279 HRESULT hr;
280 static const D2D1_MATRIX_3X2_F identity =
282 1.0f, 0.0f,
283 0.0f, 1.0f,
284 0.0f, 0.0f,
287 if (!(device = create_device()))
289 skip("Failed to create device, skipping tests.\n");
290 return;
292 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
293 0, 0, 640, 480, NULL, NULL, NULL, NULL);
294 swapchain = create_swapchain(device, window, TRUE);
295 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
296 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
297 rt = create_render_target(surface);
298 ok(!!rt, "Failed to create render target.\n");
300 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
301 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
302 ok(dpi_y == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
303 size = ID2D1RenderTarget_GetSize(rt);
304 ok(size.width == 640.0f, "Got unexpected width %.8e.\n", size.width);
305 ok(size.height == 480.0f, "Got unexpected height %.8e.\n", size.height);
306 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
307 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
308 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
310 ID2D1RenderTarget_GetTransform(rt, &matrix);
311 ok(!memcmp(&matrix, &identity, sizeof(matrix)),
312 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
313 matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32);
315 ID2D1RenderTarget_BeginDraw(rt);
317 set_color(&color, 1.0f, 1.0f, 0.0f, 1.0f);
318 ID2D1RenderTarget_Clear(rt, &color);
320 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
321 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
322 ok(dpi_x == 48.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
323 ok(dpi_y == 192.0f, "Got unexpected dpi_x %.8e.\n", dpi_y);
324 size = ID2D1RenderTarget_GetSize(rt);
325 ok(size.width == 1280.0f, "Got unexpected width %.8e.\n", size.width);
326 ok(size.height == 240.0f, "Got unexpected height %.8e.\n", size.height);
327 pixel_size = ID2D1RenderTarget_GetPixelSize(rt);
328 ok(pixel_size.width == 640, "Got unexpected width %u.\n", pixel_size.width);
329 ok(pixel_size.height == 480, "Got unexpected height %u.\n", pixel_size.height);
331 /* The effective clip rect is the intersection of all currently pushed
332 * clip rects. Clip rects are in DIPs. */
333 set_rect(&rect, 0.0f, 0.0f, 1280.0f, 80.0f);
334 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
335 set_rect(&rect, 0.0f, 0.0f, 426.0f, 240.0f);
336 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
338 set_color(&color, 0.0f, 1.0f, 0.0f, 1.0f);
339 ID2D1RenderTarget_Clear(rt, &color);
340 ID2D1RenderTarget_PopAxisAlignedClip(rt);
341 ID2D1RenderTarget_PopAxisAlignedClip(rt);
343 ID2D1RenderTarget_SetDpi(rt, 0.0f, 0.0f);
344 ID2D1RenderTarget_GetDpi(rt, &dpi_x, &dpi_y);
345 ok(dpi_x == 96.0f, "Got unexpected dpi_x %.8e.\n", dpi_x);
346 ok(dpi_y == 96.0f, "Got unexpected dpi_y %.8e.\n", dpi_y);
348 /* Transformations apply to clip rects, the effective clip rect is the
349 * (axis-aligned) bounding box of the transformed clip rect. */
350 set_point(&point, 320.0f, 240.0f);
351 D2D1MakeRotateMatrix(30.0f, point, &matrix);
352 ID2D1RenderTarget_SetTransform(rt, &matrix);
353 set_rect(&rect, 215.0f, 208.0f, 425.0f, 272.0f);
354 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
355 set_color(&color, 1.0f, 1.0f, 1.0f, 1.0f);
356 ID2D1RenderTarget_Clear(rt, &color);
357 ID2D1RenderTarget_PopAxisAlignedClip(rt);
359 /* Transformations are applied when pushing the clip rect, transformations
360 * set afterwards have no effect on the current clip rect. This includes
361 * SetDpi(). */
362 ID2D1RenderTarget_SetTransform(rt, &identity);
363 set_rect(&rect, 427.0f, 320.0f, 640.0f, 480.0f);
364 ID2D1RenderTarget_PushAxisAlignedClip(rt, &rect, D2D1_ANTIALIAS_MODE_ALIASED);
365 ID2D1RenderTarget_SetTransform(rt, &matrix);
366 ID2D1RenderTarget_SetDpi(rt, 48.0f, 192.0f);
367 set_color(&color, 1.0f, 0.0f, 0.0f, 1.0f);
368 ID2D1RenderTarget_Clear(rt, &color);
369 ID2D1RenderTarget_PopAxisAlignedClip(rt);
371 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
372 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
373 ok(compare_surface(surface, "035a44d4198d6e422e9de6185b5b2c2bac5e33c9"), "Surface does not match.\n");
375 ID2D1RenderTarget_Release(rt);
376 IDXGISurface_Release(surface);
377 IDXGISwapChain_Release(swapchain);
378 ID3D10Device1_Release(device);
379 DestroyWindow(window);
382 static void test_state_block(void)
384 IDWriteRenderingParams *text_rendering_params1, *text_rendering_params2;
385 D2D1_DRAWING_STATE_DESCRIPTION drawing_state;
386 ID2D1DrawingStateBlock *state_block;
387 IDWriteFactory *dwrite_factory;
388 IDXGISwapChain *swapchain;
389 ID2D1RenderTarget *rt;
390 ID3D10Device1 *device;
391 IDXGISurface *surface;
392 ID2D1Factory *factory;
393 ULONG refcount;
394 HWND window;
395 HRESULT hr;
396 static const D2D1_MATRIX_3X2_F identity =
398 1.0f, 0.0f,
399 0.0f, 1.0f,
400 0.0f, 0.0f,
402 static const D2D1_MATRIX_3X2_F transform1 =
404 1.0f, 2.0f,
405 3.0f, 4.0f,
406 5.0f, 6.0f,
408 static const D2D1_MATRIX_3X2_F transform2 =
410 7.0f, 8.0f,
411 9.0f, 10.0f,
412 11.0f, 12.0f,
415 if (!(device = create_device()))
417 skip("Failed to create device, skipping tests.\n");
418 return;
420 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
421 0, 0, 640, 480, NULL, NULL, NULL, NULL);
422 swapchain = create_swapchain(device, window, TRUE);
423 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
424 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
425 rt = create_render_target(surface);
426 ok(!!rt, "Failed to create render target.\n");
427 ID2D1RenderTarget_GetFactory(rt, &factory);
428 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory);
429 ok(SUCCEEDED(hr), "Failed to create dwrite factory, hr %#x.\n", hr);
430 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &text_rendering_params1);
431 ok(SUCCEEDED(hr), "Failed to create dwrite rendering params, hr %#x.\n", hr);
432 IDWriteFactory_Release(dwrite_factory);
434 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
435 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
436 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
437 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
438 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
439 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
440 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
441 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %08x%08x:%08x%08x.\n",
442 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
443 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
444 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
445 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
446 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
447 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
448 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
449 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
450 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
452 hr = ID2D1Factory_CreateDrawingStateBlock(factory, NULL, NULL, &state_block);
453 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
454 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
455 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
456 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
457 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_DEFAULT,
458 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
459 ok(!drawing_state.tag1 && !drawing_state.tag2, "Got unexpected tags %08x%08x:%08x%08x.\n",
460 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
461 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
462 ok(!memcmp(&drawing_state.transform, &identity, sizeof(drawing_state.transform)),
463 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
464 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
465 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
466 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
467 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
468 ID2D1DrawingStateBlock_Release(state_block);
470 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
471 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
472 drawing_state.tag1 = 0xdead;
473 drawing_state.tag2 = 0xbeef;
474 drawing_state.transform = transform1;
475 hr = ID2D1Factory_CreateDrawingStateBlock(factory, &drawing_state, text_rendering_params1, &state_block);
476 ok(SUCCEEDED(hr), "Failed to create drawing state block, hr %#x\n", hr);
478 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
479 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
480 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
481 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
482 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
483 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %08x%08x:%08x%08x.\n",
484 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
485 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
486 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
487 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
488 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
489 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
490 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
491 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
492 text_rendering_params2, text_rendering_params1);
493 IDWriteRenderingParams_Release(text_rendering_params2);
495 ID2D1RenderTarget_RestoreDrawingState(rt, state_block);
497 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
498 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
499 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
500 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
501 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED,
502 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
503 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
504 ok(drawing_state.tag1 == 0xdead && drawing_state.tag2 == 0xbeef, "Got unexpected tags %08x%08x:%08x%08x.\n",
505 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
506 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
507 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
508 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
509 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
510 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
511 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
512 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
513 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
514 text_rendering_params2, text_rendering_params1);
515 IDWriteRenderingParams_Release(text_rendering_params2);
517 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
518 ID2D1RenderTarget_SetTextAntialiasMode(rt, D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
519 ID2D1RenderTarget_SetTags(rt, 1, 2);
520 ID2D1RenderTarget_SetTransform(rt, &transform2);
521 ID2D1RenderTarget_SetTextRenderingParams(rt, NULL);
523 drawing_state.antialiasMode = ID2D1RenderTarget_GetAntialiasMode(rt);
524 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
525 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
526 drawing_state.textAntialiasMode = ID2D1RenderTarget_GetTextAntialiasMode(rt);
527 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
528 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
529 ID2D1RenderTarget_GetTags(rt, &drawing_state.tag1, &drawing_state.tag2);
530 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %08x%08x:%08x%08x.\n",
531 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
532 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
533 ID2D1RenderTarget_GetTransform(rt, &drawing_state.transform);
534 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
535 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
536 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
537 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
538 ID2D1RenderTarget_GetTextRenderingParams(rt, &text_rendering_params2);
539 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
541 ID2D1RenderTarget_SaveDrawingState(rt, state_block);
543 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
544 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
545 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
546 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE,
547 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
548 ok(drawing_state.tag1 == 1 && drawing_state.tag2 == 2, "Got unexpected tags %08x%08x:%08x%08x.\n",
549 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
550 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
551 ok(!memcmp(&drawing_state.transform, &transform2, sizeof(drawing_state.transform)),
552 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
553 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
554 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
555 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
556 ok(!text_rendering_params2, "Got unexpected text rendering params %p.\n", text_rendering_params2);
558 drawing_state.antialiasMode = D2D1_ANTIALIAS_MODE_ALIASED;
559 drawing_state.textAntialiasMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
560 drawing_state.tag1 = 3;
561 drawing_state.tag2 = 4;
562 drawing_state.transform = transform1;
563 ID2D1DrawingStateBlock_SetDescription(state_block, &drawing_state);
564 ID2D1DrawingStateBlock_SetTextRenderingParams(state_block, text_rendering_params1);
566 ID2D1DrawingStateBlock_GetDescription(state_block, &drawing_state);
567 ok(drawing_state.antialiasMode == D2D1_ANTIALIAS_MODE_ALIASED,
568 "Got unexpected antialias mode %#x.\n", drawing_state.antialiasMode);
569 ok(drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE,
570 "Got unexpected text antialias mode %#x.\n", drawing_state.textAntialiasMode);
571 ok(drawing_state.tag1 == 3 && drawing_state.tag2 == 4, "Got unexpected tags %08x%08x:%08x%08x.\n",
572 (unsigned int)(drawing_state.tag1 >> 32), (unsigned int)(drawing_state.tag1),
573 (unsigned int)(drawing_state.tag2 >> 32), (unsigned int)(drawing_state.tag2));
574 ok(!memcmp(&drawing_state.transform, &transform1, sizeof(drawing_state.transform)),
575 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
576 drawing_state.transform._11, drawing_state.transform._12, drawing_state.transform._21,
577 drawing_state.transform._22, drawing_state.transform._31, drawing_state.transform._32);
578 ID2D1DrawingStateBlock_GetTextRenderingParams(state_block, &text_rendering_params2);
579 ok(text_rendering_params2 == text_rendering_params1, "Got unexpected text rendering params %p, expected %p.\n",
580 text_rendering_params2, text_rendering_params1);
581 IDWriteRenderingParams_Release(text_rendering_params2);
583 ID2D1DrawingStateBlock_Release(state_block);
585 refcount = IDWriteRenderingParams_Release(text_rendering_params1);
586 ok(!refcount, "Rendering params %u references left.\n", refcount);
587 ID2D1Factory_Release(factory);
588 ID2D1RenderTarget_Release(rt);
589 IDXGISurface_Release(surface);
590 IDXGISwapChain_Release(swapchain);
591 ID3D10Device1_Release(device);
592 DestroyWindow(window);
595 static void test_color_brush(void)
597 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
598 D2D1_BRUSH_PROPERTIES brush_desc;
599 D2D1_COLOR_F color, tmp_color;
600 ID2D1SolidColorBrush *brush;
601 IDXGISwapChain *swapchain;
602 ID2D1RenderTarget *rt;
603 ID3D10Device1 *device;
604 IDXGISurface *surface;
605 D2D1_RECT_F rect;
606 float opacity;
607 HWND window;
608 HRESULT hr;
610 if (!(device = create_device()))
612 skip("Failed to create device, skipping tests.\n");
613 return;
615 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
616 0, 0, 640, 480, NULL, NULL, NULL, NULL);
617 swapchain = create_swapchain(device, window, TRUE);
618 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
619 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
620 rt = create_render_target(surface);
621 ok(!!rt, "Failed to create render target.\n");
623 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
624 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
626 set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f);
627 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, NULL, &brush);
628 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
629 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
630 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
631 set_matrix_identity(&matrix);
632 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
633 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
634 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
635 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
636 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
637 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
638 ok(!memcmp(&tmp_color, &color, sizeof(color)),
639 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
640 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
641 ID2D1SolidColorBrush_Release(brush);
643 set_color(&color, 0.0f, 1.0f, 0.0f, 0.8f);
644 brush_desc.opacity = 0.3f;
645 set_matrix_identity(&matrix);
646 scale_matrix(&matrix, 2.0f, 2.0f);
647 brush_desc.transform = matrix;
648 hr = ID2D1RenderTarget_CreateSolidColorBrush(rt, &color, &brush_desc, &brush);
649 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
650 opacity = ID2D1SolidColorBrush_GetOpacity(brush);
651 ok(opacity == 0.3f, "Got unexpected opacity %.8e.\n", opacity);
652 ID2D1SolidColorBrush_GetTransform(brush, &tmp_matrix);
653 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
654 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
655 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
656 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
657 tmp_color = ID2D1SolidColorBrush_GetColor(brush);
658 ok(!memcmp(&tmp_color, &color, sizeof(color)),
659 "Got unexpected color {%.8e, %.8e, %.8e, %.8e}.\n",
660 tmp_color.r, tmp_color.g, tmp_color.b, tmp_color.a);
662 ID2D1RenderTarget_BeginDraw(rt);
664 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
665 ID2D1RenderTarget_Clear(rt, &color);
667 ID2D1SolidColorBrush_SetOpacity(brush, 1.0f);
668 set_rect(&rect, 40.0f, 120.0f, 120.0f, 360.0f);
669 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
671 set_matrix_identity(&matrix);
672 scale_matrix(&matrix, 0.5f, 2.0f);
673 translate_matrix(&matrix, 320.0f, 240.0f);
674 rotate_matrix(&matrix, M_PI / 4.0f);
675 ID2D1RenderTarget_SetTransform(rt, &matrix);
676 set_color(&color, 1.0f, 0.0f, 0.0f, 0.625f);
677 ID2D1SolidColorBrush_SetColor(brush, &color);
678 ID2D1SolidColorBrush_SetOpacity(brush, 0.75f);
679 set_rect(&rect, -80.0f, -60.0f, 80.0f, 60.0f);
680 ID2D1RenderTarget_FillRectangle(rt, &rect, (ID2D1Brush *)brush);
682 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
683 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
684 ok(compare_surface(surface, "6d1218fca5e21fb7e287b3a439d60dbc251f5ceb"), "Surface does not match.\n");
686 ID2D1SolidColorBrush_Release(brush);
687 ID2D1RenderTarget_Release(rt);
688 IDXGISurface_Release(surface);
689 IDXGISwapChain_Release(swapchain);
690 ID3D10Device1_Release(device);
691 DestroyWindow(window);
694 static void test_bitmap_brush(void)
696 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode;
697 D2D1_MATRIX_3X2_F matrix, tmp_matrix;
698 D2D1_BITMAP_PROPERTIES bitmap_desc;
699 ID2D1Bitmap *bitmap, *tmp_bitmap;
700 D2D1_RECT_F src_rect, dst_rect;
701 D2D1_EXTEND_MODE extend_mode;
702 IDXGISwapChain *swapchain;
703 ID2D1BitmapBrush *brush;
704 ID2D1RenderTarget *rt;
705 ID3D10Device1 *device;
706 IDXGISurface *surface;
707 D2D1_COLOR_F color;
708 D2D1_SIZE_U size;
709 unsigned int i;
710 ULONG refcount;
711 float opacity;
712 HWND window;
713 HRESULT hr;
715 static const struct
717 D2D1_EXTEND_MODE extend_mode_x;
718 D2D1_EXTEND_MODE extend_mode_y;
719 float translate_x;
720 float translate_y;
721 D2D1_RECT_F rect;
723 extend_mode_tests[] =
725 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_MIRROR, -7.0f, 1.0f, {-4.0f, 0.0f, -8.0f, 4.0f}},
726 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_MIRROR, -3.0f, 1.0f, {-4.0f, 4.0f, 0.0f, 0.0f}},
727 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_MIRROR, 1.0f, 1.0f, { 4.0f, 0.0f, 0.0f, 4.0f}},
728 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_WRAP, -7.0f, 5.0f, {-8.0f, 8.0f, -4.0f, 4.0f}},
729 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP, -3.0f, 5.0f, { 0.0f, 4.0f, -4.0f, 8.0f}},
730 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_WRAP, 1.0f, 5.0f, { 0.0f, 8.0f, 4.0f, 4.0f}},
731 {D2D1_EXTEND_MODE_MIRROR, D2D1_EXTEND_MODE_CLAMP, -7.0f, 9.0f, {-4.0f, 8.0f, -8.0f, 12.0f}},
732 {D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_CLAMP, -3.0f, 9.0f, {-4.0f, 12.0f, 0.0f, 8.0f}},
733 {D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_CLAMP, 1.0f, 9.0f, { 4.0f, 8.0f, 0.0f, 12.0f}},
735 static const DWORD bitmap_data[] =
737 0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff,
738 0xff0000ff, 0xffff00ff, 0xff000000, 0xff7f7f7f,
739 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
740 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
743 if (!(device = create_device()))
745 skip("Failed to create device, skipping tests.\n");
746 return;
748 window = CreateWindowA("static", "d2d1_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
749 0, 0, 640, 480, NULL, NULL, NULL, NULL);
750 swapchain = create_swapchain(device, window, TRUE);
751 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
752 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
753 rt = create_render_target(surface);
754 ok(!!rt, "Failed to create render target.\n");
756 ID2D1RenderTarget_SetDpi(rt, 192.0f, 48.0f);
757 ID2D1RenderTarget_SetAntialiasMode(rt, D2D1_ANTIALIAS_MODE_ALIASED);
759 set_size_u(&size, 4, 4);
760 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
761 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
762 bitmap_desc.dpiX = 96.0f;
763 bitmap_desc.dpiY = 96.0f;
764 hr = ID2D1RenderTarget_CreateBitmap(rt, size, bitmap_data, 4 * sizeof(*bitmap_data), &bitmap_desc, &bitmap);
765 ok(SUCCEEDED(hr), "Failed to create bitmap, hr %#x.\n", hr);
767 /* Creating a brush with a NULL bitmap crashes on Vista, but works fine on
768 * Windows 7+. */
769 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
770 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
771 ID2D1BitmapBrush_GetBitmap(brush, &tmp_bitmap);
772 ok(tmp_bitmap == bitmap, "Got unexpected bitmap %p, expected %p.\n", tmp_bitmap, bitmap);
773 ID2D1Bitmap_Release(tmp_bitmap);
774 opacity = ID2D1BitmapBrush_GetOpacity(brush);
775 ok(opacity == 1.0f, "Got unexpected opacity %.8e.\n", opacity);
776 set_matrix_identity(&matrix);
777 ID2D1BitmapBrush_GetTransform(brush, &tmp_matrix);
778 ok(!memcmp(&tmp_matrix, &matrix, sizeof(matrix)),
779 "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n",
780 tmp_matrix._11, tmp_matrix._12, tmp_matrix._21,
781 tmp_matrix._22, tmp_matrix._31, tmp_matrix._32);
782 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
783 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
784 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
785 ok(extend_mode == D2D1_EXTEND_MODE_CLAMP, "Got unexpected extend mode %#x.\n", extend_mode);
786 interpolation_mode = ID2D1BitmapBrush_GetInterpolationMode(brush);
787 ok(interpolation_mode == D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
788 "Got unexpected interpolation mode %#x.\n", interpolation_mode);
789 ID2D1BitmapBrush_Release(brush);
791 hr = ID2D1RenderTarget_CreateBitmapBrush(rt, bitmap, NULL, NULL, &brush);
792 ok(SUCCEEDED(hr), "Failed to create brush, hr %#x.\n", hr);
793 set_matrix_identity(&matrix);
794 translate_matrix(&matrix, 40.0f, 120.0f);
795 scale_matrix(&matrix, 20.0f, 60.0f);
796 ID2D1BitmapBrush_SetTransform(brush, &matrix);
797 ID2D1BitmapBrush_SetInterpolationMode(brush, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
799 ID2D1RenderTarget_BeginDraw(rt);
801 set_color(&color, 0.0f, 0.0f, 1.0f, 1.0f);
802 ID2D1RenderTarget_Clear(rt, &color);
804 set_rect(&dst_rect, 40.0f, 120.0f, 120.0f, 360.0f);
805 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
807 set_matrix_identity(&matrix);
808 scale_matrix(&matrix, 0.5f, 2.0f);
809 translate_matrix(&matrix, 320.0f, 240.0f);
810 rotate_matrix(&matrix, M_PI / 4.0f);
811 ID2D1RenderTarget_SetTransform(rt, &matrix);
812 set_matrix_identity(&matrix);
813 translate_matrix(&matrix, -80.0f, -60.0f);
814 scale_matrix(&matrix, 40.0f, 30.0f);
815 ID2D1BitmapBrush_SetTransform(brush, &matrix);
816 ID2D1BitmapBrush_SetOpacity(brush, 0.75f);
817 set_rect(&dst_rect, -80.0f, -60.0f, 80.0f, 60.0f);
818 ID2D1RenderTarget_FillRectangle(rt, &dst_rect, (ID2D1Brush *)brush);
820 set_matrix_identity(&matrix);
821 translate_matrix(&matrix, 200.0f, 120.0f);
822 scale_matrix(&matrix, 20.0f, 60.0f);
823 ID2D1RenderTarget_SetTransform(rt, &matrix);
824 ID2D1RenderTarget_DrawBitmap(rt, bitmap, NULL, 0.25f,
825 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
826 set_rect(&dst_rect, -4.0f, 12.0f, -8.0f, 8.0f);
827 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 0.75f,
828 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, NULL);
829 set_rect(&dst_rect, 0.0f, 8.0f, 4.0f, 12.0f);
830 set_rect(&src_rect, 2.0f, 1.0f, 4.0f, 3.0f);
831 ID2D1RenderTarget_DrawBitmap(rt, bitmap, &dst_rect, 1.0f,
832 D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &src_rect);
834 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
835 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
836 ok(compare_surface(surface, "393636185359a550d459e1e5f0e25411814f724c"), "Surface does not match.\n");
838 ID2D1RenderTarget_BeginDraw(rt);
840 ID2D1RenderTarget_Clear(rt, &color);
842 ID2D1BitmapBrush_SetOpacity(brush, 1.0f);
843 for (i = 0; i < sizeof(extend_mode_tests) / sizeof(*extend_mode_tests); ++i)
845 ID2D1BitmapBrush_SetExtendModeX(brush, extend_mode_tests[i].extend_mode_x);
846 extend_mode = ID2D1BitmapBrush_GetExtendModeX(brush);
847 ok(extend_mode == extend_mode_tests[i].extend_mode_x,
848 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
849 i, extend_mode, extend_mode_tests[i].extend_mode_x);
850 ID2D1BitmapBrush_SetExtendModeY(brush, extend_mode_tests[i].extend_mode_y);
851 extend_mode = ID2D1BitmapBrush_GetExtendModeY(brush);
852 ok(extend_mode == extend_mode_tests[i].extend_mode_y,
853 "Test %u: Got unexpected extend mode %#x, expected %#x.\n",
854 i, extend_mode, extend_mode_tests[i].extend_mode_y);
855 set_matrix_identity(&matrix);
856 translate_matrix(&matrix, extend_mode_tests[i].translate_x, extend_mode_tests[i].translate_y);
857 scale_matrix(&matrix, 0.5f, 0.5f);
858 ID2D1BitmapBrush_SetTransform(brush, &matrix);
859 ID2D1RenderTarget_FillRectangle(rt, &extend_mode_tests[i].rect, (ID2D1Brush *)brush);
862 hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
863 ok(SUCCEEDED(hr), "Failed to end draw, hr %#x.\n", hr);
864 ok(compare_surface(surface, "b4b775afecdae2d26642001f4faff73663bb8b31"), "Surface does not match.\n");
866 ID2D1BitmapBrush_Release(brush);
867 refcount = ID2D1Bitmap_Release(bitmap);
868 ok(!refcount, "Bitmap has %u references left.\n", refcount);
869 ID2D1RenderTarget_Release(rt);
870 IDXGISurface_Release(surface);
871 IDXGISwapChain_Release(swapchain);
872 ID3D10Device1_Release(device);
873 DestroyWindow(window);
876 START_TEST(d2d1)
878 test_clip();
879 test_state_block();
880 test_color_brush();
881 test_bitmap_brush();