1 /* 2 * Tests for the D3DX9 core interfaces 3 * 4 * Copyright 2009 Tony Wasserka 5 * 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. 10 * 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. 15 * 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 19 */ 20 21 #define COBJMACROS 22 #include "wine/test.h" 23 #include <dxerr9.h> 24 #include "d3dx9core.h" 25 26 static inline int get_ref(IUnknown *obj) 27 { 28 IUnknown_AddRef(obj); 29 return IUnknown_Release(obj); 30 } 31 32 #define check_ref(obj, exp) _check_ref(__LINE__, obj, exp) 33 static inline void _check_ref(unsigned int line, IUnknown *obj, int exp) 34 { 35 int ref = get_ref(obj); 36 ok_(__FILE__, line)(exp == ref, "Invalid refcount. Expected %d, got %d\n", exp, ref); 37 } 38 39 #define check_release(obj, exp) _check_release(__LINE__, obj, exp) 40 static inline void _check_release(unsigned int line, IUnknown *obj, int exp) 41 { 42 int ref = IUnknown_Release(obj); 43 ok_(__FILE__, line)(ref == exp, "Invalid refcount. Expected %d, got %d\n", exp, ref); 44 } 45 46 #define admitted_error 0.0001f 47 static inline void check_mat(D3DXMATRIX got, D3DXMATRIX exp) 48 { 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; 54 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]); 65 } 66 67 static void test_ID3DXBuffer(void) 68 { 69 ID3DXBuffer *buffer; 70 HRESULT hr; 71 ULONG count; 72 DWORD size; 73 74 hr = D3DXCreateBuffer(10, NULL); 75 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateBuffer failed, got %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 76 77 hr = D3DXCreateBuffer(0, &buffer); 78 ok(hr == D3D_OK, "D3DXCreateBuffer failed, got %#x, expected %#x\n", hr, D3D_OK); 79 80 size = ID3DXBuffer_GetBufferSize(buffer); 81 ok(!size, "GetBufferSize failed, got %u, expected %u\n", size, 0); 82 83 count = ID3DXBuffer_Release(buffer); 84 ok(!count, "ID3DXBuffer has %u references left\n", count); 85 86 hr = D3DXCreateBuffer(3, &buffer); 87 ok(hr == D3D_OK, "D3DXCreateBuffer failed, got %#x, expected %#x\n", hr, D3D_OK); 88 89 size = ID3DXBuffer_GetBufferSize(buffer); 90 ok(size == 3, "GetBufferSize failed, got %u, expected %u\n", size, 3); 91 92 count = ID3DXBuffer_Release(buffer); 93 ok(!count, "ID3DXBuffer has %u references left\n", count); 94 } 95 96 static void test_ID3DXSprite(IDirect3DDevice9 *device) 97 { 98 ID3DXSprite *sprite; 99 IDirect3D9 *d3d; 100 IDirect3DDevice9 *cmpdev; 101 IDirect3DTexture9 *tex1, *tex2; 102 D3DXMATRIX mat, cmpmat; 103 D3DVIEWPORT9 vp; 104 RECT rect; 105 D3DXVECTOR3 pos, center; 106 HRESULT hr; 107 108 IDirect3DDevice9_GetDirect3D(device, &d3d); 109 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8); 110 IDirect3D9_Release(d3d); 111 ok (hr == D3D_OK, "D3DFMT_A8R8G8B8 not supported\n"); 112 if (FAILED(hr)) return; 113 114 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex1, NULL); 115 ok (hr == D3D_OK, "Failed to create first texture (error code: %#x)\n", hr); 116 if (FAILED(hr)) return; 117 118 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex2, NULL); 119 ok (hr == D3D_OK, "Failed to create second texture (error code: %#x)\n", hr); 120 if (FAILED(hr)) { 121 IDirect3DTexture9_Release(tex1); 122 return; 123 } 124 125 /* Test D3DXCreateSprite */ 126 hr = D3DXCreateSprite(device, NULL); 127 ok (hr == D3DERR_INVALIDCALL, "D3DXCreateSprite returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 128 129 hr = D3DXCreateSprite(NULL, &sprite); 130 ok (hr == D3DERR_INVALIDCALL, "D3DXCreateSprite returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 131 132 hr = D3DXCreateSprite(device, &sprite); 133 ok (hr == D3D_OK, "D3DXCreateSprite returned %#x, expected %#x\n", hr, D3D_OK); 134 135 136 /* Test ID3DXSprite_GetDevice */ 137 hr = ID3DXSprite_GetDevice(sprite, NULL); 138 ok (hr == D3DERR_INVALIDCALL, "GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 139 140 hr = ID3DXSprite_GetDevice(sprite, &cmpdev); /* cmpdev == NULL */ 141 ok (hr == D3D_OK, "GetDevice returned %#x, expected %#x\n", hr, D3D_OK); 142 143 hr = ID3DXSprite_GetDevice(sprite, &cmpdev); /* cmpdev != NULL */ 144 ok (hr == D3D_OK, "GetDevice returned %#x, expected %#x\n", hr, D3D_OK); 145 146 IDirect3DDevice9_Release(device); 147 IDirect3DDevice9_Release(device); 148 149 150 /* Test ID3DXSprite_GetTransform */ 151 hr = ID3DXSprite_GetTransform(sprite, NULL); 152 ok (hr == D3DERR_INVALIDCALL, "GetTransform returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 153 hr = ID3DXSprite_GetTransform(sprite, &mat); 154 ok (hr == D3D_OK, "GetTransform returned %#x, expected %#x\n", hr, D3D_OK); 155 if(SUCCEEDED(hr)) { 156 D3DXMATRIX identity; 157 D3DXMatrixIdentity(&identity); 158 check_mat(mat, identity); 159 } 160 161 /* Test ID3DXSprite_SetTransform */ 162 /* Set a transform and test if it gets returned correctly */ 163 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; 164 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; 165 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; 166 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; 167 168 hr = ID3DXSprite_SetTransform(sprite, NULL); 169 ok (hr == D3DERR_INVALIDCALL, "SetTransform returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 170 171 hr = ID3DXSprite_SetTransform(sprite, &mat); 172 ok (hr == D3D_OK, "SetTransform returned %#x, expected %#x\n", hr, D3D_OK); 173 if(SUCCEEDED(hr)) { 174 hr=ID3DXSprite_GetTransform(sprite, &cmpmat); 175 if(SUCCEEDED(hr)) check_mat(cmpmat, mat); 176 else skip("GetTransform returned %#x\n", hr); 177 } 178 179 /* Test ID3DXSprite_SetWorldViewLH/RH */ 180 todo_wine { 181 hr = ID3DXSprite_SetWorldViewLH(sprite, &mat, &mat); 182 ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK); 183 hr = ID3DXSprite_SetWorldViewLH(sprite, NULL, &mat); 184 ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK); 185 hr = ID3DXSprite_SetWorldViewLH(sprite, &mat, NULL); 186 ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK); 187 hr = ID3DXSprite_SetWorldViewLH(sprite, NULL, NULL); 188 ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK); 189 190 hr = ID3DXSprite_SetWorldViewRH(sprite, &mat, &mat); 191 ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK); 192 hr = ID3DXSprite_SetWorldViewRH(sprite, NULL, &mat); 193 ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK); 194 hr = ID3DXSprite_SetWorldViewRH(sprite, &mat, NULL); 195 ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK); 196 hr = ID3DXSprite_SetWorldViewRH(sprite, NULL, NULL); 197 ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK); 198 } 199 IDirect3DDevice9_BeginScene(device); 200 201 /* Test ID3DXSprite_Begin*/ 202 hr = ID3DXSprite_Begin(sprite, 0); 203 ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK); 204 205 IDirect3DDevice9_GetTransform(device, D3DTS_WORLD, &mat); 206 D3DXMatrixIdentity(&cmpmat); 207 check_mat(mat, cmpmat); 208 209 IDirect3DDevice9_GetTransform(device, D3DTS_VIEW, &mat); 210 check_mat(mat, cmpmat); 211 212 IDirect3DDevice9_GetTransform(device, D3DTS_PROJECTION, &mat); 213 IDirect3DDevice9_GetViewport(device, &vp); 214 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); 215 check_mat(mat, cmpmat); 216 217 /* Test ID3DXSprite_Flush and ID3DXSprite_End */ 218 hr = ID3DXSprite_Flush(sprite); 219 ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK); 220 221 hr = ID3DXSprite_End(sprite); 222 ok (hr == D3D_OK, "End returned %#x, expected %#x\n", hr, D3D_OK); 223 224 hr = ID3DXSprite_Flush(sprite); /* May not be called before next Begin */ 225 ok (hr == D3DERR_INVALIDCALL, "Flush returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 226 hr = ID3DXSprite_End(sprite); 227 ok (hr == D3DERR_INVALIDCALL, "End returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 228 229 /* Test ID3DXSprite_Draw */ 230 hr = ID3DXSprite_Begin(sprite, 0); 231 ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK); 232 233 if(FAILED(hr)) skip("Couldn't ID3DXSprite_Begin, can't test ID3DXSprite_Draw\n"); 234 else { /* Feed the sprite batch */ 235 int texref1, texref2; 236 237 SetRect(&rect, 53, 12, 142, 165); 238 pos.x = 2.2f; pos.y = 4.5f; pos.z = 5.1f; 239 center.x = 11.3f; center.y = 3.4f; center.z = 1.2f; 240 241 texref1 = get_ref((IUnknown*)tex1); 242 texref2 = get_ref((IUnknown*)tex2); 243 244 hr = ID3DXSprite_Draw(sprite, NULL, &rect, ¢er, &pos, D3DCOLOR_XRGB(255, 255, 255)); 245 ok (hr == D3DERR_INVALIDCALL, "Draw returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 246 247 hr = ID3DXSprite_Draw(sprite, tex1, &rect, ¢er, &pos, D3DCOLOR_XRGB(255, 255, 255)); 248 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); 249 hr = ID3DXSprite_Draw(sprite, tex2, &rect, ¢er, &pos, D3DCOLOR_XRGB( 3, 45, 66)); 250 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); 251 hr = ID3DXSprite_Draw(sprite, tex1, NULL, ¢er, &pos, D3DCOLOR_XRGB(255, 255, 255)); 252 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); 253 hr = ID3DXSprite_Draw(sprite, tex1, &rect, NULL, &pos, D3DCOLOR_XRGB(255, 255, 255)); 254 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); 255 hr = ID3DXSprite_Draw(sprite, tex1, &rect, ¢er, NULL, D3DCOLOR_XRGB(255, 255, 255)); 256 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); 257 hr = ID3DXSprite_Draw(sprite, tex1, NULL, NULL, NULL, 0); 258 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); 259 260 check_ref((IUnknown*)tex1, texref1+5); check_ref((IUnknown*)tex2, texref2+1); 261 hr = ID3DXSprite_Flush(sprite); 262 ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK); 263 hr = ID3DXSprite_Flush(sprite); /* Flushing twice should work */ 264 ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK); 265 check_ref((IUnknown*)tex1, texref1); check_ref((IUnknown*)tex2, texref2); 266 267 hr = ID3DXSprite_End(sprite); 268 ok (hr == D3D_OK, "End returned %#x, expected %#x\n", hr, D3D_OK); 269 } 270 271 /* Test ID3DXSprite_OnLostDevice and ID3DXSprite_OnResetDevice */ 272 /* Both can be called twice */ 273 hr = ID3DXSprite_OnLostDevice(sprite); 274 ok (hr == D3D_OK, "OnLostDevice returned %#x, expected %#x\n", hr, D3D_OK); 275 hr = ID3DXSprite_OnLostDevice(sprite); 276 ok (hr == D3D_OK, "OnLostDevice returned %#x, expected %#x\n", hr, D3D_OK); 277 hr = ID3DXSprite_OnResetDevice(sprite); 278 ok (hr == D3D_OK, "OnResetDevice returned %#x, expected %#x\n", hr, D3D_OK); 279 hr = ID3DXSprite_OnResetDevice(sprite); 280 ok (hr == D3D_OK, "OnResetDevice returned %#x, expected %#x\n", hr, D3D_OK); 281 282 /* Make sure everything works like before */ 283 hr = ID3DXSprite_Begin(sprite, 0); 284 ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK); 285 hr = ID3DXSprite_Draw(sprite, tex2, &rect, ¢er, &pos, D3DCOLOR_XRGB(255, 255, 255)); 286 ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); 287 hr = ID3DXSprite_Flush(sprite); 288 ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK); 289 hr = ID3DXSprite_End(sprite); 290 ok (hr == D3D_OK, "End returned %#x, expected %#x\n", hr, D3D_OK); 291 292 /* OnResetDevice makes the interface "forget" the Begin call */ 293 hr = ID3DXSprite_Begin(sprite, 0); 294 ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK); 295 hr = ID3DXSprite_OnResetDevice(sprite); 296 ok (hr == D3D_OK, "OnResetDevice returned %#x, expected %#x\n", hr, D3D_OK); 297 hr = ID3DXSprite_End(sprite); 298 ok (hr == D3DERR_INVALIDCALL, "End returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 299 300 IDirect3DDevice9_EndScene(device); 301 check_release((IUnknown*)sprite, 0); 302 check_release((IUnknown*)tex2, 0); 303 check_release((IUnknown*)tex1, 0); 304 } 305 306 static void test_ID3DXFont(IDirect3DDevice9 *device) 307 { 308 static const WCHAR testW[] = L"test"; 309 static const char long_text[] = "Example text to test clipping and other related things"; 310 static const WCHAR long_textW[] = L"Example text to test clipping and other related things"; 311 static const MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} }; 312 static const struct 313 { 314 int font_height; 315 unsigned int expected_size; 316 unsigned int expected_levels; 317 } 318 tests[] = 319 { 320 { 2, 32, 2 }, 321 { 6, 128, 4 }, 322 { 10, 256, 5 }, 323 { 12, 256, 5 }, 324 { 72, 256, 8 }, 325 { 250, 256, 9 }, 326 { 258, 512, 10 }, 327 { 512, 512, 10 }, 328 }; 329 const unsigned int size = ARRAY_SIZE(testW); 330 TEXTMETRICA metrics, expmetrics; 331 IDirect3DTexture9 *texture; 332 D3DSURFACE_DESC surf_desc; 333 IDirect3DDevice9 *bufdev; 334 GLYPHMETRICS glyph_metrics; 335 D3DXFONT_DESCA desc; 336 ID3DXSprite *sprite; 337 RECT rect, blackbox; 338 DWORD count, levels; 339 int ref, i, height; 340 ID3DXFont *font; 341 TEXTMETRICW tm; 342 POINT cellinc; 343 HRESULT hr; 344 WORD glyph; 345 BOOL ret; 346 HDC hdc; 347 char c; 348 349 /* D3DXCreateFont */ 350 ref = get_ref((IUnknown*)device); 351 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font); 352 ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK); 353 check_ref((IUnknown*)device, ref + 1); 354 check_release((IUnknown*)font, 0); 355 check_ref((IUnknown*)device, ref); 356 357 hr = D3DXCreateFontA(device, 0, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font); 358 ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK); 359 ID3DXFont_Release(font); 360 361 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, NULL, &font); 362 ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK); 363 ID3DXFont_Release(font); 364 365 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "", &font); 366 ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK); 367 ID3DXFont_Release(font); 368 369 hr = D3DXCreateFontA(NULL, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font); 370 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 371 372 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", NULL); 373 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 374 375 hr = D3DXCreateFontA(NULL, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", NULL); 376 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 377 378 379 /* D3DXCreateFontIndirect */ 380 desc.Height = 12; 381 desc.Width = 0; 382 desc.Weight = FW_DONTCARE; 383 desc.MipLevels = 0; 384 desc.Italic = FALSE; 385 desc.CharSet = DEFAULT_CHARSET; 386 desc.OutputPrecision = OUT_DEFAULT_PRECIS; 387 desc.Quality = DEFAULT_QUALITY; 388 desc.PitchAndFamily = DEFAULT_PITCH; 389 strcpy(desc.FaceName, "Tahoma"); 390 hr = D3DXCreateFontIndirectA(device, &desc, &font); 391 ok(hr == D3D_OK, "D3DXCreateFontIndirect returned %#x, expected %#x\n", hr, D3D_OK); 392 ID3DXFont_Release(font); 393 394 hr = D3DXCreateFontIndirectA(NULL, &desc, &font); 395 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFontIndirect returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 396 397 hr = D3DXCreateFontIndirectA(device, NULL, &font); 398 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFontIndirect returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 399 400 hr = D3DXCreateFontIndirectA(device, &desc, NULL); 401 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFontIndirect returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 402 403 404 /* ID3DXFont_GetDevice */ 405 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 406 DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font); 407 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 408 409 hr = ID3DXFont_GetDevice(font, NULL); 410 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); 411 412 ref = get_ref((IUnknown *)device); 413 hr = ID3DXFont_GetDevice(font, &bufdev); 414 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 415 check_release((IUnknown *)bufdev, ref); 416 417 ID3DXFont_Release(font); 418 419 420 /* ID3DXFont_GetDesc */ 421 hr = D3DXCreateFontA(device, 12, 8, FW_BOLD, 2, TRUE, ANSI_CHARSET, OUT_RASTER_PRECIS, 422 ANTIALIASED_QUALITY, VARIABLE_PITCH, "Tahoma", &font); 423 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 424 425 hr = ID3DXFont_GetDescA(font, NULL); 426 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); 427 428 hr = ID3DXFont_GetDescA(font, &desc); 429 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 430 431 ok(desc.Height == 12, "Got unexpected height %d.\n", desc.Height); 432 ok(desc.Width == 8, "Got unexpected width %u.\n", desc.Width); 433 ok(desc.Weight == FW_BOLD, "Got unexpected weight %u.\n", desc.Weight); 434 ok(desc.MipLevels == 2, "Got unexpected miplevels %u.\n", desc.MipLevels); 435 ok(desc.Italic == TRUE, "Got unexpected italic %#x.\n", desc.Italic); 436 ok(desc.CharSet == ANSI_CHARSET, "Got unexpected charset %u.\n", desc.CharSet); 437 ok(desc.OutputPrecision == OUT_RASTER_PRECIS, "Got unexpected output precision %u.\n", desc.OutputPrecision); 438 ok(desc.Quality == ANTIALIASED_QUALITY, "Got unexpected quality %u.\n", desc.Quality); 439 ok(desc.PitchAndFamily == VARIABLE_PITCH, "Got unexpected pitch and family %#x.\n", desc.PitchAndFamily); 440 ok(!strcmp(desc.FaceName, "Tahoma"), "Got unexpected facename %s.\n", debugstr_a(desc.FaceName)); 441 442 ID3DXFont_Release(font); 443 444 445 /* ID3DXFont_GetDC + ID3DXFont_GetTextMetrics */ 446 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 447 DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font); 448 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 449 450 hdc = ID3DXFont_GetDC(font); 451 ok(!!hdc, "Got unexpected hdc %p.\n", hdc); 452 453 ret = ID3DXFont_GetTextMetricsA(font, &metrics); 454 ok(ret, "Got unexpected ret %#x.\n", ret); 455 ret = GetTextMetricsA(hdc, &expmetrics); 456 ok(ret, "Got unexpected ret %#x.\n", ret); 457 458 ok(metrics.tmHeight == expmetrics.tmHeight, "Got unexpected height %d, expected %d.\n", 459 metrics.tmHeight, expmetrics.tmHeight); 460 ok(metrics.tmAscent == expmetrics.tmAscent, "Got unexpected ascent %d, expected %d.\n", 461 metrics.tmAscent, expmetrics.tmAscent); 462 ok(metrics.tmDescent == expmetrics.tmDescent, "Got unexpected descent %d, expected %d.\n", 463 metrics.tmDescent, expmetrics.tmDescent); 464 ok(metrics.tmInternalLeading == expmetrics.tmInternalLeading, "Got unexpected internal leading %d, expected %d.\n", 465 metrics.tmInternalLeading, expmetrics.tmInternalLeading); 466 ok(metrics.tmExternalLeading == expmetrics.tmExternalLeading, "Got unexpected external leading %d, expected %d.\n", 467 metrics.tmExternalLeading, expmetrics.tmExternalLeading); 468 ok(metrics.tmAveCharWidth == expmetrics.tmAveCharWidth, "Got unexpected average char width %d, expected %d.\n", 469 metrics.tmAveCharWidth, expmetrics.tmAveCharWidth); 470 ok(metrics.tmMaxCharWidth == expmetrics.tmMaxCharWidth, "Got unexpected maximum char width %d, expected %d.\n", 471 metrics.tmMaxCharWidth, expmetrics.tmMaxCharWidth); 472 ok(metrics.tmWeight == expmetrics.tmWeight, "Got unexpected weight %d, expected %d.\n", 473 metrics.tmWeight, expmetrics.tmWeight); 474 ok(metrics.tmOverhang == expmetrics.tmOverhang, "Got unexpected overhang %d, expected %d.\n", 475 metrics.tmOverhang, expmetrics.tmOverhang); 476 ok(metrics.tmDigitizedAspectX == expmetrics.tmDigitizedAspectX, "Got unexpected digitized x aspect %d, expected %d.\n", 477 metrics.tmDigitizedAspectX, expmetrics.tmDigitizedAspectX); 478 ok(metrics.tmDigitizedAspectY == expmetrics.tmDigitizedAspectY, "Got unexpected digitized y aspect %d, expected %d.\n", 479 metrics.tmDigitizedAspectY, expmetrics.tmDigitizedAspectY); 480 ok(metrics.tmFirstChar == expmetrics.tmFirstChar, "Got unexpected first char %u, expected %u.\n", 481 metrics.tmFirstChar, expmetrics.tmFirstChar); 482 ok(metrics.tmLastChar == expmetrics.tmLastChar, "Got unexpected last char %u, expected %u.\n", 483 metrics.tmLastChar, expmetrics.tmLastChar); 484 ok(metrics.tmDefaultChar == expmetrics.tmDefaultChar, "Got unexpected default char %u, expected %u.\n", 485 metrics.tmDefaultChar, expmetrics.tmDefaultChar); 486 ok(metrics.tmBreakChar == expmetrics.tmBreakChar, "Got unexpected break char %u, expected %u.\n", 487 metrics.tmBreakChar, expmetrics.tmBreakChar); 488 ok(metrics.tmItalic == expmetrics.tmItalic, "Got unexpected italic %u, expected %u.\n", 489 metrics.tmItalic, expmetrics.tmItalic); 490 ok(metrics.tmUnderlined == expmetrics.tmUnderlined, "Got unexpected underlined %u, expected %u.\n", 491 metrics.tmUnderlined, expmetrics.tmUnderlined); 492 ok(metrics.tmStruckOut == expmetrics.tmStruckOut, "Got unexpected struck out %u, expected %u.\n", 493 metrics.tmStruckOut, expmetrics.tmStruckOut); 494 ok(metrics.tmPitchAndFamily == expmetrics.tmPitchAndFamily, "Got unexpected pitch and family %u, expected %u.\n", 495 metrics.tmPitchAndFamily, expmetrics.tmPitchAndFamily); 496 ok(metrics.tmCharSet == expmetrics.tmCharSet, "Got unexpected charset %u, expected %u.\n", 497 metrics.tmCharSet, expmetrics.tmCharSet); 498 499 ID3DXFont_Release(font); 500 501 502 /* ID3DXFont_PreloadText */ 503 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 504 DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font); 505 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 506 507 hr = ID3DXFont_PreloadTextA(font, NULL, -1); 508 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); 509 hr = ID3DXFont_PreloadTextA(font, NULL, 0); 510 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 511 hr = ID3DXFont_PreloadTextA(font, NULL, 1); 512 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); 513 hr = ID3DXFont_PreloadTextA(font, "test", -1); 514 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 515 hr = ID3DXFont_PreloadTextA(font, "", 0); 516 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 517 hr = ID3DXFont_PreloadTextA(font, "", -1); 518 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 519 520 hr = ID3DXFont_PreloadTextW(font, NULL, -1); 521 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); 522 hr = ID3DXFont_PreloadTextW(font, NULL, 0); 523 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 524 hr = ID3DXFont_PreloadTextW(font, NULL, 1); 525 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); 526 hr = ID3DXFont_PreloadTextW(font, testW, -1); 527 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 528 hr = ID3DXFont_PreloadTextW(font, L"", 0); 529 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 530 hr = ID3DXFont_PreloadTextW(font, L"", -1); 531 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 532 533 check_release((IUnknown*)font, 0); 534 535 536 /* ID3DXFont_GetGlyphData, ID3DXFont_PreloadGlyphs, ID3DXFont_PreloadCharacters */ 537 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 538 DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font); 539 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 540 541 hdc = ID3DXFont_GetDC(font); 542 ok(!!hdc, "Got unexpected hdc %p.\n", hdc); 543 544 hr = ID3DXFont_GetGlyphData(font, 0, NULL, &blackbox, &cellinc); 545 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 546 hr = ID3DXFont_GetGlyphData(font, 0, &texture, NULL, &cellinc); 547 check_release((IUnknown *)texture, 1); 548 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 549 hr = ID3DXFont_GetGlyphData(font, 0, &texture, &blackbox, NULL); 550 check_release((IUnknown *)texture, 1); 551 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 552 553 hr = ID3DXFont_PreloadCharacters(font, 'b', 'a'); 554 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 555 hr = ID3DXFont_PreloadGlyphs(font, 1, 0); 556 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 557 558 hr = ID3DXFont_PreloadCharacters(font, 'a', 'a'); 559 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 560 561 for (c = 'b'; c <= 'z'; ++c) 562 { 563 count = GetGlyphIndicesA(hdc, &c, 1, &glyph, 0); 564 ok(count != GDI_ERROR, "Got unexpected count %u.\n", count); 565 566 hr = ID3DXFont_GetGlyphData(font, glyph, &texture, &blackbox, &cellinc); 567 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 568 569 levels = IDirect3DTexture9_GetLevelCount(texture); 570 todo_wine ok(levels == 5, "Character %c: got unexpected levels %u.\n", c, levels); 571 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surf_desc); 572 ok(hr == D3D_OK, "Character %c: got unexpected hr %#x.\n", c, hr); 573 ok(surf_desc.Format == D3DFMT_A8R8G8B8, "Character %c: got unexpected format %#x.\n", c, surf_desc.Format); 574 ok(surf_desc.Usage == 0, "Character %c: got unexpected usage %#x.\n", c, surf_desc.Usage); 575 ok(surf_desc.Width == 256, "Character %c: got unexpected width %u.\n", c, surf_desc.Width); 576 ok(surf_desc.Height == 256, "Character %c: got unexpected height %u.\n", c, surf_desc.Height); 577 ok(surf_desc.Pool == D3DPOOL_MANAGED, "Character %c: got unexpected pool %u.\n", c, surf_desc.Pool); 578 579 count = GetGlyphOutlineW(hdc, glyph, GGO_GLYPH_INDEX | GGO_METRICS, &glyph_metrics, 0, NULL, &mat); 580 ok(count != GDI_ERROR, "Got unexpected count %#x.\n", count); 581 582 ret = ID3DXFont_GetTextMetricsW(font, &tm); 583 ok(ret, "Got unexpected ret %#x.\n", ret); 584 585 todo_wine ok(blackbox.right - blackbox.left == glyph_metrics.gmBlackBoxX + 2, "Character %c: got %d, expected %d.\n", 586 c, blackbox.right - blackbox.left, glyph_metrics.gmBlackBoxX + 2); 587 todo_wine ok(blackbox.bottom - blackbox.top == glyph_metrics.gmBlackBoxY + 2, "Character %c: got %d, expected %d.\n", 588 c, blackbox.bottom - blackbox.top, glyph_metrics.gmBlackBoxY + 2); 589 ok(cellinc.x == glyph_metrics.gmptGlyphOrigin.x - 1, "Character %c: got %d, expected %d.\n", 590 c, cellinc.x, glyph_metrics.gmptGlyphOrigin.x - 1); 591 ok(cellinc.y == tm.tmAscent - glyph_metrics.gmptGlyphOrigin.y - 1, "Character %c: got %d, expected %d.\n", 592 c, cellinc.y, tm.tmAscent - glyph_metrics.gmptGlyphOrigin.y - 1); 593 594 check_release((IUnknown *)texture, 1); 595 } 596 597 hr = ID3DXFont_PreloadCharacters(font, 'a', 'z'); 598 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 599 600 /* Test multiple textures */ 601 hr = ID3DXFont_PreloadGlyphs(font, 0, 1000); 602 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 603 604 /* Test glyphs that are not rendered */ 605 for (glyph = 1; glyph < 4; ++glyph) 606 { 607 texture = (IDirect3DTexture9 *)0xdeadbeef; 608 hr = ID3DXFont_GetGlyphData(font, glyph, &texture, &blackbox, &cellinc); 609 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 610 ok(!texture, "Got unexpected texture %p.\n", texture); 611 } 612 613 check_release((IUnknown *)font, 0); 614 615 c = 'a'; 616 for (i = 0; i < ARRAY_SIZE(tests); ++i) 617 { 618 hr = D3DXCreateFontA(device, tests[i].font_height, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, 619 OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font); 620 ok(hr == D3D_OK, "Test %u: got unexpected hr %#x.\n", i, hr); 621 622 hdc = ID3DXFont_GetDC(font); 623 ok(!!hdc, "Test %u: got unexpected hdc %p.\n", i, hdc); 624 625 count = GetGlyphIndicesA(hdc, &c, 1, &glyph, 0); 626 ok(count != GDI_ERROR, "Test %u: got unexpected count %u.\n", i, count); 627 628 hr = ID3DXFont_GetGlyphData(font, glyph, &texture, NULL, NULL); 629 ok(hr == D3D_OK, "Test %u: got unexpected hr %#x.\n", i, hr); 630 631 levels = IDirect3DTexture9_GetLevelCount(texture); 632 todo_wine_if(tests[i].expected_levels < 9) 633 ok(levels == tests[i].expected_levels, "Test %u: got unexpected levels %u.\n", i, levels); 634 635 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surf_desc); 636 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 637 ok(surf_desc.Format == D3DFMT_A8R8G8B8, "Test %u: got unexpected format %#x.\n", i, surf_desc.Format); 638 ok(surf_desc.Usage == 0, "Test %u: got unexpected usage %#x.\n", i, surf_desc.Usage); 639 ok(surf_desc.Width == tests[i].expected_size, "Test %u: got unexpected width %u.\n", i, surf_desc.Width); 640 ok(surf_desc.Height == tests[i].expected_size, "Test %u: got unexpected height %u.\n", i, surf_desc.Height); 641 ok(surf_desc.Pool == D3DPOOL_MANAGED, "Test %u: got unexpected pool %u.\n", i, surf_desc.Pool); 642 643 IDirect3DTexture9_Release(texture); 644 645 /* ID3DXFontImpl_DrawText */ 646 D3DXCreateSprite(device, &sprite); 647 SetRect(&rect, 0, 0, 640, 480); 648 649 IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 1.0f, 0); 650 651 IDirect3DDevice9_BeginScene(device); 652 hr = ID3DXSprite_Begin(sprite, D3DXSPRITE_ALPHABLEND); 653 ok (hr == D3D_OK, "Test %d: got unexpected hr %#x.\n", i, hr); 654 655 height = ID3DXFont_DrawTextW(font, sprite, testW, -1, &rect, DT_TOP, 0xffffffff); 656 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); 657 height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_TOP, 0xffffffff); 658 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); 659 height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_RIGHT, 0xffffffff); 660 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); 661 height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_LEFT | DT_NOCLIP, 0xffffffff); 662 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); 663 664 SetRectEmpty(&rect); 665 height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, 666 DT_LEFT | DT_CALCRECT, 0xffffffff); 667 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); 668 ok(!rect.left, "Test %d: got unexpected rect left %d.\n", i, rect.left); 669 ok(!rect.top, "Test %d: got unexpected rect top %d.\n", i, rect.top); 670 todo_wine ok(rect.right, "Test %d: got unexpected rect right %d.\n", i, rect.right); 671 todo_wine ok(rect.bottom == tests[i].font_height, "Test %d: got unexpected rect bottom %d.\n", i, rect.bottom); 672 673 hr = ID3DXSprite_End(sprite); 674 ok (hr == D3D_OK, "Test %d: got unexpected hr %#x.\n", i, hr); 675 IDirect3DDevice9_EndScene(device); 676 ID3DXSprite_Release(sprite); 677 678 ID3DXFont_Release(font); 679 } 680 681 682 /* ID3DXFont_DrawTextA, ID3DXFont_DrawTextW */ 683 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 684 DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font); 685 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 686 687 SetRect(&rect, 10, 10, 200, 200); 688 689 height = ID3DXFont_DrawTextA(font, NULL, "test", -2, &rect, 0, 0xFF00FF); 690 ok(height == 12, "Got unexpected height %d.\n", height); 691 692 height = ID3DXFont_DrawTextA(font, NULL, "test", -1, &rect, 0, 0xFF00FF); 693 ok(height == 12, "Got unexpected height %d.\n", height); 694 695 height = ID3DXFont_DrawTextA(font, NULL, "test", 0, &rect, 0, 0xFF00FF); 696 ok(height == 0, "Got unexpected height %d.\n", height); 697 698 height = ID3DXFont_DrawTextA(font, NULL, "test", 1, &rect, 0, 0xFF00FF); 699 ok(height == 12, "Got unexpected height %d.\n", height); 700 701 height = ID3DXFont_DrawTextA(font, NULL, "test", 2, &rect, 0, 0xFF00FF); 702 ok(height == 12, "Got unexpected height %d.\n", height); 703 704 height = ID3DXFont_DrawTextA(font, NULL, "", 0, &rect, 0, 0xff00ff); 705 ok(height == 0, "Got unexpected height %d.\n", height); 706 707 height = ID3DXFont_DrawTextA(font, NULL, "", -1, &rect, 0, 0xff00ff); 708 ok(height == 0, "Got unexpected height %d.\n", height); 709 710 height = ID3DXFont_DrawTextA(font, NULL, "test", -1, NULL, 0, 0xFF00FF); 711 ok(height == 12, "Got unexpected height %d.\n", height); 712 713 height = ID3DXFont_DrawTextA(font, NULL, "test", -1, NULL, DT_CALCRECT, 0xFF00FF); 714 ok(height == 12, "Got unexpected height %d.\n", height); 715 716 height = ID3DXFont_DrawTextA(font, NULL, NULL, -1, NULL, 0, 0xFF00FF); 717 ok(height == 0, "Got unexpected height %d.\n", height); 718 719 SetRect(&rect, 10, 10, 50, 50); 720 721 height = ID3DXFont_DrawTextA(font, NULL, long_text, -1, &rect, DT_WORDBREAK, 0xff00ff); 722 todo_wine ok(height == 60, "Got unexpected height %d.\n", height); 723 724 height = ID3DXFont_DrawTextA(font, NULL, long_text, -1, &rect, DT_WORDBREAK | DT_NOCLIP, 0xff00ff); 725 ok(height == 96, "Got unexpected height %d.\n", height); 726 727 SetRect(&rect, 10, 10, 200, 200); 728 729 height = ID3DXFont_DrawTextW(font, NULL, testW, -1, &rect, 0, 0xFF00FF); 730 ok(height == 12, "Got unexpected height %d.\n", height); 731 732 height = ID3DXFont_DrawTextW(font, NULL, testW, 0, &rect, 0, 0xFF00FF); 733 ok(height == 0, "Got unexpected height %d.\n", height); 734 735 height = ID3DXFont_DrawTextW(font, NULL, testW, 1, &rect, 0, 0xFF00FF); 736 ok(height == 12, "Got unexpected height %d.\n", height); 737 738 height = ID3DXFont_DrawTextW(font, NULL, testW, 2, &rect, 0, 0xFF00FF); 739 ok(height == 12, "Got unexpected height %d.\n", height); 740 741 height = ID3DXFont_DrawTextW(font, NULL, L"", 0, &rect, 0, 0xff00ff); 742 ok(height == 0, "Got unexpected height %d.\n", height); 743 744 height = ID3DXFont_DrawTextW(font, NULL, L"", -1, &rect, 0, 0xff00ff); 745 ok(height == 0, "Got unexpected height %d.\n", height); 746 747 height = ID3DXFont_DrawTextW(font, NULL, testW, -1, NULL, 0, 0xFF00FF); 748 ok(height == 12, "Got unexpected height %d.\n", height); 749 750 height = ID3DXFont_DrawTextW(font, NULL, testW, -1, NULL, DT_CALCRECT, 0xFF00FF); 751 ok(height == 12, "Got unexpected height %d.\n", height); 752 753 height = ID3DXFont_DrawTextW(font, NULL, NULL, -1, NULL, 0, 0xFF00FF); 754 ok(height == 0, "Got unexpected height %d.\n", height); 755 756 SetRect(&rect, 10, 10, 50, 50); 757 758 height = ID3DXFont_DrawTextW(font, NULL, long_textW, -1, &rect, DT_WORDBREAK, 0xff00ff); 759 todo_wine ok(height == 60, "Got unexpected height %d.\n", height); 760 761 height = ID3DXFont_DrawTextW(font, NULL, long_textW, -1, &rect, DT_WORDBREAK | DT_NOCLIP, 0xff00ff); 762 ok(height == 96, "Got unexpected height %d.\n", height); 763 764 height = ID3DXFont_DrawTextW(font, NULL, L"a\na", -1, &rect, 0, 0xff00ff); 765 ok(height == 24, "Got unexpected height %d.\n", height); 766 767 height = ID3DXFont_DrawTextW(font, NULL, L"a\r\na", -1, &rect, 0, 0xff00ff); 768 ok(height == 24, "Got unexpected height %d.\n", height); 769 770 height = ID3DXFont_DrawTextW(font, NULL, L"a\ra", -1, &rect, 0, 0xff00ff); 771 ok(height == 12, "Got unexpected height %d.\n", height); 772 773 height = ID3DXFont_DrawTextW(font, NULL, L"a\na", -1, &rect, DT_SINGLELINE, 0xff00ff); 774 ok(height == 12, "Got unexpected height %d.\n", height); 775 776 height = ID3DXFont_DrawTextW(font, NULL, L"a\naaaaa aaaa", -1, &rect, 0, 0xff00ff); 777 ok(height == 24, "Got unexpected height %d.\n", height); 778 779 height = ID3DXFont_DrawTextW(font, NULL, L"a\naaaaa aaaa", -1, &rect, DT_WORDBREAK, 0xff00ff); 780 ok(height == 36, "Got unexpected height %d.\n", height); 781 782 height = ID3DXFont_DrawTextW(font, NULL, L"1\n2\n3\n4\n5\n6", -1, &rect, 0, 0xff00ff); 783 ok(height == 48, "Got unexpected height %d.\n", height); 784 785 height = ID3DXFont_DrawTextW(font, NULL, L"1\n2\n3\n4\n5\n6", -1, &rect, DT_NOCLIP, 0xff00ff); 786 ok(height == 72, "Got unexpected height %d.\n", height); 787 788 height = ID3DXFont_DrawTextW(font, NULL, L"\t\t\t\t\t\t\t\t\t\t", -1, &rect, DT_WORDBREAK, 0xff00ff); 789 todo_wine ok(height == 0, "Got unexpected height %d.\n", height); 790 791 height = ID3DXFont_DrawTextW(font, NULL, L"\t\t\t\t\t\t\t\t\t\ta", -1, &rect, DT_WORDBREAK, 0xff00ff); 792 todo_wine ok(height == 12, "Got unexpected height %d.\n", height); 793 794 height = ID3DXFont_DrawTextW(font, NULL, L"\taaaaaaaaaa", -1, &rect, DT_WORDBREAK, 0xff00ff); 795 todo_wine ok(height == 24, "Got unexpected height %d.\n", height); 796 797 height = ID3DXFont_DrawTextW(font, NULL, L"\taaaaaaaaaa", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff); 798 ok(height == 36, "Got unexpected height %d.\n", height); 799 800 height = ID3DXFont_DrawTextW(font, NULL, L"\taaa\taaa\taaa", -1, &rect, DT_WORDBREAK, 0xff00ff); 801 ok(height == 24, "Got unexpected height %d.\n", height); 802 803 height = ID3DXFont_DrawTextW(font, NULL, L"\taaa\taaa\taaa", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff); 804 todo_wine ok(height == 48, "Got unexpected height %d.\n", height); 805 806 height = ID3DXFont_DrawTextW(font, NULL, L"\t\t\t\t\t\t\t\t\t\t", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff); 807 todo_wine ok(height == 60, "Got unexpected height %d.\n", height); 808 809 height = ID3DXFont_DrawTextW(font, NULL, L"a\ta", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff); 810 ok(height == 12, "Got unexpected height %d.\n", height); 811 812 height = ID3DXFont_DrawTextW(font, NULL, L"a\ta\ta", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff); 813 todo_wine ok(height == 24, "Got unexpected height %d.\n", height); 814 815 height = ID3DXFont_DrawTextW(font, NULL, L"aaaaaaaaaaaaaaaaaaaa", -1, &rect, DT_WORDBREAK, 0xff00ff); 816 ok(height == 36, "Got unexpected height %d.\n", height); 817 818 height = ID3DXFont_DrawTextW(font, NULL, L"a a", -1, &rect, DT_WORDBREAK, 0xff00ff); 819 ok(height == 36, "Got unexpected height %d.\n", height); 820 821 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK, 0xff00ff); 822 ok(height == 36, "Got unexpected height %d.\n", height); 823 824 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK | DT_RIGHT, 0xff00ff); 825 ok(height == 36, "Got unexpected height %d.\n", height); 826 827 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK | DT_RIGHT, 0xff00ff); 828 ok(height == 36, "Got unexpected height %d.\n", height); 829 830 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_BOTTOM, 0xff00ff); 831 todo_wine ok(height == 40, "Got unexpected height %d.\n", height); 832 833 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_VCENTER, 0xff00ff); 834 todo_wine ok(height == 32, "Got unexpected height %d.\n", height); 835 836 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_RIGHT, 0xff00ff); 837 ok(height == 24, "Got unexpected height %d.\n", height); 838 839 height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER, 0xff00ff); 840 ok(height == 24, "Got unexpected height %d.\n", height); 841 842 ID3DXFont_Release(font); 843 } 844 845 static void test_D3DXCreateRenderToSurface(IDirect3DDevice9 *device) 846 { 847 int i; 848 HRESULT hr; 849 ULONG ref_count; 850 D3DXRTS_DESC desc; 851 ID3DXRenderToSurface *render = (void *)0xdeadbeef; 852 static const D3DXRTS_DESC tests[] = 853 { 854 { 0, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, 855 { 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, 856 { 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_D24S8 }, 857 { 256, 256, D3DFMT_UNKNOWN, FALSE, D3DFMT_R8G8B8 }, 858 { 0, 0, D3DFMT_UNKNOWN, FALSE, D3DFMT_UNKNOWN }, 859 { -1, -1, MAKEFOURCC('B','A','D','F'), TRUE, MAKEFOURCC('B','A','D','F') } 860 }; 861 862 hr = D3DXCreateRenderToSurface(NULL /* device */, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render); 863 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 864 ok(render == (void *)0xdeadbeef, "Got %p, expected %p\n", render, (void *)0xdeadbeef); 865 866 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, NULL /* out */); 867 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 868 869 for (i = 0; i < ARRAY_SIZE(tests); i++) 870 { 871 hr = D3DXCreateRenderToSurface(device, tests[i].Width, tests[i].Height, tests[i].Format, tests[i].DepthStencil, 872 tests[i].DepthStencilFormat, &render); 873 ok(hr == D3D_OK, "%d: D3DXCreateRenderToSurface returned %#x, expected %#x\n", i, hr, D3D_OK); 874 if (SUCCEEDED(hr)) 875 { 876 hr = ID3DXRenderToSurface_GetDesc(render, &desc); 877 ok(hr == D3D_OK, "%d: GetDesc failed %#x\n", i, hr); 878 if (SUCCEEDED(hr)) 879 { 880 ok(desc.Width == tests[i].Width, "%d: Got width %u, expected %u\n", i, desc.Width, tests[i].Width); 881 ok(desc.Height == tests[i].Height, "%d: Got height %u, expected %u\n", i, desc.Height, tests[i].Height); 882 ok(desc.Format == tests[i].Format, "%d: Got format %#x, expected %#x\n", i, desc.Format, tests[i].Format); 883 ok(desc.DepthStencil == tests[i].DepthStencil, "%d: Got depth stencil %d, expected %d\n", 884 i, desc.DepthStencil, tests[i].DepthStencil); 885 ok(desc.DepthStencilFormat == tests[i].DepthStencilFormat, "%d: Got depth stencil format %#x, expected %#x\n", 886 i, desc.DepthStencilFormat, tests[i].DepthStencilFormat); 887 } 888 ID3DXRenderToSurface_Release(render); 889 } 890 } 891 892 /* check device ref count */ 893 ref_count = get_ref((IUnknown *)device); 894 hr = D3DXCreateRenderToSurface(device, 0, 0, D3DFMT_UNKNOWN, FALSE, D3DFMT_UNKNOWN, &render); 895 check_ref((IUnknown *)device, ref_count + 1); 896 if (SUCCEEDED(hr)) ID3DXRenderToSurface_Release(render); 897 } 898 899 /* runs a set of tests for the ID3DXRenderToSurface interface created with given parameters */ 900 static void check_ID3DXRenderToSurface(IDirect3DDevice9 *device, UINT width, UINT height, D3DFORMAT format, 901 BOOL depth_stencil, D3DFORMAT depth_stencil_format, BOOL render_target) 902 { 903 HRESULT hr; 904 D3DFORMAT fmt; 905 HRESULT expected_value; 906 IDirect3DSurface9 *surface; 907 ID3DXRenderToSurface *render; 908 D3DVIEWPORT9 viewport = { 0, 0, width, height, 0.0, 1.0 }; 909 910 hr = D3DXCreateRenderToSurface(device, width, height, format, depth_stencil, depth_stencil_format, &render); 911 if (FAILED(hr)) 912 { 913 skip("Failed to create ID3DXRenderToSurface\n"); 914 return; 915 } 916 917 if (render_target) 918 hr = IDirect3DDevice9_CreateRenderTarget(device, width, height, format, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL); 919 else 920 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, format, D3DPOOL_DEFAULT, &surface, NULL); 921 if (FAILED(hr)) 922 { 923 skip("Failed to create surface\n"); 924 ID3DXRenderToSurface_Release(render); 925 return; 926 } 927 928 /* viewport */ 929 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 930 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); 931 check_ref((IUnknown *)surface, 2); 932 if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 933 934 /* invalid viewport */ 935 viewport.Width = 2 * width; 936 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 937 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 938 939 viewport.X = width / 2; 940 viewport.Width = width; 941 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 942 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 943 944 viewport.X = width; 945 viewport.Width = width; 946 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 947 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 948 949 /* rendering to a part of a surface is only allowed for render target surfaces */ 950 expected_value = render_target ? D3D_OK : D3DERR_INVALIDCALL; 951 952 viewport.X = 0; 953 viewport.Width = width / 2; 954 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 955 ok(hr == expected_value, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, expected_value); 956 if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 957 958 viewport.X = width / 2; 959 viewport.Width = width - width / 2; 960 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 961 ok(hr == expected_value, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, expected_value); 962 if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 963 964 check_release((IUnknown *)surface, 0); 965 966 /* surfaces with different sizes */ 967 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width / 2, width / 2, format, D3DPOOL_DEFAULT, &surface, NULL); 968 if (FAILED(hr)) 969 { 970 skip("Failed to create surface\n"); 971 ID3DXRenderToSurface_Release(render); 972 return; 973 } 974 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 975 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 976 check_release((IUnknown *)surface, 0); 977 978 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2 * width, 2 * height, format, D3DPOOL_DEFAULT, &surface, NULL); 979 if (FAILED(hr)) 980 { 981 skip("Failed to create surface\n"); 982 ID3DXRenderToSurface_Release(render); 983 return; 984 } 985 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 986 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 987 viewport.X = 0; 988 viewport.Y = 0; 989 viewport.Width = width; 990 viewport.Height = height; 991 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 992 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 993 check_release((IUnknown *)surface, 0); 994 995 /* surfaces with different formats */ 996 for (fmt = D3DFMT_A8R8G8B8; fmt <= D3DFMT_X8R8G8B8; fmt++) 997 { 998 HRESULT expected_result = (fmt != format) ? D3DERR_INVALIDCALL : D3D_OK; 999 1000 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, fmt, D3DPOOL_DEFAULT, &surface, NULL); 1001 if (FAILED(hr)) 1002 { 1003 skip("Failed to create surface\n"); 1004 continue; 1005 } 1006 1007 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 1008 ok(hr == expected_result, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, expected_result); 1009 1010 if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 1011 check_release((IUnknown *)surface, 0); 1012 } 1013 1014 check_release((IUnknown *)render, 0); 1015 } 1016 1017 struct device_state 1018 { 1019 IDirect3DSurface9 *render_target; 1020 IDirect3DSurface9 *depth_stencil; 1021 D3DVIEWPORT9 viewport; 1022 }; 1023 1024 static void release_device_state(struct device_state *state) 1025 { 1026 if (state->render_target) IDirect3DSurface9_Release(state->render_target); 1027 if (state->depth_stencil) IDirect3DSurface9_Release(state->depth_stencil); 1028 memset(state, 0, sizeof(*state)); 1029 } 1030 1031 static HRESULT retrieve_device_state(IDirect3DDevice9 *device, struct device_state *state) 1032 { 1033 HRESULT hr; 1034 1035 memset(state, 0, sizeof(*state)); 1036 1037 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &state->render_target); 1038 if (FAILED(hr)) goto cleanup; 1039 1040 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &state->depth_stencil); 1041 if (hr == D3DERR_NOTFOUND) 1042 state->depth_stencil = NULL; 1043 else if (FAILED(hr)) 1044 goto cleanup; 1045 1046 hr = IDirect3DDevice9_GetViewport(device, &state->viewport); 1047 if (SUCCEEDED(hr)) return hr; 1048 1049 cleanup: 1050 release_device_state(state); 1051 return hr; 1052 } 1053 1054 static HRESULT apply_device_state(IDirect3DDevice9 *device, struct device_state *state) 1055 { 1056 HRESULT hr; 1057 HRESULT status = D3D_OK; 1058 1059 hr = IDirect3DDevice9_SetRenderTarget(device, 0, state->render_target); 1060 if (FAILED(hr)) status = hr; 1061 1062 hr = IDirect3DDevice9_SetDepthStencilSurface(device, state->depth_stencil); 1063 if (FAILED(hr)) status = hr; 1064 1065 hr = IDirect3DDevice9_SetViewport(device, &state->viewport); 1066 if (FAILED(hr)) status = hr; 1067 1068 return status; 1069 } 1070 1071 static void compare_device_state(struct device_state *state1, struct device_state *state2, BOOL equal) 1072 { 1073 BOOL cmp; 1074 const char *message = equal ? "differs" : "is the same"; 1075 1076 cmp = state1->render_target == state2->render_target; 1077 ok(equal ? cmp : !cmp, "Render target %s %p, %p\n", message, state1->render_target, state2->render_target); 1078 1079 cmp = state1->depth_stencil == state2->depth_stencil; 1080 ok(equal ? cmp : !cmp, "Depth stencil surface %s %p, %p\n", message, state1->depth_stencil, state2->depth_stencil); 1081 1082 cmp = state1->viewport.X == state2->viewport.X && state1->viewport.Y == state2->viewport.Y 1083 && state1->viewport.Width == state2->viewport.Width && state1->viewport.Height == state2->viewport.Height; 1084 ok(equal ? cmp : !cmp, "Viewport %s (%u, %u, %u, %u), (%u, %u, %u, %u)\n", message, 1085 state1->viewport.X, state1->viewport.Y, state1->viewport.Width, state1->viewport.Height, 1086 state2->viewport.X, state2->viewport.Y, state2->viewport.Width, state2->viewport.Height); 1087 } 1088 1089 static void test_ID3DXRenderToSurface_device_state(IDirect3DDevice9 *device) 1090 { 1091 HRESULT hr; 1092 IDirect3DSurface9 *surface = NULL; 1093 ID3DXRenderToSurface *render = NULL; 1094 struct device_state pre_state; 1095 struct device_state current_state; 1096 IDirect3DSurface9 *depth_stencil_surface; 1097 1098 /* make sure there is a depth stencil surface present */ 1099 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &depth_stencil_surface); 1100 if (SUCCEEDED(hr)) 1101 { 1102 IDirect3DSurface9_Release(depth_stencil_surface); 1103 depth_stencil_surface = NULL; 1104 } 1105 else if (hr == D3DERR_NOTFOUND) 1106 { 1107 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 256, 256, D3DFMT_D24X8, 1108 D3DMULTISAMPLE_NONE, 0, TRUE, &depth_stencil_surface, NULL); 1109 if (SUCCEEDED(hr)) IDirect3DDevice9_SetDepthStencilSurface(device, depth_stencil_surface); 1110 } 1111 1112 if (FAILED(hr)) 1113 { 1114 skip("Failed to create depth stencil surface\n"); 1115 return; 1116 } 1117 1118 hr = IDirect3DDevice9_CreateRenderTarget(device, 256, 256, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, 1119 FALSE, &surface, NULL); 1120 if (FAILED(hr)) 1121 { 1122 skip("Failed to create render target\n"); 1123 goto cleanup; 1124 } 1125 1126 hr = retrieve_device_state(device, &pre_state); 1127 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1128 1129 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24X8, &render); 1130 ok(hr == D3D_OK, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3D_OK); 1131 if (SUCCEEDED(hr)) 1132 { 1133 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 1134 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); 1135 1136 hr = retrieve_device_state(device, ¤t_state); 1137 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1138 compare_device_state(¤t_state, &pre_state, FALSE); 1139 release_device_state(¤t_state); 1140 1141 hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 1142 ok(hr == D3D_OK, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3D_OK); 1143 1144 hr = retrieve_device_state(device, ¤t_state); 1145 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1146 compare_device_state(¤t_state, &pre_state, TRUE); 1147 release_device_state(¤t_state); 1148 1149 check_release((IUnknown *)render, 0); 1150 } 1151 1152 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render); 1153 if (SUCCEEDED(hr)) 1154 { 1155 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 1156 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); 1157 1158 hr = retrieve_device_state(device, ¤t_state); 1159 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1160 compare_device_state(¤t_state, &pre_state, FALSE); 1161 release_device_state(¤t_state); 1162 1163 hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 1164 ok(hr == D3D_OK, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3D_OK); 1165 1166 hr = retrieve_device_state(device, ¤t_state); 1167 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1168 compare_device_state(¤t_state, &pre_state, TRUE); 1169 release_device_state(¤t_state); 1170 1171 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 1172 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); 1173 1174 hr = retrieve_device_state(device, ¤t_state); 1175 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1176 compare_device_state(¤t_state, &pre_state, FALSE); 1177 release_device_state(¤t_state); 1178 1179 check_release((IUnknown *)render, 0); 1180 1181 /* if EndScene isn't called, the device state isn't restored */ 1182 hr = retrieve_device_state(device, ¤t_state); 1183 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1184 compare_device_state(¤t_state, &pre_state, FALSE); 1185 release_device_state(¤t_state); 1186 1187 hr = apply_device_state(device, &pre_state); 1188 ok(SUCCEEDED(hr), "Failed to restore previous device state\n"); 1189 1190 IDirect3DDevice9_EndScene(device); 1191 } 1192 1193 release_device_state(&pre_state); 1194 1195 cleanup: 1196 if (depth_stencil_surface) 1197 { 1198 IDirect3DDevice9_SetDepthStencilSurface(device, NULL); 1199 IDirect3DSurface9_Release(depth_stencil_surface); 1200 } 1201 1202 if (surface) check_release((IUnknown *)surface, 0); 1203 } 1204 1205 static void test_ID3DXRenderToSurface(IDirect3DDevice9 *device) 1206 { 1207 int i; 1208 HRESULT hr; 1209 ULONG ref_count; 1210 IDirect3DDevice9 *out_device; 1211 ID3DXRenderToSurface *render; 1212 IDirect3DSurface9 *surface; 1213 D3DVIEWPORT9 viewport = { 0, 0, 256, 256, 0.0, 1.0 }; 1214 D3DXRTS_DESC tests[] = { 1215 { 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, 1216 { 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24S8 }, 1217 { 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24X8 }, 1218 { 512, 512, D3DFMT_X8R8G8B8, FALSE, D3DFMT_X8R8G8B8 }, 1219 { 1024, 1024, D3DFMT_X8R8G8B8, TRUE, D3DFMT_D24S8 } 1220 }; 1221 1222 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render); 1223 ok(hr == D3D_OK, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3D_OK); 1224 if (FAILED(hr)) return; 1225 1226 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 256, 256, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, NULL); 1227 if (SUCCEEDED(hr)) 1228 { 1229 ID3DXRenderToSurface *render_surface; 1230 1231 /* GetDevice */ 1232 hr = ID3DXRenderToSurface_GetDevice(render, NULL /* device */); 1233 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1234 1235 ref_count = get_ref((IUnknown *)device); 1236 hr = ID3DXRenderToSurface_GetDevice(render, &out_device); 1237 ok(hr == D3D_OK, "ID3DXRenderToSurface::GetDevice returned %#x, expected %#x\n", hr, D3D_OK); 1238 check_release((IUnknown *)out_device, ref_count); 1239 1240 /* BeginScene and EndScene */ 1241 hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 1242 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1243 1244 hr = ID3DXRenderToSurface_BeginScene(render, NULL /* surface */, &viewport); 1245 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1246 1247 ref_count = get_ref((IUnknown *)surface); 1248 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 1249 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); 1250 if (SUCCEEDED(hr)) 1251 { 1252 check_ref((IUnknown *)surface, ref_count + 1); 1253 1254 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 1255 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1256 1257 hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 1258 ok(hr == D3D_OK, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3D_OK); 1259 1260 check_ref((IUnknown *)surface, ref_count); 1261 } 1262 1263 /* error handling is deferred to BeginScene */ 1264 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_UNKNOWN, &render_surface); 1265 ok(hr == D3D_OK, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3D_OK); 1266 hr = ID3DXRenderToSurface_BeginScene(render_surface, surface, NULL); 1267 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1268 check_release((IUnknown *)render_surface, 0); 1269 1270 check_release((IUnknown *)surface, 0); 1271 } 1272 else skip("Failed to create surface\n"); 1273 1274 check_release((IUnknown *)render, 0); 1275 1276 for (i = 0; i < ARRAY_SIZE(tests); i++) 1277 { 1278 check_ID3DXRenderToSurface(device, tests[i].Width, tests[i].Height, tests[i].Format, tests[i].DepthStencil, tests[i].DepthStencilFormat, TRUE); 1279 check_ID3DXRenderToSurface(device, tests[i].Width, tests[i].Height, tests[i].Format, tests[i].DepthStencil, tests[i].DepthStencilFormat, FALSE); 1280 } 1281 1282 test_ID3DXRenderToSurface_device_state(device); 1283 } 1284 1285 static void test_D3DXCreateRenderToEnvMap(IDirect3DDevice9 *device) 1286 { 1287 int i; 1288 HRESULT hr; 1289 ULONG ref_count; 1290 D3DXRTE_DESC desc; 1291 ID3DXRenderToEnvMap *render; 1292 static const struct { 1293 D3DXRTE_DESC parameters; 1294 D3DXRTE_DESC expected_values; 1295 } tests[] = { 1296 { { 0, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, { 1, 1, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN } }, 1297 { { 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, { 256, 9, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN } }, 1298 { { 256, 4, D3DFMT_A8R8G8B8, FALSE, D3DFMT_D24S8 }, { 256, 4, D3DFMT_A8R8G8B8, FALSE, D3DFMT_D24S8 } }, 1299 { { 256, 256, D3DFMT_UNKNOWN, FALSE, D3DFMT_R8G8B8 }, { 256, 9, D3DFMT_A8R8G8B8, FALSE, D3DFMT_R8G8B8 } }, 1300 { { -1, -1, D3DFMT_A8R8G8B8, TRUE, D3DFMT_DXT1 }, { 256, 9, D3DFMT_A8R8G8B8, TRUE, D3DFMT_DXT1 } }, 1301 { { 256, 1, D3DFMT_X8R8G8B8, TRUE, D3DFMT_UNKNOWN }, { 256, 1, D3DFMT_X8R8G8B8, TRUE, D3DFMT_UNKNOWN } } 1302 }; 1303 1304 for (i = 0; i < ARRAY_SIZE(tests); i++) 1305 { 1306 const D3DXRTE_DESC *parameters = &tests[i].parameters; 1307 const D3DXRTE_DESC *expected = &tests[i].expected_values; 1308 hr = D3DXCreateRenderToEnvMap(device, parameters->Size, parameters->MipLevels, parameters->Format, 1309 parameters->DepthStencil, parameters->DepthStencilFormat, &render); 1310 ok(hr == D3D_OK, "%d: D3DXCreateRenderToEnvMap returned %#x, expected %#x\n", i, hr, D3D_OK); 1311 if (SUCCEEDED(hr)) 1312 { 1313 hr = ID3DXRenderToEnvMap_GetDesc(render, &desc); 1314 ok(hr == D3D_OK, "%d: GetDesc failed %#x\n", i, hr); 1315 if (SUCCEEDED(hr)) 1316 { 1317 ok(desc.Size == expected->Size, "%d: Got size %u, expected %u\n", i, desc.Size, expected->Size); 1318 ok(desc.MipLevels == expected->MipLevels, "%d: Got miplevels %u, expected %u\n", i, desc.MipLevels, expected->MipLevels); 1319 ok(desc.Format == expected->Format, "%d: Got format %#x, expected %#x\n", i, desc.Format, expected->Format); 1320 ok(desc.DepthStencil == expected->DepthStencil, "%d: Got depth stencil %d, expected %d\n", 1321 i, expected->DepthStencil, expected->DepthStencil); 1322 ok(desc.DepthStencilFormat == expected->DepthStencilFormat, "%d: Got depth stencil format %#x, expected %#x\n", 1323 i, expected->DepthStencilFormat, expected->DepthStencilFormat); 1324 } 1325 check_release((IUnknown *)render, 0); 1326 } 1327 } 1328 1329 /* check device ref count */ 1330 ref_count = get_ref((IUnknown *)device); 1331 hr = D3DXCreateRenderToEnvMap(device, 0, 0, D3DFMT_UNKNOWN, FALSE, D3DFMT_UNKNOWN, &render); 1332 check_ref((IUnknown *)device, ref_count + 1); 1333 if (SUCCEEDED(hr)) ID3DXRenderToEnvMap_Release(render); 1334 } 1335 1336 static void test_ID3DXRenderToEnvMap_cube_map(IDirect3DDevice9 *device) 1337 { 1338 HRESULT hr; 1339 IDirect3DCubeTexture9 *cube_texture = NULL; 1340 ID3DXRenderToEnvMap *render = NULL; 1341 struct device_state pre_state; 1342 struct device_state current_state; 1343 1344 hr = IDirect3DDevice9_CreateCubeTexture(device, 256, 0, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, 1345 &cube_texture, NULL); 1346 if (FAILED(hr)) 1347 { 1348 skip("Failed to create cube texture\n"); 1349 return; 1350 } 1351 1352 hr = retrieve_device_state(device, &pre_state); 1353 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1354 1355 hr = D3DXCreateRenderToEnvMap(device, 256, 0, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24X8, &render); 1356 ok(hr == D3D_OK, "D3DCreateRenderToEnvMap returned %#x, expected %#x\n", hr, D3D_OK); 1357 if (SUCCEEDED(hr)) 1358 { 1359 DWORD face; 1360 1361 hr = ID3DXRenderToEnvMap_End(render, D3DX_FILTER_NONE); 1362 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::End returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1363 1364 hr = ID3DXRenderToEnvMap_BeginCube(render, cube_texture); 1365 ok(hr == D3D_OK, "ID3DXRenderToEnvMap::BeginCube returned %#x, expected %#x\n", hr, D3D_OK); 1366 1367 hr = retrieve_device_state(device, ¤t_state); 1368 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1369 compare_device_state(¤t_state, &pre_state, TRUE); 1370 release_device_state(¤t_state); 1371 1372 for (face = D3DCUBEMAP_FACE_POSITIVE_X; face <= D3DCUBEMAP_FACE_NEGATIVE_Z; face++) 1373 { 1374 hr = ID3DXRenderToEnvMap_Face(render, face, D3DX_FILTER_POINT); 1375 ok(hr == D3D_OK, "ID3DXRenderToEnvMap::Face returned %#x, expected %#x\n", hr, D3D_OK); 1376 1377 hr = retrieve_device_state(device, ¤t_state); 1378 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1379 compare_device_state(¤t_state, &pre_state, FALSE); 1380 release_device_state(¤t_state); 1381 } 1382 1383 hr = ID3DXRenderToEnvMap_End(render, D3DX_FILTER_POINT); 1384 ok(hr == D3D_OK, "ID3DXRenderToEnvMap::End returned %#x, expected %#x\n", hr, D3D_OK); 1385 1386 hr = retrieve_device_state(device, ¤t_state); 1387 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1388 compare_device_state(¤t_state, &pre_state, TRUE); 1389 release_device_state(¤t_state); 1390 1391 check_release((IUnknown *)render, 0); 1392 } 1393 1394 release_device_state(&pre_state); 1395 1396 check_release((IUnknown *)cube_texture, 0); 1397 } 1398 1399 static void test_ID3DXRenderToEnvMap(IDirect3DDevice9 *device) 1400 { 1401 HRESULT hr; 1402 ID3DXRenderToEnvMap *render; 1403 IDirect3DSurface9 *depth_stencil_surface; 1404 1405 hr = D3DXCreateRenderToEnvMap(device, 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render); 1406 if (SUCCEEDED(hr)) 1407 { 1408 ULONG ref_count; 1409 IDirect3DDevice9 *out_device; 1410 1411 hr = ID3DXRenderToEnvMap_GetDesc(render, NULL); 1412 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::GetDesc returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1413 1414 hr = ID3DXRenderToEnvMap_GetDevice(render, NULL); 1415 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1416 1417 ref_count = get_ref((IUnknown *)device); 1418 hr = ID3DXRenderToEnvMap_GetDevice(render, &out_device); 1419 ok(hr == D3D_OK, "ID3DXRenderToEnvMap::GetDevice returned %#x, expected %#x\n", hr, D3D_OK); 1420 ok(out_device == device, "ID3DXRenderToEnvMap::GetDevice returned different device\n"); 1421 check_release((IUnknown *)device, ref_count); 1422 1423 hr = ID3DXRenderToEnvMap_End(render, D3DX_FILTER_NONE); 1424 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::End returned %#x, expected %#x\n", hr, D3D_OK); 1425 1426 hr = ID3DXRenderToEnvMap_BeginCube(render, NULL); 1427 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginCube returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1428 1429 hr = ID3DXRenderToEnvMap_BeginHemisphere(render, NULL, NULL); 1430 todo_wine ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginHemisphere returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1431 1432 hr = ID3DXRenderToEnvMap_BeginParabolic(render, NULL, NULL); 1433 todo_wine ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginParabolic returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1434 1435 hr = ID3DXRenderToEnvMap_BeginSphere(render, NULL); 1436 todo_wine ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginSphere returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1437 1438 check_release((IUnknown *)render, 0); 1439 } else skip("Failed to create ID3DXRenderToEnvMap\n"); 1440 1441 /* make sure there is a depth stencil surface present */ 1442 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &depth_stencil_surface); 1443 if (SUCCEEDED(hr)) 1444 { 1445 IDirect3DSurface9_Release(depth_stencil_surface); 1446 depth_stencil_surface = NULL; 1447 } 1448 else if (hr == D3DERR_NOTFOUND) 1449 { 1450 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 256, 256, D3DFMT_D24X8, 1451 D3DMULTISAMPLE_NONE, 0, TRUE, &depth_stencil_surface, NULL); 1452 if (SUCCEEDED(hr)) IDirect3DDevice9_SetDepthStencilSurface(device, depth_stencil_surface); 1453 } 1454 1455 if (FAILED(hr)) 1456 { 1457 skip("Failed to create depth stencil surface\n"); 1458 return; 1459 } 1460 1461 test_ID3DXRenderToEnvMap_cube_map(device); 1462 1463 if (depth_stencil_surface) 1464 { 1465 IDirect3DDevice9_SetDepthStencilSurface(device, NULL); 1466 IDirect3DSurface9_Release(depth_stencil_surface); 1467 } 1468 } 1469 1470 START_TEST(core) 1471 { 1472 HWND wnd; 1473 IDirect3D9 *d3d; 1474 IDirect3DDevice9 *device; 1475 D3DPRESENT_PARAMETERS d3dpp; 1476 HRESULT hr; 1477 1478 if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, 1479 640, 480, NULL, NULL, NULL, NULL))) 1480 { 1481 skip("Couldn't create application window\n"); 1482 return; 1483 } 1484 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION))) 1485 { 1486 skip("Couldn't create IDirect3D9 object\n"); 1487 DestroyWindow(wnd); 1488 return; 1489 } 1490 1491 ZeroMemory(&d3dpp, sizeof(d3dpp)); 1492 d3dpp.Windowed = TRUE; 1493 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 1494 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); 1495 if(FAILED(hr)) { 1496 skip("Failed to create IDirect3DDevice9 object %#x\n", hr); 1497 IDirect3D9_Release(d3d); 1498 DestroyWindow(wnd); 1499 return; 1500 } 1501 1502 test_ID3DXBuffer(); 1503 test_ID3DXSprite(device); 1504 test_ID3DXFont(device); 1505 test_D3DXCreateRenderToSurface(device); 1506 test_ID3DXRenderToSurface(device); 1507 test_D3DXCreateRenderToEnvMap(device); 1508 test_ID3DXRenderToEnvMap(device); 1509 1510 check_release((IUnknown*)device, 0); 1511 check_release((IUnknown*)d3d, 0); 1512 if (wnd) DestroyWindow(wnd); 1513 } 1514