diff --git a/audit/history.jsonl b/audit/history.jsonl index 026a9308..080d9401 100644 --- a/audit/history.jsonl +++ b/audit/history.jsonl @@ -638,3 +638,4 @@ {"date": "2026-09-30", "unit": "EterLib/SkyBox.cpp", "action": "port", "evidence": "verbatim except native-terrain gate on Render/RenderCloud and qualified CSkyObject::Destroy in the destructor; port.login_flow (map teardown), live-client sky screenshot matches previous build"} {"date": "2026-09-30", "unit": "EterLib/GrpScreen.cpp", "action": "port", "evidence": "verbatim; 2d draws -> UIRender commands, Show without the web-page rects; D3D8 shim gains TestCooperativeLevel/Reset/Present/GetVertexShader + ID3DXMesh; port.app_loop (3D line/bar draws, device not lost), port.login_flow (picking/projection)"} {"date": "2026-09-30", "unit": "EterLib/GrpDevice.cpp", "action": "port", "evidence": "verbatim except Create (recording device in place of Direct3DCreate8/detector/CreateDevice, EL3D_ConfirmDevice on its caps); RecordingDevice decodes declaration-only vertex shaders to stream-0 FVFs; GrpScreen Show uses the GrpDevice browser globals; port.app_loop (PT/PNT/PNT2 FVFs, max texture 4096), full ctest, live-client screenshot matches"} +{"date": "2026-09-30", "unit": "EterLib/GrpDetector.cpp", "action": "port", "evidence": "verbatim; IDirect3D8 shim completed (adapter count/caps/format checks/CreateDevice) and implemented once as the host adapter behind Direct3DCreate8 (RecordingDevice.cpp), which CPythonGraphic::GetD3D also returns; GrpDevice::Create now verbatim but for the D3DX debug meshes; port.app_loop (800x600x32 HWVP D16 mode, ms_lpd3d, GetString), full ctest, live-client screenshot matches"} diff --git a/audit/port-map/EterLib/GrpDetector.cpp.json b/audit/port-map/EterLib/GrpDetector.cpp.json new file mode 100644 index 00000000..6dc5c882 --- /dev/null +++ b/audit/port-map/EterLib/GrpDetector.cpp.json @@ -0,0 +1,251 @@ +{ + "reference": "EterLib/GrpDetector.cpp", + "reference_sha256": "91699012029ee35c85e22aaad1ad6732b3c5dcf1dfde38dd5f57fca5a1ca543b", + "priority": "P4", + "contracts": [], + "functions": { + "CompareD3DDisplayModeOrder": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:CompareD3DDisplayModeOrder" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CAdapterDisplayModeList::GetDisplayModeNum": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CAdapterDisplayModeList::GetDisplayModeNum" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CAdapterDisplayModeList::GetPixelFormatNum": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CAdapterDisplayModeList::GetPixelFormatNum" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CAdapterDisplayModeList::GetDisplayModer": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CAdapterDisplayModeList::GetDisplayModer" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CAdapterDisplayModeList::GetPixelFormatr": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CAdapterDisplayModeList::GetPixelFormatr" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CAdapterDisplayModeList::Build": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CAdapterDisplayModeList::Build" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_SModeInfo::GetString": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_SModeInfo::GetString" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CDeviceInfo::GetD3DModeInfoNum": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CDeviceInfo::GetD3DModeInfoNum" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CDeviceInfo::GetD3DModeInfop": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CDeviceInfo::GetD3DModeInfop" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CDeviceInfo::FindDepthStencilFormat": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CDeviceInfo::FindDepthStencilFormat" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CDeviceInfo::Build": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CDeviceInfo::Build" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CDeviceInfo::Find": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CDeviceInfo::Find" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CDeviceInfo::GetString": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CDeviceInfo::GetString" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CAdapterInfo::GetDesktopD3DDisplayModer": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CAdapterInfo::GetDesktopD3DDisplayModer" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CAdapterInfo::GetDesktopD3DDisplayModep": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CAdapterInfo::GetDesktopD3DDisplayModep" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CAdapterInfo::GetD3DDeviceInfop": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CAdapterInfo::GetD3DDeviceInfop" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CAdapterInfo::GetD3DModeInfop": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CAdapterInfo::GetD3DModeInfop" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CAdapterInfo::Find": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CAdapterInfo::Find" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CAdapterInfo::Build": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CAdapterInfo::Build" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CAdapterInfo::GetString": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CAdapterInfo::GetString" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CDisplayModeAutoDetector::D3D_CDisplayModeAutoDetector": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CDisplayModeAutoDetector::D3D_CDisplayModeAutoDetector" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CDisplayModeAutoDetector::~D3D_CDisplayModeAutoDetector": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CDisplayModeAutoDetector::~D3D_CDisplayModeAutoDetector" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CDisplayModeAutoDetector::GetD3DAdapterInfop": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CDisplayModeAutoDetector::GetD3DAdapterInfop" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CDisplayModeAutoDetector::GetD3DModeInfop": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CDisplayModeAutoDetector::GetD3DModeInfop" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CDisplayModeAutoDetector::Find": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CDisplayModeAutoDetector::Find" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CDisplayModeAutoDetector::Build": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CDisplayModeAutoDetector::Build" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + }, + "D3D_CDisplayModeAutoDetector::GetString": { + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpDetector.cpp:D3D_CDisplayModeAutoDetector::GetString" + ], + "test": [ + "tests/port/port_app_loop_test.cpp" + ] + } + } +} diff --git a/audit/port-map/EterLib/GrpDevice.cpp.json b/audit/port-map/EterLib/GrpDevice.cpp.json index 9430d245..b49ac829 100644 --- a/audit/port-map/EterLib/GrpDevice.cpp.json +++ b/audit/port-map/EterLib/GrpDevice.cpp.json @@ -221,7 +221,7 @@ "tests/port/port_app_loop_test.cpp", "tests/port/port_login_flow_test.cpp" ], - "note": "40250: GetDC, Direct3DCreate8, D3D_CDisplayModeAutoDetector Build/Find (EL3D_ConfirmDevice per device), driver black list, CreateDevice with a refresh-rate retry, DXT CheckDeviceFormat, SetWindowPos, D3DXCreateSphere/Cylinder, SIS/3dfx caps. Port: MtCreateRecordingDevice in place of the Direct3D object and detection; the present parameters the detector does not choose are set as 40250; EL3D_ConfirmDevice runs on the one device's caps; no debug meshes; no adapter identifier. Invariant: same state manager, matrix stack, screen matrices, stream shaders, default IB/PDT VB and texture-memory/border caps after Create." + "note": "40250: also makes the debug sphere/cylinder meshes (D3DXCreateSphere/D3DXCreateCylinder). Port: verbatim over the host adapter (Direct3DCreate8 in RecordingDevice.cpp: one HAL adapter, CreateDevice makes the recording device); no D3DX mesh builders, so ms_lpSphereMesh/ms_lpCylinderMesh stay NULL. Invariant: same detection, present parameters, state manager, matrices, stream shaders, default buffers and caps flags." }, "CGraphicDevice::__InitializePDTVertexBufferList": { "status": "PORTED", diff --git a/audit/port-map/EterPythonLib/PythonGraphic.cpp.json b/audit/port-map/EterPythonLib/PythonGraphic.cpp.json index 91bbfdd6..0c0a3987 100644 --- a/audit/port-map/EterPythonLib/PythonGraphic.cpp.json +++ b/audit/port-map/EterPythonLib/PythonGraphic.cpp.json @@ -17,9 +17,10 @@ "src/platform/EterPythonLib/PythonGraphic.cpp:CPythonGraphic::GetD3D" ], "test": [ + "tests/port/port_app_loop_test.cpp", "tests/port/port_login_flow_test.cpp" ], - "note": "40250 returns the IDirect3D8 it created; the port has no D3D8 object, so a CDummyDirect3D8 answers the only caller (CPythonSystem::GetDisplaySettings) with adapter modes 800x600/1024x768/1280x1024 X8R8G8B8 @60. Invariant: systemSetting.GetResolutionCount() > 0 and every mode passes the >=800x600 filter." + "note": "40250 returns ms_lpd3d, which CPythonApplication::Create made before GetDisplaySettings. Port: PythonBoot::Start runs GetDisplaySettings before app.Create, so it returns Direct3DCreate8's host adapter (RecordingDevice.cpp), the object CGraphicDevice::Create later keeps in ms_lpd3d; modes 800x600/1024x768/1280x1024 X8R8G8B8 @60. Invariant: systemSetting.GetResolutionCount() > 0 and every mode passes the >=800x600 filter." }, "CPythonGraphic::GetOrthoDepth": { "status": "PORTED", diff --git a/src/platform/EterLib/GrpDetector.cpp b/src/platform/EterLib/GrpDetector.cpp index f0886ebc..e2e62052 100644 --- a/src/platform/EterLib/GrpDetector.cpp +++ b/src/platform/EterLib/GrpDetector.cpp @@ -1,165 +1,648 @@ -// Platform skeleton for EterLib/GrpDetector.h (40250 EterLib/GrpDetector.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. +// 40250 EterLib/GrpDetector.cpp, verbatim. #include "EterLib/StdAfx.h" +#include "EterBase/Stl.h" #include "EterLib/GrpDetector.h" -#include "../PlatformStub.h" - -auto D3D_SModeInfo::GetString(std::string *) -> void +struct FIsEqualD3DDisplayMode { - MT_PLATFORM_STUB(); + FIsEqualD3DDisplayMode(D3DDISPLAYMODE* pkD3DDMChk) + { + m_pkD3DDMChk=pkD3DDMChk; + } + BOOL operator() (D3DDISPLAYMODE& rkD3DDMTest) + { + if (rkD3DDMTest.Width!=m_pkD3DDMChk->Width) + return FALSE; + + if (rkD3DDMTest.Height!=m_pkD3DDMChk->Height) + return FALSE; + + if (rkD3DDMTest.Format!=m_pkD3DDMChk->Format) + return FALSE; + + return TRUE; + } + + D3DDISPLAYMODE* m_pkD3DDMChk; +}; + +static int CompareD3DDisplayModeOrder( const VOID* arg1, const VOID* arg2 ) +{ + D3DDISPLAYMODE* p1 = (D3DDISPLAYMODE*)arg1; + D3DDISPLAYMODE* p2 = (D3DDISPLAYMODE*)arg2; + + if( p1->Format > p2->Format ) return -1; + if( p1->Format < p2->Format ) return +1; + if( p1->Width < p2->Width ) return -1; + if( p1->Width > p2->Width ) return +1; + if( p1->Height < p2->Height ) return -1; + if( p1->Height > p2->Height ) return +1; + + return 0; } -auto D3D_CAdapterDisplayModeList::Build(IDirect3D8 &, D3DFORMAT, UINT) -> void + + +///////////////////////////////////////////////////////////////////////////////// + +UINT D3D_CAdapterDisplayModeList::GetDisplayModeNum() { - MT_PLATFORM_STUB(); + return m_uD3DDMNum; } -auto D3D_CAdapterDisplayModeList::GetDisplayModeNum() -> UINT +UINT D3D_CAdapterDisplayModeList::GetPixelFormatNum() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + return m_uD3DFmtNum; } -auto D3D_CAdapterDisplayModeList::GetPixelFormatNum() -> UINT + +const D3DDISPLAYMODE& D3D_CAdapterDisplayModeList::GetDisplayModer(UINT iD3DDM) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + assert(iD3DDM const D3DDISPLAYMODE & +const D3DFORMAT& D3D_CAdapterDisplayModeList::GetPixelFormatr(UINT iD3DFmt) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + assert(iD3DFmt const D3DFORMAT & +VOID D3D_CAdapterDisplayModeList::Build(IDirect3D8& rkD3D, D3DFORMAT eD3DFmtDefault, UINT iD3DAdapterInfo) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + D3DDISPLAYMODE* akD3DDM=m_akD3DDM; + D3DFORMAT* aeD3DFmt=m_aeD3DFmt; + + UINT uD3DDMNum=0; + UINT uD3DFmtNum=0; + + aeD3DFmt[uD3DFmtNum++]=eD3DFmtDefault; + + UINT uAdapterModeNum=rkD3D.GetAdapterModeCount(iD3DAdapterInfo); + for (UINT iD3DAdapterInfoMode=0; iD3DAdapterInfoMode BOOL -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); +///////////////////////////////////////////////////////////////////////////////// + +VOID D3D_SModeInfo::GetString(std::string* pstEnumList) +{ + UINT uScrDepthBits=16; + switch (m_eD3DFmtPixel) + { + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + case D3DFMT_R8G8B8: + uScrDepthBits=32; + break; + } + + int iVP=0; + + switch (m_dwD3DBehavior) + { + case D3DCREATE_HARDWARE_VERTEXPROCESSING: + iVP=1; + break; + case D3DCREATE_MIXED_VERTEXPROCESSING: + iVP=2; + break; + case D3DCREATE_SOFTWARE_VERTEXPROCESSING: + iVP=3; + break; + } + + static const char* szVP[4]= + { + "UNKNOWN", + "HWVP", + "MXVP", + "SWVP", + }; + + char szText[1024+1]; + _snprintf(szText, sizeof(szText), "%dx%dx%d %s\r\n", m_uScrWidth, m_uScrHeight, uScrDepthBits, szVP[iVP]); + pstEnumList->append(szText); } -auto D3D_CDeviceInfo::Find(UINT, UINT, UINT, BOOL, UINT *) -> BOOL +///////////////////////////////////////////////////////////////////////////////// + +const CHAR* D3D_CDeviceInfo::msc_aszD3DDevDesc[D3DDEVICETYPE_NUM] = {"HAL", "REF"}; +const D3DDEVTYPE D3D_CDeviceInfo::msc_aeD3DDevType[D3DDEVICETYPE_NUM]={D3DDEVTYPE_HAL, D3DDEVTYPE_REF}; + + +UINT D3D_CDeviceInfo::GetD3DModeInfoNum() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + return m_uD3DModeInfoNum; } -auto D3D_CDeviceInfo::GetD3DModeInfoNum() -> UINT +D3D_SModeInfo* D3D_CDeviceInfo::GetD3DModeInfop(UINT iD3D_SModeInfo) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + if (iD3D_SModeInfo >= m_uD3DModeInfoNum) + return NULL; + + return &m_akD3DModeInfo[iD3D_SModeInfo]; } -auto D3D_CDeviceInfo::GetString(std::string *) -> void +BOOL D3D_CDeviceInfo::FindDepthStencilFormat(IDirect3D8& rkD3D, UINT iD3DAdapterInfo, D3DDEVTYPE DeviceType, D3DFORMAT TargetFormat, D3DFORMAT* pDepthStencilFormat ) { - MT_PLATFORM_STUB(); + UINT m_dwMinDepthBits = 16; + UINT m_dwMinStencilBits = 0; + + if( m_dwMinDepthBits <= 16 && m_dwMinStencilBits == 0 ) + { + if( SUCCEEDED( rkD3D.CheckDeviceFormat( iD3DAdapterInfo, DeviceType, + TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) ) + { + if( SUCCEEDED( rkD3D.CheckDepthStencilMatch( iD3DAdapterInfo, DeviceType, + TargetFormat, TargetFormat, D3DFMT_D16 ) ) ) + { + *pDepthStencilFormat = D3DFMT_D16; + return TRUE; + } + } + } + + if( m_dwMinDepthBits <= 15 && m_dwMinStencilBits <= 1 ) + { + if( SUCCEEDED( rkD3D.CheckDeviceFormat( iD3DAdapterInfo, DeviceType, + TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D15S1 ) ) ) + { + if( SUCCEEDED( rkD3D.CheckDepthStencilMatch( iD3DAdapterInfo, DeviceType, + TargetFormat, TargetFormat, D3DFMT_D15S1 ) ) ) + { + *pDepthStencilFormat = D3DFMT_D15S1; + return TRUE; + } + } + } + + if( m_dwMinDepthBits <= 24 && m_dwMinStencilBits == 0 ) + { + if( SUCCEEDED( rkD3D.CheckDeviceFormat( iD3DAdapterInfo, DeviceType, + TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) ) + { + if( SUCCEEDED( rkD3D.CheckDepthStencilMatch( iD3DAdapterInfo, DeviceType, + TargetFormat, TargetFormat, D3DFMT_D24X8 ) ) ) + { + *pDepthStencilFormat = D3DFMT_D24X8; + return TRUE; + } + } + } + + if( m_dwMinDepthBits <= 24 && m_dwMinStencilBits <= 8 ) + { + if( SUCCEEDED( rkD3D.CheckDeviceFormat( iD3DAdapterInfo, DeviceType, + TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) ) + { + if( SUCCEEDED( rkD3D.CheckDepthStencilMatch( iD3DAdapterInfo, DeviceType, + TargetFormat, TargetFormat, D3DFMT_D24S8 ) ) ) + { + *pDepthStencilFormat = D3DFMT_D24S8; + return TRUE; + } + } + } + + if( m_dwMinDepthBits <= 24 && m_dwMinStencilBits <= 4 ) + { + if( SUCCEEDED( rkD3D.CheckDeviceFormat( iD3DAdapterInfo, DeviceType, + TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X4S4 ) ) ) + { + if( SUCCEEDED( rkD3D.CheckDepthStencilMatch( iD3DAdapterInfo, DeviceType, + TargetFormat, TargetFormat, D3DFMT_D24X4S4 ) ) ) + { + *pDepthStencilFormat = D3DFMT_D24X4S4; + return TRUE; + } + } + } + + if( m_dwMinDepthBits <= 32 && m_dwMinStencilBits == 0 ) + { + if( SUCCEEDED( rkD3D.CheckDeviceFormat( iD3DAdapterInfo, DeviceType, + TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D32 ) ) ) + { + if( SUCCEEDED( rkD3D.CheckDepthStencilMatch( iD3DAdapterInfo, DeviceType, + TargetFormat, TargetFormat, D3DFMT_D32 ) ) ) + { + *pDepthStencilFormat = D3DFMT_D32; + return TRUE; + } + } + } + + return FALSE; } -auto D3D_CDeviceInfo::FindDepthStencilFormat(IDirect3D8 &, UINT, D3DDEVTYPE, D3DFORMAT, D3DFORMAT *) -> BOOL -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); +BOOL D3D_CDeviceInfo::Build(IDirect3D8& rkD3D, UINT iD3DAdapterInfo, UINT iDevType, D3D_CAdapterDisplayModeList& rkD3DADMList, BOOL (*pfnConfirmDevice)(D3DCAPS8& rkD3DCaps, UINT uBehavior, D3DFORMAT eD3DFmt)) +{ + assert(pfnConfirmDevice!=NULL && "D3D_CDeviceInfo::Build"); + + const D3DDEVTYPE c_eD3DDevType=msc_aeD3DDevType[iDevType]; + const TCHAR* c_szD3DDevDesc=msc_aszD3DDevDesc[iDevType]; + + m_eD3DDevType = c_eD3DDevType; + rkD3D.GetDeviceCaps(iD3DAdapterInfo, c_eD3DDevType, &m_kD3DCaps); + + m_szDevDesc = c_szD3DDevDesc; + m_uD3DModeInfoNum=0; + m_canDoWindowed = FALSE; + m_isWindowed = FALSE; + m_eD3DMSTFullscreen = D3DMULTISAMPLE_NONE; + m_eD3DMSTWindowed = D3DMULTISAMPLE_NONE; + + BOOL aisFormatConfirmed[20]; + DWORD adwD3DBehavior[20]; + D3DFORMAT aeD3DFmtDepthStencil[20]; + + BOOL isHALExists = FALSE; + BOOL isHALWindowedCompatible = FALSE; + BOOL isHALDesktopCompatible = FALSE; + BOOL isHALSampleCompatible = FALSE; + + // GetFlagInfo + { + UINT uD3DFmtNum=rkD3DADMList.GetPixelFormatNum(); + + for (DWORD iFmt=0; iFmt0) + return TRUE; + + return FALSE; } -auto D3D_CDeviceInfo::GetD3DModeInfor(UINT) -> D3D_SModeInfo & +BOOL D3D_CDeviceInfo::Find(UINT uScrWidth, UINT uScrHeight, UINT uScrDepthBits, BOOL isWindowed, UINT* piD3DModeInfo) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + if (isWindowed) + if (!m_isWindowed) + return FALSE; + + for (UINT iD3D_SModeInfo=0; iD3D_SModeInfo D3D_SModeInfo * +VOID D3D_CDeviceInfo::GetString(std::string* pstEnumList) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + char szText[1024+1]; + _snprintf(szText, sizeof(szText), "%s\r\n========================================\r\n", m_szDevDesc); + pstEnumList->append(szText); + + for (UINT iD3D_SModeInfo=0; iD3D_SModeInfoappend(szText); + + D3D_SModeInfo& rkModeInfo=m_akD3DModeInfo[iD3D_SModeInfo]; + rkModeInfo.GetString(pstEnumList); + } + + pstEnumList->append("\r\n"); } -decltype(D3D_CDeviceInfo::msc_aszD3DDevDesc) D3D_CDeviceInfo::msc_aszD3DDevDesc{}; +///////////////////////////////////////////////////////////////////////////// -decltype(D3D_CDeviceInfo::msc_aeD3DDevType) D3D_CDeviceInfo::msc_aeD3DDevType{}; - -auto D3D_CAdapterInfo::Find(UINT, UINT, UINT, BOOL, UINT *, UINT *) -> BOOL +D3DDISPLAYMODE& D3D_CAdapterInfo::GetDesktopD3DDisplayModer() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + return m_kD3DDMDesktop; } -auto D3D_CAdapterInfo::Build(IDirect3D8 &, UINT, PFNCONFIRMDEVICE) -> BOOL +D3DDISPLAYMODE* D3D_CAdapterInfo::GetDesktopD3DDisplayModep() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + return &m_kD3DDMDesktop; } -auto D3D_CAdapterInfo::GetString(std::string *) -> void +D3D_CDeviceInfo* D3D_CAdapterInfo::GetD3DDeviceInfop(UINT iD3DDevInfo) { - MT_PLATFORM_STUB(); + if (iD3DDevInfo >= m_uD3DDevInfoNum) + return NULL; + + return &m_akD3DDevInfo[iD3DDevInfo]; } -auto D3D_CAdapterInfo::GetDesktopD3DDisplayModer() -> D3DDISPLAYMODE & +D3D_SModeInfo* D3D_CAdapterInfo::GetD3DModeInfop(UINT iD3DDevInfo, UINT iD3D_SModeInfo) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + D3D_CDeviceInfo* pkD3DDevInfo=GetD3DDeviceInfop(iD3DDevInfo); + if (pkD3DDevInfo) + { + D3D_SModeInfo* pkD3DModeInfo=pkD3DDevInfo->GetD3DModeInfop(iD3D_SModeInfo); + if (pkD3DModeInfo) + return pkD3DModeInfo; + } + return NULL; } -auto D3D_CAdapterInfo::GetDesktopD3DDisplayModep() -> D3DDISPLAYMODE * +BOOL D3D_CAdapterInfo::Find(UINT uScrWidth, UINT uScrHeight, UINT uScrDepthBits, BOOL isWindowed, UINT* piD3DModeInfo, UINT* piD3DDevInfo) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + for (UINT iDevInfo=0; iDevInfo D3D_CDeviceInfo * +BOOL D3D_CAdapterInfo::Build(IDirect3D8& rkD3D, UINT iD3DAdapterInfo, PFNCONFIRMDEVICE pfnConfirmDevice) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + D3DDISPLAYMODE& rkD3DDMDesktop=m_kD3DDMDesktop; + if (FAILED(rkD3D.GetAdapterDisplayMode(iD3DAdapterInfo, &rkD3DDMDesktop))) + return FALSE; + + rkD3D.GetAdapterIdentifier(iD3DAdapterInfo, D3DENUM_NO_WHQL_LEVEL, &m_kD3DAdapterIdentifier); + + m_iCurD3DDevInfo=0; + m_uD3DDevInfoNum=0; + + D3D_CAdapterDisplayModeList kD3DADMList; + kD3DADMList.Build(rkD3D, m_kD3DDMDesktop.Format, iD3DAdapterInfo); + + D3D_CDeviceInfo* akD3DDevInfo=m_akD3DDevInfo; + for (UINT iDevType=0; iDevType0) + return TRUE; + + return FALSE; } -auto D3D_CAdapterInfo::GetD3DModeInfop(UINT, UINT) -> D3D_SModeInfo * +VOID D3D_CAdapterInfo::GetString(std::string* pstEnumList) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + for (UINT iDevInfo=0; iDevInfoappend(szText); + + D3D_CDeviceInfo& rkD3DDevInfo=m_akD3DDevInfo[iDevInfo]; + rkD3DDevInfo.GetString(pstEnumList); + } } +///////////////////////////////////////////////////////////////////////////// + D3D_CDisplayModeAutoDetector::D3D_CDisplayModeAutoDetector() { - MT_PLATFORM_STUB(); + m_uD3DAdapterInfoCount=0; } D3D_CDisplayModeAutoDetector::~D3D_CDisplayModeAutoDetector() { - MT_PLATFORM_STUB(); } -auto D3D_CDisplayModeAutoDetector::Find(UINT, UINT, UINT, BOOL, UINT *, UINT *, UINT *) -> BOOL +D3D_CAdapterInfo* D3D_CDisplayModeAutoDetector::GetD3DAdapterInfop(UINT iD3DAdapterInfo) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + if (iD3DAdapterInfo >= m_uD3DAdapterInfoCount) + return NULL; + + return &m_akD3DAdapterInfo[iD3DAdapterInfo]; } -auto D3D_CDisplayModeAutoDetector::Build(IDirect3D8 &, PFNCONFIRMDEVICE) -> BOOL -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); +D3D_SModeInfo* D3D_CDisplayModeAutoDetector::GetD3DModeInfop(UINT iD3DAdapterInfo, UINT iD3DDevInfo, UINT iD3D_SModeInfo) +{ + D3D_CAdapterInfo* pkD3DAdapterInfo=GetD3DAdapterInfop(iD3DAdapterInfo); + if (pkD3DAdapterInfo) + { + D3D_CDeviceInfo* pkD3DDevInfo=pkD3DAdapterInfo->GetD3DDeviceInfop(iD3DDevInfo); + if (pkD3DDevInfo) + { + D3D_SModeInfo* pkD3D_SModeInfo=pkD3DDevInfo->GetD3DModeInfop(iD3D_SModeInfo); + if (pkD3D_SModeInfo) + return pkD3D_SModeInfo; + } + } + return NULL; } -auto D3D_CDisplayModeAutoDetector::GetD3DAdapterInfop(UINT) -> D3D_CAdapterInfo * +BOOL D3D_CDisplayModeAutoDetector::Find(UINT uScrWidth, UINT uScrHeight, UINT uScrDepthBits, BOOL isWindowed, UINT* piD3DModeInfo, UINT* piD3DDevInfo, UINT* piD3DAdapterInfo) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + for (UINT iD3DAdapterInfo=0; iD3DAdapterInfo D3D_SModeInfo * +BOOL D3D_CDisplayModeAutoDetector::Build(IDirect3D8& rkD3D, PFNCONFIRMDEVICE pfnConfirmDevice) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + m_uD3DAdapterInfoCount=0; + + UINT uTotalAdapterCount=rkD3D.GetAdapterCount(); + uTotalAdapterCount=min(uTotalAdapterCount, D3DADAPTERINFO_NUM); + + for (UINT iD3DAdapterInfo=0; iD3DAdapterInfo0) + return TRUE; + + return FALSE; } -auto D3D_CDisplayModeAutoDetector::GetString(std::string *) -> void +VOID D3D_CDisplayModeAutoDetector::GetString(std::string* pstEnumList) { - MT_PLATFORM_STUB(); + for (UINT iD3DAdapterInfo=0; iD3DAdapterInfoappend(szText); + + D3D_CAdapterInfo& rkAdapterInfo=m_akD3DAdapterInfo[iD3DAdapterInfo]; + rkAdapterInfo.GetString(pstEnumList); + } } diff --git a/src/platform/EterLib/GrpDevice.cpp b/src/platform/EterLib/GrpDevice.cpp index b9319143..17e2fccc 100644 --- a/src/platform/EterLib/GrpDevice.cpp +++ b/src/platform/EterLib/GrpDevice.cpp @@ -1,12 +1,9 @@ -// 40250 EterLib/GrpDevice.cpp, verbatim but for CGraphicDevice::Create, which makes the recording device -// (RecordingDevice.h) in place of the Direct3D object, adapter detection and CreateDevice. +// 40250 EterLib/GrpDevice.cpp, verbatim. Direct3DCreate8 is the host adapter of RecordingDevice.cpp. #include "EterLib/StdAfx.h" #include "EterLib/GrpDevice.h" #include "EterBase/Stl.h" #include "EterBase/Debug.h" -#include "RecordingDevice.h" - bool GRAPHICS_CAPS_CAN_NOT_DRAW_LINE = false; bool GRAPHICS_CAPS_CAN_NOT_DRAW_SHADOW = false; bool GRAPHICS_CAPS_HALF_SIZE_IMAGE = false; @@ -359,12 +356,69 @@ int CGraphicDevice::Create(HWND hWnd, int iHres, int iVres, bool Windowed, int / ms_iHeight = iVres; ms_hWnd = hWnd; - // PORT: in place of GetDC, Direct3DCreate8, the D3D_CDisplayModeAutoDetector adapter/mode search, the - // driver black list, CreateDevice with its refresh-rate retry, the DXT format checks and the full-screen - // SetWindowPos: the recording device (RecordingDevice.h) renders through the host, which owns the window - // and supports DXT and hardware T&L at any refresh rate. - ms_lpd3dDevice = MtCreateRecordingDevice(iHres, iVres); + ms_hDC = GetDC(hWnd); + ms_lpd3d = Direct3DCreate8(D3D_SDK_VERSION); + if (!ms_lpd3d) + return CREATE_NO_DIRECTX; + + if (!ms_kD3DDetector.Build(*ms_lpd3d, EL3D_ConfirmDevice)) + return CREATE_ENUM; + + if (!ms_kD3DDetector.Find(800, 600, 32, TRUE, &ms_iD3DModeInfo, &ms_iD3DDevInfo, &ms_iD3DAdapterInfo)) + return CREATE_DETECT; + + std::string stDevList; + ms_kD3DDetector.GetString(&stDevList); + + //Tracen(stDevList.c_str()); + //Tracenf("adapter %d, device %d, mode %d", ms_iD3DAdapterInfo, ms_iD3DDevInfo, ms_iD3DModeInfo); + + D3D_CAdapterInfo * pkD3DAdapterInfo = ms_kD3DDetector.GetD3DAdapterInfop(ms_iD3DAdapterInfo); + if (!pkD3DAdapterInfo) + { + Tracenf("adapter %d is EMPTY", ms_iD3DAdapterInfo); + return CREATE_DETECT; + } + + if (__IsInDriverBlackList(*pkD3DAdapterInfo)) + { + iRet |= CREATE_BAD_DRIVER; + __WarningMessage(hWnd, CREATE_BAD_DRIVER); + } + + D3D_SModeInfo * pkD3DModeInfo = pkD3DAdapterInfo->GetD3DModeInfop(ms_iD3DDevInfo, ms_iD3DModeInfo); + if (!pkD3DModeInfo) + { + Tracenf("device %d, mode %d is EMPTY", ms_iD3DDevInfo, ms_iD3DModeInfo); + return CREATE_DETECT; + } + + D3DADAPTER_IDENTIFIER8& rkD3DAdapterId=pkD3DAdapterInfo->GetIdentifier(); + if (Windowed && + strnicmp(rkD3DAdapterId.Driver, "3dfx", 4)==0 && + 22 == pkD3DAdapterInfo->GetDesktopD3DDisplayModer().Format) + { + return CREATE_FORMAT; + } + + if (pkD3DModeInfo->m_dwD3DBehavior==D3DCREATE_SOFTWARE_VERTEXPROCESSING) + { + iRet |= CREATE_NO_TNL; + + // DISABLE_NOTIFY_NOT_SUPPORT_TNL_MESSAGE + //__WarningMessage(hWnd, CREATE_NO_TNL); + // END_OF_DISABLE_NOTIFY_NOT_SUPPORT_TNL_MESSAGE + } + + std::string stModeInfo; + pkD3DModeInfo->GetString(&stModeInfo); + + //Tracen(stModeInfo.c_str()); + + int ErrorCorrection = 0; + +RETRY: ZeroMemory(&ms_d3dPresentParameter, sizeof(ms_d3dPresentParameter)); ms_d3dPresentParameter.Windowed = Windowed; @@ -374,13 +428,90 @@ int CGraphicDevice::Create(HWND hWnd, int iHres, int iVres, bool Windowed, int / ms_d3dPresentParameter.BackBufferCount = m_uBackBufferCount; ms_d3dPresentParameter.SwapEffect = D3DSWAPEFFECT_DISCARD; - if (!Windowed) + if (Windowed) + { + ms_d3dPresentParameter.BackBufferFormat = pkD3DAdapterInfo->GetDesktopD3DDisplayModer().Format; + } + else + { + ms_d3dPresentParameter.BackBufferFormat = pkD3DModeInfo->m_eD3DFmtPixel; ms_d3dPresentParameter.FullScreen_RefreshRateInHz = iReflashRate; + } ms_d3dPresentParameter.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; ms_d3dPresentParameter.EnableAutoDepthStencil = TRUE; + ms_d3dPresentParameter.AutoDepthStencilFormat = pkD3DModeInfo->m_eD3DFmtDepthStencil; - ms_dwD3DBehavior = D3DCREATE_HARDWARE_VERTEXPROCESSING; + ms_dwD3DBehavior = pkD3DModeInfo->m_dwD3DBehavior; + + if (FAILED(ms_hLastResult = ms_lpd3d->CreateDevice( + ms_iD3DAdapterInfo, + D3DDEVTYPE_HAL, + hWnd, + // 2004. 1. 9 myevan 버텍스 프로세싱 방식 자동 선택 추가 + pkD3DModeInfo->m_dwD3DBehavior, + &ms_d3dPresentParameter, + &ms_lpd3dDevice))) + { + switch (ms_hLastResult) + { + case D3DERR_INVALIDCALL: + Tracen("IDirect3DDevice.CreateDevice - ERROR D3DERR_INVALIDCALL\nThe method call is invalid. For example, a method's parameter may have an invalid value."); + break; + case D3DERR_NOTAVAILABLE: + Tracen("IDirect3DDevice.CreateDevice - ERROR D3DERR_NOTAVAILABLE\nThis device does not support the queried technique. "); + break; + case D3DERR_OUTOFVIDEOMEMORY: + Tracen("IDirect3DDevice.CreateDevice - ERROR D3DERR_OUTOFVIDEOMEMORY\nDirect3D does not have enough display memory to perform the operation"); + break; + default: + Tracenf("IDirect3DDevice.CreateDevice - ERROR %d", ms_hLastResult); + break; + } + + if (ErrorCorrection) + return CREATE_DEVICE; + + // 2004. 1. 9 myevan 큰의미 없는 코드인듯.. 에러나면 표시하고 종료하자 + iReflashRate = 0; + ++ErrorCorrection; + iRet = CREATE_REFRESHRATE; + goto RETRY; + } + + // Check DXT Support Info + if(ms_lpd3d->CheckDeviceFormat( + ms_iD3DAdapterInfo, + D3DDEVTYPE_HAL, + ms_d3dPresentParameter.BackBufferFormat, + 0, + D3DRTYPE_TEXTURE, + D3DFMT_DXT1) == D3DERR_NOTAVAILABLE) + { + ms_bSupportDXT = false; + } + + if(ms_lpd3d->CheckDeviceFormat( + ms_iD3DAdapterInfo, + D3DDEVTYPE_HAL, + ms_d3dPresentParameter.BackBufferFormat, + 0, + D3DRTYPE_TEXTURE, + D3DFMT_DXT3) == D3DERR_NOTAVAILABLE) + { + ms_bSupportDXT = false; + } + + if(ms_lpd3d->CheckDeviceFormat( + ms_iD3DAdapterInfo, + D3DDEVTYPE_HAL, + ms_d3dPresentParameter.BackBufferFormat, + 0, + D3DRTYPE_TEXTURE, + D3DFMT_DXT5) == D3DERR_NOTAVAILABLE) + { + ms_bSupportDXT = false; + } if (FAILED((ms_hLastResult = ms_lpd3dDevice->GetDeviceCaps(&ms_d3dCaps)))) { @@ -388,9 +519,10 @@ int CGraphicDevice::Create(HWND hWnd, int iHres, int iVres, bool Windowed, int / return CREATE_GET_DEVICE_CAPS2; } - // PORT: the detector runs EL3D_ConfirmDevice on each device's caps; here on the one device (max texture size). - if (!EL3D_ConfirmDevice(ms_d3dCaps, ms_dwD3DBehavior, ms_d3dPresentParameter.BackBufferFormat)) - return CREATE_DETECT; + if (!Windowed) + SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, iHres, iVres, SWP_SHOWWINDOW); + + //Tracef("vertex shader version : %X\n",(DWORD)ms_d3dCaps.VertexShaderVersion); ms_lpd3dDevice->GetViewport(&ms_Viewport); @@ -448,7 +580,20 @@ int CGraphicDevice::Create(HWND hWnd, int iHres, int iVres, bool Windowed, int / else GRAPHICS_CAPS_CAN_NOT_TEXTURE_ADDRESS_BORDER=true; - // PORT: the SIS/3dfx driver caps have no adapter identifier to test. + //D3DADAPTER_IDENTIFIER8& rkD3DAdapterId=pkD3DAdapterInfo->GetIdentifier(); + if (strnicmp(rkD3DAdapterId.Driver, "SIS", 3) == 0) + { + GRAPHICS_CAPS_CAN_NOT_DRAW_LINE = true; + GRAPHICS_CAPS_CAN_NOT_DRAW_SHADOW = true; + GRAPHICS_CAPS_HALF_SIZE_IMAGE = true; + ms_isLowTextureMemory = true; + } + else if (strnicmp(rkD3DAdapterId.Driver, "3dfx", 4) == 0) + { + GRAPHICS_CAPS_CAN_NOT_DRAW_SHADOW = true; + GRAPHICS_CAPS_HALF_SIZE_IMAGE = true; + ms_isLowTextureMemory = true; + } return (iRet); } diff --git a/src/platform/EterLib/RecordingDevice.cpp b/src/platform/EterLib/RecordingDevice.cpp index e0e18d90..2f4d91e3 100644 --- a/src/platform/EterLib/RecordingDevice.cpp +++ b/src/platform/EterLib/RecordingDevice.cpp @@ -232,6 +232,30 @@ struct DeviceIndexBuffer final : MtCpuIndexBuffer } }; +// PORT: a D3D8 HAL on a T&L card (D3DDEVCAPS_HWTRANSFORMANDLIGHT), 8 lights, 4 texture stages, +// vertex shader 1.1 and T&L vertex clipping, as the D3D8 runtime reports for current GPUs; with +// these CGraphicBase::IsFastTNL() is true, so auto tiling picks the hardware-transform terrain. +// Caps2 D3DCAPS2_CANRENDERWINDOWED: the frame goes to a window (the adapter's desktop mode). +void host_device_caps(D3DCAPS8* caps) +{ + std::memset(caps, 0, sizeof(*caps)); + caps->Caps2 = D3DCAPS2_CANRENDERWINDOWED; + caps->DevCaps = D3DDEVCAPS_HWTRANSFORMANDLIGHT; + caps->VertexShaderVersion = D3DVS_VERSION(1, 1); + caps->PrimitiveMiscCaps = D3DPMISCCAPS_CLIPTLVERTS; + caps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS; + caps->MaxActiveLights = 8; + caps->MaxTextureBlendStages = 4; + caps->MaxSimultaneousTextures = 4; + caps->MaxTextureWidth = caps->MaxTextureHeight = 4096; + caps->MaxAnisotropy = 16; + caps->MaxPrimitiveCount = 0xFFFFF; + caps->MaxVertexIndex = 0xFFFFF; + caps->MaxStreams = 8; + caps->MaxStreamStride = 255; + caps->TextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_MIRROR; +} + class RecordingDevice final : public IDirect3DDevice8 { public: @@ -290,26 +314,9 @@ public: return refs; } - // PORT: a D3D8 HAL on a T&L card (D3DDEVCAPS_HWTRANSFORMANDLIGHT), 8 lights, 4 texture stages, - // vertex shader 1.1 and T&L vertex clipping, as the D3D8 runtime reports for current GPUs; with - // these CGraphicBase::IsFastTNL() is true, so auto tiling picks the hardware-transform terrain. HRESULT GetDeviceCaps(D3DCAPS8* caps) override { - std::memset(caps, 0, sizeof(*caps)); - caps->DevCaps = D3DDEVCAPS_HWTRANSFORMANDLIGHT; - caps->VertexShaderVersion = D3DVS_VERSION(1, 1); - caps->PrimitiveMiscCaps = D3DPMISCCAPS_CLIPTLVERTS; - caps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS; - caps->MaxActiveLights = 8; - caps->MaxTextureBlendStages = 4; - caps->MaxSimultaneousTextures = 4; - caps->MaxTextureWidth = caps->MaxTextureHeight = 4096; - caps->MaxAnisotropy = 16; - caps->MaxPrimitiveCount = 0xFFFFF; - caps->MaxVertexIndex = 0xFFFFF; - caps->MaxStreams = 8; - caps->MaxStreamStride = 255; - caps->TextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_MIRROR; + host_device_caps(caps); return S_OK; } HRESULT GetViewport(D3DVIEWPORT8* viewport) override @@ -1313,6 +1320,73 @@ bool MtCpuMemoryTexture(const std::string& name, UIMemoryTexture* out) IDirect3DDevice8* MtCreateRecordingDevice(int width, int height) { return new RecordingDevice(width, height); } +namespace { +// PORT: the one adapter behind Direct3DCreate8: a HAL device with host_device_caps, every format usable, +// no reference rasterizer, and the display modes CPythonSystem::GetDisplaySettings lists as resolutions +// on a 1024x768 X8R8G8B8 desktop. CreateDevice makes the recording device at the back-buffer size. +class HostDirect3D8 final : public IDirect3D8 +{ +public: + ULONG Release() override { return 0; } + UINT GetAdapterCount() override { return 1; } + HRESULT GetAdapterIdentifier(UINT, DWORD, D3DADAPTER_IDENTIFIER8* pIdentifier) override + { + if (!pIdentifier) return E_FAIL; + memset(pIdentifier, 0, sizeof(D3DADAPTER_IDENTIFIER8)); + strncpy(pIdentifier->Driver, "dummy", sizeof(pIdentifier->Driver)); + strncpy(pIdentifier->Description, "Dummy Direct3D8", sizeof(pIdentifier->Description)); + return S_OK; + } + HRESULT GetAdapterDisplayMode(UINT, D3DDISPLAYMODE* pMode) override + { + if (!pMode) return E_FAIL; + pMode->Width = 1024; + pMode->Height = 768; + pMode->RefreshRate = 60; + pMode->Format = D3DFMT_X8R8G8B8; + return S_OK; + } + UINT GetAdapterModeCount(UINT) override + { + return 3; + } + HRESULT EnumAdapterModes(UINT, UINT Mode, D3DDISPLAYMODE* pMode) override + { + if (!pMode) return E_FAIL; + static const D3DDISPLAYMODE s_modes[] = { + { 800, 600, 60, D3DFMT_X8R8G8B8 }, + { 1024, 768, 60, D3DFMT_X8R8G8B8 }, + { 1280, 1024, 60, D3DFMT_X8R8G8B8 }, + }; + if (Mode >= 3) return E_FAIL; + *pMode = s_modes[Mode]; + return S_OK; + } + HRESULT CheckDeviceType(UINT, D3DDEVTYPE CheckType, D3DFORMAT, D3DFORMAT, BOOL) override + { + return CheckType == D3DDEVTYPE_HAL ? S_OK : D3DERR_NOTAVAILABLE; + } + HRESULT CheckDeviceFormat(UINT, D3DDEVTYPE, D3DFORMAT, DWORD, D3DRESOURCETYPE, D3DFORMAT) override { return S_OK; } + HRESULT CheckDepthStencilMatch(UINT, D3DDEVTYPE, D3DFORMAT, D3DFORMAT, D3DFORMAT) override { return S_OK; } + HRESULT GetDeviceCaps(UINT, D3DDEVTYPE, D3DCAPS8* pCaps) override + { + host_device_caps(pCaps); + return S_OK; + } + HRESULT CreateDevice(UINT, D3DDEVTYPE, HWND, DWORD, D3DPRESENT_PARAMETERS* pp, IDirect3DDevice8** out) override + { + *out = MtCreateRecordingDevice(int(pp->BackBufferWidth), int(pp->BackBufferHeight)); + return S_OK; + } +}; +} + +IDirect3D8* Direct3DCreate8(UINT) +{ + static HostDirect3D8 s_d3d; + return &s_d3d; +} + void SetNativeTerrainRenderEnabled(bool enabled) { g_native_terrain_override = enabled ? 1 : 0; diff --git a/src/platform/EterPythonLib/PythonGraphic.cpp b/src/platform/EterPythonLib/PythonGraphic.cpp index d8fc3db3..4290662f 100644 --- a/src/platform/EterPythonLib/PythonGraphic.cpp +++ b/src/platform/EterPythonLib/PythonGraphic.cpp @@ -33,58 +33,17 @@ CPythonGraphic::~CPythonGraphic() Tracef("Python Graphic Clear\n"); } -namespace -{ -class CDummyDirect3D8 : public IDirect3D8 -{ -public: - HRESULT GetAdapterIdentifier(UINT, DWORD, D3DADAPTER_IDENTIFIER8* pIdentifier) override - { - if (!pIdentifier) return E_FAIL; - memset(pIdentifier, 0, sizeof(D3DADAPTER_IDENTIFIER8)); - strncpy(pIdentifier->Driver, "dummy", sizeof(pIdentifier->Driver)); - strncpy(pIdentifier->Description, "Dummy Direct3D8", sizeof(pIdentifier->Description)); - return S_OK; - } - HRESULT GetAdapterDisplayMode(UINT, D3DDISPLAYMODE* pMode) override - { - if (!pMode) return E_FAIL; - pMode->Width = 1024; - pMode->Height = 768; - pMode->RefreshRate = 60; - pMode->Format = D3DFMT_X8R8G8B8; - return S_OK; - } - UINT GetAdapterModeCount(UINT) override - { - return 3; - } - HRESULT EnumAdapterModes(UINT, UINT Mode, D3DDISPLAYMODE* pMode) override - { - if (!pMode) return E_FAIL; - static const D3DDISPLAYMODE s_modes[] = { - { 800, 600, 60, D3DFMT_X8R8G8B8 }, - { 1024, 768, 60, D3DFMT_X8R8G8B8 }, - { 1280, 1024, 60, D3DFMT_X8R8G8B8 }, - }; - if (Mode >= 3) return E_FAIL; - *pMode = s_modes[Mode]; - return S_OK; - } -}; -} - // 40250 PythonGraphic.cpp:8 void CPythonGraphic::Destroy() { } -// 40250 PythonGraphic.cpp:12. PORT: no IDirect3D8 exists; a stand-in reports the adapter modes CPythonSystem -// lists as resolutions. +// 40250 PythonGraphic.cpp:12 returns ms_lpd3d. PORT: PythonBoot::Start runs CPythonSystem::GetDisplaySettings +// before app.Create makes the device (40250 runs it after, in CPythonApplication::Create), so this hands out +// the host adapter Direct3DCreate8 returns, the same object CGraphicDevice::Create keeps in ms_lpd3d. LPDIRECT3D8 CPythonGraphic::GetD3D() { - static CDummyDirect3D8 s_dummyD3D; - return &s_dummyD3D; + return Direct3DCreate8(D3D_SDK_VERSION); } void CPythonGraphic::SetViewport(float x, float y, float width, float height) diff --git a/src/port/common/D3D8Types.h b/src/port/common/D3D8Types.h index fd8bca1b..dcd6fb54 100644 --- a/src/port/common/D3D8Types.h +++ b/src/port/common/D3D8Types.h @@ -508,6 +508,9 @@ typedef enum _D3DVERTEXBLENDFLAGS { // d3d8.h device-lost results (MAKE_D3DHRESULT(2152), (2153)). #define D3DERR_DEVICELOST ((HRESULT)0x88760868L) #define D3DERR_DEVICENOTRESET ((HRESULT)0x88760869L) +#define D3DERR_NOTAVAILABLE ((HRESULT)0x8876086AL) +#define D3DERR_OUTOFVIDEOMEMORY ((HRESULT)0x8876017CL) +#define D3DERR_INVALIDCALL ((HRESULT)0x8876086CL) // d3d8types.h vertex shader declaration tokens typedef enum _D3DVSD_TOKENTYPE @@ -692,6 +695,8 @@ typedef struct _D3DCAPS8 } D3DCAPS8; #define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L +#define D3DDEVCAPS_PUREDEVICE 0x00100000L +#define D3DCAPS2_CANRENDERWINDOWED 0x00080000L #define D3DCAPS2_FULLSCREENGAMMA 0x00020000L typedef struct _D3DGAMMARAMP @@ -726,15 +731,6 @@ typedef struct _D3DGAMMARAMP // upcasts 40250 relies on (texture -> base texture) compile; of the resources only the buffers carry #define D3DENUM_NO_WHQL_LEVEL 0x00000002L -struct IDirect3D8 -{ - virtual ~IDirect3D8() = default; - virtual ULONG Release() { return 0; } - virtual HRESULT GetAdapterIdentifier(UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER8* pIdentifier) = 0; - virtual HRESULT GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE* pMode) = 0; - virtual UINT GetAdapterModeCount(UINT Adapter) = 0; - virtual HRESULT EnumAdapterModes(UINT Adapter, UINT Mode, D3DDISPLAYMODE* pMode) = 0; -}; typedef enum _D3DRESOURCETYPE { D3DRTYPE_SURFACE = 1, @@ -747,6 +743,26 @@ typedef enum _D3DRESOURCETYPE D3DRTYPE_FORCE_DWORD = 0x7fffffff } D3DRESOURCETYPE; +struct IDirect3DDevice8; +struct IDirect3D8 +{ + virtual ~IDirect3D8() = default; + virtual ULONG Release() = 0; + virtual UINT GetAdapterCount() = 0; + virtual HRESULT GetAdapterIdentifier(UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER8* pIdentifier) = 0; + virtual UINT GetAdapterModeCount(UINT Adapter) = 0; + virtual HRESULT EnumAdapterModes(UINT Adapter, UINT Mode, D3DDISPLAYMODE* pMode) = 0; + virtual HRESULT GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE* pMode) = 0; + virtual HRESULT CheckDeviceType(UINT Adapter, D3DDEVTYPE CheckType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL Windowed) = 0; + virtual HRESULT CheckDeviceFormat(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) = 0; + virtual HRESULT CheckDepthStencilMatch(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) = 0; + virtual HRESULT GetDeviceCaps(UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS8* pCaps) = 0; + virtual HRESULT CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice8** ppReturnedDeviceInterface) = 0; +}; +// d3d8.h; platform/EterLib/RecordingDevice.cpp implements the one host adapter. +#define D3D_SDK_VERSION 220 +IDirect3D8* Direct3DCreate8(UINT SDKVersion); + typedef struct _D3DLOCKED_RECT { INT Pitch; diff --git a/src/port/common/Win32Crt.h b/src/port/common/Win32Crt.h index a61747db..f95b2ed4 100644 --- a/src/port/common/Win32Crt.h +++ b/src/port/common/Win32Crt.h @@ -103,8 +103,6 @@ uintptr_t _beginthreadex(void* security, unsigned stack_size, unsigned (*start_a #define MB_TOPMOST 0x00040000L #define IDOK 1 int MessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType); -// user32 ReleaseDC: the host owns the window and hands out no DC, so there is none to release. -inline int ReleaseDC(HWND, HDC) { return 1; } // winmm `timeGetTime`: milliseconds since system start, wrapping at 2^32. DWORD timeGetTime(); diff --git a/src/port/common/shim/win32/winuser.h b/src/port/common/shim/win32/winuser.h index 3f47d2d5..01bada9e 100644 --- a/src/port/common/shim/win32/winuser.h +++ b/src/port/common/shim/win32/winuser.h @@ -30,6 +30,14 @@ typedef WORD ATOM; #define SWP_NOSIZE 0x0001 #define SWP_NOMOVE 0x0002 #define SWP_NOZORDER 0x0004 +#define SWP_SHOWWINDOW 0x0040 + +#define HWND_TOP ((HWND)0) +#define HWND_TOPMOST ((HWND)-1) + +// GetDC/ReleaseDC: the host draws the window, so there is no GDI device context to hand out. +inline HDC GetDC(HWND) { return NULL; } +inline int ReleaseDC(HWND, HDC) { return 1; } #define PM_NOREMOVE 0x0000 #define PM_REMOVE 0x0001 diff --git a/tests/port/port_app_loop_test.cpp b/tests/port/port_app_loop_test.cpp index eafddf9e..598c9024 100644 --- a/tests/port/port_app_loop_test.cpp +++ b/tests/port/port_app_loop_test.cpp @@ -40,6 +40,11 @@ struct GraphicBaseAccess : CGraphicBase static DWORD PT() { return ms_ptVS; } static DWORD PNT() { return ms_pntVS; } static DWORD PNT2() { return ms_pnt2VS; } + static LPDIRECT3D8 D3D() { return ms_lpd3d; } + static D3D_SModeInfo* Mode() { return ms_kD3DDetector.GetD3DModeInfop(ms_iD3DAdapterInfo, ms_iD3DDevInfo, ms_iD3DModeInfo); } + static const D3DPRESENT_PARAMETERS& PP() { return ms_d3dPresentParameter; } + static DWORD Behavior() { return ms_dwD3DBehavior; } + static void DetectorString(std::string* s) { ms_kD3DDetector.GetString(s); } }; static int g_failures = 0; @@ -309,6 +314,19 @@ int main(int argc, char** argv) CHECK(GraphicBaseAccess::PNT() == (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)); CHECK(GraphicBaseAccess::PNT2() == (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX2)); CHECK(GetMaxTextureWidth() == 4096 && GetMaxTextureHeight() == 4096); + // D3D_CDisplayModeAutoDetector over the host adapter: its HAL device, the 800x600x32 mode Create asks + // for, hardware vertex processing and the first depth format FindDepthStencilFormat tries (D16). + CHECK(GraphicBaseAccess::D3D() == Direct3DCreate8(D3D_SDK_VERSION)); + { + D3D_SModeInfo* mode = GraphicBaseAccess::Mode(); + CHECK(mode && mode->m_uScrWidth == 800 && mode->m_uScrHeight == 600 && mode->m_eD3DFmtPixel == D3DFMT_X8R8G8B8); + CHECK(mode && mode->m_dwD3DBehavior == D3DCREATE_HARDWARE_VERTEXPROCESSING && mode->m_eD3DFmtDepthStencil == D3DFMT_D16); + CHECK(GraphicBaseAccess::Behavior() == D3DCREATE_HARDWARE_VERTEXPROCESSING); + CHECK(GraphicBaseAccess::PP().AutoDepthStencilFormat == D3DFMT_D16 && GraphicBaseAccess::PP().BackBufferFormat == D3DFMT_X8R8G8B8); + std::string modes; + GraphicBaseAccess::DetectorString(&modes); + CHECK(modes.find("800x600x32 HWVP") != std::string::npos); + } { CScreen screen; CHECK(!screen.IsLostDevice() && screen.RestoreDevice());