directmanipulation: Return S_OK form viewport_SetViewportOptions stub.
[wine/zf.git] / dlls / d3dx9_36 / tests / core.c
blob020f18e622cbc5dbe099bae242bf8bea3ae4579e
1 /*
2 * Tests for the D3DX9 core interfaces
4 * Copyright 2009 Tony Wasserka
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
22 #include "wine/test.h"
23 #include <dxerr9.h>
24 #include "d3dx9core.h"
26 static inline int get_ref(IUnknown *obj)
28 IUnknown_AddRef(obj);
29 return IUnknown_Release(obj);
32 #define check_ref(obj, exp) _check_ref(__LINE__, obj, exp)
33 static inline void _check_ref(unsigned int line, IUnknown *obj, int exp)
35 int ref = get_ref(obj);
36 ok_(__FILE__, line)(exp == ref, "Invalid refcount. Expected %d, got %d\n", exp, ref);
39 #define check_release(obj, exp) _check_release(__LINE__, obj, exp)
40 static inline void _check_release(unsigned int line, IUnknown *obj, int exp)
42 int ref = IUnknown_Release(obj);
43 ok_(__FILE__, line)(ref == exp, "Invalid refcount. Expected %d, got %d\n", exp, ref);
46 #define admitted_error 0.0001f
47 static inline void check_mat(D3DXMATRIX got, D3DXMATRIX exp)
49 int i, j, equal=1;
50 for (i=0; i<4; i++)
51 for (j=0; j<4; j++)
52 if (fabs(U(exp).m[i][j]-U(got).m[i][j]) > admitted_error)
53 equal=0;
55 ok(equal, "Got matrix\n\t(%f,%f,%f,%f\n\t %f,%f,%f,%f\n\t %f,%f,%f,%f\n\t %f,%f,%f,%f)\n"
56 "Expected matrix=\n\t(%f,%f,%f,%f\n\t %f,%f,%f,%f\n\t %f,%f,%f,%f\n\t %f,%f,%f,%f)\n",
57 U(got).m[0][0],U(got).m[0][1],U(got).m[0][2],U(got).m[0][3],
58 U(got).m[1][0],U(got).m[1][1],U(got).m[1][2],U(got).m[1][3],
59 U(got).m[2][0],U(got).m[2][1],U(got).m[2][2],U(got).m[2][3],
60 U(got).m[3][0],U(got).m[3][1],U(got).m[3][2],U(got).m[3][3],
61 U(exp).m[0][0],U(exp).m[0][1],U(exp).m[0][2],U(exp).m[0][3],
62 U(exp).m[1][0],U(exp).m[1][1],U(exp).m[1][2],U(exp).m[1][3],
63 U(exp).m[2][0],U(exp).m[2][1],U(exp).m[2][2],U(exp).m[2][3],
64 U(exp).m[3][0],U(exp).m[3][1],U(exp).m[3][2],U(exp).m[3][3]);
67 #define check_rect(rect, left, top, right, bottom) _check_rect(__LINE__, rect, left, top, right, bottom)
68 static inline void _check_rect(unsigned int line, const RECT *rect, int left, int top, int right, int bottom)
70 ok_(__FILE__, line)(rect->left == left, "Unexpected rect.left %d\n", rect->left);
71 ok_(__FILE__, line)(rect->top == top, "Unexpected rect.top %d\n", rect->top);
72 ok_(__FILE__, line)(rect->right == right, "Unexpected rect.right %d\n", rect->right);
73 ok_(__FILE__, line)(rect->bottom == bottom, "Unexpected rect.bottom %d\n", rect->bottom);
76 static void test_ID3DXBuffer(void)
78 ID3DXBuffer *buffer;
79 HRESULT hr;
80 ULONG count;
81 DWORD size;
83 hr = D3DXCreateBuffer(10, NULL);
84 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateBuffer failed, got %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
86 hr = D3DXCreateBuffer(0, &buffer);
87 ok(hr == D3D_OK, "D3DXCreateBuffer failed, got %#x, expected %#x\n", hr, D3D_OK);
89 size = ID3DXBuffer_GetBufferSize(buffer);
90 ok(!size, "GetBufferSize failed, got %u, expected %u\n", size, 0);
92 count = ID3DXBuffer_Release(buffer);
93 ok(!count, "ID3DXBuffer has %u references left\n", count);
95 hr = D3DXCreateBuffer(3, &buffer);
96 ok(hr == D3D_OK, "D3DXCreateBuffer failed, got %#x, expected %#x\n", hr, D3D_OK);
98 size = ID3DXBuffer_GetBufferSize(buffer);
99 ok(size == 3, "GetBufferSize failed, got %u, expected %u\n", size, 3);
101 count = ID3DXBuffer_Release(buffer);
102 ok(!count, "ID3DXBuffer has %u references left\n", count);
105 static void test_ID3DXSprite(IDirect3DDevice9 *device)
107 ID3DXSprite *sprite;
108 IDirect3D9 *d3d;
109 IDirect3DDevice9 *cmpdev;
110 IDirect3DTexture9 *tex1, *tex2;
111 D3DXMATRIX mat, cmpmat;
112 D3DVIEWPORT9 vp;
113 RECT rect;
114 D3DXVECTOR3 pos, center;
115 HRESULT hr;
117 IDirect3DDevice9_GetDirect3D(device, &d3d);
118 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8);
119 IDirect3D9_Release(d3d);
120 ok (hr == D3D_OK, "D3DFMT_A8R8G8B8 not supported\n");
121 if (FAILED(hr)) return;
123 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex1, NULL);
124 ok (hr == D3D_OK, "Failed to create first texture (error code: %#x)\n", hr);
125 if (FAILED(hr)) return;
127 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex2, NULL);
128 ok (hr == D3D_OK, "Failed to create second texture (error code: %#x)\n", hr);
129 if (FAILED(hr)) {
130 IDirect3DTexture9_Release(tex1);
131 return;
134 /* Test D3DXCreateSprite */
135 hr = D3DXCreateSprite(device, NULL);
136 ok (hr == D3DERR_INVALIDCALL, "D3DXCreateSprite returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
138 hr = D3DXCreateSprite(NULL, &sprite);
139 ok (hr == D3DERR_INVALIDCALL, "D3DXCreateSprite returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
141 hr = D3DXCreateSprite(device, &sprite);
142 ok (hr == D3D_OK, "D3DXCreateSprite returned %#x, expected %#x\n", hr, D3D_OK);
145 /* Test ID3DXSprite_GetDevice */
146 hr = ID3DXSprite_GetDevice(sprite, NULL);
147 ok (hr == D3DERR_INVALIDCALL, "GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
149 hr = ID3DXSprite_GetDevice(sprite, &cmpdev); /* cmpdev == NULL */
150 ok (hr == D3D_OK, "GetDevice returned %#x, expected %#x\n", hr, D3D_OK);
152 hr = ID3DXSprite_GetDevice(sprite, &cmpdev); /* cmpdev != NULL */
153 ok (hr == D3D_OK, "GetDevice returned %#x, expected %#x\n", hr, D3D_OK);
155 IDirect3DDevice9_Release(device);
156 IDirect3DDevice9_Release(device);
159 /* Test ID3DXSprite_GetTransform */
160 hr = ID3DXSprite_GetTransform(sprite, NULL);
161 ok (hr == D3DERR_INVALIDCALL, "GetTransform returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
162 hr = ID3DXSprite_GetTransform(sprite, &mat);
163 ok (hr == D3D_OK, "GetTransform returned %#x, expected %#x\n", hr, D3D_OK);
164 if(SUCCEEDED(hr)) {
165 D3DXMATRIX identity;
166 D3DXMatrixIdentity(&identity);
167 check_mat(mat, identity);
170 /* Test ID3DXSprite_SetTransform */
171 /* Set a transform and test if it gets returned correctly */
172 U(mat).m[0][0]=2.1f; U(mat).m[0][1]=6.5f; U(mat).m[0][2]=-9.6f; U(mat).m[0][3]=1.7f;
173 U(mat).m[1][0]=4.2f; U(mat).m[1][1]=-2.5f; U(mat).m[1][2]=2.1f; U(mat).m[1][3]=5.5f;
174 U(mat).m[2][0]=-2.6f; U(mat).m[2][1]=0.3f; U(mat).m[2][2]=8.6f; U(mat).m[2][3]=8.4f;
175 U(mat).m[3][0]=6.7f; U(mat).m[3][1]=-5.1f; U(mat).m[3][2]=6.1f; U(mat).m[3][3]=2.2f;
177 hr = ID3DXSprite_SetTransform(sprite, NULL);
178 ok (hr == D3DERR_INVALIDCALL, "SetTransform returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
180 hr = ID3DXSprite_SetTransform(sprite, &mat);
181 ok (hr == D3D_OK, "SetTransform returned %#x, expected %#x\n", hr, D3D_OK);
182 if(SUCCEEDED(hr)) {
183 hr=ID3DXSprite_GetTransform(sprite, &cmpmat);
184 if(SUCCEEDED(hr)) check_mat(cmpmat, mat);
185 else skip("GetTransform returned %#x\n", hr);
188 /* Test ID3DXSprite_SetWorldViewLH/RH */
189 todo_wine {
190 hr = ID3DXSprite_SetWorldViewLH(sprite, &mat, &mat);
191 ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK);
192 hr = ID3DXSprite_SetWorldViewLH(sprite, NULL, &mat);
193 ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK);
194 hr = ID3DXSprite_SetWorldViewLH(sprite, &mat, NULL);
195 ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK);
196 hr = ID3DXSprite_SetWorldViewLH(sprite, NULL, NULL);
197 ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK);
199 hr = ID3DXSprite_SetWorldViewRH(sprite, &mat, &mat);
200 ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK);
201 hr = ID3DXSprite_SetWorldViewRH(sprite, NULL, &mat);
202 ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK);
203 hr = ID3DXSprite_SetWorldViewRH(sprite, &mat, NULL);
204 ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK);
205 hr = ID3DXSprite_SetWorldViewRH(sprite, NULL, NULL);
206 ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK);
208 IDirect3DDevice9_BeginScene(device);
210 /* Test ID3DXSprite_Begin*/
211 hr = ID3DXSprite_Begin(sprite, 0);
212 ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK);
214 IDirect3DDevice9_GetTransform(device, D3DTS_WORLD, &mat);
215 D3DXMatrixIdentity(&cmpmat);
216 check_mat(mat, cmpmat);
218 IDirect3DDevice9_GetTransform(device, D3DTS_VIEW, &mat);
219 check_mat(mat, cmpmat);
221 IDirect3DDevice9_GetTransform(device, D3DTS_PROJECTION, &mat);
222 IDirect3DDevice9_GetViewport(device, &vp);
223 D3DXMatrixOrthoOffCenterLH(&cmpmat, vp.X+0.5f, (float)vp.Width+vp.X+0.5f, (float)vp.Height+vp.Y+0.5f, vp.Y+0.5f, vp.MinZ, vp.MaxZ);
224 check_mat(mat, cmpmat);
226 /* Test ID3DXSprite_Flush and ID3DXSprite_End */
227 hr = ID3DXSprite_Flush(sprite);
228 ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK);
230 hr = ID3DXSprite_End(sprite);
231 ok (hr == D3D_OK, "End returned %#x, expected %#x\n", hr, D3D_OK);
233 hr = ID3DXSprite_Flush(sprite); /* May not be called before next Begin */
234 ok (hr == D3DERR_INVALIDCALL, "Flush returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
235 hr = ID3DXSprite_End(sprite);
236 ok (hr == D3DERR_INVALIDCALL, "End returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
238 /* Test ID3DXSprite_Draw */
239 hr = ID3DXSprite_Begin(sprite, 0);
240 ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK);
242 if(FAILED(hr)) skip("Couldn't ID3DXSprite_Begin, can't test ID3DXSprite_Draw\n");
243 else { /* Feed the sprite batch */
244 int texref1, texref2;
246 SetRect(&rect, 53, 12, 142, 165);
247 pos.x = 2.2f; pos.y = 4.5f; pos.z = 5.1f;
248 center.x = 11.3f; center.y = 3.4f; center.z = 1.2f;
250 texref1 = get_ref((IUnknown*)tex1);
251 texref2 = get_ref((IUnknown*)tex2);
253 hr = ID3DXSprite_Draw(sprite, NULL, &rect, &center, &pos, D3DCOLOR_XRGB(255, 255, 255));
254 ok (hr == D3DERR_INVALIDCALL, "Draw returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
256 hr = ID3DXSprite_Draw(sprite, tex1, &rect, &center, &pos, D3DCOLOR_XRGB(255, 255, 255));
257 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);
258 hr = ID3DXSprite_Draw(sprite, tex2, &rect, &center, &pos, D3DCOLOR_XRGB( 3, 45, 66));
259 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);
260 hr = ID3DXSprite_Draw(sprite, tex1, NULL, &center, &pos, D3DCOLOR_XRGB(255, 255, 255));
261 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);
262 hr = ID3DXSprite_Draw(sprite, tex1, &rect, NULL, &pos, D3DCOLOR_XRGB(255, 255, 255));
263 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);
264 hr = ID3DXSprite_Draw(sprite, tex1, &rect, &center, NULL, D3DCOLOR_XRGB(255, 255, 255));
265 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);
266 hr = ID3DXSprite_Draw(sprite, tex1, NULL, NULL, NULL, 0);
267 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);
269 check_ref((IUnknown*)tex1, texref1+5); check_ref((IUnknown*)tex2, texref2+1);
270 hr = ID3DXSprite_Flush(sprite);
271 ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK);
272 hr = ID3DXSprite_Flush(sprite); /* Flushing twice should work */
273 ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK);
274 check_ref((IUnknown*)tex1, texref1); check_ref((IUnknown*)tex2, texref2);
276 hr = ID3DXSprite_End(sprite);
277 ok (hr == D3D_OK, "End returned %#x, expected %#x\n", hr, D3D_OK);
280 /* Test ID3DXSprite_OnLostDevice and ID3DXSprite_OnResetDevice */
281 /* Both can be called twice */
282 hr = ID3DXSprite_OnLostDevice(sprite);
283 ok (hr == D3D_OK, "OnLostDevice returned %#x, expected %#x\n", hr, D3D_OK);
284 hr = ID3DXSprite_OnLostDevice(sprite);
285 ok (hr == D3D_OK, "OnLostDevice returned %#x, expected %#x\n", hr, D3D_OK);
286 hr = ID3DXSprite_OnResetDevice(sprite);
287 ok (hr == D3D_OK, "OnResetDevice returned %#x, expected %#x\n", hr, D3D_OK);
288 hr = ID3DXSprite_OnResetDevice(sprite);
289 ok (hr == D3D_OK, "OnResetDevice returned %#x, expected %#x\n", hr, D3D_OK);
291 /* Make sure everything works like before */
292 hr = ID3DXSprite_Begin(sprite, 0);
293 ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK);
294 hr = ID3DXSprite_Draw(sprite, tex2, &rect, &center, &pos, D3DCOLOR_XRGB(255, 255, 255));
295 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);
296 hr = ID3DXSprite_Flush(sprite);
297 ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK);
298 hr = ID3DXSprite_End(sprite);
299 ok (hr == D3D_OK, "End returned %#x, expected %#x\n", hr, D3D_OK);
301 /* OnResetDevice makes the interface "forget" the Begin call */
302 hr = ID3DXSprite_Begin(sprite, 0);
303 ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK);
304 hr = ID3DXSprite_OnResetDevice(sprite);
305 ok (hr == D3D_OK, "OnResetDevice returned %#x, expected %#x\n", hr, D3D_OK);
306 hr = ID3DXSprite_End(sprite);
307 ok (hr == D3DERR_INVALIDCALL, "End returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
309 IDirect3DDevice9_EndScene(device);
310 check_release((IUnknown*)sprite, 0);
311 check_release((IUnknown*)tex2, 0);
312 check_release((IUnknown*)tex1, 0);
315 static void test_ID3DXFont(IDirect3DDevice9 *device)
317 static const WCHAR testW[] = L"test";
318 static const char long_text[] = "Example text to test clipping and other related things";
319 static const WCHAR long_textW[] = L"Example text to test clipping and other related things";
320 static const MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
321 static const struct
323 int font_height;
324 unsigned int expected_size;
325 unsigned int expected_levels;
327 tests[] =
329 { 2, 32, 2 },
330 { 6, 128, 4 },
331 { 10, 256, 5 },
332 { 12, 256, 5 },
333 { 72, 256, 8 },
334 { 250, 256, 9 },
335 { 258, 512, 10 },
336 { 512, 512, 10 },
338 const unsigned int size = ARRAY_SIZE(testW);
339 TEXTMETRICA metrics, expmetrics;
340 IDirect3DTexture9 *texture;
341 D3DSURFACE_DESC surf_desc;
342 IDirect3DDevice9 *bufdev;
343 GLYPHMETRICS glyph_metrics;
344 D3DXFONT_DESCA desc;
345 ID3DXSprite *sprite;
346 RECT rect, blackbox;
347 DWORD count, levels;
348 int ref, i, height;
349 ID3DXFont *font;
350 TEXTMETRICW tm;
351 POINT cellinc;
352 HRESULT hr;
353 WORD glyph;
354 BOOL ret;
355 HDC hdc;
356 char c;
358 /* D3DXCreateFont */
359 ref = get_ref((IUnknown*)device);
360 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
361 ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK);
362 check_ref((IUnknown*)device, ref + 1);
363 check_release((IUnknown*)font, 0);
364 check_ref((IUnknown*)device, ref);
366 hr = D3DXCreateFontA(device, 0, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
367 ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK);
368 ID3DXFont_Release(font);
370 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, NULL, &font);
371 ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK);
372 ID3DXFont_Release(font);
374 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "", &font);
375 ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK);
376 ID3DXFont_Release(font);
378 hr = D3DXCreateFontA(NULL, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
379 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
381 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", NULL);
382 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
384 hr = D3DXCreateFontA(NULL, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", NULL);
385 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
388 /* D3DXCreateFontIndirect */
389 desc.Height = 12;
390 desc.Width = 0;
391 desc.Weight = FW_DONTCARE;
392 desc.MipLevels = 0;
393 desc.Italic = FALSE;
394 desc.CharSet = DEFAULT_CHARSET;
395 desc.OutputPrecision = OUT_DEFAULT_PRECIS;
396 desc.Quality = DEFAULT_QUALITY;
397 desc.PitchAndFamily = DEFAULT_PITCH;
398 strcpy(desc.FaceName, "Tahoma");
399 hr = D3DXCreateFontIndirectA(device, &desc, &font);
400 ok(hr == D3D_OK, "D3DXCreateFontIndirect returned %#x, expected %#x\n", hr, D3D_OK);
401 ID3DXFont_Release(font);
403 hr = D3DXCreateFontIndirectA(NULL, &desc, &font);
404 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFontIndirect returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
406 hr = D3DXCreateFontIndirectA(device, NULL, &font);
407 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFontIndirect returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
409 hr = D3DXCreateFontIndirectA(device, &desc, NULL);
410 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFontIndirect returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
413 /* ID3DXFont_GetDevice */
414 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
415 DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
416 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
418 hr = ID3DXFont_GetDevice(font, NULL);
419 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
421 ref = get_ref((IUnknown *)device);
422 hr = ID3DXFont_GetDevice(font, &bufdev);
423 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
424 check_release((IUnknown *)bufdev, ref);
426 ID3DXFont_Release(font);
429 /* ID3DXFont_GetDesc */
430 hr = D3DXCreateFontA(device, 12, 8, FW_BOLD, 2, TRUE, ANSI_CHARSET, OUT_RASTER_PRECIS,
431 ANTIALIASED_QUALITY, VARIABLE_PITCH, "Tahoma", &font);
432 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
434 hr = ID3DXFont_GetDescA(font, NULL);
435 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
437 hr = ID3DXFont_GetDescA(font, &desc);
438 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
440 ok(desc.Height == 12, "Got unexpected height %d.\n", desc.Height);
441 ok(desc.Width == 8, "Got unexpected width %u.\n", desc.Width);
442 ok(desc.Weight == FW_BOLD, "Got unexpected weight %u.\n", desc.Weight);
443 ok(desc.MipLevels == 2, "Got unexpected miplevels %u.\n", desc.MipLevels);
444 ok(desc.Italic == TRUE, "Got unexpected italic %#x.\n", desc.Italic);
445 ok(desc.CharSet == ANSI_CHARSET, "Got unexpected charset %u.\n", desc.CharSet);
446 ok(desc.OutputPrecision == OUT_RASTER_PRECIS, "Got unexpected output precision %u.\n", desc.OutputPrecision);
447 ok(desc.Quality == ANTIALIASED_QUALITY, "Got unexpected quality %u.\n", desc.Quality);
448 ok(desc.PitchAndFamily == VARIABLE_PITCH, "Got unexpected pitch and family %#x.\n", desc.PitchAndFamily);
449 ok(!strcmp(desc.FaceName, "Tahoma"), "Got unexpected facename %s.\n", debugstr_a(desc.FaceName));
451 ID3DXFont_Release(font);
454 /* ID3DXFont_GetDC + ID3DXFont_GetTextMetrics */
455 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
456 DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
457 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
459 hdc = ID3DXFont_GetDC(font);
460 ok(!!hdc, "Got unexpected hdc %p.\n", hdc);
462 ret = ID3DXFont_GetTextMetricsA(font, &metrics);
463 ok(ret, "Got unexpected ret %#x.\n", ret);
464 ret = GetTextMetricsA(hdc, &expmetrics);
465 ok(ret, "Got unexpected ret %#x.\n", ret);
467 ok(metrics.tmHeight == expmetrics.tmHeight, "Got unexpected height %d, expected %d.\n",
468 metrics.tmHeight, expmetrics.tmHeight);
469 ok(metrics.tmAscent == expmetrics.tmAscent, "Got unexpected ascent %d, expected %d.\n",
470 metrics.tmAscent, expmetrics.tmAscent);
471 ok(metrics.tmDescent == expmetrics.tmDescent, "Got unexpected descent %d, expected %d.\n",
472 metrics.tmDescent, expmetrics.tmDescent);
473 ok(metrics.tmInternalLeading == expmetrics.tmInternalLeading, "Got unexpected internal leading %d, expected %d.\n",
474 metrics.tmInternalLeading, expmetrics.tmInternalLeading);
475 ok(metrics.tmExternalLeading == expmetrics.tmExternalLeading, "Got unexpected external leading %d, expected %d.\n",
476 metrics.tmExternalLeading, expmetrics.tmExternalLeading);
477 ok(metrics.tmAveCharWidth == expmetrics.tmAveCharWidth, "Got unexpected average char width %d, expected %d.\n",
478 metrics.tmAveCharWidth, expmetrics.tmAveCharWidth);
479 ok(metrics.tmMaxCharWidth == expmetrics.tmMaxCharWidth, "Got unexpected maximum char width %d, expected %d.\n",
480 metrics.tmMaxCharWidth, expmetrics.tmMaxCharWidth);
481 ok(metrics.tmWeight == expmetrics.tmWeight, "Got unexpected weight %d, expected %d.\n",
482 metrics.tmWeight, expmetrics.tmWeight);
483 ok(metrics.tmOverhang == expmetrics.tmOverhang, "Got unexpected overhang %d, expected %d.\n",
484 metrics.tmOverhang, expmetrics.tmOverhang);
485 ok(metrics.tmDigitizedAspectX == expmetrics.tmDigitizedAspectX, "Got unexpected digitized x aspect %d, expected %d.\n",
486 metrics.tmDigitizedAspectX, expmetrics.tmDigitizedAspectX);
487 ok(metrics.tmDigitizedAspectY == expmetrics.tmDigitizedAspectY, "Got unexpected digitized y aspect %d, expected %d.\n",
488 metrics.tmDigitizedAspectY, expmetrics.tmDigitizedAspectY);
489 ok(metrics.tmFirstChar == expmetrics.tmFirstChar, "Got unexpected first char %u, expected %u.\n",
490 metrics.tmFirstChar, expmetrics.tmFirstChar);
491 ok(metrics.tmLastChar == expmetrics.tmLastChar, "Got unexpected last char %u, expected %u.\n",
492 metrics.tmLastChar, expmetrics.tmLastChar);
493 ok(metrics.tmDefaultChar == expmetrics.tmDefaultChar, "Got unexpected default char %u, expected %u.\n",
494 metrics.tmDefaultChar, expmetrics.tmDefaultChar);
495 ok(metrics.tmBreakChar == expmetrics.tmBreakChar, "Got unexpected break char %u, expected %u.\n",
496 metrics.tmBreakChar, expmetrics.tmBreakChar);
497 ok(metrics.tmItalic == expmetrics.tmItalic, "Got unexpected italic %u, expected %u.\n",
498 metrics.tmItalic, expmetrics.tmItalic);
499 ok(metrics.tmUnderlined == expmetrics.tmUnderlined, "Got unexpected underlined %u, expected %u.\n",
500 metrics.tmUnderlined, expmetrics.tmUnderlined);
501 ok(metrics.tmStruckOut == expmetrics.tmStruckOut, "Got unexpected struck out %u, expected %u.\n",
502 metrics.tmStruckOut, expmetrics.tmStruckOut);
503 ok(metrics.tmPitchAndFamily == expmetrics.tmPitchAndFamily, "Got unexpected pitch and family %u, expected %u.\n",
504 metrics.tmPitchAndFamily, expmetrics.tmPitchAndFamily);
505 ok(metrics.tmCharSet == expmetrics.tmCharSet, "Got unexpected charset %u, expected %u.\n",
506 metrics.tmCharSet, expmetrics.tmCharSet);
508 ID3DXFont_Release(font);
511 /* ID3DXFont_PreloadText */
512 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
513 DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
514 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
516 hr = ID3DXFont_PreloadTextA(font, NULL, -1);
517 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
518 hr = ID3DXFont_PreloadTextA(font, NULL, 0);
519 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
520 hr = ID3DXFont_PreloadTextA(font, NULL, 1);
521 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
522 hr = ID3DXFont_PreloadTextA(font, "test", -1);
523 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
524 hr = ID3DXFont_PreloadTextA(font, "", 0);
525 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
526 hr = ID3DXFont_PreloadTextA(font, "", -1);
527 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
529 hr = ID3DXFont_PreloadTextW(font, NULL, -1);
530 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
531 hr = ID3DXFont_PreloadTextW(font, NULL, 0);
532 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
533 hr = ID3DXFont_PreloadTextW(font, NULL, 1);
534 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
535 hr = ID3DXFont_PreloadTextW(font, testW, -1);
536 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
537 hr = ID3DXFont_PreloadTextW(font, L"", 0);
538 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
539 hr = ID3DXFont_PreloadTextW(font, L"", -1);
540 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
542 check_release((IUnknown*)font, 0);
545 /* ID3DXFont_GetGlyphData, ID3DXFont_PreloadGlyphs, ID3DXFont_PreloadCharacters */
546 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
547 DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
548 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
550 hdc = ID3DXFont_GetDC(font);
551 ok(!!hdc, "Got unexpected hdc %p.\n", hdc);
553 hr = ID3DXFont_GetGlyphData(font, 0, NULL, &blackbox, &cellinc);
554 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
555 hr = ID3DXFont_GetGlyphData(font, 0, &texture, NULL, &cellinc);
556 check_release((IUnknown *)texture, 1);
557 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
558 hr = ID3DXFont_GetGlyphData(font, 0, &texture, &blackbox, NULL);
559 check_release((IUnknown *)texture, 1);
560 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
562 hr = ID3DXFont_PreloadCharacters(font, 'b', 'a');
563 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
564 hr = ID3DXFont_PreloadGlyphs(font, 1, 0);
565 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
567 hr = ID3DXFont_PreloadCharacters(font, 'a', 'a');
568 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
570 for (c = 'b'; c <= 'z'; ++c)
572 count = GetGlyphIndicesA(hdc, &c, 1, &glyph, 0);
573 ok(count != GDI_ERROR, "Got unexpected count %u.\n", count);
575 hr = ID3DXFont_GetGlyphData(font, glyph, &texture, &blackbox, &cellinc);
576 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
578 levels = IDirect3DTexture9_GetLevelCount(texture);
579 todo_wine ok(levels == 5, "Character %c: got unexpected levels %u.\n", c, levels);
580 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surf_desc);
581 ok(hr == D3D_OK, "Character %c: got unexpected hr %#x.\n", c, hr);
582 ok(surf_desc.Format == D3DFMT_A8R8G8B8, "Character %c: got unexpected format %#x.\n", c, surf_desc.Format);
583 ok(surf_desc.Usage == 0, "Character %c: got unexpected usage %#x.\n", c, surf_desc.Usage);
584 ok(surf_desc.Width == 256, "Character %c: got unexpected width %u.\n", c, surf_desc.Width);
585 ok(surf_desc.Height == 256, "Character %c: got unexpected height %u.\n", c, surf_desc.Height);
586 ok(surf_desc.Pool == D3DPOOL_MANAGED, "Character %c: got unexpected pool %u.\n", c, surf_desc.Pool);
588 count = GetGlyphOutlineW(hdc, glyph, GGO_GLYPH_INDEX | GGO_METRICS, &glyph_metrics, 0, NULL, &mat);
589 ok(count != GDI_ERROR, "Got unexpected count %#x.\n", count);
591 ret = ID3DXFont_GetTextMetricsW(font, &tm);
592 ok(ret, "Got unexpected ret %#x.\n", ret);
594 todo_wine ok(blackbox.right - blackbox.left == glyph_metrics.gmBlackBoxX + 2, "Character %c: got %d, expected %d.\n",
595 c, blackbox.right - blackbox.left, glyph_metrics.gmBlackBoxX + 2);
596 todo_wine ok(blackbox.bottom - blackbox.top == glyph_metrics.gmBlackBoxY + 2, "Character %c: got %d, expected %d.\n",
597 c, blackbox.bottom - blackbox.top, glyph_metrics.gmBlackBoxY + 2);
598 ok(cellinc.x == glyph_metrics.gmptGlyphOrigin.x - 1, "Character %c: got %d, expected %d.\n",
599 c, cellinc.x, glyph_metrics.gmptGlyphOrigin.x - 1);
600 ok(cellinc.y == tm.tmAscent - glyph_metrics.gmptGlyphOrigin.y - 1, "Character %c: got %d, expected %d.\n",
601 c, cellinc.y, tm.tmAscent - glyph_metrics.gmptGlyphOrigin.y - 1);
603 check_release((IUnknown *)texture, 1);
606 hr = ID3DXFont_PreloadCharacters(font, 'a', 'z');
607 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
609 /* Test multiple textures */
610 hr = ID3DXFont_PreloadGlyphs(font, 0, 1000);
611 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
613 /* Test glyphs that are not rendered */
614 for (glyph = 1; glyph < 4; ++glyph)
616 texture = (IDirect3DTexture9 *)0xdeadbeef;
617 hr = ID3DXFont_GetGlyphData(font, glyph, &texture, &blackbox, &cellinc);
618 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
619 ok(!texture, "Got unexpected texture %p.\n", texture);
622 check_release((IUnknown *)font, 0);
624 c = 'a';
625 for (i = 0; i < ARRAY_SIZE(tests); ++i)
627 hr = D3DXCreateFontA(device, tests[i].font_height, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET,
628 OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
629 ok(hr == D3D_OK, "Test %u: got unexpected hr %#x.\n", i, hr);
631 hdc = ID3DXFont_GetDC(font);
632 ok(!!hdc, "Test %u: got unexpected hdc %p.\n", i, hdc);
634 count = GetGlyphIndicesA(hdc, &c, 1, &glyph, 0);
635 ok(count != GDI_ERROR, "Test %u: got unexpected count %u.\n", i, count);
637 hr = ID3DXFont_GetGlyphData(font, glyph, &texture, NULL, NULL);
638 ok(hr == D3D_OK, "Test %u: got unexpected hr %#x.\n", i, hr);
640 levels = IDirect3DTexture9_GetLevelCount(texture);
641 todo_wine_if(tests[i].expected_levels < 9)
642 ok(levels == tests[i].expected_levels, "Test %u: got unexpected levels %u.\n", i, levels);
644 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surf_desc);
645 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
646 ok(surf_desc.Format == D3DFMT_A8R8G8B8, "Test %u: got unexpected format %#x.\n", i, surf_desc.Format);
647 ok(surf_desc.Usage == 0, "Test %u: got unexpected usage %#x.\n", i, surf_desc.Usage);
648 ok(surf_desc.Width == tests[i].expected_size, "Test %u: got unexpected width %u.\n", i, surf_desc.Width);
649 ok(surf_desc.Height == tests[i].expected_size, "Test %u: got unexpected height %u.\n", i, surf_desc.Height);
650 ok(surf_desc.Pool == D3DPOOL_MANAGED, "Test %u: got unexpected pool %u.\n", i, surf_desc.Pool);
652 IDirect3DTexture9_Release(texture);
654 /* ID3DXFontImpl_DrawText */
655 D3DXCreateSprite(device, &sprite);
656 SetRect(&rect, 0, 0, 640, 480);
658 IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 1.0f, 0);
660 IDirect3DDevice9_BeginScene(device);
661 hr = ID3DXSprite_Begin(sprite, D3DXSPRITE_ALPHABLEND);
662 ok (hr == D3D_OK, "Test %d: got unexpected hr %#x.\n", i, hr);
664 height = ID3DXFont_DrawTextW(font, sprite, testW, -1, &rect, DT_TOP, 0xffffffff);
665 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height);
666 height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_TOP, 0xffffffff);
667 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height);
668 height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_RIGHT, 0xffffffff);
669 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height);
670 height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_LEFT | DT_NOCLIP, 0xffffffff);
671 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height);
673 SetRectEmpty(&rect);
674 height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect,
675 DT_LEFT | DT_CALCRECT, 0xffffffff);
676 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height);
677 ok(!rect.left, "Test %d: got unexpected rect left %d.\n", i, rect.left);
678 ok(!rect.top, "Test %d: got unexpected rect top %d.\n", i, rect.top);
679 ok(rect.right, "Test %d: got unexpected rect right %d.\n", i, rect.right);
680 ok(rect.bottom == tests[i].font_height, "Test %d: got unexpected rect bottom %d.\n", i, rect.bottom);
682 hr = ID3DXSprite_End(sprite);
683 ok (hr == D3D_OK, "Test %d: got unexpected hr %#x.\n", i, hr);
684 IDirect3DDevice9_EndScene(device);
685 ID3DXSprite_Release(sprite);
687 ID3DXFont_Release(font);
691 /* ID3DXFont_DrawTextA, ID3DXFont_DrawTextW */
692 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
693 DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font);
694 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
696 SetRect(&rect, 10, 10, 200, 200);
698 height = ID3DXFont_DrawTextA(font, NULL, "test", -2, &rect, 0, 0xFF00FF);
699 ok(height == 12, "Got unexpected height %d.\n", height);
701 height = ID3DXFont_DrawTextA(font, NULL, "test", -1, &rect, 0, 0xFF00FF);
702 ok(height == 12, "Got unexpected height %d.\n", height);
704 height = ID3DXFont_DrawTextA(font, NULL, "test", 0, &rect, 0, 0xFF00FF);
705 ok(height == 0, "Got unexpected height %d.\n", height);
707 height = ID3DXFont_DrawTextA(font, NULL, "test", 1, &rect, 0, 0xFF00FF);
708 ok(height == 12, "Got unexpected height %d.\n", height);
710 height = ID3DXFont_DrawTextA(font, NULL, "test", 2, &rect, 0, 0xFF00FF);
711 ok(height == 12, "Got unexpected height %d.\n", height);
713 height = ID3DXFont_DrawTextA(font, NULL, "", 0, &rect, 0, 0xff00ff);
714 ok(height == 0, "Got unexpected height %d.\n", height);
716 height = ID3DXFont_DrawTextA(font, NULL, "", -1, &rect, 0, 0xff00ff);
717 ok(height == 0, "Got unexpected height %d.\n", height);
719 height = ID3DXFont_DrawTextA(font, NULL, "test", -1, NULL, 0, 0xFF00FF);
720 ok(height == 12, "Got unexpected height %d.\n", height);
722 height = ID3DXFont_DrawTextA(font, NULL, "test", -1, NULL, DT_CALCRECT, 0xFF00FF);
723 ok(height == 12, "Got unexpected height %d.\n", height);
725 height = ID3DXFont_DrawTextA(font, NULL, NULL, -1, NULL, 0, 0xFF00FF);
726 ok(height == 0, "Got unexpected height %d.\n", height);
728 SetRect(&rect, 10, 10, 50, 50);
730 height = ID3DXFont_DrawTextA(font, NULL, long_text, -1, &rect, DT_WORDBREAK, 0xff00ff);
731 todo_wine ok(height == 60, "Got unexpected height %d.\n", height);
733 height = ID3DXFont_DrawTextA(font, NULL, long_text, -1, &rect, DT_WORDBREAK | DT_NOCLIP, 0xff00ff);
734 ok(height == 96, "Got unexpected height %d.\n", height);
736 SetRect(&rect, 10, 10, 200, 200);
738 height = ID3DXFont_DrawTextW(font, NULL, testW, -1, &rect, 0, 0xFF00FF);
739 ok(height == 12, "Got unexpected height %d.\n", height);
741 height = ID3DXFont_DrawTextW(font, NULL, testW, 0, &rect, 0, 0xFF00FF);
742 ok(height == 0, "Got unexpected height %d.\n", height);
744 height = ID3DXFont_DrawTextW(font, NULL, testW, 1, &rect, 0, 0xFF00FF);
745 ok(height == 12, "Got unexpected height %d.\n", height);
747 height = ID3DXFont_DrawTextW(font, NULL, testW, 2, &rect, 0, 0xFF00FF);
748 ok(height == 12, "Got unexpected height %d.\n", height);
750 height = ID3DXFont_DrawTextW(font, NULL, L"", 0, &rect, 0, 0xff00ff);
751 ok(height == 0, "Got unexpected height %d.\n", height);
753 height = ID3DXFont_DrawTextW(font, NULL, L"", -1, &rect, 0, 0xff00ff);
754 ok(height == 0, "Got unexpected height %d.\n", height);
756 height = ID3DXFont_DrawTextW(font, NULL, testW, -1, NULL, 0, 0xFF00FF);
757 ok(height == 12, "Got unexpected height %d.\n", height);
759 height = ID3DXFont_DrawTextW(font, NULL, testW, -1, NULL, DT_CALCRECT, 0xFF00FF);
760 ok(height == 12, "Got unexpected height %d.\n", height);
762 height = ID3DXFont_DrawTextW(font, NULL, NULL, -1, NULL, 0, 0xFF00FF);
763 ok(height == 0, "Got unexpected height %d.\n", height);
765 SetRect(&rect, 10, 10, 50, 50);
767 height = ID3DXFont_DrawTextW(font, NULL, long_textW, -1, &rect, DT_WORDBREAK, 0xff00ff);
768 todo_wine ok(height == 60, "Got unexpected height %d.\n", height);
770 height = ID3DXFont_DrawTextW(font, NULL, long_textW, -1, &rect, DT_WORDBREAK | DT_NOCLIP, 0xff00ff);
771 ok(height == 96, "Got unexpected height %d.\n", height);
773 height = ID3DXFont_DrawTextW(font, NULL, L"a\na", -1, NULL, 0, 0xff00ff);
774 ok(height == 24, "Got unexpected height %d.\n", height);
776 height = ID3DXFont_DrawTextW(font, NULL, L"a\na", -1, &rect, 0, 0xff00ff);
777 ok(height == 24, "Got unexpected height %d.\n", height);
779 height = ID3DXFont_DrawTextW(font, NULL, L"a\r\na", -1, &rect, 0, 0xff00ff);
780 ok(height == 24, "Got unexpected height %d.\n", height);
782 height = ID3DXFont_DrawTextW(font, NULL, L"a\ra", -1, &rect, 0, 0xff00ff);
783 ok(height == 12, "Got unexpected height %d.\n", height);
785 height = ID3DXFont_DrawTextW(font, NULL, L"a\na", -1, &rect, DT_SINGLELINE, 0xff00ff);
786 ok(height == 12, "Got unexpected height %d.\n", height);
788 height = ID3DXFont_DrawTextW(font, NULL, L"a\naaaaa aaaa", -1, &rect, DT_SINGLELINE, 0xff00ff);
789 ok(height == 12, "Got unexpected height %d.\n", height);
791 height = ID3DXFont_DrawTextW(font, NULL, L"a\naaaaa aaaa", -1, &rect, 0, 0xff00ff);
792 ok(height == 24, "Got unexpected height %d.\n", height);
794 height = ID3DXFont_DrawTextW(font, NULL, L"a\naaaaa aaaa", -1, &rect, DT_WORDBREAK, 0xff00ff);
795 ok(height == 36, "Got unexpected height %d.\n", height);
797 height = ID3DXFont_DrawTextW(font, NULL, L"a\naaaaa aaaa", -1, &rect, DT_WORDBREAK | DT_SINGLELINE, 0xff00ff);
798 ok(height == 12, "Got unexpected height %d.\n", height);
800 height = ID3DXFont_DrawTextW(font, NULL, L"1\n2\n3\n4\n5\n6", -1, &rect, 0, 0xff00ff);
801 ok(height == 48, "Got unexpected height %d.\n", height);
803 height = ID3DXFont_DrawTextW(font, NULL, L"1\n2\n3\n4\n5\n6", -1, &rect, DT_NOCLIP, 0xff00ff);
804 ok(height == 72, "Got unexpected height %d.\n", height);
806 height = ID3DXFont_DrawTextW(font, NULL, L"\t\t\t\t\t\t\t\t\t\t", -1, &rect, DT_WORDBREAK, 0xff00ff);
807 todo_wine ok(height == 0, "Got unexpected height %d.\n", height);
809 height = ID3DXFont_DrawTextW(font, NULL, L"\t\t\t\t\t\t\t\t\t\ta", -1, &rect, DT_WORDBREAK, 0xff00ff);
810 todo_wine ok(height == 12, "Got unexpected height %d.\n", height);
812 height = ID3DXFont_DrawTextW(font, NULL, L"\taaaaaaaaaa", -1, &rect, DT_WORDBREAK, 0xff00ff);
813 todo_wine ok(height == 24, "Got unexpected height %d.\n", height);
815 height = ID3DXFont_DrawTextW(font, NULL, L"\taaaaaaaaaa", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff);
816 ok(height == 36, "Got unexpected height %d.\n", height);
818 height = ID3DXFont_DrawTextW(font, NULL, L"\taaa\taaa\taaa", -1, &rect, DT_WORDBREAK, 0xff00ff);
819 ok(height == 24, "Got unexpected height %d.\n", height);
821 height = ID3DXFont_DrawTextW(font, NULL, L"\taaa\taaa\taaa", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff);
822 todo_wine ok(height == 48, "Got unexpected height %d.\n", height);
824 height = ID3DXFont_DrawTextW(font, NULL, L"\t\t\t\t\t\t\t\t\t\t", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff);
825 todo_wine ok(height == 60, "Got unexpected height %d.\n", height);
827 height = ID3DXFont_DrawTextW(font, NULL, L"a\ta", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff);
828 ok(height == 12, "Got unexpected height %d.\n", height);
830 height = ID3DXFont_DrawTextW(font, NULL, L"a\ta\ta", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff);
831 todo_wine ok(height == 24, "Got unexpected height %d.\n", height);
833 height = ID3DXFont_DrawTextW(font, NULL, L"aaaaaaaaaaaaaaaaaaaa", -1, &rect, DT_WORDBREAK, 0xff00ff);
834 ok(height == 36, "Got unexpected height %d.\n", height);
836 height = ID3DXFont_DrawTextW(font, NULL, L"a a", -1, &rect, DT_WORDBREAK, 0xff00ff);
837 ok(height == 36, "Got unexpected height %d.\n", height);
839 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK, 0xff00ff);
840 ok(height == 36, "Got unexpected height %d.\n", height);
842 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK | DT_RIGHT, 0xff00ff);
843 ok(height == 36, "Got unexpected height %d.\n", height);
845 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK | DT_CENTER, 0xff00ff);
846 ok(height == 36, "Got unexpected height %d.\n", height);
848 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_BOTTOM, 0xff00ff);
849 ok(height == 40, "Got unexpected height %d.\n", height);
851 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_VCENTER, 0xff00ff);
852 ok(height == 32, "Got unexpected height %d.\n", height);
854 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_RIGHT, 0xff00ff);
855 ok(height == 24, "Got unexpected height %d.\n", height);
857 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER, 0xff00ff);
858 ok(height == 24, "Got unexpected height %d.\n", height);
860 SetRect(&rect, 10, 10, 50, 50);
861 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CALCRECT, 0xff00ff);
862 ok(height == 24, "Got unexpected height %d.\n", height);
863 check_rect(&rect, 10, 10, 30, 34);
865 SetRect(&rect, -10, 10, 30, 50);
866 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CALCRECT, 0xff00ff);
867 ok(height == 24, "Got unexpected height %d.\n", height);
868 check_rect(&rect, -10, 10, 10, 34);
870 SetRect(&rect, 10, -10, 50, 30);
871 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CALCRECT, 0xff00ff);
872 ok(height == 24, "Got unexpected height %d.\n", height);
873 check_rect(&rect, 10, -10, 30, 14);
875 SetRect(&rect, 10, 10, -30, 50);
876 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CALCRECT, 0xff00ff);
877 ok(height == 24, "Got unexpected height %d.\n", height);
878 check_rect(&rect, 10, 10, 30, 34);
880 SetRect(&rect, 10, 10, 50, -30);
881 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CALCRECT, 0xff00ff);
882 ok(height == 24, "Got unexpected height %d.\n", height);
883 check_rect(&rect, 10, 10, 30, 34);
885 SetRect(&rect, 10, 10, 50, 50);
886 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
887 ok(height == 24, "Got unexpected height %d.\n", height);
888 check_rect(&rect, 10, 10, 30, 34);
890 SetRect(&rect, -10, 10, 30, 50);
891 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
892 ok(height == 24, "Got unexpected height %d.\n", height);
893 check_rect(&rect, -10, 10, 10, 34);
895 SetRect(&rect, 10, -10, 50, 30);
896 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
897 ok(height == 24, "Got unexpected height %d.\n", height);
898 check_rect(&rect, 10, -10, 30, 14);
900 SetRect(&rect, 10, 10, -30, 50);
901 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
902 ok(height == 12, "Got unexpected height %d.\n", height);
903 check_rect(&rect, 10, 10, 53, 22);
905 SetRect(&rect, 10, 10, 50, -30);
906 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
907 ok(height == 24, "Got unexpected height %d.\n", height);
908 check_rect(&rect, 10, 10, 30, 34);
910 SetRect(&rect, 10, 10, 50, 50);
911 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_BOTTOM | DT_CALCRECT, 0xff00ff);
912 ok(height == 40, "Got unexpected height %d.\n", height);
913 check_rect(&rect, 10, 26, 30, 50);
915 SetRect(&rect, -10, 10, 30, 50);
916 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_BOTTOM | DT_CALCRECT, 0xff00ff);
917 ok(height == 40, "Got unexpected height %d.\n", height);
918 check_rect(&rect, -10, 26, 10, 50);
920 SetRect(&rect, 10, -10, 50, 30);
921 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_BOTTOM | DT_CALCRECT, 0xff00ff);
922 ok(height == 40, "Got unexpected height %d.\n", height);
923 check_rect(&rect, 10, 6, 30, 30);
925 SetRect(&rect, 10, 10, -30, 50);
926 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_BOTTOM | DT_CALCRECT, 0xff00ff);
927 ok(height == 40, "Got unexpected height %d.\n", height);
928 check_rect(&rect, 10, 26, 30, 50);
930 SetRect(&rect, 10, 10, 50, -30);
931 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_BOTTOM | DT_CALCRECT, 0xff00ff);
932 ok(height == -40, "Got unexpected height %d.\n", height);
933 check_rect(&rect, 10, -54, 30, -30);
935 SetRect(&rect, 10, 10, 50, 50);
936 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_BOTTOM | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
937 ok(height == 40, "Got unexpected height %d.\n", height);
938 check_rect(&rect, 10, 26, 30, 50);
940 SetRect(&rect, -10, 10, 30, 50);
941 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_BOTTOM | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
942 ok(height == 40, "Got unexpected height %d.\n", height);
943 check_rect(&rect, -10, 26, 10, 50);
945 SetRect(&rect, 10, -10, 50, 30);
946 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_BOTTOM | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
947 ok(height == 40, "Got unexpected height %d.\n", height);
948 check_rect(&rect, 10, 6, 30, 30);
950 SetRect(&rect, 10, 10, -30, 50);
951 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_BOTTOM | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
952 ok(height == 40, "Got unexpected height %d.\n", height);
953 check_rect(&rect, 10, 38, 53, 50);
955 SetRect(&rect, 10, 10, 50, -30);
956 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_BOTTOM | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
957 ok(height == -40, "Got unexpected height %d.\n", height);
958 check_rect(&rect, 10, -54, 30, -30);
960 SetRect(&rect, 10, 10, 50, 50);
961 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_VCENTER | DT_CALCRECT, 0xff00ff);
962 ok(height == 32, "Got unexpected height %d.\n", height);
963 check_rect(&rect, 10, 18, 30, 42);
965 SetRect(&rect, -10, 10, 30, 50);
966 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_VCENTER | DT_CALCRECT, 0xff00ff);
967 ok(height == 32, "Got unexpected height %d.\n", height);
968 check_rect(&rect, -10, 18, 10, 42);
970 SetRect(&rect, 10, -10, 50, 30);
971 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_VCENTER | DT_CALCRECT, 0xff00ff);
972 ok(height == 32, "Got unexpected height %d.\n", height);
973 check_rect(&rect, 10, -2, 30, 22);
975 SetRect(&rect, 10, 10, -30, 50);
976 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_VCENTER | DT_CALCRECT, 0xff00ff);
977 ok(height == 32, "Got unexpected height %d.\n", height);
978 check_rect(&rect, 10, 18, 30, 42);
980 SetRect(&rect, 10, 10, 50, -30);
981 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_VCENTER | DT_CALCRECT, 0xff00ff);
982 ok(height == -8, "Got unexpected height %d.\n", height);
983 check_rect(&rect, 10, -22, 30, 2);
985 SetRect(&rect, 10, 10, 50, 50);
986 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_VCENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
987 ok(height == 32, "Got unexpected height %d.\n", height);
988 check_rect(&rect, 10, 18, 30, 42);
990 SetRect(&rect, -10, 10, 30, 50);
991 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_VCENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
992 ok(height == 32, "Got unexpected height %d.\n", height);
993 check_rect(&rect, -10, 18, 10, 42);
995 SetRect(&rect, 10, -10, 50, 30);
996 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_VCENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
997 ok(height == 32, "Got unexpected height %d.\n", height);
998 check_rect(&rect, 10, -2, 30, 22);
1000 SetRect(&rect, 10, 10, -30, 50);
1001 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_VCENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1002 ok(height == 26, "Got unexpected height %d.\n", height);
1003 check_rect(&rect, 10, 24, 53, 36);
1005 SetRect(&rect, 10, 10, 50, -30);
1006 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_VCENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1007 ok(height == -8, "Got unexpected height %d.\n", height);
1008 check_rect(&rect, 10, -22, 30, 2);
1010 SetRect(&rect, 10, 10, 50, 50);
1011 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_RIGHT | DT_CALCRECT, 0xff00ff);
1012 ok(height == 24, "Got unexpected height %d.\n", height);
1013 check_rect(&rect, 30, 10, 50, 34);
1015 SetRect(&rect, -10, 10, 30, 50);
1016 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_RIGHT | DT_CALCRECT, 0xff00ff);
1017 ok(height == 24, "Got unexpected height %d.\n", height);
1018 check_rect(&rect, 10, 10, 30, 34);
1020 SetRect(&rect, 10, -10, 50, 30);
1021 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_RIGHT | DT_CALCRECT, 0xff00ff);
1022 ok(height == 24, "Got unexpected height %d.\n", height);
1023 check_rect(&rect, 30, -10, 50, 14);
1025 SetRect(&rect, 10, 10, -30, 50);
1026 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_RIGHT | DT_CALCRECT, 0xff00ff);
1027 ok(height == 24, "Got unexpected height %d.\n", height);
1028 check_rect(&rect, -50, 10, -30, 34);
1030 SetRect(&rect, 10, 10, 50, -30);
1031 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_RIGHT | DT_CALCRECT, 0xff00ff);
1032 ok(height == 24, "Got unexpected height %d.\n", height);
1033 check_rect(&rect, 30, 10, 50, 34);
1035 SetRect(&rect, 10, 10, 50, 50);
1036 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_RIGHT | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1037 ok(height == 24, "Got unexpected height %d.\n", height);
1038 check_rect(&rect, 30, 10, 50, 34);
1040 SetRect(&rect, -10, 10, 30, 50);
1041 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_RIGHT | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1042 ok(height == 24, "Got unexpected height %d.\n", height);
1043 check_rect(&rect, 10, 10, 30, 34);
1045 SetRect(&rect, 10, -10, 50, 30);
1046 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_RIGHT | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1047 ok(height == 24, "Got unexpected height %d.\n", height);
1048 check_rect(&rect, 30, -10, 50, 14);
1050 SetRect(&rect, 10, 10, -30, 50);
1051 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_RIGHT | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1052 ok(height == 12, "Got unexpected height %d.\n", height);
1053 check_rect(&rect, -73, 10, -30, 22);
1055 SetRect(&rect, 10, 10, 50, -30);
1056 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_RIGHT | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1057 ok(height == 24, "Got unexpected height %d.\n", height);
1058 check_rect(&rect, 30, 10, 50, 34);
1060 SetRect(&rect, 10, 10, 50, 50);
1061 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER | DT_CALCRECT, 0xff00ff);
1062 ok(height == 24, "Got unexpected height %d.\n", height);
1063 check_rect(&rect, 20, 10, 40, 34);
1065 SetRect(&rect, -10, 10, 30, 50);
1066 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER | DT_CALCRECT, 0xff00ff);
1067 ok(height == 24, "Got unexpected height %d.\n", height);
1068 check_rect(&rect, 0, 10, 20, 34);
1070 SetRect(&rect, 10, -10, 50, 30);
1071 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER | DT_CALCRECT, 0xff00ff);
1072 ok(height == 24, "Got unexpected height %d.\n", height);
1073 check_rect(&rect, 20, -10, 40, 14);
1075 SetRect(&rect, 10, 10, -30, 50);
1076 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER | DT_CALCRECT, 0xff00ff);
1077 ok(height == 24, "Got unexpected height %d.\n", height);
1078 check_rect(&rect, -20, 10, 0, 34);
1080 SetRect(&rect, 10, 10, 50, -30);
1081 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER | DT_CALCRECT, 0xff00ff);
1082 ok(height == 24, "Got unexpected height %d.\n", height);
1083 check_rect(&rect, 20, 10, 40, 34);
1085 SetRect(&rect, 10, 10, 50, 50);
1086 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_CENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1087 ok(height == 24, "Got unexpected height %d.\n", height);
1088 check_rect(&rect, 20, 10, 40, 34);
1090 SetRect(&rect, -10, 10, 30, 50);
1091 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_CENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1092 ok(height == 24, "Got unexpected height %d.\n", height);
1093 check_rect(&rect, 0, 10, 20, 34);
1095 SetRect(&rect, 10, -10, 50, 30);
1096 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_CENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1097 ok(height == 24, "Got unexpected height %d.\n", height);
1098 check_rect(&rect, 20, -10, 40, 14);
1100 SetRect(&rect, 10, 10, -30, 50);
1101 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_CENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1102 ok(height == 12, "Got unexpected height %d.\n", height);
1103 check_rect(&rect, -31, 10, 12, 22);
1105 SetRect(&rect, 10, 10, 50, -30);
1106 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_CENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1107 ok(height == 24, "Got unexpected height %d.\n", height);
1108 check_rect(&rect, 20, 10, 40, 34);
1110 SetRect(&rect, 10, 10, 50, 50);
1111 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER | DT_VCENTER | DT_CALCRECT, 0xff00ff);
1112 ok(height == 32, "Got unexpected height %d.\n", height);
1113 check_rect(&rect, 20, 18, 40, 42);
1115 SetRect(&rect, 10, 10, 50, 50);
1116 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER | DT_VCENTER | DT_CALCRECT, 0xff00ff);
1117 ok(height == 32, "Got unexpected height %d.\n", height);
1118 check_rect(&rect, 20, 18, 40, 42);
1120 SetRect(&rect, -10, 10, 30, 50);
1121 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER | DT_VCENTER | DT_CALCRECT, 0xff00ff);
1122 ok(height == 32, "Got unexpected height %d.\n", height);
1123 check_rect(&rect, 0, 18, 20, 42);
1125 SetRect(&rect, 10, -10, 50, 30);
1126 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER | DT_VCENTER | DT_CALCRECT, 0xff00ff);
1127 ok(height == 32, "Got unexpected height %d.\n", height);
1128 check_rect(&rect, 20, -2, 40, 22);
1130 SetRect(&rect, 10, 10, -30, 50);
1131 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER | DT_VCENTER | DT_CALCRECT, 0xff00ff);
1132 ok(height == 32, "Got unexpected height %d.\n", height);
1133 check_rect(&rect, -20, 18, 0, 42);
1135 SetRect(&rect, 10, 10, 50, -30);
1136 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER | DT_VCENTER | DT_CALCRECT, 0xff00ff);
1137 ok(height == -8, "Got unexpected height %d.\n", height);
1138 check_rect(&rect, 20, -22, 40, 2);
1140 SetRect(&rect, 10, 10, 50, 50);
1141 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1142 ok(height == 32, "Got unexpected height %d.\n", height);
1143 check_rect(&rect, 20, 18, 40, 42);
1145 SetRect(&rect, 10, 10, 50, 50);
1146 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1147 ok(height == 32, "Got unexpected height %d.\n", height);
1148 check_rect(&rect, 20, 18, 40, 42);
1150 SetRect(&rect, -10, 10, 30, 50);
1151 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1152 ok(height == 32, "Got unexpected height %d.\n", height);
1153 check_rect(&rect, 0, 18, 20, 42);
1155 SetRect(&rect, 10, -10, 50, 30);
1156 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1157 ok(height == 32, "Got unexpected height %d.\n", height);
1158 check_rect(&rect, 20, -2, 40, 22);
1160 SetRect(&rect, 10, 10, -30, 50);
1161 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1162 ok(height == 26, "Got unexpected height %d.\n", height);
1163 check_rect(&rect, -31, 24, 12, 36);
1165 SetRect(&rect, 10, 10, 50, -30);
1166 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_CALCRECT, 0xff00ff);
1167 ok(height == -8, "Got unexpected height %d.\n", height);
1168 check_rect(&rect, 20, -22, 40, 2);
1170 ID3DXFont_Release(font);
1173 static void test_D3DXCreateRenderToSurface(IDirect3DDevice9 *device)
1175 int i;
1176 HRESULT hr;
1177 ULONG ref_count;
1178 D3DXRTS_DESC desc;
1179 ID3DXRenderToSurface *render = (void *)0xdeadbeef;
1180 static const D3DXRTS_DESC tests[] =
1182 { 0, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN },
1183 { 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN },
1184 { 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_D24S8 },
1185 { 256, 256, D3DFMT_UNKNOWN, FALSE, D3DFMT_R8G8B8 },
1186 { 0, 0, D3DFMT_UNKNOWN, FALSE, D3DFMT_UNKNOWN },
1187 { -1, -1, MAKEFOURCC('B','A','D','F'), TRUE, MAKEFOURCC('B','A','D','F') }
1190 hr = D3DXCreateRenderToSurface(NULL /* device */, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render);
1191 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1192 ok(render == (void *)0xdeadbeef, "Got %p, expected %p\n", render, (void *)0xdeadbeef);
1194 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, NULL /* out */);
1195 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1197 for (i = 0; i < ARRAY_SIZE(tests); i++)
1199 hr = D3DXCreateRenderToSurface(device, tests[i].Width, tests[i].Height, tests[i].Format, tests[i].DepthStencil,
1200 tests[i].DepthStencilFormat, &render);
1201 ok(hr == D3D_OK, "%d: D3DXCreateRenderToSurface returned %#x, expected %#x\n", i, hr, D3D_OK);
1202 if (SUCCEEDED(hr))
1204 hr = ID3DXRenderToSurface_GetDesc(render, &desc);
1205 ok(hr == D3D_OK, "%d: GetDesc failed %#x\n", i, hr);
1206 if (SUCCEEDED(hr))
1208 ok(desc.Width == tests[i].Width, "%d: Got width %u, expected %u\n", i, desc.Width, tests[i].Width);
1209 ok(desc.Height == tests[i].Height, "%d: Got height %u, expected %u\n", i, desc.Height, tests[i].Height);
1210 ok(desc.Format == tests[i].Format, "%d: Got format %#x, expected %#x\n", i, desc.Format, tests[i].Format);
1211 ok(desc.DepthStencil == tests[i].DepthStencil, "%d: Got depth stencil %d, expected %d\n",
1212 i, desc.DepthStencil, tests[i].DepthStencil);
1213 ok(desc.DepthStencilFormat == tests[i].DepthStencilFormat, "%d: Got depth stencil format %#x, expected %#x\n",
1214 i, desc.DepthStencilFormat, tests[i].DepthStencilFormat);
1216 ID3DXRenderToSurface_Release(render);
1220 /* check device ref count */
1221 ref_count = get_ref((IUnknown *)device);
1222 hr = D3DXCreateRenderToSurface(device, 0, 0, D3DFMT_UNKNOWN, FALSE, D3DFMT_UNKNOWN, &render);
1223 check_ref((IUnknown *)device, ref_count + 1);
1224 if (SUCCEEDED(hr)) ID3DXRenderToSurface_Release(render);
1227 /* runs a set of tests for the ID3DXRenderToSurface interface created with given parameters */
1228 static void check_ID3DXRenderToSurface(IDirect3DDevice9 *device, UINT width, UINT height, D3DFORMAT format,
1229 BOOL depth_stencil, D3DFORMAT depth_stencil_format, BOOL render_target)
1231 HRESULT hr;
1232 D3DFORMAT fmt;
1233 HRESULT expected_value;
1234 IDirect3DSurface9 *surface;
1235 ID3DXRenderToSurface *render;
1236 D3DVIEWPORT9 viewport = { 0, 0, width, height, 0.0, 1.0 };
1238 hr = D3DXCreateRenderToSurface(device, width, height, format, depth_stencil, depth_stencil_format, &render);
1239 if (FAILED(hr))
1241 skip("Failed to create ID3DXRenderToSurface\n");
1242 return;
1245 if (render_target)
1246 hr = IDirect3DDevice9_CreateRenderTarget(device, width, height, format, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
1247 else
1248 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, format, D3DPOOL_DEFAULT, &surface, NULL);
1249 if (FAILED(hr))
1251 skip("Failed to create surface\n");
1252 ID3DXRenderToSurface_Release(render);
1253 return;
1256 /* viewport */
1257 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport);
1258 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK);
1259 check_ref((IUnknown *)surface, 2);
1260 if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE);
1262 /* invalid viewport */
1263 viewport.Width = 2 * width;
1264 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport);
1265 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1267 viewport.X = width / 2;
1268 viewport.Width = width;
1269 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport);
1270 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1272 viewport.X = width;
1273 viewport.Width = width;
1274 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport);
1275 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1277 /* rendering to a part of a surface is only allowed for render target surfaces */
1278 expected_value = render_target ? D3D_OK : D3DERR_INVALIDCALL;
1280 viewport.X = 0;
1281 viewport.Width = width / 2;
1282 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport);
1283 ok(hr == expected_value, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, expected_value);
1284 if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE);
1286 viewport.X = width / 2;
1287 viewport.Width = width - width / 2;
1288 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport);
1289 ok(hr == expected_value, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, expected_value);
1290 if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE);
1292 check_release((IUnknown *)surface, 0);
1294 /* surfaces with different sizes */
1295 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width / 2, width / 2, format, D3DPOOL_DEFAULT, &surface, NULL);
1296 if (FAILED(hr))
1298 skip("Failed to create surface\n");
1299 ID3DXRenderToSurface_Release(render);
1300 return;
1302 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL);
1303 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1304 check_release((IUnknown *)surface, 0);
1306 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2 * width, 2 * height, format, D3DPOOL_DEFAULT, &surface, NULL);
1307 if (FAILED(hr))
1309 skip("Failed to create surface\n");
1310 ID3DXRenderToSurface_Release(render);
1311 return;
1313 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL);
1314 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1315 viewport.X = 0;
1316 viewport.Y = 0;
1317 viewport.Width = width;
1318 viewport.Height = height;
1319 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport);
1320 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1321 check_release((IUnknown *)surface, 0);
1323 /* surfaces with different formats */
1324 for (fmt = D3DFMT_A8R8G8B8; fmt <= D3DFMT_X8R8G8B8; fmt++)
1326 HRESULT expected_result = (fmt != format) ? D3DERR_INVALIDCALL : D3D_OK;
1328 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, fmt, D3DPOOL_DEFAULT, &surface, NULL);
1329 if (FAILED(hr))
1331 skip("Failed to create surface\n");
1332 continue;
1335 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL);
1336 ok(hr == expected_result, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, expected_result);
1338 if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE);
1339 check_release((IUnknown *)surface, 0);
1342 check_release((IUnknown *)render, 0);
1345 struct device_state
1347 IDirect3DSurface9 *render_target;
1348 IDirect3DSurface9 *depth_stencil;
1349 D3DVIEWPORT9 viewport;
1352 static void release_device_state(struct device_state *state)
1354 if (state->render_target) IDirect3DSurface9_Release(state->render_target);
1355 if (state->depth_stencil) IDirect3DSurface9_Release(state->depth_stencil);
1356 memset(state, 0, sizeof(*state));
1359 static HRESULT retrieve_device_state(IDirect3DDevice9 *device, struct device_state *state)
1361 HRESULT hr;
1363 memset(state, 0, sizeof(*state));
1365 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &state->render_target);
1366 if (FAILED(hr)) goto cleanup;
1368 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &state->depth_stencil);
1369 if (hr == D3DERR_NOTFOUND)
1370 state->depth_stencil = NULL;
1371 else if (FAILED(hr))
1372 goto cleanup;
1374 hr = IDirect3DDevice9_GetViewport(device, &state->viewport);
1375 if (SUCCEEDED(hr)) return hr;
1377 cleanup:
1378 release_device_state(state);
1379 return hr;
1382 static HRESULT apply_device_state(IDirect3DDevice9 *device, struct device_state *state)
1384 HRESULT hr;
1385 HRESULT status = D3D_OK;
1387 hr = IDirect3DDevice9_SetRenderTarget(device, 0, state->render_target);
1388 if (FAILED(hr)) status = hr;
1390 hr = IDirect3DDevice9_SetDepthStencilSurface(device, state->depth_stencil);
1391 if (FAILED(hr)) status = hr;
1393 hr = IDirect3DDevice9_SetViewport(device, &state->viewport);
1394 if (FAILED(hr)) status = hr;
1396 return status;
1399 static void compare_device_state(struct device_state *state1, struct device_state *state2, BOOL equal)
1401 BOOL cmp;
1402 const char *message = equal ? "differs" : "is the same";
1404 cmp = state1->render_target == state2->render_target;
1405 ok(equal ? cmp : !cmp, "Render target %s %p, %p\n", message, state1->render_target, state2->render_target);
1407 cmp = state1->depth_stencil == state2->depth_stencil;
1408 ok(equal ? cmp : !cmp, "Depth stencil surface %s %p, %p\n", message, state1->depth_stencil, state2->depth_stencil);
1410 cmp = state1->viewport.X == state2->viewport.X && state1->viewport.Y == state2->viewport.Y
1411 && state1->viewport.Width == state2->viewport.Width && state1->viewport.Height == state2->viewport.Height;
1412 ok(equal ? cmp : !cmp, "Viewport %s (%u, %u, %u, %u), (%u, %u, %u, %u)\n", message,
1413 state1->viewport.X, state1->viewport.Y, state1->viewport.Width, state1->viewport.Height,
1414 state2->viewport.X, state2->viewport.Y, state2->viewport.Width, state2->viewport.Height);
1417 static void test_ID3DXRenderToSurface_device_state(IDirect3DDevice9 *device)
1419 HRESULT hr;
1420 IDirect3DSurface9 *surface = NULL;
1421 ID3DXRenderToSurface *render = NULL;
1422 struct device_state pre_state;
1423 struct device_state current_state;
1424 IDirect3DSurface9 *depth_stencil_surface;
1426 /* make sure there is a depth stencil surface present */
1427 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &depth_stencil_surface);
1428 if (SUCCEEDED(hr))
1430 IDirect3DSurface9_Release(depth_stencil_surface);
1431 depth_stencil_surface = NULL;
1433 else if (hr == D3DERR_NOTFOUND)
1435 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 256, 256, D3DFMT_D24X8,
1436 D3DMULTISAMPLE_NONE, 0, TRUE, &depth_stencil_surface, NULL);
1437 if (SUCCEEDED(hr)) IDirect3DDevice9_SetDepthStencilSurface(device, depth_stencil_surface);
1440 if (FAILED(hr))
1442 skip("Failed to create depth stencil surface\n");
1443 return;
1446 hr = IDirect3DDevice9_CreateRenderTarget(device, 256, 256, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0,
1447 FALSE, &surface, NULL);
1448 if (FAILED(hr))
1450 skip("Failed to create render target\n");
1451 goto cleanup;
1454 hr = retrieve_device_state(device, &pre_state);
1455 ok(SUCCEEDED(hr), "Failed to retrieve device state\n");
1457 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24X8, &render);
1458 ok(hr == D3D_OK, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3D_OK);
1459 if (SUCCEEDED(hr))
1461 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL);
1462 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK);
1464 hr = retrieve_device_state(device, &current_state);
1465 ok(SUCCEEDED(hr), "Failed to retrieve device state\n");
1466 compare_device_state(&current_state, &pre_state, FALSE);
1467 release_device_state(&current_state);
1469 hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE);
1470 ok(hr == D3D_OK, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3D_OK);
1472 hr = retrieve_device_state(device, &current_state);
1473 ok(SUCCEEDED(hr), "Failed to retrieve device state\n");
1474 compare_device_state(&current_state, &pre_state, TRUE);
1475 release_device_state(&current_state);
1477 check_release((IUnknown *)render, 0);
1480 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render);
1481 if (SUCCEEDED(hr))
1483 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL);
1484 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK);
1486 hr = retrieve_device_state(device, &current_state);
1487 ok(SUCCEEDED(hr), "Failed to retrieve device state\n");
1488 compare_device_state(&current_state, &pre_state, FALSE);
1489 release_device_state(&current_state);
1491 hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE);
1492 ok(hr == D3D_OK, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3D_OK);
1494 hr = retrieve_device_state(device, &current_state);
1495 ok(SUCCEEDED(hr), "Failed to retrieve device state\n");
1496 compare_device_state(&current_state, &pre_state, TRUE);
1497 release_device_state(&current_state);
1499 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL);
1500 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK);
1502 hr = retrieve_device_state(device, &current_state);
1503 ok(SUCCEEDED(hr), "Failed to retrieve device state\n");
1504 compare_device_state(&current_state, &pre_state, FALSE);
1505 release_device_state(&current_state);
1507 check_release((IUnknown *)render, 0);
1509 /* if EndScene isn't called, the device state isn't restored */
1510 hr = retrieve_device_state(device, &current_state);
1511 ok(SUCCEEDED(hr), "Failed to retrieve device state\n");
1512 compare_device_state(&current_state, &pre_state, FALSE);
1513 release_device_state(&current_state);
1515 hr = apply_device_state(device, &pre_state);
1516 ok(SUCCEEDED(hr), "Failed to restore previous device state\n");
1518 IDirect3DDevice9_EndScene(device);
1521 release_device_state(&pre_state);
1523 cleanup:
1524 if (depth_stencil_surface)
1526 IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
1527 IDirect3DSurface9_Release(depth_stencil_surface);
1530 if (surface) check_release((IUnknown *)surface, 0);
1533 static void test_ID3DXRenderToSurface(IDirect3DDevice9 *device)
1535 int i;
1536 HRESULT hr;
1537 ULONG ref_count;
1538 IDirect3DDevice9 *out_device;
1539 ID3DXRenderToSurface *render;
1540 IDirect3DSurface9 *surface;
1541 D3DVIEWPORT9 viewport = { 0, 0, 256, 256, 0.0, 1.0 };
1542 D3DXRTS_DESC tests[] = {
1543 { 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN },
1544 { 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24S8 },
1545 { 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24X8 },
1546 { 512, 512, D3DFMT_X8R8G8B8, FALSE, D3DFMT_X8R8G8B8 },
1547 { 1024, 1024, D3DFMT_X8R8G8B8, TRUE, D3DFMT_D24S8 }
1550 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render);
1551 ok(hr == D3D_OK, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3D_OK);
1552 if (FAILED(hr)) return;
1554 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 256, 256, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, NULL);
1555 if (SUCCEEDED(hr))
1557 ID3DXRenderToSurface *render_surface;
1559 /* GetDevice */
1560 hr = ID3DXRenderToSurface_GetDevice(render, NULL /* device */);
1561 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1563 ref_count = get_ref((IUnknown *)device);
1564 hr = ID3DXRenderToSurface_GetDevice(render, &out_device);
1565 ok(hr == D3D_OK, "ID3DXRenderToSurface::GetDevice returned %#x, expected %#x\n", hr, D3D_OK);
1566 check_release((IUnknown *)out_device, ref_count);
1568 /* BeginScene and EndScene */
1569 hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE);
1570 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1572 hr = ID3DXRenderToSurface_BeginScene(render, NULL /* surface */, &viewport);
1573 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1575 ref_count = get_ref((IUnknown *)surface);
1576 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL);
1577 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK);
1578 if (SUCCEEDED(hr))
1580 check_ref((IUnknown *)surface, ref_count + 1);
1582 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL);
1583 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1585 hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE);
1586 ok(hr == D3D_OK, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3D_OK);
1588 check_ref((IUnknown *)surface, ref_count);
1591 /* error handling is deferred to BeginScene */
1592 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_UNKNOWN, &render_surface);
1593 ok(hr == D3D_OK, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3D_OK);
1594 hr = ID3DXRenderToSurface_BeginScene(render_surface, surface, NULL);
1595 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1596 check_release((IUnknown *)render_surface, 0);
1598 check_release((IUnknown *)surface, 0);
1600 else skip("Failed to create surface\n");
1602 check_release((IUnknown *)render, 0);
1604 for (i = 0; i < ARRAY_SIZE(tests); i++)
1606 check_ID3DXRenderToSurface(device, tests[i].Width, tests[i].Height, tests[i].Format, tests[i].DepthStencil, tests[i].DepthStencilFormat, TRUE);
1607 check_ID3DXRenderToSurface(device, tests[i].Width, tests[i].Height, tests[i].Format, tests[i].DepthStencil, tests[i].DepthStencilFormat, FALSE);
1610 test_ID3DXRenderToSurface_device_state(device);
1613 static void test_D3DXCreateRenderToEnvMap(IDirect3DDevice9 *device)
1615 int i;
1616 HRESULT hr;
1617 ULONG ref_count;
1618 D3DXRTE_DESC desc;
1619 ID3DXRenderToEnvMap *render;
1620 static const struct {
1621 D3DXRTE_DESC parameters;
1622 D3DXRTE_DESC expected_values;
1623 } tests[] = {
1624 { { 0, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, { 1, 1, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN } },
1625 { { 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, { 256, 9, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN } },
1626 { { 256, 4, D3DFMT_A8R8G8B8, FALSE, D3DFMT_D24S8 }, { 256, 4, D3DFMT_A8R8G8B8, FALSE, D3DFMT_D24S8 } },
1627 { { 256, 256, D3DFMT_UNKNOWN, FALSE, D3DFMT_R8G8B8 }, { 256, 9, D3DFMT_A8R8G8B8, FALSE, D3DFMT_R8G8B8 } },
1628 { { -1, -1, D3DFMT_A8R8G8B8, TRUE, D3DFMT_DXT1 }, { 256, 9, D3DFMT_A8R8G8B8, TRUE, D3DFMT_DXT1 } },
1629 { { 256, 1, D3DFMT_X8R8G8B8, TRUE, D3DFMT_UNKNOWN }, { 256, 1, D3DFMT_X8R8G8B8, TRUE, D3DFMT_UNKNOWN } }
1632 for (i = 0; i < ARRAY_SIZE(tests); i++)
1634 const D3DXRTE_DESC *parameters = &tests[i].parameters;
1635 const D3DXRTE_DESC *expected = &tests[i].expected_values;
1636 hr = D3DXCreateRenderToEnvMap(device, parameters->Size, parameters->MipLevels, parameters->Format,
1637 parameters->DepthStencil, parameters->DepthStencilFormat, &render);
1638 ok(hr == D3D_OK, "%d: D3DXCreateRenderToEnvMap returned %#x, expected %#x\n", i, hr, D3D_OK);
1639 if (SUCCEEDED(hr))
1641 hr = ID3DXRenderToEnvMap_GetDesc(render, &desc);
1642 ok(hr == D3D_OK, "%d: GetDesc failed %#x\n", i, hr);
1643 if (SUCCEEDED(hr))
1645 ok(desc.Size == expected->Size, "%d: Got size %u, expected %u\n", i, desc.Size, expected->Size);
1646 ok(desc.MipLevels == expected->MipLevels, "%d: Got miplevels %u, expected %u\n", i, desc.MipLevels, expected->MipLevels);
1647 ok(desc.Format == expected->Format, "%d: Got format %#x, expected %#x\n", i, desc.Format, expected->Format);
1648 ok(desc.DepthStencil == expected->DepthStencil, "%d: Got depth stencil %d, expected %d\n",
1649 i, expected->DepthStencil, expected->DepthStencil);
1650 ok(desc.DepthStencilFormat == expected->DepthStencilFormat, "%d: Got depth stencil format %#x, expected %#x\n",
1651 i, expected->DepthStencilFormat, expected->DepthStencilFormat);
1653 check_release((IUnknown *)render, 0);
1657 /* check device ref count */
1658 ref_count = get_ref((IUnknown *)device);
1659 hr = D3DXCreateRenderToEnvMap(device, 0, 0, D3DFMT_UNKNOWN, FALSE, D3DFMT_UNKNOWN, &render);
1660 check_ref((IUnknown *)device, ref_count + 1);
1661 if (SUCCEEDED(hr)) ID3DXRenderToEnvMap_Release(render);
1664 static void test_ID3DXRenderToEnvMap_cube_map(IDirect3DDevice9 *device)
1666 HRESULT hr;
1667 IDirect3DCubeTexture9 *cube_texture = NULL;
1668 ID3DXRenderToEnvMap *render = NULL;
1669 struct device_state pre_state;
1670 struct device_state current_state;
1672 hr = IDirect3DDevice9_CreateCubeTexture(device, 256, 0, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
1673 &cube_texture, NULL);
1674 if (FAILED(hr))
1676 skip("Failed to create cube texture\n");
1677 return;
1680 hr = retrieve_device_state(device, &pre_state);
1681 ok(SUCCEEDED(hr), "Failed to retrieve device state\n");
1683 hr = D3DXCreateRenderToEnvMap(device, 256, 0, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24X8, &render);
1684 ok(hr == D3D_OK, "D3DCreateRenderToEnvMap returned %#x, expected %#x\n", hr, D3D_OK);
1685 if (SUCCEEDED(hr))
1687 DWORD face;
1689 hr = ID3DXRenderToEnvMap_End(render, D3DX_FILTER_NONE);
1690 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::End returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1692 hr = ID3DXRenderToEnvMap_BeginCube(render, cube_texture);
1693 ok(hr == D3D_OK, "ID3DXRenderToEnvMap::BeginCube returned %#x, expected %#x\n", hr, D3D_OK);
1695 hr = retrieve_device_state(device, &current_state);
1696 ok(SUCCEEDED(hr), "Failed to retrieve device state\n");
1697 compare_device_state(&current_state, &pre_state, TRUE);
1698 release_device_state(&current_state);
1700 for (face = D3DCUBEMAP_FACE_POSITIVE_X; face <= D3DCUBEMAP_FACE_NEGATIVE_Z; face++)
1702 hr = ID3DXRenderToEnvMap_Face(render, face, D3DX_FILTER_POINT);
1703 ok(hr == D3D_OK, "ID3DXRenderToEnvMap::Face returned %#x, expected %#x\n", hr, D3D_OK);
1705 hr = retrieve_device_state(device, &current_state);
1706 ok(SUCCEEDED(hr), "Failed to retrieve device state\n");
1707 compare_device_state(&current_state, &pre_state, FALSE);
1708 release_device_state(&current_state);
1711 hr = ID3DXRenderToEnvMap_End(render, D3DX_FILTER_POINT);
1712 ok(hr == D3D_OK, "ID3DXRenderToEnvMap::End returned %#x, expected %#x\n", hr, D3D_OK);
1714 hr = retrieve_device_state(device, &current_state);
1715 ok(SUCCEEDED(hr), "Failed to retrieve device state\n");
1716 compare_device_state(&current_state, &pre_state, TRUE);
1717 release_device_state(&current_state);
1719 check_release((IUnknown *)render, 0);
1722 release_device_state(&pre_state);
1724 check_release((IUnknown *)cube_texture, 0);
1727 static void test_ID3DXRenderToEnvMap(IDirect3DDevice9 *device)
1729 HRESULT hr;
1730 ID3DXRenderToEnvMap *render;
1731 IDirect3DSurface9 *depth_stencil_surface;
1733 hr = D3DXCreateRenderToEnvMap(device, 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render);
1734 if (SUCCEEDED(hr))
1736 ULONG ref_count;
1737 IDirect3DDevice9 *out_device;
1739 hr = ID3DXRenderToEnvMap_GetDesc(render, NULL);
1740 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::GetDesc returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1742 hr = ID3DXRenderToEnvMap_GetDevice(render, NULL);
1743 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1745 ref_count = get_ref((IUnknown *)device);
1746 hr = ID3DXRenderToEnvMap_GetDevice(render, &out_device);
1747 ok(hr == D3D_OK, "ID3DXRenderToEnvMap::GetDevice returned %#x, expected %#x\n", hr, D3D_OK);
1748 ok(out_device == device, "ID3DXRenderToEnvMap::GetDevice returned different device\n");
1749 check_release((IUnknown *)device, ref_count);
1751 hr = ID3DXRenderToEnvMap_End(render, D3DX_FILTER_NONE);
1752 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::End returned %#x, expected %#x\n", hr, D3D_OK);
1754 hr = ID3DXRenderToEnvMap_BeginCube(render, NULL);
1755 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginCube returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1757 hr = ID3DXRenderToEnvMap_BeginHemisphere(render, NULL, NULL);
1758 todo_wine ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginHemisphere returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1760 hr = ID3DXRenderToEnvMap_BeginParabolic(render, NULL, NULL);
1761 todo_wine ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginParabolic returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1763 hr = ID3DXRenderToEnvMap_BeginSphere(render, NULL);
1764 todo_wine ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginSphere returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
1766 check_release((IUnknown *)render, 0);
1767 } else skip("Failed to create ID3DXRenderToEnvMap\n");
1769 /* make sure there is a depth stencil surface present */
1770 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &depth_stencil_surface);
1771 if (SUCCEEDED(hr))
1773 IDirect3DSurface9_Release(depth_stencil_surface);
1774 depth_stencil_surface = NULL;
1776 else if (hr == D3DERR_NOTFOUND)
1778 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 256, 256, D3DFMT_D24X8,
1779 D3DMULTISAMPLE_NONE, 0, TRUE, &depth_stencil_surface, NULL);
1780 if (SUCCEEDED(hr)) IDirect3DDevice9_SetDepthStencilSurface(device, depth_stencil_surface);
1783 if (FAILED(hr))
1785 skip("Failed to create depth stencil surface\n");
1786 return;
1789 test_ID3DXRenderToEnvMap_cube_map(device);
1791 if (depth_stencil_surface)
1793 IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
1794 IDirect3DSurface9_Release(depth_stencil_surface);
1798 START_TEST(core)
1800 HWND wnd;
1801 IDirect3D9 *d3d;
1802 IDirect3DDevice9 *device;
1803 D3DPRESENT_PARAMETERS d3dpp;
1804 HRESULT hr;
1806 if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
1807 640, 480, NULL, NULL, NULL, NULL)))
1809 skip("Couldn't create application window\n");
1810 return;
1812 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
1814 skip("Couldn't create IDirect3D9 object\n");
1815 DestroyWindow(wnd);
1816 return;
1819 ZeroMemory(&d3dpp, sizeof(d3dpp));
1820 d3dpp.Windowed = TRUE;
1821 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1822 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
1823 if(FAILED(hr)) {
1824 skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
1825 IDirect3D9_Release(d3d);
1826 DestroyWindow(wnd);
1827 return;
1830 test_ID3DXBuffer();
1831 test_ID3DXSprite(device);
1832 test_ID3DXFont(device);
1833 test_D3DXCreateRenderToSurface(device);
1834 test_ID3DXRenderToSurface(device);
1835 test_D3DXCreateRenderToEnvMap(device);
1836 test_ID3DXRenderToEnvMap(device);
1838 check_release((IUnknown*)device, 0);
1839 check_release((IUnknown*)d3d, 0);
1840 if (wnd) DestroyWindow(wnd);