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 todo_wine { 508 hr = ID3DXFont_PreloadTextA(font, NULL, -1); 509 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); 510 hr = ID3DXFont_PreloadTextA(font, NULL, 0); 511 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 512 hr = ID3DXFont_PreloadTextA(font, NULL, 1); 513 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); 514 hr = ID3DXFont_PreloadTextA(font, "test", -1); 515 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 516 hr = ID3DXFont_PreloadTextA(font, "", 0); 517 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 518 hr = ID3DXFont_PreloadTextA(font, "", -1); 519 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 520 521 hr = ID3DXFont_PreloadTextW(font, NULL, -1); 522 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); 523 hr = ID3DXFont_PreloadTextW(font, NULL, 0); 524 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 525 hr = ID3DXFont_PreloadTextW(font, NULL, 1); 526 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); 527 hr = ID3DXFont_PreloadTextW(font, testW, -1); 528 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 529 hr = ID3DXFont_PreloadTextW(font, L"", 0); 530 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 531 hr = ID3DXFont_PreloadTextW(font, L"", -1); 532 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 533 } 534 535 check_release((IUnknown*)font, 0); 536 537 538 /* ID3DXFont_GetGlyphData, ID3DXFont_PreloadGlyphs, ID3DXFont_PreloadCharacters */ 539 hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 540 DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font); 541 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 542 543 hdc = ID3DXFont_GetDC(font); 544 ok(!!hdc, "Got unexpected hdc %p.\n", hdc); 545 546 todo_wine { 547 hr = ID3DXFont_GetGlyphData(font, 0, NULL, &blackbox, &cellinc); 548 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 549 hr = ID3DXFont_GetGlyphData(font, 0, &texture, NULL, &cellinc); 550 if(SUCCEEDED(hr)) check_release((IUnknown *)texture, 1); 551 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 552 hr = ID3DXFont_GetGlyphData(font, 0, &texture, &blackbox, NULL); 553 if(SUCCEEDED(hr)) check_release((IUnknown *)texture, 1); 554 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 555 } 556 hr = ID3DXFont_PreloadCharacters(font, 'b', 'a'); 557 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 558 hr = ID3DXFont_PreloadGlyphs(font, 1, 0); 559 todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 560 561 hr = ID3DXFont_PreloadCharacters(font, 'a', 'a'); 562 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 563 564 for (c = 'b'; c <= 'z'; ++c) 565 { 566 count = GetGlyphIndicesA(hdc, &c, 1, &glyph, 0); 567 ok(count != GDI_ERROR, "Got unexpected count %u.\n", count); 568 569 hr = ID3DXFont_GetGlyphData(font, glyph, &texture, &blackbox, &cellinc); 570 todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 571 if (FAILED(hr)) 572 continue; 573 574 levels = IDirect3DTexture9_GetLevelCount(texture); 575 ok(levels == 5, "Character %c: got unexpected levels %u.\n", c, levels); 576 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surf_desc); 577 ok(hr == D3D_OK, "Character %c: got unexpected hr %#x.\n", c, hr); 578 ok(surf_desc.Format == D3DFMT_A8R8G8B8, "Character %c: got unexpected format %#x.\n", c, surf_desc.Format); 579 ok(surf_desc.Usage == 0, "Character %c: got unexpected usage %#x.\n", c, surf_desc.Usage); 580 ok(surf_desc.Width == 256, "Character %c: got unexpected width %u.\n", c, surf_desc.Width); 581 ok(surf_desc.Height == 256, "Character %c: got unexpected height %u.\n", c, surf_desc.Height); 582 ok(surf_desc.Pool == D3DPOOL_MANAGED, "Character %c: got unexpected pool %u.\n", c, surf_desc.Pool); 583 584 count = GetGlyphOutlineW(hdc, glyph, GGO_GLYPH_INDEX | GGO_METRICS, &glyph_metrics, 0, NULL, &mat); 585 ok(count != GDI_ERROR, "Got unexpected count %#x.\n", count); 586 587 ret = ID3DXFont_GetTextMetricsW(font, &tm); 588 ok(ret, "Got unexpected ret %#x.\n", ret); 589 ok(blackbox.right - blackbox.left == glyph_metrics.gmBlackBoxX + 2, "Character %c: got %d, expected %d.\n", 590 c, blackbox.right - blackbox.left, glyph_metrics.gmBlackBoxX + 2); 591 ok(blackbox.bottom - blackbox.top == glyph_metrics.gmBlackBoxY + 2, "Character %c: got %d, expected %d.\n", 592 c, blackbox.bottom - blackbox.top, glyph_metrics.gmBlackBoxY + 2); 593 ok(cellinc.x == glyph_metrics.gmptGlyphOrigin.x - 1, "Character %c: got %d, expected %d.\n", 594 c, cellinc.x, glyph_metrics.gmptGlyphOrigin.x - 1); 595 ok(cellinc.y == tm.tmAscent - glyph_metrics.gmptGlyphOrigin.y - 1, "Character %c: got %d, expected %d.\n", 596 c, cellinc.y, tm.tmAscent - glyph_metrics.gmptGlyphOrigin.y - 1); 597 598 check_release((IUnknown *)texture, 1); 599 } 600 601 hr = ID3DXFont_PreloadCharacters(font, 'a', 'z'); 602 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 603 604 /* Test multiple textures */ 605 hr = ID3DXFont_PreloadGlyphs(font, 0, 1000); 606 todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 607 608 /* Test glyphs that are not rendered */ 609 for (glyph = 1; glyph < 4; ++glyph) 610 { 611 texture = (IDirect3DTexture9 *)0xdeadbeef; 612 hr = ID3DXFont_GetGlyphData(font, glyph, &texture, &blackbox, &cellinc); 613 todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 614 todo_wine ok(!texture, "Got unexpected texture %p.\n", texture); 615 } 616 617 check_release((IUnknown *)font, 0); 618 619 c = 'a'; 620 for (i = 0; i < ARRAY_SIZE(tests); ++i) 621 { 622 hr = D3DXCreateFontA(device, tests[i].font_height, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, 623 OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font); 624 ok(hr == D3D_OK, "Test %u: got unexpected hr %#x.\n", i, hr); 625 626 hdc = ID3DXFont_GetDC(font); 627 ok(!!hdc, "Test %u: got unexpected hdc %p.\n", i, hdc); 628 629 count = GetGlyphIndicesA(hdc, &c, 1, &glyph, 0); 630 ok(count != GDI_ERROR, "Test %u: got unexpected count %u.\n", i, count); 631 632 hr = ID3DXFont_GetGlyphData(font, glyph, &texture, NULL, NULL); 633 todo_wine ok(hr == D3D_OK, "Test %u: got unexpected hr %#x.\n", i, hr); 634 if(SUCCEEDED(hr)) { 635 DWORD levels; 636 D3DSURFACE_DESC desc; 637 638 levels = IDirect3DTexture9_GetLevelCount(texture); 639 ok(levels == tests[i].expected_levels, "Test %u: got unexpected levels %u.\n", i, levels); 640 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); 641 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); 642 ok(desc.Format == D3DFMT_A8R8G8B8, "Test %u: got unexpected format %#x.\n", i, desc.Format); 643 ok(desc.Usage == 0, "Test %u: got unexpected usage %#x.\n", i, desc.Usage); 644 ok(desc.Width == tests[i].expected_size, "Test %u: got unexpected width %u.\n", i, desc.Width); 645 ok(desc.Height == tests[i].expected_size, "Test %u: got unexpected height %u.\n", i, desc.Height); 646 ok(desc.Pool == D3DPOOL_MANAGED, "Test %u: got unexpected pool %u.\n", i, desc.Pool); 647 648 IDirect3DTexture9_Release(texture); 649 } 650 651 /* ID3DXFontImpl_DrawText */ 652 D3DXCreateSprite(device, &sprite); 653 SetRect(&rect, 0, 0, 640, 480); 654 655 IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 1.0f, 0); 656 657 IDirect3DDevice9_BeginScene(device); 658 hr = ID3DXSprite_Begin(sprite, D3DXSPRITE_ALPHABLEND); 659 ok (hr == D3D_OK, "Test %d: got unexpected hr %#x.\n", i, hr); 660 661 todo_wine 662 { 663 height = ID3DXFont_DrawTextW(font, sprite, testW, -1, &rect, DT_TOP, 0xffffffff); 664 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); 665 height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_TOP, 0xffffffff); 666 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); 667 height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_RIGHT, 0xffffffff); 668 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); 669 height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_LEFT | DT_NOCLIP, 0xffffffff); 670 ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); 671 } 672 673 SetRectEmpty(&rect); 674 height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, 675 DT_LEFT | DT_CALCRECT, 0xffffffff); 676 todo_wine 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 todo_wine ok(rect.right, "Test %d: got unexpected rect right %d.\n", i, rect.right); 680 todo_wine ok(rect.bottom == tests[i].font_height, "Test %d: got unexpected rect bottom %d.\n", i, rect.bottom); 681 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); 686 687 ID3DXFont_Release(font); 688 } 689 690 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); 695 696 todo_wine { 697 SetRect(&rect, 10, 10, 200, 200); 698 699 height = ID3DXFont_DrawTextA(font, NULL, "test", -2, &rect, 0, 0xFF00FF); 700 ok(height == 12, "Got unexpected height %d.\n", height); 701 702 height = ID3DXFont_DrawTextA(font, NULL, "test", -1, &rect, 0, 0xFF00FF); 703 ok(height == 12, "Got unexpected height %d.\n", height); 704 705 height = ID3DXFont_DrawTextA(font, NULL, "test", 0, &rect, 0, 0xFF00FF); 706 ok(height == 0, "Got unexpected height %d.\n", height); 707 708 height = ID3DXFont_DrawTextA(font, NULL, "test", 1, &rect, 0, 0xFF00FF); 709 ok(height == 12, "Got unexpected height %d.\n", height); 710 711 height = ID3DXFont_DrawTextA(font, NULL, "test", 2, &rect, 0, 0xFF00FF); 712 ok(height == 12, "Got unexpected height %d.\n", height); 713 714 height = ID3DXFont_DrawTextA(font, NULL, "", 0, &rect, 0, 0xff00ff); 715 ok(height == 0, "Got unexpected height %d.\n", height); 716 717 height = ID3DXFont_DrawTextA(font, NULL, "", -1, &rect, 0, 0xff00ff); 718 ok(height == 0, "Got unexpected height %d.\n", height); 719 720 height = ID3DXFont_DrawTextA(font, NULL, "test", -1, NULL, 0, 0xFF00FF); 721 ok(height == 12, "Got unexpected height %d.\n", height); 722 723 height = ID3DXFont_DrawTextA(font, NULL, "test", -1, NULL, DT_CALCRECT, 0xFF00FF); 724 ok(height == 12, "Got unexpected height %d.\n", height); 725 726 height = ID3DXFont_DrawTextA(font, NULL, NULL, -1, NULL, 0, 0xFF00FF); 727 ok(height == 0, "Got unexpected height %d.\n", height); 728 729 SetRect(&rect, 10, 10, 50, 50); 730 731 height = ID3DXFont_DrawTextA(font, NULL, long_text, -1, &rect, DT_WORDBREAK, 0xff00ff); 732 ok(height == 60, "Got unexpected height %d.\n", height); 733 734 height = ID3DXFont_DrawTextA(font, NULL, long_text, -1, &rect, DT_WORDBREAK | DT_NOCLIP, 0xff00ff); 735 ok(height == 96, "Got unexpected height %d.\n", height); 736 737 SetRect(&rect, 10, 10, 200, 200); 738 739 height = ID3DXFont_DrawTextW(font, NULL, testW, -1, &rect, 0, 0xFF00FF); 740 ok(height == 12, "Got unexpected height %d.\n", height); 741 742 height = ID3DXFont_DrawTextW(font, NULL, testW, 0, &rect, 0, 0xFF00FF); 743 ok(height == 0, "Got unexpected height %d.\n", height); 744 745 height = ID3DXFont_DrawTextW(font, NULL, testW, 1, &rect, 0, 0xFF00FF); 746 ok(height == 12, "Got unexpected height %d.\n", height); 747 748 height = ID3DXFont_DrawTextW(font, NULL, testW, 2, &rect, 0, 0xFF00FF); 749 ok(height == 12, "Got unexpected height %d.\n", height); 750 751 height = ID3DXFont_DrawTextW(font, NULL, L"", 0, &rect, 0, 0xff00ff); 752 ok(height == 0, "Got unexpected height %d.\n", height); 753 754 height = ID3DXFont_DrawTextW(font, NULL, L"", -1, &rect, 0, 0xff00ff); 755 ok(height == 0, "Got unexpected height %d.\n", height); 756 757 height = ID3DXFont_DrawTextW(font, NULL, testW, -1, NULL, 0, 0xFF00FF); 758 ok(height == 12, "Got unexpected height %d.\n", height); 759 760 height = ID3DXFont_DrawTextW(font, NULL, testW, -1, NULL, DT_CALCRECT, 0xFF00FF); 761 ok(height == 12, "Got unexpected height %d.\n", height); 762 763 height = ID3DXFont_DrawTextW(font, NULL, NULL, -1, NULL, 0, 0xFF00FF); 764 ok(height == 0, "Got unexpected height %d.\n", height); 765 766 SetRect(&rect, 10, 10, 50, 50); 767 768 height = ID3DXFont_DrawTextW(font, NULL, long_textW, -1, &rect, DT_WORDBREAK, 0xff00ff); 769 ok(height == 60, "Got unexpected height %d.\n", height); 770 771 height = ID3DXFont_DrawTextW(font, NULL, long_textW, -1, &rect, DT_WORDBREAK | DT_NOCLIP, 0xff00ff); 772 ok(height == 96, "Got unexpected height %d.\n", height); 773 } 774 775 ID3DXFont_Release(font); 776 } 777 778 static void test_D3DXCreateRenderToSurface(IDirect3DDevice9 *device) 779 { 780 int i; 781 HRESULT hr; 782 ULONG ref_count; 783 D3DXRTS_DESC desc; 784 ID3DXRenderToSurface *render = (void *)0xdeadbeef; 785 static const D3DXRTS_DESC tests[] = 786 { 787 { 0, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, 788 { 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, 789 { 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_D24S8 }, 790 { 256, 256, D3DFMT_UNKNOWN, FALSE, D3DFMT_R8G8B8 }, 791 { 0, 0, D3DFMT_UNKNOWN, FALSE, D3DFMT_UNKNOWN }, 792 { -1, -1, MAKEFOURCC('B','A','D','F'), TRUE, MAKEFOURCC('B','A','D','F') } 793 }; 794 795 hr = D3DXCreateRenderToSurface(NULL /* device */, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render); 796 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 797 ok(render == (void *)0xdeadbeef, "Got %p, expected %p\n", render, (void *)0xdeadbeef); 798 799 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, NULL /* out */); 800 ok(hr == D3DERR_INVALIDCALL, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 801 802 for (i = 0; i < ARRAY_SIZE(tests); i++) 803 { 804 hr = D3DXCreateRenderToSurface(device, tests[i].Width, tests[i].Height, tests[i].Format, tests[i].DepthStencil, 805 tests[i].DepthStencilFormat, &render); 806 ok(hr == D3D_OK, "%d: D3DXCreateRenderToSurface returned %#x, expected %#x\n", i, hr, D3D_OK); 807 if (SUCCEEDED(hr)) 808 { 809 hr = ID3DXRenderToSurface_GetDesc(render, &desc); 810 ok(hr == D3D_OK, "%d: GetDesc failed %#x\n", i, hr); 811 if (SUCCEEDED(hr)) 812 { 813 ok(desc.Width == tests[i].Width, "%d: Got width %u, expected %u\n", i, desc.Width, tests[i].Width); 814 ok(desc.Height == tests[i].Height, "%d: Got height %u, expected %u\n", i, desc.Height, tests[i].Height); 815 ok(desc.Format == tests[i].Format, "%d: Got format %#x, expected %#x\n", i, desc.Format, tests[i].Format); 816 ok(desc.DepthStencil == tests[i].DepthStencil, "%d: Got depth stencil %d, expected %d\n", 817 i, desc.DepthStencil, tests[i].DepthStencil); 818 ok(desc.DepthStencilFormat == tests[i].DepthStencilFormat, "%d: Got depth stencil format %#x, expected %#x\n", 819 i, desc.DepthStencilFormat, tests[i].DepthStencilFormat); 820 } 821 ID3DXRenderToSurface_Release(render); 822 } 823 } 824 825 /* check device ref count */ 826 ref_count = get_ref((IUnknown *)device); 827 hr = D3DXCreateRenderToSurface(device, 0, 0, D3DFMT_UNKNOWN, FALSE, D3DFMT_UNKNOWN, &render); 828 check_ref((IUnknown *)device, ref_count + 1); 829 if (SUCCEEDED(hr)) ID3DXRenderToSurface_Release(render); 830 } 831 832 /* runs a set of tests for the ID3DXRenderToSurface interface created with given parameters */ 833 static void check_ID3DXRenderToSurface(IDirect3DDevice9 *device, UINT width, UINT height, D3DFORMAT format, 834 BOOL depth_stencil, D3DFORMAT depth_stencil_format, BOOL render_target) 835 { 836 HRESULT hr; 837 D3DFORMAT fmt; 838 HRESULT expected_value; 839 IDirect3DSurface9 *surface; 840 ID3DXRenderToSurface *render; 841 D3DVIEWPORT9 viewport = { 0, 0, width, height, 0.0, 1.0 }; 842 843 hr = D3DXCreateRenderToSurface(device, width, height, format, depth_stencil, depth_stencil_format, &render); 844 if (FAILED(hr)) 845 { 846 skip("Failed to create ID3DXRenderToSurface\n"); 847 return; 848 } 849 850 if (render_target) 851 hr = IDirect3DDevice9_CreateRenderTarget(device, width, height, format, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL); 852 else 853 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, format, D3DPOOL_DEFAULT, &surface, NULL); 854 if (FAILED(hr)) 855 { 856 skip("Failed to create surface\n"); 857 ID3DXRenderToSurface_Release(render); 858 return; 859 } 860 861 /* viewport */ 862 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 863 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); 864 check_ref((IUnknown *)surface, 2); 865 if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 866 867 /* invalid viewport */ 868 viewport.Width = 2 * width; 869 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 870 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 871 872 viewport.X = width / 2; 873 viewport.Width = width; 874 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 875 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 876 877 viewport.X = width; 878 viewport.Width = width; 879 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 880 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 881 882 /* rendering to a part of a surface is only allowed for render target surfaces */ 883 expected_value = render_target ? D3D_OK : D3DERR_INVALIDCALL; 884 885 viewport.X = 0; 886 viewport.Width = width / 2; 887 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 888 ok(hr == expected_value, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, expected_value); 889 if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 890 891 viewport.X = width / 2; 892 viewport.Width = width - width / 2; 893 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 894 ok(hr == expected_value, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, expected_value); 895 if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 896 897 check_release((IUnknown *)surface, 0); 898 899 /* surfaces with different sizes */ 900 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width / 2, width / 2, format, D3DPOOL_DEFAULT, &surface, NULL); 901 if (FAILED(hr)) 902 { 903 skip("Failed to create surface\n"); 904 ID3DXRenderToSurface_Release(render); 905 return; 906 } 907 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 908 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 909 check_release((IUnknown *)surface, 0); 910 911 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2 * width, 2 * height, format, D3DPOOL_DEFAULT, &surface, NULL); 912 if (FAILED(hr)) 913 { 914 skip("Failed to create surface\n"); 915 ID3DXRenderToSurface_Release(render); 916 return; 917 } 918 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 919 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 920 viewport.X = 0; 921 viewport.Y = 0; 922 viewport.Width = width; 923 viewport.Height = height; 924 hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); 925 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 926 check_release((IUnknown *)surface, 0); 927 928 /* surfaces with different formats */ 929 for (fmt = D3DFMT_A8R8G8B8; fmt <= D3DFMT_X8R8G8B8; fmt++) 930 { 931 HRESULT expected_result = (fmt != format) ? D3DERR_INVALIDCALL : D3D_OK; 932 933 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, fmt, D3DPOOL_DEFAULT, &surface, NULL); 934 if (FAILED(hr)) 935 { 936 skip("Failed to create surface\n"); 937 continue; 938 } 939 940 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 941 ok(hr == expected_result, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, expected_result); 942 943 if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 944 check_release((IUnknown *)surface, 0); 945 } 946 947 check_release((IUnknown *)render, 0); 948 } 949 950 struct device_state 951 { 952 IDirect3DSurface9 *render_target; 953 IDirect3DSurface9 *depth_stencil; 954 D3DVIEWPORT9 viewport; 955 }; 956 957 static void release_device_state(struct device_state *state) 958 { 959 if (state->render_target) IDirect3DSurface9_Release(state->render_target); 960 if (state->depth_stencil) IDirect3DSurface9_Release(state->depth_stencil); 961 memset(state, 0, sizeof(*state)); 962 } 963 964 static HRESULT retrieve_device_state(IDirect3DDevice9 *device, struct device_state *state) 965 { 966 HRESULT hr; 967 968 memset(state, 0, sizeof(*state)); 969 970 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &state->render_target); 971 if (FAILED(hr)) goto cleanup; 972 973 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &state->depth_stencil); 974 if (hr == D3DERR_NOTFOUND) 975 state->depth_stencil = NULL; 976 else if (FAILED(hr)) 977 goto cleanup; 978 979 hr = IDirect3DDevice9_GetViewport(device, &state->viewport); 980 if (SUCCEEDED(hr)) return hr; 981 982 cleanup: 983 release_device_state(state); 984 return hr; 985 } 986 987 static HRESULT apply_device_state(IDirect3DDevice9 *device, struct device_state *state) 988 { 989 HRESULT hr; 990 HRESULT status = D3D_OK; 991 992 hr = IDirect3DDevice9_SetRenderTarget(device, 0, state->render_target); 993 if (FAILED(hr)) status = hr; 994 995 hr = IDirect3DDevice9_SetDepthStencilSurface(device, state->depth_stencil); 996 if (FAILED(hr)) status = hr; 997 998 hr = IDirect3DDevice9_SetViewport(device, &state->viewport); 999 if (FAILED(hr)) status = hr; 1000 1001 return status; 1002 } 1003 1004 static void compare_device_state(struct device_state *state1, struct device_state *state2, BOOL equal) 1005 { 1006 BOOL cmp; 1007 const char *message = equal ? "differs" : "is the same"; 1008 1009 cmp = state1->render_target == state2->render_target; 1010 ok(equal ? cmp : !cmp, "Render target %s %p, %p\n", message, state1->render_target, state2->render_target); 1011 1012 cmp = state1->depth_stencil == state2->depth_stencil; 1013 ok(equal ? cmp : !cmp, "Depth stencil surface %s %p, %p\n", message, state1->depth_stencil, state2->depth_stencil); 1014 1015 cmp = state1->viewport.X == state2->viewport.X && state1->viewport.Y == state2->viewport.Y 1016 && state1->viewport.Width == state2->viewport.Width && state1->viewport.Height == state2->viewport.Height; 1017 ok(equal ? cmp : !cmp, "Viewport %s (%u, %u, %u, %u), (%u, %u, %u, %u)\n", message, 1018 state1->viewport.X, state1->viewport.Y, state1->viewport.Width, state1->viewport.Height, 1019 state2->viewport.X, state2->viewport.Y, state2->viewport.Width, state2->viewport.Height); 1020 } 1021 1022 static void test_ID3DXRenderToSurface_device_state(IDirect3DDevice9 *device) 1023 { 1024 HRESULT hr; 1025 IDirect3DSurface9 *surface = NULL; 1026 ID3DXRenderToSurface *render = NULL; 1027 struct device_state pre_state; 1028 struct device_state current_state; 1029 IDirect3DSurface9 *depth_stencil_surface; 1030 1031 /* make sure there is a depth stencil surface present */ 1032 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &depth_stencil_surface); 1033 if (SUCCEEDED(hr)) 1034 { 1035 IDirect3DSurface9_Release(depth_stencil_surface); 1036 depth_stencil_surface = NULL; 1037 } 1038 else if (hr == D3DERR_NOTFOUND) 1039 { 1040 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 256, 256, D3DFMT_D24X8, 1041 D3DMULTISAMPLE_NONE, 0, TRUE, &depth_stencil_surface, NULL); 1042 if (SUCCEEDED(hr)) IDirect3DDevice9_SetDepthStencilSurface(device, depth_stencil_surface); 1043 } 1044 1045 if (FAILED(hr)) 1046 { 1047 skip("Failed to create depth stencil surface\n"); 1048 return; 1049 } 1050 1051 hr = IDirect3DDevice9_CreateRenderTarget(device, 256, 256, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, 1052 FALSE, &surface, NULL); 1053 if (FAILED(hr)) 1054 { 1055 skip("Failed to create render target\n"); 1056 goto cleanup; 1057 } 1058 1059 hr = retrieve_device_state(device, &pre_state); 1060 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1061 1062 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24X8, &render); 1063 ok(hr == D3D_OK, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3D_OK); 1064 if (SUCCEEDED(hr)) 1065 { 1066 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 1067 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); 1068 1069 hr = retrieve_device_state(device, ¤t_state); 1070 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1071 compare_device_state(¤t_state, &pre_state, FALSE); 1072 release_device_state(¤t_state); 1073 1074 hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 1075 ok(hr == D3D_OK, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3D_OK); 1076 1077 hr = retrieve_device_state(device, ¤t_state); 1078 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1079 compare_device_state(¤t_state, &pre_state, TRUE); 1080 release_device_state(¤t_state); 1081 1082 check_release((IUnknown *)render, 0); 1083 } 1084 1085 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render); 1086 if (SUCCEEDED(hr)) 1087 { 1088 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 1089 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); 1090 1091 hr = retrieve_device_state(device, ¤t_state); 1092 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1093 compare_device_state(¤t_state, &pre_state, FALSE); 1094 release_device_state(¤t_state); 1095 1096 hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 1097 ok(hr == D3D_OK, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3D_OK); 1098 1099 hr = retrieve_device_state(device, ¤t_state); 1100 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1101 compare_device_state(¤t_state, &pre_state, TRUE); 1102 release_device_state(¤t_state); 1103 1104 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 1105 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); 1106 1107 hr = retrieve_device_state(device, ¤t_state); 1108 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1109 compare_device_state(¤t_state, &pre_state, FALSE); 1110 release_device_state(¤t_state); 1111 1112 check_release((IUnknown *)render, 0); 1113 1114 /* if EndScene isn't called, the device state isn't restored */ 1115 hr = retrieve_device_state(device, ¤t_state); 1116 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1117 compare_device_state(¤t_state, &pre_state, FALSE); 1118 release_device_state(¤t_state); 1119 1120 hr = apply_device_state(device, &pre_state); 1121 ok(SUCCEEDED(hr), "Failed to restore previous device state\n"); 1122 1123 IDirect3DDevice9_EndScene(device); 1124 } 1125 1126 release_device_state(&pre_state); 1127 1128 cleanup: 1129 if (depth_stencil_surface) 1130 { 1131 IDirect3DDevice9_SetDepthStencilSurface(device, NULL); 1132 IDirect3DSurface9_Release(depth_stencil_surface); 1133 } 1134 1135 if (surface) check_release((IUnknown *)surface, 0); 1136 } 1137 1138 static void test_ID3DXRenderToSurface(IDirect3DDevice9 *device) 1139 { 1140 int i; 1141 HRESULT hr; 1142 ULONG ref_count; 1143 IDirect3DDevice9 *out_device; 1144 ID3DXRenderToSurface *render; 1145 IDirect3DSurface9 *surface; 1146 D3DVIEWPORT9 viewport = { 0, 0, 256, 256, 0.0, 1.0 }; 1147 D3DXRTS_DESC tests[] = { 1148 { 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, 1149 { 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24S8 }, 1150 { 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24X8 }, 1151 { 512, 512, D3DFMT_X8R8G8B8, FALSE, D3DFMT_X8R8G8B8 }, 1152 { 1024, 1024, D3DFMT_X8R8G8B8, TRUE, D3DFMT_D24S8 } 1153 }; 1154 1155 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render); 1156 ok(hr == D3D_OK, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3D_OK); 1157 if (FAILED(hr)) return; 1158 1159 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 256, 256, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, NULL); 1160 if (SUCCEEDED(hr)) 1161 { 1162 ID3DXRenderToSurface *render_surface; 1163 1164 /* GetDevice */ 1165 hr = ID3DXRenderToSurface_GetDevice(render, NULL /* device */); 1166 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1167 1168 ref_count = get_ref((IUnknown *)device); 1169 hr = ID3DXRenderToSurface_GetDevice(render, &out_device); 1170 ok(hr == D3D_OK, "ID3DXRenderToSurface::GetDevice returned %#x, expected %#x\n", hr, D3D_OK); 1171 check_release((IUnknown *)out_device, ref_count); 1172 1173 /* BeginScene and EndScene */ 1174 hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 1175 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1176 1177 hr = ID3DXRenderToSurface_BeginScene(render, NULL /* surface */, &viewport); 1178 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1179 1180 ref_count = get_ref((IUnknown *)surface); 1181 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 1182 ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); 1183 if (SUCCEEDED(hr)) 1184 { 1185 check_ref((IUnknown *)surface, ref_count + 1); 1186 1187 hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); 1188 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1189 1190 hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); 1191 ok(hr == D3D_OK, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3D_OK); 1192 1193 check_ref((IUnknown *)surface, ref_count); 1194 } 1195 1196 /* error handling is deferred to BeginScene */ 1197 hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_UNKNOWN, &render_surface); 1198 ok(hr == D3D_OK, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3D_OK); 1199 hr = ID3DXRenderToSurface_BeginScene(render_surface, surface, NULL); 1200 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1201 check_release((IUnknown *)render_surface, 0); 1202 1203 check_release((IUnknown *)surface, 0); 1204 } 1205 else skip("Failed to create surface\n"); 1206 1207 check_release((IUnknown *)render, 0); 1208 1209 for (i = 0; i < ARRAY_SIZE(tests); i++) 1210 { 1211 check_ID3DXRenderToSurface(device, tests[i].Width, tests[i].Height, tests[i].Format, tests[i].DepthStencil, tests[i].DepthStencilFormat, TRUE); 1212 check_ID3DXRenderToSurface(device, tests[i].Width, tests[i].Height, tests[i].Format, tests[i].DepthStencil, tests[i].DepthStencilFormat, FALSE); 1213 } 1214 1215 test_ID3DXRenderToSurface_device_state(device); 1216 } 1217 1218 static void test_D3DXCreateRenderToEnvMap(IDirect3DDevice9 *device) 1219 { 1220 int i; 1221 HRESULT hr; 1222 ULONG ref_count; 1223 D3DXRTE_DESC desc; 1224 ID3DXRenderToEnvMap *render; 1225 static const struct { 1226 D3DXRTE_DESC parameters; 1227 D3DXRTE_DESC expected_values; 1228 } tests[] = { 1229 { { 0, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, { 1, 1, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN } }, 1230 { { 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, { 256, 9, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN } }, 1231 { { 256, 4, D3DFMT_A8R8G8B8, FALSE, D3DFMT_D24S8 }, { 256, 4, D3DFMT_A8R8G8B8, FALSE, D3DFMT_D24S8 } }, 1232 { { 256, 256, D3DFMT_UNKNOWN, FALSE, D3DFMT_R8G8B8 }, { 256, 9, D3DFMT_A8R8G8B8, FALSE, D3DFMT_R8G8B8 } }, 1233 { { -1, -1, D3DFMT_A8R8G8B8, TRUE, D3DFMT_DXT1 }, { 256, 9, D3DFMT_A8R8G8B8, TRUE, D3DFMT_DXT1 } }, 1234 { { 256, 1, D3DFMT_X8R8G8B8, TRUE, D3DFMT_UNKNOWN }, { 256, 1, D3DFMT_X8R8G8B8, TRUE, D3DFMT_UNKNOWN } } 1235 }; 1236 1237 for (i = 0; i < ARRAY_SIZE(tests); i++) 1238 { 1239 const D3DXRTE_DESC *parameters = &tests[i].parameters; 1240 const D3DXRTE_DESC *expected = &tests[i].expected_values; 1241 hr = D3DXCreateRenderToEnvMap(device, parameters->Size, parameters->MipLevels, parameters->Format, 1242 parameters->DepthStencil, parameters->DepthStencilFormat, &render); 1243 ok(hr == D3D_OK, "%d: D3DXCreateRenderToEnvMap returned %#x, expected %#x\n", i, hr, D3D_OK); 1244 if (SUCCEEDED(hr)) 1245 { 1246 hr = ID3DXRenderToEnvMap_GetDesc(render, &desc); 1247 ok(hr == D3D_OK, "%d: GetDesc failed %#x\n", i, hr); 1248 if (SUCCEEDED(hr)) 1249 { 1250 ok(desc.Size == expected->Size, "%d: Got size %u, expected %u\n", i, desc.Size, expected->Size); 1251 ok(desc.MipLevels == expected->MipLevels, "%d: Got miplevels %u, expected %u\n", i, desc.MipLevels, expected->MipLevels); 1252 ok(desc.Format == expected->Format, "%d: Got format %#x, expected %#x\n", i, desc.Format, expected->Format); 1253 ok(desc.DepthStencil == expected->DepthStencil, "%d: Got depth stencil %d, expected %d\n", 1254 i, expected->DepthStencil, expected->DepthStencil); 1255 ok(desc.DepthStencilFormat == expected->DepthStencilFormat, "%d: Got depth stencil format %#x, expected %#x\n", 1256 i, expected->DepthStencilFormat, expected->DepthStencilFormat); 1257 } 1258 check_release((IUnknown *)render, 0); 1259 } 1260 } 1261 1262 /* check device ref count */ 1263 ref_count = get_ref((IUnknown *)device); 1264 hr = D3DXCreateRenderToEnvMap(device, 0, 0, D3DFMT_UNKNOWN, FALSE, D3DFMT_UNKNOWN, &render); 1265 check_ref((IUnknown *)device, ref_count + 1); 1266 if (SUCCEEDED(hr)) ID3DXRenderToEnvMap_Release(render); 1267 } 1268 1269 static void test_ID3DXRenderToEnvMap_cube_map(IDirect3DDevice9 *device) 1270 { 1271 HRESULT hr; 1272 IDirect3DCubeTexture9 *cube_texture = NULL; 1273 ID3DXRenderToEnvMap *render = NULL; 1274 struct device_state pre_state; 1275 struct device_state current_state; 1276 1277 hr = IDirect3DDevice9_CreateCubeTexture(device, 256, 0, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, 1278 &cube_texture, NULL); 1279 if (FAILED(hr)) 1280 { 1281 skip("Failed to create cube texture\n"); 1282 return; 1283 } 1284 1285 hr = retrieve_device_state(device, &pre_state); 1286 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1287 1288 hr = D3DXCreateRenderToEnvMap(device, 256, 0, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24X8, &render); 1289 ok(hr == D3D_OK, "D3DCreateRenderToEnvMap returned %#x, expected %#x\n", hr, D3D_OK); 1290 if (SUCCEEDED(hr)) 1291 { 1292 DWORD face; 1293 1294 hr = ID3DXRenderToEnvMap_End(render, D3DX_FILTER_NONE); 1295 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::End returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1296 1297 hr = ID3DXRenderToEnvMap_BeginCube(render, cube_texture); 1298 ok(hr == D3D_OK, "ID3DXRenderToEnvMap::BeginCube returned %#x, expected %#x\n", hr, D3D_OK); 1299 1300 hr = retrieve_device_state(device, ¤t_state); 1301 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1302 compare_device_state(¤t_state, &pre_state, TRUE); 1303 release_device_state(¤t_state); 1304 1305 for (face = D3DCUBEMAP_FACE_POSITIVE_X; face <= D3DCUBEMAP_FACE_NEGATIVE_Z; face++) 1306 { 1307 hr = ID3DXRenderToEnvMap_Face(render, face, D3DX_FILTER_POINT); 1308 ok(hr == D3D_OK, "ID3DXRenderToEnvMap::Face returned %#x, expected %#x\n", hr, D3D_OK); 1309 1310 hr = retrieve_device_state(device, ¤t_state); 1311 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1312 compare_device_state(¤t_state, &pre_state, FALSE); 1313 release_device_state(¤t_state); 1314 } 1315 1316 hr = ID3DXRenderToEnvMap_End(render, D3DX_FILTER_POINT); 1317 ok(hr == D3D_OK, "ID3DXRenderToEnvMap::End returned %#x, expected %#x\n", hr, D3D_OK); 1318 1319 hr = retrieve_device_state(device, ¤t_state); 1320 ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); 1321 compare_device_state(¤t_state, &pre_state, TRUE); 1322 release_device_state(¤t_state); 1323 1324 check_release((IUnknown *)render, 0); 1325 } 1326 1327 release_device_state(&pre_state); 1328 1329 check_release((IUnknown *)cube_texture, 0); 1330 } 1331 1332 static void test_ID3DXRenderToEnvMap(IDirect3DDevice9 *device) 1333 { 1334 HRESULT hr; 1335 ID3DXRenderToEnvMap *render; 1336 IDirect3DSurface9 *depth_stencil_surface; 1337 1338 hr = D3DXCreateRenderToEnvMap(device, 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render); 1339 if (SUCCEEDED(hr)) 1340 { 1341 ULONG ref_count; 1342 IDirect3DDevice9 *out_device; 1343 1344 hr = ID3DXRenderToEnvMap_GetDesc(render, NULL); 1345 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::GetDesc returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1346 1347 hr = ID3DXRenderToEnvMap_GetDevice(render, NULL); 1348 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1349 1350 ref_count = get_ref((IUnknown *)device); 1351 hr = ID3DXRenderToEnvMap_GetDevice(render, &out_device); 1352 ok(hr == D3D_OK, "ID3DXRenderToEnvMap::GetDevice returned %#x, expected %#x\n", hr, D3D_OK); 1353 ok(out_device == device, "ID3DXRenderToEnvMap::GetDevice returned different device\n"); 1354 check_release((IUnknown *)device, ref_count); 1355 1356 hr = ID3DXRenderToEnvMap_End(render, D3DX_FILTER_NONE); 1357 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::End returned %#x, expected %#x\n", hr, D3D_OK); 1358 1359 hr = ID3DXRenderToEnvMap_BeginCube(render, NULL); 1360 ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginCube returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1361 1362 hr = ID3DXRenderToEnvMap_BeginHemisphere(render, NULL, NULL); 1363 todo_wine ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginHemisphere returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1364 1365 hr = ID3DXRenderToEnvMap_BeginParabolic(render, NULL, NULL); 1366 todo_wine ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginParabolic returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1367 1368 hr = ID3DXRenderToEnvMap_BeginSphere(render, NULL); 1369 todo_wine ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginSphere returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); 1370 1371 check_release((IUnknown *)render, 0); 1372 } else skip("Failed to create ID3DXRenderToEnvMap\n"); 1373 1374 /* make sure there is a depth stencil surface present */ 1375 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &depth_stencil_surface); 1376 if (SUCCEEDED(hr)) 1377 { 1378 IDirect3DSurface9_Release(depth_stencil_surface); 1379 depth_stencil_surface = NULL; 1380 } 1381 else if (hr == D3DERR_NOTFOUND) 1382 { 1383 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 256, 256, D3DFMT_D24X8, 1384 D3DMULTISAMPLE_NONE, 0, TRUE, &depth_stencil_surface, NULL); 1385 if (SUCCEEDED(hr)) IDirect3DDevice9_SetDepthStencilSurface(device, depth_stencil_surface); 1386 } 1387 1388 if (FAILED(hr)) 1389 { 1390 skip("Failed to create depth stencil surface\n"); 1391 return; 1392 } 1393 1394 test_ID3DXRenderToEnvMap_cube_map(device); 1395 1396 if (depth_stencil_surface) 1397 { 1398 IDirect3DDevice9_SetDepthStencilSurface(device, NULL); 1399 IDirect3DSurface9_Release(depth_stencil_surface); 1400 } 1401 } 1402 1403 START_TEST(core) 1404 { 1405 HWND wnd; 1406 IDirect3D9 *d3d; 1407 IDirect3DDevice9 *device; 1408 D3DPRESENT_PARAMETERS d3dpp; 1409 HRESULT hr; 1410 1411 if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, 1412 640, 480, NULL, NULL, NULL, NULL))) 1413 { 1414 skip("Couldn't create application window\n"); 1415 return; 1416 } 1417 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION))) 1418 { 1419 skip("Couldn't create IDirect3D9 object\n"); 1420 DestroyWindow(wnd); 1421 return; 1422 } 1423 1424 ZeroMemory(&d3dpp, sizeof(d3dpp)); 1425 d3dpp.Windowed = TRUE; 1426 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 1427 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); 1428 if(FAILED(hr)) { 1429 skip("Failed to create IDirect3DDevice9 object %#x\n", hr); 1430 IDirect3D9_Release(d3d); 1431 DestroyWindow(wnd); 1432 return; 1433 } 1434 1435 test_ID3DXBuffer(); 1436 test_ID3DXSprite(device); 1437 test_ID3DXFont(device); 1438 test_D3DXCreateRenderToSurface(device); 1439 test_ID3DXRenderToSurface(device); 1440 test_D3DXCreateRenderToEnvMap(device); 1441 test_ID3DXRenderToEnvMap(device); 1442 1443 check_release((IUnknown*)device, 0); 1444 check_release((IUnknown*)d3d, 0); 1445 if (wnd) DestroyWindow(wnd); 1446 } 1447