1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS ReactX 4 * FILE: dll/directx/d3d9/d3d9_impl.c 5 * PURPOSE: IDirect3D9 implementation 6 * PROGRAMERS: Gregor Brunmar <gregor (dot) brunmar (at) home (dot) se> 7 */ 8 9 #include "d3d9_common.h" 10 #include <d3d9.h> 11 #include <debug.h> 12 #include "d3d9_helpers.h" 13 #include "adapter.h" 14 #include "device.h" 15 #include "format.h" 16 17 #define LOCK_D3D9() EnterCriticalSection(&This->d3d9_cs); 18 #define UNLOCK_D3D9() LeaveCriticalSection(&This->d3d9_cs); 19 20 /* Convert a IDirect3D9 pointer safely to the internal implementation struct */ 21 static LPDIRECT3D9_INT IDirect3D9ToImpl(LPDIRECT3D9 iface) 22 { 23 if (NULL == iface) 24 return NULL; 25 26 return (LPDIRECT3D9_INT)((ULONG_PTR)iface - FIELD_OFFSET(DIRECT3D9_INT, lpVtbl)); 27 } 28 29 /* IDirect3D9: IUnknown implementation */ 30 static HRESULT WINAPI IDirect3D9Impl_QueryInterface(LPDIRECT3D9 iface, REFIID riid, LPVOID* ppvObject) 31 { 32 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 33 34 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirect3D9)) 35 { 36 IUnknown_AddRef(iface); 37 *ppvObject = &This->lpVtbl; 38 return S_OK; 39 } 40 41 *ppvObject = NULL; 42 return E_NOINTERFACE; 43 } 44 45 static ULONG WINAPI IDirect3D9Impl_AddRef(LPDIRECT3D9 iface) 46 { 47 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 48 ULONG ref = InterlockedIncrement(&This->lRefCnt); 49 50 return ref; 51 } 52 53 static ULONG WINAPI IDirect3D9Impl_Release(LPDIRECT3D9 iface) 54 { 55 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 56 ULONG ref = InterlockedDecrement(&This->lRefCnt); 57 58 if (ref == 0) 59 { 60 EnterCriticalSection(&This->d3d9_cs); 61 /* TODO: Free resources here */ 62 LeaveCriticalSection(&This->d3d9_cs); 63 AlignedFree(This); 64 } 65 66 return ref; 67 } 68 69 /* IDirect3D9 interface */ 70 static HRESULT WINAPI IDirect3D9Impl_RegisterSoftwareDevice(LPDIRECT3D9 iface, void* pInitializeFunction) 71 { 72 UNIMPLEMENTED 73 74 return D3D_OK; 75 } 76 77 /*++ 78 * @name IDirect3D9::GetAdapterCount 79 * @implemented 80 * 81 * The function IDirect3D9Impl_GetAdapterCount returns the number of adapters 82 * 83 * @param LPDIRECT3D iface 84 * Pointer to the IDirect3D9 object returned from Direct3DCreate9() 85 * 86 * @return UINT 87 * The number of display adapters on the system when Direct3DCreate9() was called. 88 * 89 */ 90 static UINT WINAPI IDirect3D9Impl_GetAdapterCount(LPDIRECT3D9 iface) 91 { 92 UINT NumDisplayAdapters; 93 94 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 95 LOCK_D3D9(); 96 97 NumDisplayAdapters = This->NumDisplayAdapters; 98 99 UNLOCK_D3D9(); 100 return NumDisplayAdapters; 101 } 102 103 /*++ 104 * @name IDirect3D9::GetAdapterIdentifier 105 * @implemented 106 * 107 * The function IDirect3D9Impl_GetAdapterIdentifier gathers information about 108 * a specified display adapter and fills the pIdentifier argument with the available information. 109 * 110 * @param LPDIRECT3D iface 111 * Pointer to the IDirect3D9 object returned from Direct3DCreate9() 112 * 113 * @param UINT Adapter 114 * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. 115 * The maximum value for this is the value returned by IDirect3D::GetAdapterCount() - 1. 116 * 117 * @param DWORD Flags 118 * Ignored at the moment, but the only valid flag is D3DENUM_WHQL_LEVEL 119 * 120 * @param D3DADAPTER_IDENTIFIER9* pIdentifier 121 * Pointer to a D3DADAPTER_IDENTIFIER9 structure to be filled with the available information 122 * about the display adapter. 123 * 124 * @return HRESULT 125 * If the method successfully fills the pIdentified structure, the return value is D3D_OK. 126 * If Adapter is out of range, Flags is invalid or pIdentifier is a bad pointer, the return value 127 * will be D3DERR_INVALIDCALL. 128 * 129 */ 130 HRESULT WINAPI IDirect3D9Impl_GetAdapterIdentifier(LPDIRECT3D9 iface, UINT Adapter, DWORD Flags, 131 D3DADAPTER_IDENTIFIER9* pIdentifier) 132 { 133 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 134 LOCK_D3D9(); 135 136 if (Adapter >= This->NumDisplayAdapters) 137 { 138 DPRINT1("Invalid Adapter number specified"); 139 UNLOCK_D3D9(); 140 return D3DERR_INVALIDCALL; 141 } 142 143 if (Flags & ~D3DENUM_WHQL_LEVEL) 144 { 145 DPRINT1("Invalid Flags specified"); 146 UNLOCK_D3D9(); 147 return D3DERR_INVALIDCALL; 148 } 149 150 if (NULL == pIdentifier) 151 { 152 DPRINT1("Invalid pIdentifier parameter specified"); 153 UNLOCK_D3D9(); 154 return D3DERR_INVALIDCALL; 155 } 156 157 memset(pIdentifier, 0, sizeof(D3DADAPTER_IDENTIFIER9)); 158 159 if (FALSE == GetAdapterInfo(This->DisplayAdapters[Adapter].szDeviceName, pIdentifier)) 160 { 161 DPRINT1("Internal error: Couldn't get the adapter info for device (%d): %s", Adapter, This->DisplayAdapters[Adapter].szDeviceName); 162 UNLOCK_D3D9(); 163 return D3DERR_INVALIDCALL; 164 } 165 166 UNLOCK_D3D9(); 167 return D3D_OK; 168 } 169 170 /*++ 171 * @name IDirect3D9::GetAdapterModeCount 172 * @implemented 173 * 174 * The function IDirect3D9Impl_GetAdapterModeCount looks if the specified display adapter supports 175 * a specific pixel format and counts the available display modes for that format. 176 * 177 * @param LPDIRECT3D iface 178 * Pointer to the IDirect3D9 object returned from Direct3DCreate9() 179 * 180 * @param UINT Adapter 181 * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. 182 * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. 183 * 184 * @param D3DFORMAT Format 185 * The pixel format to search for 186 * 187 * @return HRESULT 188 * If the method is successful it returns the number of display modes with the specified Format. 189 * If Adapter is out of range, the return value will be 0. 190 * 191 */ 192 static UINT WINAPI IDirect3D9Impl_GetAdapterModeCount(LPDIRECT3D9 iface, UINT Adapter, D3DFORMAT Format) 193 { 194 UINT AdapterModeCount; 195 196 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 197 LOCK_D3D9(); 198 199 if (Adapter >= This->NumDisplayAdapters) 200 { 201 DPRINT1("Invalid Adapter number specified"); 202 UNLOCK_D3D9(); 203 return D3DERR_INVALIDCALL; 204 } 205 206 if (Format != D3DFMT_A2R10G10B10) 207 { 208 AdapterModeCount = GetDisplayFormatCount( 209 Format, 210 This->DisplayAdapters[Adapter].pSupportedD3DFormats, 211 This->DisplayAdapters[Adapter].NumSupportedD3DFormats); 212 } 213 else 214 { 215 AdapterModeCount = GetDisplayFormatCount( 216 Format, 217 This->DisplayAdapters[Adapter].pSupportedD3DExtendedFormats, 218 This->DisplayAdapters[Adapter].NumSupportedD3DExtendedFormats); 219 } 220 221 UNLOCK_D3D9(); 222 return AdapterModeCount; 223 } 224 225 /*++ 226 * @name IDirect3D9::EnumAdapterModes 227 * @implemented 228 * 229 * The function IDirect3D9Impl_EnumAdapterModes looks if the specified display adapter supports 230 * a specific pixel format and fills the pMode argument with the available display modes for that format. 231 * This function is often used in a loop to enumerate all the display modes the adapter supports. 232 * 233 * @param LPDIRECT3D iface 234 * Pointer to the IDirect3D9 object returned from Direct3DCreate9() 235 * 236 * @param UINT Adapter 237 * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. 238 * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. 239 * 240 * @param D3DFORMAT Format 241 * The pixel format to search for 242 * 243 * @param UINT Mode 244 * Index within the pixel format to be returned. 245 * The maximum value for this is the value returned by IDirect3D9::GetAdapterModeCount() - 1. 246 * 247 * @param D3DDISPLAYMODE* pMode 248 * Pointer to a D3DDISPLAYMODE structure to be filled with the display mode information 249 * for the specified format. 250 * 251 * @return HRESULT 252 * If the method successfully fills the pMode structure, the return value is D3D_OK. 253 * If Adapter is out of range, pMode is a bad pointer or, no modes for the specified 254 * format was found or the mode parameter was invalid - the return value will be D3DERR_INVALIDCALL. 255 * 256 */ 257 static HRESULT WINAPI IDirect3D9Impl_EnumAdapterModes(LPDIRECT3D9 iface, UINT Adapter, D3DFORMAT Format, 258 UINT Mode, D3DDISPLAYMODE* pMode) 259 { 260 const D3DDISPLAYMODE* pMatchingDisplayFormat; 261 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 262 LOCK_D3D9(); 263 264 if (Adapter >= This->NumDisplayAdapters) 265 { 266 DPRINT1("Invalid Adapter number specified"); 267 UNLOCK_D3D9(); 268 return D3DERR_INVALIDCALL; 269 } 270 271 if (NULL == pMode) 272 { 273 DPRINT1("Invalid pMode parameter specified"); 274 UNLOCK_D3D9(); 275 return D3DERR_INVALIDCALL; 276 } 277 278 if (Format != D3DFMT_A2R10G10B10) 279 { 280 pMatchingDisplayFormat = FindDisplayFormat( 281 Format, 282 Mode, 283 This->DisplayAdapters[Adapter].pSupportedD3DFormats, 284 This->DisplayAdapters[Adapter].NumSupportedD3DFormats); 285 } 286 else 287 { 288 pMatchingDisplayFormat = FindDisplayFormat( 289 Format, 290 Mode, 291 This->DisplayAdapters[Adapter].pSupportedD3DExtendedFormats, 292 This->DisplayAdapters[Adapter].NumSupportedD3DExtendedFormats); 293 } 294 295 if (pMatchingDisplayFormat != NULL) 296 { 297 *pMode = *pMatchingDisplayFormat; 298 } 299 UNLOCK_D3D9(); 300 301 302 if (pMatchingDisplayFormat == NULL) 303 return D3DERR_INVALIDCALL; 304 305 return D3D_OK; 306 } 307 308 /*++ 309 * @name IDirect3D9::GetAdapterDisplayMode 310 * @implemented 311 * 312 * The function IDirect3D9Impl_GetAdapterDisplayMode fills the pMode argument with the 313 * currently set display mode. 314 * 315 * @param LPDIRECT3D iface 316 * Pointer to the IDirect3D9 object returned from Direct3DCreate9() 317 * 318 * @param UINT Adapter 319 * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. 320 * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. 321 * 322 * @param D3DDISPLAYMODE* pMode 323 * Pointer to a D3DDISPLAYMODE structure to be filled with the current display mode information. 324 * 325 * @return HRESULT 326 * If the method successfully fills the pMode structure, the return value is D3D_OK. 327 * If Adapter is out of range or pMode is a bad pointer, the return value will be D3DERR_INVALIDCALL. 328 * 329 */ 330 static HRESULT WINAPI IDirect3D9Impl_GetAdapterDisplayMode(LPDIRECT3D9 iface, UINT Adapter, D3DDISPLAYMODE* pMode) 331 { 332 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 333 LOCK_D3D9(); 334 335 if (Adapter >= This->NumDisplayAdapters) 336 { 337 DPRINT1("Invalid Adapter number specified"); 338 UNLOCK_D3D9(); 339 return D3DERR_INVALIDCALL; 340 } 341 342 if (NULL == pMode) 343 { 344 DPRINT1("Invalid pMode parameter specified"); 345 UNLOCK_D3D9(); 346 return D3DERR_INVALIDCALL; 347 } 348 349 /* TODO: Handle (This->DisplayAdapters[Adapter].bInUseFlag == FALSE) */ 350 if (FALSE == GetAdapterMode(This->DisplayAdapters[Adapter].szDeviceName, pMode)) 351 DPRINT1("Internal error, GetAdapterMode() failed."); 352 353 UNLOCK_D3D9(); 354 return D3D_OK; 355 } 356 357 358 /*++ 359 * @name IDirect3D9::CheckDeviceType 360 * @implemented 361 * 362 * The function IDirect3D9Impl_CheckDeviceType checks if a specific D3DFORMAT is hardware accelerated 363 * on the specified display adapter. 364 * 365 * @param LPDIRECT3D iface 366 * Pointer to the IDirect3D9 object returned from Direct3DCreate9() 367 * 368 * @param UINT Adapter 369 * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. 370 * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. 371 * 372 * @param D3DDEVTYPE DeviceType 373 * One of the D3DDEVTYPE enum members. 374 * 375 * @param D3DFORMAT DisplayFormat 376 * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode to be checked. 377 * 378 * @param D3DFORMAT BackBufferFormat 379 * One of the D3DFORMAT enum members for the render target mode to be checked. D3DFMT_UNKNOWN is only allowed in windowed mode. 380 * 381 * @param BOOL Windowed 382 * If this value is TRUE, the D3DFORMAT check will be done for windowed mode and FALSE equals fullscreen mode. 383 * 384 * @return HRESULT 385 * If the format is hardware accelerated, the method returns D3D_OK. 386 * If the format isn't hardware accelerated or unsupported - the return value will be D3DERR_NOTAVAILABLE. 387 * If Adapter is out of range, DeviceType is invalid, 388 * DisplayFormat or BackBufferFormat is invalid - the return value will be D3DERR_INVALIDCALL. 389 * 390 */ 391 static HRESULT WINAPI IDirect3D9Impl_CheckDeviceType(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, 392 D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL Windowed) 393 { 394 HRESULT hResult; 395 396 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 397 LOCK_D3D9(); 398 399 if (Adapter >= This->NumDisplayAdapters) 400 { 401 DPRINT1("Invalid Adapter number specified"); 402 UNLOCK_D3D9(); 403 return D3DERR_INVALIDCALL; 404 } 405 406 if (DeviceType != D3DDEVTYPE_HAL && 407 DeviceType != D3DDEVTYPE_REF && 408 DeviceType != D3DDEVTYPE_SW) 409 { 410 DPRINT1("Invalid DeviceType specified"); 411 UNLOCK_D3D9(); 412 return D3DERR_INVALIDCALL; 413 } 414 415 if ((BackBufferFormat == D3DFMT_UNKNOWN) && 416 (Windowed != FALSE)) 417 { 418 BackBufferFormat = DisplayFormat; 419 } 420 421 if (DisplayFormat == D3DFMT_UNKNOWN && BackBufferFormat == D3DFMT_UNKNOWN) 422 { 423 DPRINT1("Invalid D3DFORMAT specified"); 424 UNLOCK_D3D9(); 425 return D3DERR_INVALIDCALL; 426 } 427 428 if (FALSE == IsBackBufferFormat(BackBufferFormat)) 429 { 430 DPRINT1("Invalid D3DFORMAT specified"); 431 UNLOCK_D3D9(); 432 return D3DERR_NOTAVAILABLE; 433 } 434 435 if (TRUE == Windowed && TRUE == IsExtendedFormat(DisplayFormat)) 436 { 437 DPRINT1("Extended display modes can only be used in fullscreen mode"); 438 UNLOCK_D3D9(); 439 return D3DERR_NOTAVAILABLE; 440 } 441 442 hResult = CheckDeviceType(&This->DisplayAdapters[Adapter].DriverCaps, DisplayFormat, BackBufferFormat, Windowed); 443 444 UNLOCK_D3D9(); 445 return hResult; 446 } 447 448 449 /*++ 450 * @name IDirect3D9::CheckDeviceFormat 451 * @implemented 452 * 453 * The function IDirect3D9Impl_CheckDeviceFormat checks if a specific D3DFORMAT 454 * can be used for a specific purpose like texture, depth/stencil buffer or as a render target 455 * on the specified display adapter. 456 * 457 * @param LPDIRECT3D iface 458 * Pointer to the IDirect3D9 object returned from Direct3DCreate9() 459 * 460 * @param UINT Adapter 461 * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. 462 * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. 463 * 464 * @param D3DDEVTYPE DeviceType 465 * One of the D3DDEVTYPE enum members. 466 * 467 * @param D3DFORMAT AdapterFormat 468 * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode to be checked. 469 * 470 * @param DWORD Usage 471 * Valid values are any of the D3DUSAGE_QUERY constants or any of these D3DUSAGE constants: 472 * D3DUSAGE_AUTOGENMIPMAP, D3DUSAGE_DEPTHSTENCIL, D3DUSAGE_DMAP, D3DUSAGE_DYNAMIC, 473 * D3DUSAGE_NONSECURE, D3DUSAGE_RENDERTARGET and D3DUSAGE_SOFTWAREPROCESSING. 474 * 475 * @param D3DRESOURCETYPE RType 476 * One of the D3DRESOURCETYPE enum members. Specifies what format will be used for. 477 * 478 * @param D3DFORMAT CheckFormat 479 * One of the D3DFORMAT enum members for the surface format to be checked. 480 * 481 * @return HRESULT 482 * If the format is compatible with the specified usage and resource type, the method returns D3D_OK. 483 * If the format isn't compatible with the specified usage and resource type - the return value will be D3DERR_NOTAVAILABLE. 484 * If Adapter is out of range, DeviceType is invalid, AdapterFormat or CheckFormat is invalid, 485 * Usage and RType isn't compatible - the return value will be D3DERR_INVALIDCALL. 486 * 487 */ 488 static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormat(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, 489 D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, 490 D3DFORMAT CheckFormat) 491 { 492 LPD3D9_DRIVERCAPS pDriverCaps; 493 BOOL bIsTextureRType = FALSE; 494 HRESULT hResult; 495 496 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 497 LOCK_D3D9(); 498 499 if (Adapter >= This->NumDisplayAdapters) 500 { 501 DPRINT1("Invalid Adapter number specified"); 502 UNLOCK_D3D9(); 503 return D3DERR_INVALIDCALL; 504 } 505 506 if (DeviceType != D3DDEVTYPE_HAL && 507 DeviceType != D3DDEVTYPE_REF && 508 DeviceType != D3DDEVTYPE_SW) 509 { 510 DPRINT1("Invalid DeviceType specified"); 511 UNLOCK_D3D9(); 512 return D3DERR_INVALIDCALL; 513 } 514 515 if (AdapterFormat == D3DFMT_UNKNOWN || 516 CheckFormat == D3DFMT_UNKNOWN) 517 { 518 DPRINT1("Invalid D3DFORMAT specified"); 519 UNLOCK_D3D9(); 520 return D3DERR_INVALIDCALL; 521 } 522 523 if ((Usage & (D3DUSAGE_DONOTCLIP | D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_TEXTAPI | D3DUSAGE_WRITEONLY)) != 0) 524 { 525 DPRINT1("Invalid Usage specified"); 526 UNLOCK_D3D9(); 527 return D3DERR_INVALIDCALL; 528 } 529 530 if (RType == D3DRTYPE_TEXTURE || 531 RType == D3DRTYPE_VOLUMETEXTURE || 532 RType == D3DRTYPE_CUBETEXTURE) 533 { 534 bIsTextureRType = TRUE; 535 } 536 else if (RType == D3DRTYPE_SURFACE && 537 (Usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)) == 0 && 538 Usage != 0) 539 { 540 DPRINT1("When RType is set to D3DRTYPE_SURFACE, Usage must be 0 or have set D3DUSAGE_DEPTHSTENCIL or D3DUSAGE_RENDERTARGET"); 541 UNLOCK_D3D9(); 542 return D3DERR_INVALIDCALL; 543 } 544 545 if ((Usage & D3DUSAGE_DEPTHSTENCIL) != 0) 546 { 547 if (FALSE == IsZBufferFormat(CheckFormat)) 548 { 549 DPRINT1("Invalid CheckFormat Z-Buffer format"); 550 UNLOCK_D3D9(); 551 return D3DERR_INVALIDCALL; 552 } 553 554 if ((Usage & D3DUSAGE_AUTOGENMIPMAP) != 0) 555 { 556 DPRINT1("Invalid Usage specified, D3DUSAGE_DEPTHSTENCIL and D3DUSAGE_AUTOGENMIPMAP can't be combined."); 557 UNLOCK_D3D9(); 558 return D3DERR_INVALIDCALL; 559 } 560 } 561 562 if (FALSE == bIsTextureRType && 563 RType != D3DRTYPE_SURFACE && 564 RType != D3DRTYPE_VOLUME) 565 { 566 DPRINT1("Invalid RType specified"); 567 UNLOCK_D3D9(); 568 return D3DERR_INVALIDCALL; 569 } 570 571 if ((Usage & (D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)) != 0) 572 { 573 if (RType == D3DRTYPE_VOLUME || RType == D3DRTYPE_VOLUMETEXTURE) 574 { 575 DPRINT1("Invalid Usage specified, D3DUSAGE_AUTOGENMIPMAP, D3DUSAGE_DEPTHSTENCIL and D3DUSAGE_RENDERTARGET can't be combined with RType D3DRTYPE_VOLUME or D3DRTYPE_VOLUMETEXTURE"); 576 UNLOCK_D3D9(); 577 return D3DERR_INVALIDCALL; 578 } 579 } 580 581 if (FALSE == bIsTextureRType && 582 (Usage & D3DUSAGE_QUERY_VERTEXTEXTURE) != 0) 583 { 584 DPRINT1("Invalid Usage specified, D3DUSAGE_QUERY_VERTEXTEXTURE can only be used with a texture RType"); 585 UNLOCK_D3D9(); 586 return D3DERR_INVALIDCALL; 587 } 588 589 if ((Usage & D3DUSAGE_AUTOGENMIPMAP) != 0 && 590 TRUE == IsMultiElementFormat(CheckFormat)) 591 { 592 DPRINT1("Invalid Usage specified, D3DUSAGE_AUTOGENMIPMAP can't be used with a multi-element format"); 593 UNLOCK_D3D9(); 594 return D3DERR_INVALIDCALL; 595 } 596 597 pDriverCaps = &This->DisplayAdapters[Adapter].DriverCaps; 598 if (((Usage & D3DUSAGE_DYNAMIC) != 0) && (bIsTextureRType != FALSE)) 599 { 600 if ((pDriverCaps->DriverCaps9.Caps2 & D3DCAPS2_DYNAMICTEXTURES) == 0) 601 { 602 DPRINT1("Driver doesn't support dynamic textures"); 603 UNLOCK_D3D9(); 604 return D3DERR_NOTAVAILABLE; 605 } 606 607 if ((Usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)) != 0) 608 { 609 DPRINT1("Invalid Usage specified, D3DUSAGE_DEPTHSTENCIL and D3DUSAGE_RENDERTARGET can't be combined with D3DUSAGE_DYNAMIC and a texture RType"); 610 UNLOCK_D3D9(); 611 return D3DERR_INVALIDCALL; 612 } 613 } 614 615 if ((Usage & D3DUSAGE_DMAP) != 0) 616 { 617 if ((pDriverCaps->DriverCaps9.DevCaps2 & (D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH | D3DDEVCAPS2_DMAPNPATCH)) == 0) 618 { 619 DPRINT1("Driver doesn't support displacement mapping"); 620 UNLOCK_D3D9(); 621 return D3DERR_NOTAVAILABLE; 622 } 623 624 if (RType != D3DRTYPE_TEXTURE) 625 { 626 DPRINT1("Invalid Usage specified, D3DUSAGE_DMAP must be combined with RType D3DRTYPE_TEXTURE"); 627 UNLOCK_D3D9(); 628 return D3DERR_INVALIDCALL; 629 } 630 } 631 632 hResult = CheckDeviceFormat(pDriverCaps, AdapterFormat, Usage, RType, CheckFormat); 633 634 UNLOCK_D3D9(); 635 return hResult; 636 } 637 638 static HRESULT WINAPI IDirect3D9Impl_CheckDeviceMultiSampleType(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, 639 D3DFORMAT SurfaceFormat, BOOL Windowed, 640 D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) 641 { 642 UNIMPLEMENTED 643 644 return D3D_OK; 645 } 646 647 648 /*++ 649 * @name IDirect3D9::CheckDepthStencilMatch 650 * @implemented 651 * 652 * The function IDirect3D9Impl_CheckDepthStencilMatch checks if a specific combination 653 * of a render target D3DFORMAT and a depth-stencil D3DFORMAT can be used with a specified 654 * D3DFORMAT on the specified display adapter. 655 * 656 * @param LPDIRECT3D iface 657 * Pointer to the IDirect3D9 object returned from Direct3DCreate9() 658 * 659 * @param UINT Adapter 660 * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. 661 * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. 662 * 663 * @param D3DDEVTYPE DeviceType 664 * One of the D3DDEVTYPE enum members. 665 * 666 * @param D3DFORMAT AdapterFormat 667 * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN that the display adapter mode where the test should occur. 668 * 669 * @param D3DFORMAT RenderTargetFormat 670 * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode's render target format to be tested. 671 * 672 * @param D3DFORMAT DepthStencilFormat 673 * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode's depth-stencil format to be tested. 674 * 675 * @return HRESULT 676 * If the DepthStencilFormat can be used with the RenderTargetFormat under the specified AdapterFormat, 677 * the method returns D3D_OK. 678 * If the DepthStencilFormat can NOT used with the RenderTargetFormat under the specified AdapterFormat, 679 * the method returns D3DERR_NOTAVAILABLE. 680 * If Adapter is out of range, DeviceType is invalid, 681 * AdapterFormat, RenderTargetFormat or DepthStencilFormat is invalid, the method returns D3DERR_INVALIDCALL. 682 * 683 */ 684 static HRESULT WINAPI IDirect3D9Impl_CheckDepthStencilMatch(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, 685 D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, 686 D3DFORMAT DepthStencilFormat) 687 { 688 HRESULT hResult; 689 690 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 691 LOCK_D3D9(); 692 693 if (Adapter >= This->NumDisplayAdapters) 694 { 695 DPRINT1("Invalid Adapter number specified"); 696 UNLOCK_D3D9(); 697 return D3DERR_INVALIDCALL; 698 } 699 700 if (DeviceType != D3DDEVTYPE_HAL && 701 DeviceType != D3DDEVTYPE_REF && 702 DeviceType != D3DDEVTYPE_SW) 703 { 704 DPRINT1("Invalid DeviceType specified"); 705 UNLOCK_D3D9(); 706 return D3DERR_INVALIDCALL; 707 } 708 709 if (AdapterFormat == D3DFMT_UNKNOWN || 710 RenderTargetFormat == D3DFMT_UNKNOWN || 711 DepthStencilFormat == D3DFMT_UNKNOWN) 712 { 713 DPRINT1("Invalid D3DFORMAT specified"); 714 UNLOCK_D3D9(); 715 return D3DERR_INVALIDCALL; 716 } 717 718 hResult = CheckDepthStencilMatch(&This->DisplayAdapters[Adapter].DriverCaps, AdapterFormat, RenderTargetFormat, DepthStencilFormat); 719 720 UNLOCK_D3D9(); 721 return hResult; 722 } 723 724 725 /*++ 726 * @name IDirect3D9::CheckDeviceFormatConversion 727 * @implemented 728 * 729 * The function IDirect3D9Impl_CheckDeviceFormatConversion checks if a specific D3DFORMAT 730 * can be converted to another on the specified display adapter. 731 * 732 * @param LPDIRECT3D iface 733 * Pointer to the IDirect3D9 object returned from Direct3DCreate9() 734 * 735 * @param UINT Adapter 736 * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. 737 * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. 738 * 739 * @param D3DDEVTYPE DeviceType 740 * One of the D3DDEVTYPE enum members. Only D3DDEVTYPE_HAL can potentially return D3D_OK. 741 * 742 * @param D3DFORMAT SourceFormat 743 * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode to be converted from. 744 * 745 * @param D3DFORMAT TargetFormat 746 * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode to be converted to. 747 * 748 * @return HRESULT 749 * If the SourceFormat can be converted to the TargetFormat, the method returns D3D_OK. 750 * If the SourceFormat can NOT be converted to the TargetFormat, the method returns D3DERR_NOTAVAILABLE. 751 * If Adapter is out of range, DeviceType is invalid, 752 * SourceFormat or TargetFormat is invalid, the method returns D3DERR_INVALIDCALL. 753 * 754 */ 755 static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormatConversion(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, 756 D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) 757 { 758 HRESULT hResult; 759 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 760 LOCK_D3D9(); 761 762 if (Adapter >= This->NumDisplayAdapters) 763 { 764 DPRINT1("Invalid Adapter number specified"); 765 UNLOCK_D3D9(); 766 return D3DERR_INVALIDCALL; 767 } 768 769 if (DeviceType != D3DDEVTYPE_HAL && 770 DeviceType != D3DDEVTYPE_REF && 771 DeviceType != D3DDEVTYPE_SW) 772 { 773 DPRINT1("Invalid DeviceType specified"); 774 UNLOCK_D3D9(); 775 return D3DERR_INVALIDCALL; 776 } 777 778 if (SourceFormat == D3DFMT_UNKNOWN || 779 TargetFormat == D3DFMT_UNKNOWN) 780 { 781 DPRINT1("Invalid D3DFORMAT specified"); 782 UNLOCK_D3D9(); 783 return D3DERR_NOTAVAILABLE; 784 } 785 786 if (DeviceType == D3DDEVTYPE_HAL) 787 { 788 hResult = CheckDeviceFormatConversion(&This->DisplayAdapters[Adapter].DriverCaps, SourceFormat, TargetFormat); 789 } 790 else 791 { 792 hResult = D3DERR_NOTAVAILABLE; 793 } 794 795 UNLOCK_D3D9(); 796 return hResult; 797 } 798 799 800 /*++ 801 * @name IDirect3D9::GetDeviceCaps 802 * @implemented 803 * 804 * The function IDirect3D9Impl_GetDeviceCaps fills the pCaps argument with the 805 * capabilities of the specified adapter and device type. 806 * 807 * @param LPDIRECT3D iface 808 * Pointer to the IDirect3D9 object returned from Direct3DCreate9() 809 * 810 * @param UINT Adapter 811 * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. 812 * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. 813 * 814 * @param D3DDEVTYPE DeviceType 815 * One of the D3DDEVTYPE enum members. 816 * NOTE: Currently only D3DDEVTYPE_HAL is implemented. 817 * 818 * @param D3DCAPS9* pCaps 819 * Pointer to a D3DCAPS9 structure to be filled with the adapter's device type capabilities. 820 * 821 * @return HRESULT 822 * If the method successfully fills the pCaps structure, the return value is D3D_OK. 823 * If Adapter is out of range or pCaps is a bad pointer, the return value will be D3DERR_INVALIDCALL. 824 * If DeviceType is invalid, the return value will be D3DERR_INVALIDDEVICE. 825 * 826 */ 827 static HRESULT WINAPI IDirect3D9Impl_GetDeviceCaps(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) 828 { 829 HRESULT hResult; 830 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 831 LOCK_D3D9(); 832 833 if (Adapter >= This->NumDisplayAdapters) 834 { 835 DPRINT1("Invalid Adapter number specified"); 836 UNLOCK_D3D9(); 837 return D3DERR_INVALIDCALL; 838 } 839 840 if (NULL == pCaps) 841 { 842 DPRINT1("Invalid pCaps parameter specified"); 843 UNLOCK_D3D9(); 844 return D3DERR_INVALIDCALL; 845 } 846 847 hResult = GetAdapterCaps(&This->DisplayAdapters[Adapter], DeviceType, pCaps); 848 849 UNLOCK_D3D9(); 850 return hResult; 851 } 852 853 /*++ 854 * @name IDirect3D9::GetAdapterMonitor 855 * @implemented 856 * 857 * The function IDirect3D9Impl_GetAdapterMonitor returns the monitor associated 858 * with the specified display adapter. 859 * 860 * @param LPDIRECT3D iface 861 * Pointer to the IDirect3D9 object returned from Direct3DCreate9() 862 * 863 * @param UINT Adapter 864 * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. 865 * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. 866 * 867 * @return HMONITOR 868 * If the method successfully it returns the HMONITOR belonging to the specified adapter. 869 * If the method fails, the return value is NULL. 870 * 871 */ 872 static HMONITOR WINAPI IDirect3D9Impl_GetAdapterMonitor(LPDIRECT3D9 iface, UINT Adapter) 873 { 874 HMONITOR hAdapterMonitor = NULL; 875 876 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 877 LOCK_D3D9(); 878 879 if (Adapter < This->NumDisplayAdapters) 880 { 881 hAdapterMonitor = GetAdapterMonitor(This->DisplayAdapters[Adapter].szDeviceName); 882 } 883 else 884 { 885 DPRINT1("Invalid Adapter number specified"); 886 } 887 888 UNLOCK_D3D9(); 889 return hAdapterMonitor; 890 } 891 892 /*++ 893 * @name IDirect3D9::CreateDevice 894 * @implemented 895 * 896 * The function IDirect3D9Impl_CreateDevice creates an IDirect3DDevice9 object 897 * that represents the display adapter. 898 * 899 * @param LPDIRECT3D iface 900 * Pointer to the IDirect3D9 object returned from Direct3DCreate9() 901 * 902 * @param UINT Adapter 903 * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. 904 * The maximum value for this is the value returned by IDirect3D::GetAdapterCount() - 1. 905 * 906 * @param D3DDEVTYPE DeviceType 907 * One of the D3DDEVTYPE enum members. 908 * 909 * @param HWND hFocusWindow 910 * A window handle that is used as a reference when Direct3D should switch between 911 * foreground mode and background mode. 912 * 913 * @param DWORD BehaviourFlags 914 * Any valid combination of the D3DCREATE constants. 915 * 916 * @param D3DPRESENT_PARAMETERS* pPresentationParameters 917 * Pointer to a D3DPRESENT_PARAMETERS structure describing the parameters for the device 918 * to be created. If D3DCREATE_ADAPTERGROUP_DEVICE is specified in the BehaviourFlags parameter, 919 * the pPresentationParameters is treated as an array. 920 * 921 * @param IDirect3DDevice9** ppReturnedDeviceInterface 922 * Return object that represents the created device. 923 * 924 * @return HRESULT 925 * If the method successfully creates a device and returns a valid ppReturnedDeviceInterface object, 926 * the return value is D3D_OK. 927 * If Adapter is out of range, DeviceType is invalid, hFocusWindow is not a valid, BehaviourFlags is invalid 928 * pPresentationParameters is invalid or ppReturnedDeviceInterface is a bad pointer, the return value 929 * will be D3DERR_INVALIDCALL. 930 * 931 */ 932 static HRESULT WINAPI IDirect3D9Impl_CreateDevice(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, 933 HWND hFocusWindow, DWORD BehaviourFlags, 934 D3DPRESENT_PARAMETERS* pPresentationParameters, 935 struct IDirect3DDevice9** ppReturnedDeviceInterface) 936 { 937 DWORD NumAdaptersToCreate; 938 HRESULT Ret; 939 940 LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); 941 LOCK_D3D9(); 942 943 if (Adapter >= This->NumDisplayAdapters) 944 { 945 DPRINT1("Invalid Adapter number specified"); 946 UNLOCK_D3D9(); 947 return D3DERR_INVALIDCALL; 948 } 949 950 if (DeviceType != D3DDEVTYPE_HAL && 951 DeviceType != D3DDEVTYPE_REF && 952 DeviceType != D3DDEVTYPE_SW) 953 { 954 DPRINT1("Invalid DeviceType specified"); 955 UNLOCK_D3D9(); 956 return D3DERR_INVALIDCALL; 957 } 958 959 if (DeviceType != D3DDEVTYPE_HAL) 960 { 961 UNIMPLEMENTED 962 DPRINT1("Sorry, only D3DDEVTYPE_HAL is implemented at this time..."); 963 return D3DERR_INVALIDCALL; 964 } 965 966 if (hFocusWindow != NULL && FALSE == IsWindow(hFocusWindow)) 967 { 968 DPRINT1("Invalid hFocusWindow parameter specified, expected NULL or a valid HWND"); 969 UNLOCK_D3D9(); 970 return D3DERR_INVALIDCALL; 971 } 972 973 if (NULL == pPresentationParameters) 974 { 975 DPRINT1("Invalid pPresentationParameters parameter specified"); 976 UNLOCK_D3D9(); 977 return D3DERR_INVALIDCALL; 978 } 979 980 if (pPresentationParameters->hDeviceWindow != NULL && FALSE == IsWindow(pPresentationParameters->hDeviceWindow)) 981 { 982 DPRINT1("Invalid pPresentationParameters->hDeviceWindow parameter specified, expected NULL or a valid HWND"); 983 UNLOCK_D3D9(); 984 return D3DERR_INVALIDCALL; 985 } 986 987 if (FALSE == pPresentationParameters->Windowed && hFocusWindow == NULL) 988 { 989 DPRINT1("When pPresentationParameters->Windowed is not set, hFocusWindow must be a valid HWND"); 990 UNLOCK_D3D9(); 991 return D3DERR_INVALIDCALL; 992 } 993 994 if (NULL == hFocusWindow && NULL == pPresentationParameters->hDeviceWindow) 995 { 996 DPRINT1("Any of pPresentationParameters->Windowed and hFocusWindow must be set to a valid HWND"); 997 UNLOCK_D3D9(); 998 return D3DERR_INVALIDCALL; 999 } 1000 1001 if (Adapter > 0 && NULL == pPresentationParameters->hDeviceWindow) 1002 { 1003 DPRINT1("Invalid pPresentationParameters->hDeviceWindow, must be set to a valid unique HWND when Adapter is greater than 0"); 1004 UNLOCK_D3D9(); 1005 return D3DERR_INVALIDCALL; 1006 } 1007 1008 if (NULL == ppReturnedDeviceInterface) 1009 { 1010 DPRINT1("Invalid ppReturnedDeviceInterface parameter specified"); 1011 UNLOCK_D3D9(); 1012 return D3DERR_INVALIDCALL; 1013 } 1014 1015 if ((BehaviourFlags & D3DCREATE_ADAPTERGROUP_DEVICE) != 0) 1016 NumAdaptersToCreate = This->DisplayAdapters[Adapter].NumAdaptersInGroup; 1017 else 1018 NumAdaptersToCreate = 1; 1019 1020 *ppReturnedDeviceInterface = 0; 1021 1022 Ret = CreateD3D9HalDevice(This, Adapter, hFocusWindow, BehaviourFlags, pPresentationParameters, NumAdaptersToCreate, ppReturnedDeviceInterface); 1023 1024 UNLOCK_D3D9(); 1025 return Ret; 1026 } 1027 1028 IDirect3D9Vtbl Direct3D9_Vtbl = 1029 { 1030 /* IUnknown */ 1031 IDirect3D9Impl_QueryInterface, 1032 IDirect3D9Impl_AddRef, 1033 IDirect3D9Impl_Release, 1034 1035 /* IDirect3D9 */ 1036 IDirect3D9Impl_RegisterSoftwareDevice, 1037 IDirect3D9Impl_GetAdapterCount, 1038 IDirect3D9Impl_GetAdapterIdentifier, 1039 IDirect3D9Impl_GetAdapterModeCount, 1040 IDirect3D9Impl_EnumAdapterModes, 1041 IDirect3D9Impl_GetAdapterDisplayMode, 1042 IDirect3D9Impl_CheckDeviceType, 1043 IDirect3D9Impl_CheckDeviceFormat, 1044 IDirect3D9Impl_CheckDeviceMultiSampleType, 1045 IDirect3D9Impl_CheckDepthStencilMatch, 1046 IDirect3D9Impl_CheckDeviceFormatConversion, 1047 IDirect3D9Impl_GetDeviceCaps, 1048 IDirect3D9Impl_GetAdapterMonitor, 1049 IDirect3D9Impl_CreateDevice 1050 }; 1051