/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS ReactX * FILE: dll/directx/d3d9/d3d9_impl.c * PURPOSE: IDirect3D9 implementation * PROGRAMERS: Gregor Brunmar */ #include "d3d9_common.h" #include #include #include "d3d9_helpers.h" #include "adapter.h" #include "device.h" #include "format.h" #define LOCK_D3D9() EnterCriticalSection(&This->d3d9_cs); #define UNLOCK_D3D9() LeaveCriticalSection(&This->d3d9_cs); /* Convert a IDirect3D9 pointer safely to the internal implementation struct */ static LPDIRECT3D9_INT IDirect3D9ToImpl(LPDIRECT3D9 iface) { if (NULL == iface) return NULL; return (LPDIRECT3D9_INT)((ULONG_PTR)iface - FIELD_OFFSET(DIRECT3D9_INT, lpVtbl)); } /* IDirect3D9: IUnknown implementation */ static HRESULT WINAPI IDirect3D9Impl_QueryInterface(LPDIRECT3D9 iface, REFIID riid, LPVOID* ppvObject) { LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirect3D9)) { IUnknown_AddRef(iface); *ppvObject = &This->lpVtbl; return S_OK; } *ppvObject = NULL; return E_NOINTERFACE; } static ULONG WINAPI IDirect3D9Impl_AddRef(LPDIRECT3D9 iface) { LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); ULONG ref = InterlockedIncrement(&This->lRefCnt); return ref; } static ULONG WINAPI IDirect3D9Impl_Release(LPDIRECT3D9 iface) { LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); ULONG ref = InterlockedDecrement(&This->lRefCnt); if (ref == 0) { EnterCriticalSection(&This->d3d9_cs); /* TODO: Free resources here */ LeaveCriticalSection(&This->d3d9_cs); AlignedFree(This); } return ref; } /* IDirect3D9 interface */ static HRESULT WINAPI IDirect3D9Impl_RegisterSoftwareDevice(LPDIRECT3D9 iface, void* pInitializeFunction) { UNIMPLEMENTED return D3D_OK; } /*++ * @name IDirect3D9::GetAdapterCount * @implemented * * The function IDirect3D9Impl_GetAdapterCount returns the number of adapters * * @param LPDIRECT3D iface * Pointer to the IDirect3D9 object returned from Direct3DCreate9() * * @return UINT * The number of display adapters on the system when Direct3DCreate9() was called. * */ static UINT WINAPI IDirect3D9Impl_GetAdapterCount(LPDIRECT3D9 iface) { UINT NumDisplayAdapters; LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); LOCK_D3D9(); NumDisplayAdapters = This->NumDisplayAdapters; UNLOCK_D3D9(); return NumDisplayAdapters; } /*++ * @name IDirect3D9::GetAdapterIdentifier * @implemented * * The function IDirect3D9Impl_GetAdapterIdentifier gathers information about * a specified display adapter and fills the pIdentifier argument with the available information. * * @param LPDIRECT3D iface * Pointer to the IDirect3D9 object returned from Direct3DCreate9() * * @param UINT Adapter * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. * The maximum value for this is the value returned by IDirect3D::GetAdapterCount() - 1. * * @param DWORD Flags * Ignored at the moment, but the only valid flag is D3DENUM_WHQL_LEVEL * * @param D3DADAPTER_IDENTIFIER9* pIdentifier * Pointer to a D3DADAPTER_IDENTIFIER9 structure to be filled with the available information * about the display adapter. * * @return HRESULT * If the method successfully fills the pIdentified structure, the return value is D3D_OK. * If Adapter is out of range, Flags is invalid or pIdentifier is a bad pointer, the return value * will be D3DERR_INVALIDCALL. * */ HRESULT WINAPI IDirect3D9Impl_GetAdapterIdentifier(LPDIRECT3D9 iface, UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) { LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); LOCK_D3D9(); if (Adapter >= This->NumDisplayAdapters) { DPRINT1("Invalid Adapter number specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (Flags & ~D3DENUM_WHQL_LEVEL) { DPRINT1("Invalid Flags specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (NULL == pIdentifier) { DPRINT1("Invalid pIdentifier parameter specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } memset(pIdentifier, 0, sizeof(D3DADAPTER_IDENTIFIER9)); if (FALSE == GetAdapterInfo(This->DisplayAdapters[Adapter].szDeviceName, pIdentifier)) { DPRINT1("Internal error: Couldn't get the adapter info for device (%d): %s", Adapter, This->DisplayAdapters[Adapter].szDeviceName); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } UNLOCK_D3D9(); return D3D_OK; } /*++ * @name IDirect3D9::GetAdapterModeCount * @implemented * * The function IDirect3D9Impl_GetAdapterModeCount looks if the specified display adapter supports * a specific pixel format and counts the available display modes for that format. * * @param LPDIRECT3D iface * Pointer to the IDirect3D9 object returned from Direct3DCreate9() * * @param UINT Adapter * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. * * @param D3DFORMAT Format * The pixel format to search for * * @return HRESULT * If the method is successful it returns the number of display modes with the specified Format. * If Adapter is out of range, the return value will be 0. * */ static UINT WINAPI IDirect3D9Impl_GetAdapterModeCount(LPDIRECT3D9 iface, UINT Adapter, D3DFORMAT Format) { UINT AdapterModeCount; LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); LOCK_D3D9(); if (Adapter >= This->NumDisplayAdapters) { DPRINT1("Invalid Adapter number specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (Format != D3DFMT_A2R10G10B10) { AdapterModeCount = GetDisplayFormatCount( Format, This->DisplayAdapters[Adapter].pSupportedD3DFormats, This->DisplayAdapters[Adapter].NumSupportedD3DFormats); } else { AdapterModeCount = GetDisplayFormatCount( Format, This->DisplayAdapters[Adapter].pSupportedD3DExtendedFormats, This->DisplayAdapters[Adapter].NumSupportedD3DExtendedFormats); } UNLOCK_D3D9(); return AdapterModeCount; } /*++ * @name IDirect3D9::EnumAdapterModes * @implemented * * The function IDirect3D9Impl_EnumAdapterModes looks if the specified display adapter supports * a specific pixel format and fills the pMode argument with the available display modes for that format. * This function is often used in a loop to enumerate all the display modes the adapter supports. * * @param LPDIRECT3D iface * Pointer to the IDirect3D9 object returned from Direct3DCreate9() * * @param UINT Adapter * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. * * @param D3DFORMAT Format * The pixel format to search for * * @param UINT Mode * Index within the pixel format to be returned. * The maximum value for this is the value returned by IDirect3D9::GetAdapterModeCount() - 1. * * @param D3DDISPLAYMODE* pMode * Pointer to a D3DDISPLAYMODE structure to be filled with the display mode information * for the specified format. * * @return HRESULT * If the method successfully fills the pMode structure, the return value is D3D_OK. * If Adapter is out of range, pMode is a bad pointer or, no modes for the specified * format was found or the mode parameter was invalid - the return value will be D3DERR_INVALIDCALL. * */ static HRESULT WINAPI IDirect3D9Impl_EnumAdapterModes(LPDIRECT3D9 iface, UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) { const D3DDISPLAYMODE* pMatchingDisplayFormat; LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); LOCK_D3D9(); if (Adapter >= This->NumDisplayAdapters) { DPRINT1("Invalid Adapter number specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (NULL == pMode) { DPRINT1("Invalid pMode parameter specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (Format != D3DFMT_A2R10G10B10) { pMatchingDisplayFormat = FindDisplayFormat( Format, Mode, This->DisplayAdapters[Adapter].pSupportedD3DFormats, This->DisplayAdapters[Adapter].NumSupportedD3DFormats); } else { pMatchingDisplayFormat = FindDisplayFormat( Format, Mode, This->DisplayAdapters[Adapter].pSupportedD3DExtendedFormats, This->DisplayAdapters[Adapter].NumSupportedD3DExtendedFormats); } if (pMatchingDisplayFormat != NULL) { *pMode = *pMatchingDisplayFormat; } UNLOCK_D3D9(); if (pMatchingDisplayFormat == NULL) return D3DERR_INVALIDCALL; return D3D_OK; } /*++ * @name IDirect3D9::GetAdapterDisplayMode * @implemented * * The function IDirect3D9Impl_GetAdapterDisplayMode fills the pMode argument with the * currently set display mode. * * @param LPDIRECT3D iface * Pointer to the IDirect3D9 object returned from Direct3DCreate9() * * @param UINT Adapter * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. * * @param D3DDISPLAYMODE* pMode * Pointer to a D3DDISPLAYMODE structure to be filled with the current display mode information. * * @return HRESULT * If the method successfully fills the pMode structure, the return value is D3D_OK. * If Adapter is out of range or pMode is a bad pointer, the return value will be D3DERR_INVALIDCALL. * */ static HRESULT WINAPI IDirect3D9Impl_GetAdapterDisplayMode(LPDIRECT3D9 iface, UINT Adapter, D3DDISPLAYMODE* pMode) { LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); LOCK_D3D9(); if (Adapter >= This->NumDisplayAdapters) { DPRINT1("Invalid Adapter number specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (NULL == pMode) { DPRINT1("Invalid pMode parameter specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } /* TODO: Handle (This->DisplayAdapters[Adapter].bInUseFlag == FALSE) */ if (FALSE == GetAdapterMode(This->DisplayAdapters[Adapter].szDeviceName, pMode)) DPRINT1("Internal error, GetAdapterMode() failed."); UNLOCK_D3D9(); return D3D_OK; } /*++ * @name IDirect3D9::CheckDeviceType * @implemented * * The function IDirect3D9Impl_CheckDeviceType checks if a specific D3DFORMAT is hardware accelerated * on the specified display adapter. * * @param LPDIRECT3D iface * Pointer to the IDirect3D9 object returned from Direct3DCreate9() * * @param UINT Adapter * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. * * @param D3DDEVTYPE DeviceType * One of the D3DDEVTYPE enum members. * * @param D3DFORMAT DisplayFormat * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode to be checked. * * @param D3DFORMAT BackBufferFormat * One of the D3DFORMAT enum members for the render target mode to be checked. D3DFMT_UNKNOWN is only allowed in windowed mode. * * @param BOOL Windowed * If this value is TRUE, the D3DFORMAT check will be done for windowed mode and FALSE equals fullscreen mode. * * @return HRESULT * If the format is hardware accelerated, the method returns D3D_OK. * If the format isn't hardware accelerated or unsupported - the return value will be D3DERR_NOTAVAILABLE. * If Adapter is out of range, DeviceType is invalid, * DisplayFormat or BackBufferFormat is invalid - the return value will be D3DERR_INVALIDCALL. * */ static HRESULT WINAPI IDirect3D9Impl_CheckDeviceType(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL Windowed) { HRESULT hResult; LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); LOCK_D3D9(); if (Adapter >= This->NumDisplayAdapters) { DPRINT1("Invalid Adapter number specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (DeviceType != D3DDEVTYPE_HAL && DeviceType != D3DDEVTYPE_REF && DeviceType != D3DDEVTYPE_SW) { DPRINT1("Invalid DeviceType specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if ((BackBufferFormat == D3DFMT_UNKNOWN) && (Windowed != FALSE)) { BackBufferFormat = DisplayFormat; } if (DisplayFormat == D3DFMT_UNKNOWN && BackBufferFormat == D3DFMT_UNKNOWN) { DPRINT1("Invalid D3DFORMAT specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (FALSE == IsBackBufferFormat(BackBufferFormat)) { DPRINT1("Invalid D3DFORMAT specified"); UNLOCK_D3D9(); return D3DERR_NOTAVAILABLE; } if (TRUE == Windowed && TRUE == IsExtendedFormat(DisplayFormat)) { DPRINT1("Extended display modes can only be used in fullscreen mode"); UNLOCK_D3D9(); return D3DERR_NOTAVAILABLE; } hResult = CheckDeviceType(&This->DisplayAdapters[Adapter].DriverCaps, DisplayFormat, BackBufferFormat, Windowed); UNLOCK_D3D9(); return hResult; } /*++ * @name IDirect3D9::CheckDeviceFormat * @implemented * * The function IDirect3D9Impl_CheckDeviceFormat checks if a specific D3DFORMAT * can be used for a specific purpose like texture, depth/stencil buffer or as a render target * on the specified display adapter. * * @param LPDIRECT3D iface * Pointer to the IDirect3D9 object returned from Direct3DCreate9() * * @param UINT Adapter * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. * * @param D3DDEVTYPE DeviceType * One of the D3DDEVTYPE enum members. * * @param D3DFORMAT AdapterFormat * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode to be checked. * * @param DWORD Usage * Valid values are any of the D3DUSAGE_QUERY constants or any of these D3DUSAGE constants: * D3DUSAGE_AUTOGENMIPMAP, D3DUSAGE_DEPTHSTENCIL, D3DUSAGE_DMAP, D3DUSAGE_DYNAMIC, * D3DUSAGE_NONSECURE, D3DUSAGE_RENDERTARGET and D3DUSAGE_SOFTWAREPROCESSING. * * @param D3DRESOURCETYPE RType * One of the D3DRESOURCETYPE enum members. Specifies what format will be used for. * * @param D3DFORMAT CheckFormat * One of the D3DFORMAT enum members for the surface format to be checked. * * @return HRESULT * If the format is compatible with the specified usage and resource type, the method returns D3D_OK. * If the format isn't compatible with the specified usage and resource type - the return value will be D3DERR_NOTAVAILABLE. * If Adapter is out of range, DeviceType is invalid, AdapterFormat or CheckFormat is invalid, * Usage and RType isn't compatible - the return value will be D3DERR_INVALIDCALL. * */ static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormat(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) { LPD3D9_DRIVERCAPS pDriverCaps; BOOL bIsTextureRType = FALSE; HRESULT hResult; LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); LOCK_D3D9(); if (Adapter >= This->NumDisplayAdapters) { DPRINT1("Invalid Adapter number specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (DeviceType != D3DDEVTYPE_HAL && DeviceType != D3DDEVTYPE_REF && DeviceType != D3DDEVTYPE_SW) { DPRINT1("Invalid DeviceType specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (AdapterFormat == D3DFMT_UNKNOWN || CheckFormat == D3DFMT_UNKNOWN) { DPRINT1("Invalid D3DFORMAT specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if ((Usage & (D3DUSAGE_DONOTCLIP | D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_TEXTAPI | D3DUSAGE_WRITEONLY)) != 0) { DPRINT1("Invalid Usage specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (RType == D3DRTYPE_TEXTURE || RType == D3DRTYPE_VOLUMETEXTURE || RType == D3DRTYPE_CUBETEXTURE) { bIsTextureRType = TRUE; } else if (RType == D3DRTYPE_SURFACE && (Usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)) == 0 && Usage != 0) { DPRINT1("When RType is set to D3DRTYPE_SURFACE, Usage must be 0 or have set D3DUSAGE_DEPTHSTENCIL or D3DUSAGE_RENDERTARGET"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if ((Usage & D3DUSAGE_DEPTHSTENCIL) != 0) { if (FALSE == IsZBufferFormat(CheckFormat)) { DPRINT1("Invalid CheckFormat Z-Buffer format"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if ((Usage & D3DUSAGE_AUTOGENMIPMAP) != 0) { DPRINT1("Invalid Usage specified, D3DUSAGE_DEPTHSTENCIL and D3DUSAGE_AUTOGENMIPMAP can't be combined."); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } } if (FALSE == bIsTextureRType && RType != D3DRTYPE_SURFACE && RType != D3DRTYPE_VOLUME) { DPRINT1("Invalid RType specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if ((Usage & (D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)) != 0) { if (RType == D3DRTYPE_VOLUME || RType == D3DRTYPE_VOLUMETEXTURE) { DPRINT1("Invalid Usage specified, D3DUSAGE_AUTOGENMIPMAP, D3DUSAGE_DEPTHSTENCIL and D3DUSAGE_RENDERTARGET can't be combined with RType D3DRTYPE_VOLUME or D3DRTYPE_VOLUMETEXTURE"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } } if (FALSE == bIsTextureRType && (Usage & D3DUSAGE_QUERY_VERTEXTEXTURE) != 0) { DPRINT1("Invalid Usage specified, D3DUSAGE_QUERY_VERTEXTEXTURE can only be used with a texture RType"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if ((Usage & D3DUSAGE_AUTOGENMIPMAP) != 0 && TRUE == IsMultiElementFormat(CheckFormat)) { DPRINT1("Invalid Usage specified, D3DUSAGE_AUTOGENMIPMAP can't be used with a multi-element format"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } pDriverCaps = &This->DisplayAdapters[Adapter].DriverCaps; if (((Usage & D3DUSAGE_DYNAMIC) != 0) && (bIsTextureRType != FALSE)) { if ((pDriverCaps->DriverCaps9.Caps2 & D3DCAPS2_DYNAMICTEXTURES) == 0) { DPRINT1("Driver doesn't support dynamic textures"); UNLOCK_D3D9(); return D3DERR_NOTAVAILABLE; } if ((Usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)) != 0) { DPRINT1("Invalid Usage specified, D3DUSAGE_DEPTHSTENCIL and D3DUSAGE_RENDERTARGET can't be combined with D3DUSAGE_DYNAMIC and a texture RType"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } } if ((Usage & D3DUSAGE_DMAP) != 0) { if ((pDriverCaps->DriverCaps9.DevCaps2 & (D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH | D3DDEVCAPS2_DMAPNPATCH)) == 0) { DPRINT1("Driver doesn't support displacement mapping"); UNLOCK_D3D9(); return D3DERR_NOTAVAILABLE; } if (RType != D3DRTYPE_TEXTURE) { DPRINT1("Invalid Usage specified, D3DUSAGE_DMAP must be combined with RType D3DRTYPE_TEXTURE"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } } hResult = CheckDeviceFormat(pDriverCaps, AdapterFormat, Usage, RType, CheckFormat); UNLOCK_D3D9(); return hResult; } static HRESULT WINAPI IDirect3D9Impl_CheckDeviceMultiSampleType(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) { UNIMPLEMENTED return D3D_OK; } /*++ * @name IDirect3D9::CheckDepthStencilMatch * @implemented * * The function IDirect3D9Impl_CheckDepthStencilMatch checks if a specific combination * of a render target D3DFORMAT and a depth-stencil D3DFORMAT can be used with a specified * D3DFORMAT on the specified display adapter. * * @param LPDIRECT3D iface * Pointer to the IDirect3D9 object returned from Direct3DCreate9() * * @param UINT Adapter * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. * * @param D3DDEVTYPE DeviceType * One of the D3DDEVTYPE enum members. * * @param D3DFORMAT AdapterFormat * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN that the display adapter mode where the test should occur. * * @param D3DFORMAT RenderTargetFormat * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode's render target format to be tested. * * @param D3DFORMAT DepthStencilFormat * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode's depth-stencil format to be tested. * * @return HRESULT * If the DepthStencilFormat can be used with the RenderTargetFormat under the specified AdapterFormat, * the method returns D3D_OK. * If the DepthStencilFormat can NOT used with the RenderTargetFormat under the specified AdapterFormat, * the method returns D3DERR_NOTAVAILABLE. * If Adapter is out of range, DeviceType is invalid, * AdapterFormat, RenderTargetFormat or DepthStencilFormat is invalid, the method returns D3DERR_INVALIDCALL. * */ static HRESULT WINAPI IDirect3D9Impl_CheckDepthStencilMatch(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) { HRESULT hResult; LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); LOCK_D3D9(); if (Adapter >= This->NumDisplayAdapters) { DPRINT1("Invalid Adapter number specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (DeviceType != D3DDEVTYPE_HAL && DeviceType != D3DDEVTYPE_REF && DeviceType != D3DDEVTYPE_SW) { DPRINT1("Invalid DeviceType specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (AdapterFormat == D3DFMT_UNKNOWN || RenderTargetFormat == D3DFMT_UNKNOWN || DepthStencilFormat == D3DFMT_UNKNOWN) { DPRINT1("Invalid D3DFORMAT specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } hResult = CheckDepthStencilMatch(&This->DisplayAdapters[Adapter].DriverCaps, AdapterFormat, RenderTargetFormat, DepthStencilFormat); UNLOCK_D3D9(); return hResult; } /*++ * @name IDirect3D9::CheckDeviceFormatConversion * @implemented * * The function IDirect3D9Impl_CheckDeviceFormatConversion checks if a specific D3DFORMAT * can be converted to another on the specified display adapter. * * @param LPDIRECT3D iface * Pointer to the IDirect3D9 object returned from Direct3DCreate9() * * @param UINT Adapter * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. * * @param D3DDEVTYPE DeviceType * One of the D3DDEVTYPE enum members. Only D3DDEVTYPE_HAL can potentially return D3D_OK. * * @param D3DFORMAT SourceFormat * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode to be converted from. * * @param D3DFORMAT TargetFormat * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode to be converted to. * * @return HRESULT * If the SourceFormat can be converted to the TargetFormat, the method returns D3D_OK. * If the SourceFormat can NOT be converted to the TargetFormat, the method returns D3DERR_NOTAVAILABLE. * If Adapter is out of range, DeviceType is invalid, * SourceFormat or TargetFormat is invalid, the method returns D3DERR_INVALIDCALL. * */ static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormatConversion(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) { HRESULT hResult; LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); LOCK_D3D9(); if (Adapter >= This->NumDisplayAdapters) { DPRINT1("Invalid Adapter number specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (DeviceType != D3DDEVTYPE_HAL && DeviceType != D3DDEVTYPE_REF && DeviceType != D3DDEVTYPE_SW) { DPRINT1("Invalid DeviceType specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (SourceFormat == D3DFMT_UNKNOWN || TargetFormat == D3DFMT_UNKNOWN) { DPRINT1("Invalid D3DFORMAT specified"); UNLOCK_D3D9(); return D3DERR_NOTAVAILABLE; } if (DeviceType == D3DDEVTYPE_HAL) { hResult = CheckDeviceFormatConversion(&This->DisplayAdapters[Adapter].DriverCaps, SourceFormat, TargetFormat); } else { hResult = D3DERR_NOTAVAILABLE; } UNLOCK_D3D9(); return hResult; } /*++ * @name IDirect3D9::GetDeviceCaps * @implemented * * The function IDirect3D9Impl_GetDeviceCaps fills the pCaps argument with the * capabilities of the specified adapter and device type. * * @param LPDIRECT3D iface * Pointer to the IDirect3D9 object returned from Direct3DCreate9() * * @param UINT Adapter * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. * * @param D3DDEVTYPE DeviceType * One of the D3DDEVTYPE enum members. * NOTE: Currently only D3DDEVTYPE_HAL is implemented. * * @param D3DCAPS9* pCaps * Pointer to a D3DCAPS9 structure to be filled with the adapter's device type capabilities. * * @return HRESULT * If the method successfully fills the pCaps structure, the return value is D3D_OK. * If Adapter is out of range or pCaps is a bad pointer, the return value will be D3DERR_INVALIDCALL. * If DeviceType is invalid, the return value will be D3DERR_INVALIDDEVICE. * */ static HRESULT WINAPI IDirect3D9Impl_GetDeviceCaps(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) { HRESULT hResult; LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); LOCK_D3D9(); if (Adapter >= This->NumDisplayAdapters) { DPRINT1("Invalid Adapter number specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (NULL == pCaps) { DPRINT1("Invalid pCaps parameter specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } hResult = GetAdapterCaps(&This->DisplayAdapters[Adapter], DeviceType, pCaps); UNLOCK_D3D9(); return hResult; } /*++ * @name IDirect3D9::GetAdapterMonitor * @implemented * * The function IDirect3D9Impl_GetAdapterMonitor returns the monitor associated * with the specified display adapter. * * @param LPDIRECT3D iface * Pointer to the IDirect3D9 object returned from Direct3DCreate9() * * @param UINT Adapter * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. * The maximum value for this is the value returned by IDirect3D9::GetAdapterCount() - 1. * * @return HMONITOR * If the method successfully it returns the HMONITOR belonging to the specified adapter. * If the method fails, the return value is NULL. * */ static HMONITOR WINAPI IDirect3D9Impl_GetAdapterMonitor(LPDIRECT3D9 iface, UINT Adapter) { HMONITOR hAdapterMonitor = NULL; LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); LOCK_D3D9(); if (Adapter < This->NumDisplayAdapters) { hAdapterMonitor = GetAdapterMonitor(This->DisplayAdapters[Adapter].szDeviceName); } else { DPRINT1("Invalid Adapter number specified"); } UNLOCK_D3D9(); return hAdapterMonitor; } /*++ * @name IDirect3D9::CreateDevice * @implemented * * The function IDirect3D9Impl_CreateDevice creates an IDirect3DDevice9 object * that represents the display adapter. * * @param LPDIRECT3D iface * Pointer to the IDirect3D9 object returned from Direct3DCreate9() * * @param UINT Adapter * Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. * The maximum value for this is the value returned by IDirect3D::GetAdapterCount() - 1. * * @param D3DDEVTYPE DeviceType * One of the D3DDEVTYPE enum members. * * @param HWND hFocusWindow * A window handle that is used as a reference when Direct3D should switch between * foreground mode and background mode. * * @param DWORD BehaviourFlags * Any valid combination of the D3DCREATE constants. * * @param D3DPRESENT_PARAMETERS* pPresentationParameters * Pointer to a D3DPRESENT_PARAMETERS structure describing the parameters for the device * to be created. If D3DCREATE_ADAPTERGROUP_DEVICE is specified in the BehaviourFlags parameter, * the pPresentationParameters is treated as an array. * * @param IDirect3DDevice9** ppReturnedDeviceInterface * Return object that represents the created device. * * @return HRESULT * If the method successfully creates a device and returns a valid ppReturnedDeviceInterface object, * the return value is D3D_OK. * If Adapter is out of range, DeviceType is invalid, hFocusWindow is not a valid, BehaviourFlags is invalid * pPresentationParameters is invalid or ppReturnedDeviceInterface is a bad pointer, the return value * will be D3DERR_INVALIDCALL. * */ static HRESULT WINAPI IDirect3D9Impl_CreateDevice(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, struct IDirect3DDevice9** ppReturnedDeviceInterface) { DWORD NumAdaptersToCreate; HRESULT Ret; LPDIRECT3D9_INT This = IDirect3D9ToImpl(iface); LOCK_D3D9(); if (Adapter >= This->NumDisplayAdapters) { DPRINT1("Invalid Adapter number specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (DeviceType != D3DDEVTYPE_HAL && DeviceType != D3DDEVTYPE_REF && DeviceType != D3DDEVTYPE_SW) { DPRINT1("Invalid DeviceType specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (DeviceType != D3DDEVTYPE_HAL) { UNIMPLEMENTED DPRINT1("Sorry, only D3DDEVTYPE_HAL is implemented at this time..."); return D3DERR_INVALIDCALL; } if (hFocusWindow != NULL && FALSE == IsWindow(hFocusWindow)) { DPRINT1("Invalid hFocusWindow parameter specified, expected NULL or a valid HWND"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (NULL == pPresentationParameters) { DPRINT1("Invalid pPresentationParameters parameter specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (pPresentationParameters->hDeviceWindow != NULL && FALSE == IsWindow(pPresentationParameters->hDeviceWindow)) { DPRINT1("Invalid pPresentationParameters->hDeviceWindow parameter specified, expected NULL or a valid HWND"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (FALSE == pPresentationParameters->Windowed && hFocusWindow == NULL) { DPRINT1("When pPresentationParameters->Windowed is not set, hFocusWindow must be a valid HWND"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (NULL == hFocusWindow && NULL == pPresentationParameters->hDeviceWindow) { DPRINT1("Any of pPresentationParameters->Windowed and hFocusWindow must be set to a valid HWND"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (Adapter > 0 && NULL == pPresentationParameters->hDeviceWindow) { DPRINT1("Invalid pPresentationParameters->hDeviceWindow, must be set to a valid unique HWND when Adapter is greater than 0"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if (NULL == ppReturnedDeviceInterface) { DPRINT1("Invalid ppReturnedDeviceInterface parameter specified"); UNLOCK_D3D9(); return D3DERR_INVALIDCALL; } if ((BehaviourFlags & D3DCREATE_ADAPTERGROUP_DEVICE) != 0) NumAdaptersToCreate = This->DisplayAdapters[Adapter].NumAdaptersInGroup; else NumAdaptersToCreate = 1; *ppReturnedDeviceInterface = 0; Ret = CreateD3D9HalDevice(This, Adapter, hFocusWindow, BehaviourFlags, pPresentationParameters, NumAdaptersToCreate, ppReturnedDeviceInterface); UNLOCK_D3D9(); return Ret; } IDirect3D9Vtbl Direct3D9_Vtbl = { /* IUnknown */ IDirect3D9Impl_QueryInterface, IDirect3D9Impl_AddRef, IDirect3D9Impl_Release, /* IDirect3D9 */ IDirect3D9Impl_RegisterSoftwareDevice, IDirect3D9Impl_GetAdapterCount, IDirect3D9Impl_GetAdapterIdentifier, IDirect3D9Impl_GetAdapterModeCount, IDirect3D9Impl_EnumAdapterModes, IDirect3D9Impl_GetAdapterDisplayMode, IDirect3D9Impl_CheckDeviceType, IDirect3D9Impl_CheckDeviceFormat, IDirect3D9Impl_CheckDeviceMultiSampleType, IDirect3D9Impl_CheckDepthStencilMatch, IDirect3D9Impl_CheckDeviceFormatConversion, IDirect3D9Impl_GetDeviceCaps, IDirect3D9Impl_GetAdapterMonitor, IDirect3D9Impl_CreateDevice };