From b5d413afa657ccbd2bd80b00ff09083572bc6a5a Mon Sep 17 00:00:00 2001 From: shenlei Date: Wed, 30 Sep 2026 14:40:57 +0900 Subject: [PATCH] port: GrpScreen verbatim 40250 (2d draws via UIRender, D3D8 shim device-lost/Present/ID3DXMesh) Co-Authored-By: Claude Opus 5.5 --- audit/history.jsonl | 1 + audit/port-map/EterLib/GrpScreen.cpp.json | 406 +++++++-- src/platform/EterLib/GrpScreen.cpp | 979 ++++++++++++++++------ src/platform/EterLib/RecordingDevice.cpp | 10 + src/port/common/D3D8Types.h | 11 + src/port/common/shim/sdk/d3dx8.h | 12 +- tests/port/port_app_loop_test.cpp | 29 + 7 files changed, 1125 insertions(+), 323 deletions(-) diff --git a/audit/history.jsonl b/audit/history.jsonl index 753cd562..00e70685 100644 --- a/audit/history.jsonl +++ b/audit/history.jsonl @@ -636,3 +636,4 @@ {"date": "2026-09-30", "unit": "EterLib/GrpFontTexture.cpp", "action": "port", "evidence": "40250 bodies over Win32Gdi; HiDPI oversample adaptations noted; port.text"} {"date": "2026-09-30", "unit": "EterLib/GrpTextInstance.cpp", "action": "port", "evidence": "verbatim except Render draw calls -> UIRender commands; port.text, port.app_loop"} {"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)"} diff --git a/audit/port-map/EterLib/GrpScreen.cpp.json b/audit/port-map/EterLib/GrpScreen.cpp.json index 5fa332fc..743f2f32 100644 --- a/audit/port-map/EterLib/GrpScreen.cpp.json +++ b/audit/port-map/EterLib/GrpScreen.cpp.json @@ -5,175 +5,469 @@ "contracts": [], "functions": { "CScreen::RenderLine3d": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderLine3d" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::RenderBox3d": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderBox3d" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::RenderBar3d": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderBar3d" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::RenderGradationBar3d": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderGradationBar3d" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::RenderLineCube": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderLineCube" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::RenderCube": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderCube" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::RenderLine2d": { - "status": "TODO" + "status": "ADAPTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderLine2d" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ], + "note": "40250: RenderLine3d at z. Port: under CPythonGraphic::SetOrtho2D the UI is drawn from UIRender commands, not device primitives (the recording device ignores ortho line lists and draws untextured ortho quads without their diffuse), so the 2d form emits the command directly. Invariant: same corners and colours." }, "CScreen::RenderBox2d": { "status": "ADAPTED", "impl": [ "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderBox2d" ], - "test": "tests/port/port_app_loop_test.cpp", - "note": "40250 four edge line pairs, including the bottom edge extending one pixel, are recorded into the Godot UI command stream." + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ], + "note": "40250: RenderBox3d at z (four line pairs, bottom edge one pixel longer). Port: under CPythonGraphic::SetOrtho2D the UI is drawn from UIRender commands, not device primitives (the recording device ignores ortho line lists and draws untextured ortho quads without their diffuse), so the 2d form emits the command directly. Invariant: same corners and colours." }, "CScreen::RenderBar2d": { - "status": "TODO" + "status": "ADAPTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderBar2d" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ], + "note": "40250: RenderBar3d at z. Port: under CPythonGraphic::SetOrtho2D the UI is drawn from UIRender commands, not device primitives (the recording device ignores ortho line lists and draws untextured ortho quads without their diffuse), so the 2d form emits the command directly. Invariant: same corners and colours." }, "CScreen::RenderGradationBar2d": { "status": "ADAPTED", "impl": [ "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderGradationBar2d" ], - "test": "tests/port/port_app_loop_test.cpp", - "note": "40250 top and bottom vertex colours are serialized as a vertically interpolated Godot canvas polygon; zero-width and zero-height guards match the source." + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ], + "note": "40250: RenderGradationBar3d at z (start colour on the top edge, end colour on the bottom; returns for zero width/height). Port: under CPythonGraphic::SetOrtho2D the UI is drawn from UIRender commands, not device primitives (the recording device ignores ortho line lists and draws untextured ortho quads without their diffuse), so the 2d form emits the command directly. Invariant: same corners and colours." }, "CScreen::RenderCircle2d": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderCircle2d" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::RenderCircle3d": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderCircle3d" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::RenderD3DXMesh": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderD3DXMesh" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::RenderSphere": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderSphere" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::RenderCylinder": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderCylinder" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::RenderTextureBox": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderTextureBox" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::RenderBillboard": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RenderBillboard" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::DrawMinorGrid": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::DrawMinorGrid" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::DrawGrid": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::DrawGrid" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::SetCursorPosition": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ "src/platform/EterLib/GrpScreen.cpp:CScreen::SetCursorPosition" ], - "test": "tests/port/port_login_flow_test.cpp", - "note": "40250 body verbatim in the platform layer (pick ray through the cursor)." + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::GetCursorPosition": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::GetCursorPosition" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::GetCursorXYPosition": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::GetCursorXYPosition" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::GetCursorZPosition": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::GetCursorZPosition" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::GetPickingPosition": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::GetPickingPosition" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::SetDiffuseColor": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::SetDiffuseColor" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::SetClearColor": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::SetClearColor" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::SetClearDepth": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::SetClearDepth" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::SetClearStencil": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::SetClearStencil" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::ClearDepthBuffer": { - "status": "NEEDS_LIVE", + "status": "PORTED", "impl": [ "src/platform/EterLib/GrpScreen.cpp:CScreen::ClearDepthBuffer" ], - "note": "Statement-equivalent Clear(ZBUFFER, ms_clearColor, ms_clearDepth, ms_clearStencil). The port had ms_clearDepth/ms_diffuseColor zero-initialized instead of 40250's 1.0f/0xffffffff; fixed. RecordingDevice now records back-buffer clears in draw order and the native renderer executes them (vkCmdClearAttachments over the current viewport); before, the clear was dropped. Native fake-server char select shows the model again with the clear executed; Windows screenshot parity open." + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::Clear": { - "status": "NEEDS_LIVE", + "status": "PORTED", "impl": [ "src/platform/EterLib/GrpScreen.cpp:CScreen::Clear" ], - "note": "Statement-equivalent Clear(TARGET|ZBUFFER); executed in draw order by the native renderer since the clear-entry change. Windows screenshot parity open." + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::IsLostDevice": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::IsLostDevice" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::RestoreDevice": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::RestoreDevice" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::Begin": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::Begin" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::End": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::End" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::Show": { - "status": "TODO" + "status": "ADAPTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::Show" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ], + "note": "40250: Present, or four Present rects around g_rcBrowser while the in-game web page is open. Port: g_isBrowserMode/g_rcBrowser are file statics (false/empty) since PythonApplicationWebPage is DIVERGENT; the rects cast to LONG (32-bit on LP64); the recording device's Present is D3D_OK and the host presents the frame. Invariant: whole back buffer presented." }, "CScreen::ProjectPosition": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ "src/platform/EterLib/GrpScreen.cpp:CScreen::ProjectPosition" ], - "note": "Body verbatim; D3DXVec3Project/Unproject come from port/common/D3DXMath.cpp (D3DX semantics, null matrix = identity).", - "test": "tests/port/port_login_flow_test.cpp ground-item step (port.login_flow: ALT frame projects the item name tail, textTail Pick returns the ground item VID)" + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::UnprojectPosition": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ "src/platform/EterLib/GrpScreen.cpp:CScreen::UnprojectPosition" ], - "note": "Body verbatim; D3DXVec3Project/Unproject come from port/common/D3DXMath.cpp (D3DX semantics, null matrix = identity).", - "test": "tests/port/port_login_flow_test.cpp ground-item step (port.login_flow: ALT frame projects the item name tail, textTail Pick returns the ground item VID)" + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::SetColorOperation": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::SetColorOperation" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::SetDiffuseOperation": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::SetDiffuseOperation" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::SetBlendOperation": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::SetBlendOperation" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::SetOneColorOperation": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::SetOneColorOperation" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::SetAddColorOperation": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::SetAddColorOperation" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::Identity": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::Identity" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::CScreen": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::CScreen" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::~CScreen": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::~CScreen" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] }, "CScreen::BuildViewFrustum": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "src/platform/EterLib/GrpScreen.cpp:CScreen::BuildViewFrustum" + ], + "test": [ + "tests/port/port_app_loop_test.cpp", + "tests/port/port_login_flow_test.cpp" + ] } } } diff --git a/src/platform/EterLib/GrpScreen.cpp b/src/platform/EterLib/GrpScreen.cpp index 869a9290..a59f1c32 100644 --- a/src/platform/EterLib/GrpScreen.cpp +++ b/src/platform/EterLib/GrpScreen.cpp @@ -1,261 +1,509 @@ -// Platform skeleton for EterLib/GrpScreen.h (40250 EterLib/GrpScreen.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. +// 40250 EterLib/GrpScreen.cpp, verbatim. #include "EterLib/StdAfx.h" #include "EterLib/GrpScreen.h" -#include "EterLib/StateManager.h" #include "EterLib/Camera.h" +#include "EterLib/StateManager.h" -#include "../PlatformStub.h" #include "UIRenderCommands.h" -#include -// 40250 GrpScreen.cpp:838 -CScreen::CScreen() +DWORD CScreen::ms_diffuseColor = 0xffffffff; +DWORD CScreen::ms_clearColor = 0L; +DWORD CScreen::ms_clearStencil = 0L; +float CScreen::ms_clearDepth = 1.0f; +Frustum CScreen::ms_frustum; + +extern bool GRAPHICS_CAPS_CAN_NOT_DRAW_LINE; + +void CScreen::RenderLine3d(float sx, float sy, float sz, float ex, float ey, float ez) { + if (GRAPHICS_CAPS_CAN_NOT_DRAW_LINE) + return; + + assert(ms_lpd3dDevice != NULL); + + SPDTVertexRaw vertices[2] = + { + { sx, sy, sz, ms_diffuseColor, 0.0f, 0.0f }, + { ex, ey, ez, ms_diffuseColor, 0.0f, 0.0f } + }; + + // 2004.11.18.myevan.DrawIndexPrimitiveUP -> DynamicVertexBuffer + if (SetPDTStream(vertices, 2)) + { + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); + STATEMANAGER.DrawPrimitive(D3DPT_LINELIST, 0, 1); + } } -CScreen::~CScreen() +void CScreen::RenderBox3d(float sx, float sy, float sz, float ex, float ey, float ez) { + if (GRAPHICS_CAPS_CAN_NOT_DRAW_LINE) + return; + + assert(ms_lpd3dDevice != NULL); + + SPDTVertexRaw vertices[8] = + { + { sx, sy, sz, ms_diffuseColor, 0.0f, 0.0f }, // 0 + { ex, sy, sz, ms_diffuseColor, 0.0f, 0.0f }, // 1 + + { sx, sy, sz, ms_diffuseColor, 0.0f, 0.0f }, // 0 + { sx, ey, ez, ms_diffuseColor, 0.0f, 0.0f }, // 2 + + { ex, sy, sz, ms_diffuseColor, 0.0f, 0.0f }, // 1 + { ex, ey, ez, ms_diffuseColor, 0.0f, 0.0f }, // 3 + + { sx, ey, ez, ms_diffuseColor, 0.0f, 0.0f }, // 2 + { ex+1.0f, ey, ez, ms_diffuseColor, 0.0f, 0.0f } // 3, (x가 1증가된 3) + }; + + // 2004.11.18.myevan.DrawIndexPrimitiveUP -> DynamicVertexBuffer + if (SetPDTStream(vertices, 8)) + { + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); + STATEMANAGER.DrawPrimitive(D3DPT_LINELIST, 0, 4); + } } -auto CScreen::ClearDepthBuffer() -> void -{ - if (ms_lpd3dDevice) - ms_lpd3dDevice->Clear(0L, NULL, D3DCLEAR_ZBUFFER, ms_clearColor, ms_clearDepth, ms_clearStencil); -} - -auto CScreen::Clear() -> void -{ - if (ms_lpd3dDevice) - ms_lpd3dDevice->Clear(0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, ms_clearColor, ms_clearDepth, ms_clearStencil); -} - -// 40250 GrpScreen.cpp:691. CPythonApplication::Process brackets the frame's render with Begin/End; only -// inside the scene does CStateManager hand transforms to the recording device. -bool CScreen::Begin() +void CScreen::RenderBar3d(float sx, float sy, float sz, float ex, float ey, float ez) { assert(ms_lpd3dDevice != NULL); - ResetFaceCount(); - if (!STATEMANAGER.BeginScene()) + SPDTVertexRaw vertices[4] = { - Tracenf("BeginScene FAILED\n"); - return false; + { sx, sy, sz, ms_diffuseColor, 0.0f, 0.0f }, + { sx, ey, ez, ms_diffuseColor, 0.0f, 0.0f }, + { ex, sy, sz, ms_diffuseColor, 0.0f, 0.0f }, + { ex, ey, ez, ms_diffuseColor, 0.0f, 0.0f }, + }; + + + + if (SetPDTStream(vertices, 4)) + { + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); + STATEMANAGER.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + } +} + +void CScreen::RenderBar3d(const D3DXVECTOR3 * c_pv3Positions) +{ + assert(ms_lpd3dDevice != NULL); + + SPDTVertexRaw vertices[4] = + { + { c_pv3Positions[0].x, c_pv3Positions[0].y, c_pv3Positions[0].z, ms_diffuseColor, 0.0f, 0.0f }, + { c_pv3Positions[2].x, c_pv3Positions[2].y, c_pv3Positions[2].z, ms_diffuseColor, 0.0f, 0.0f }, + { c_pv3Positions[1].x, c_pv3Positions[1].y, c_pv3Positions[1].z, ms_diffuseColor, 0.0f, 0.0f }, + { c_pv3Positions[3].x, c_pv3Positions[3].y, c_pv3Positions[3].z, ms_diffuseColor, 0.0f, 0.0f }, + }; + + + if (SetPDTStream(vertices, 4)) + { + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); + STATEMANAGER.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + } +} + +void CScreen::RenderGradationBar3d(float sx, float sy, float sz, float ex, float ey, float ez, DWORD dwStartColor, DWORD dwEndColor) +{ + assert(ms_lpd3dDevice != NULL); + if (sx==ex) return; + if (sy==ey) return; + + SPDTVertexRaw vertices[4] = + { + { sx, sy, sz, dwStartColor, 0.0f, 0.0f }, + { sx, ey, ez, dwEndColor, 0.0f, 0.0f }, + { ex, sy, sz, dwStartColor, 0.0f, 0.0f }, + { ex, ey, ez, dwEndColor, 0.0f, 0.0f }, + }; + + if (SetPDTStream(vertices, 4)) + { + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); + STATEMANAGER.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + } +} + +void CScreen::RenderLineCube(float sx, float sy, float sz, float ex, float ey, float ez) +{ + SPDTVertexRaw vertices[8] = + { + { sx, sy, sz, ms_diffuseColor, 0.0f, 0.0f }, + { ex, sy, sz, ms_diffuseColor, 0.0f, 0.0f }, + { sx, ey, sz, ms_diffuseColor, 0.0f, 0.0f }, + { ex, ey, sz, ms_diffuseColor, 0.0f, 0.0f }, + { sx, sy, ez, ms_diffuseColor, 0.0f, 0.0f }, + { ex, sy, ez, ms_diffuseColor, 0.0f, 0.0f }, + { sx, ey, ez, ms_diffuseColor, 0.0f, 0.0f }, + { ex, ey, ez, ms_diffuseColor, 0.0f, 0.0f }, + }; + + + if (SetPDTStream(vertices, 8)) + { + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); + STATEMANAGER.SetTransform(D3DTS_WORLD, ms_lpd3dMatStack->GetTop()); + SetDefaultIndexBuffer(DEFAULT_IB_LINE_CUBE); + + STATEMANAGER.DrawIndexedPrimitive(D3DPT_LINELIST, 0, 8, 0, 4*3); + } +} + +void CScreen::RenderCube(float sx, float sy, float sz, float ex, float ey, float ez) +{ + SPDTVertexRaw vertices[8] = + { + { sx, sy, sz, ms_diffuseColor, 0.0f, 0.0f }, + { ex, sy, sz, ms_diffuseColor, 0.0f, 0.0f }, + { sx, ey, sz, ms_diffuseColor, 0.0f, 0.0f }, + { ex, ey, sz, ms_diffuseColor, 0.0f, 0.0f }, + { sx, sy, ez, ms_diffuseColor, 0.0f, 0.0f }, + { ex, sy, ez, ms_diffuseColor, 0.0f, 0.0f }, + { sx, ey, ez, ms_diffuseColor, 0.0f, 0.0f }, + { ex, ey, ez, ms_diffuseColor, 0.0f, 0.0f }, + }; + + + if (SetPDTStream(vertices, 8)) + { + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); + STATEMANAGER.SetTransform(D3DTS_WORLD, ms_lpd3dMatStack->GetTop()); + + SetDefaultIndexBuffer(DEFAULT_IB_FILL_CUBE); + STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 8, 0, 4*3); + } +} + +void CScreen::RenderCube(float sx, float sy, float sz, float ex, float ey, float ez, D3DXMATRIX matRotation) +{ + D3DXVECTOR3 v3Center = D3DXVECTOR3((sx + ex) * 0.5f, (sy + ey) * 0.5f, (sz + ez) * 0.5f); + D3DXVECTOR3 v3Vertex[8] = + { + D3DXVECTOR3(sx, sy, sz), + D3DXVECTOR3(ex, sy, sz), + D3DXVECTOR3(sx, ey, sz), + D3DXVECTOR3(ex, ey, sz), + D3DXVECTOR3(sx, sy, ez), + D3DXVECTOR3(ex, sy, ez), + D3DXVECTOR3(sx, ey, ez), + D3DXVECTOR3(ex, ey, ez), + }; + SPDTVertexRaw vertices[8]; + + for(int i = 0; i < 8; i++) + { + v3Vertex[i] = v3Vertex[i] - v3Center; + D3DXVec3TransformCoord(&v3Vertex[i], &v3Vertex[i], &matRotation); + v3Vertex[i] = v3Vertex[i] + v3Center; + vertices[i].px = v3Vertex[i].x; + vertices[i].py = v3Vertex[i].y; + vertices[i].pz = v3Vertex[i].z; + vertices[i].diffuse = ms_diffuseColor; + vertices[i].u = 0.0f; vertices[i].v = 0.0f; } - return true; + if (SetPDTStream(vertices, 8)) + { + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); + STATEMANAGER.SetTransform(D3DTS_WORLD, ms_lpd3dMatStack->GetTop()); + + SetDefaultIndexBuffer(DEFAULT_IB_FILL_CUBE); + STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 8, 0, 4*3); + } } -// 40250 GrpScreen.cpp:705 -void CScreen::End() -{ - STATEMANAGER.EndScene(); -} - -auto CScreen::Show(HWND) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::Show(RECT *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::Show(RECT *, HWND) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::RenderLine2d(float sx, float sy, float ex, float ey, float) -> void +void CScreen::RenderLine2d(float sx, float sy, float ex, float ey, float z) { + // PORT: under CPythonGraphic::SetOrtho2D the UI is drawn from UIRender commands (UIRenderCommands.h), + // not from device primitives; the command carries the same corners and diffuse colour. UIRenderAdd({UIRenderCommand::Line, sx, sy, ex, ey, ms_diffuseColor}); } -auto CScreen::RenderBox2d(float sx, float sy, float ex, float ey, float) -> void +void CScreen::RenderBox2d(float sx, float sy, float ex, float ey, float z) { - // 40250's four line pairs, including its one-pixel extension of the bottom edge. + // PORT: under CPythonGraphic::SetOrtho2D the UI is drawn from UIRender commands (UIRenderCommands.h), + // not from device primitives; the command carries the same corners and diffuse colour. + // RenderBox3d's four line pairs, including its one-pixel extension of the bottom edge. UIRenderAdd({UIRenderCommand::Line, sx, sy, ex, sy, ms_diffuseColor}); UIRenderAdd({UIRenderCommand::Line, sx, sy, sx, ey, ms_diffuseColor}); UIRenderAdd({UIRenderCommand::Line, ex, sy, ex, ey, ms_diffuseColor}); UIRenderAdd({UIRenderCommand::Line, sx, ey, ex + 1.0f, ey, ms_diffuseColor}); } -auto CScreen::RenderBar2d(float sx, float sy, float ex, float ey, float) -> void +void CScreen::RenderBar2d(float sx, float sy, float ex, float ey, float z) { + // PORT: under CPythonGraphic::SetOrtho2D the UI is drawn from UIRender commands (UIRenderCommands.h), + // not from device primitives; the command carries the same corners and diffuse colour. UIRenderAdd({UIRenderCommand::Bar, sx, sy, ex, ey, ms_diffuseColor}); } -auto CScreen::RenderGradationBar2d(float sx, float sy, float ex, float ey, DWORD start, DWORD end, float) -> void +void CScreen::RenderGradationBar2d(float sx, float sy, float ex, float ey, DWORD dwStartColor, DWORD dwEndColor, float ez) { - if (sx == ex || sy == ey) - return; - UIRenderCommand command{UIRenderCommand::GradientBar, sx, sy, ex, ey, start}; - command.end_argb = end; + // PORT: under CPythonGraphic::SetOrtho2D the UI is drawn from UIRender commands (UIRenderCommands.h), + // not from device primitives; the command carries the same corners and diffuse colour. + // RenderGradationBar3d's early-outs, then its start colour at the top edge and end colour at the bottom. + if (sx==ex) return; + if (sy==ey) return; + UIRenderCommand command{UIRenderCommand::GradientBar, sx, sy, ex, ey, dwStartColor}; + command.end_argb = dwEndColor; UIRenderAdd(std::move(command)); } -auto CScreen::RenderCircle2d(float, float, float, float, int) -> void +void CScreen::RenderCircle2d(float fx, float fy, float fz, float fRadius, int iStep) { - MT_PLATFORM_STUB(); + int count; + float theta, delta; + float x, y, z; + std::vector pts; + + pts.clear(); + pts.resize(iStep); + + theta = 0.0; + delta = 2 * D3DX_PI / float(iStep); + + for (count=0; count void +void CScreen::RenderCircle3d(float fx, float fy, float fz, float fRadius, int iStep) { - MT_PLATFORM_STUB(); + int count; + float theta, delta; + std::vector pts; + + pts.clear(); + pts.resize(iStep); + + theta = 0.0; + delta = 2 * D3DX_PI / float(iStep); + + const D3DXMATRIX & c_rmatInvView = CCameraManager::Instance().GetCurrentCamera()->GetBillboardMatrix(); + + for (count=0; count void +class CD3DXMeshRenderingOption : public CScreen { - MT_PLATFORM_STUB(); +public: + DWORD m_dwVS; + + CD3DXMeshRenderingOption(D3DFILLMODE d3dFillMode, const D3DXMATRIX & c_rmatWorld) + { + ms_lpd3dDevice->GetVertexShader(&m_dwVS); + + STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + STATEMANAGER.SetRenderState(D3DRS_FILLMODE, d3dFillMode); + STATEMANAGER.SaveTransform(D3DTS_WORLD, &c_rmatWorld); + + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + } + + virtual ~CD3DXMeshRenderingOption() + { + ms_lpd3dDevice->SetVertexShader(m_dwVS); + + STATEMANAGER.RestoreTransform(D3DTS_WORLD); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG1); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLOROP); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAOP); + STATEMANAGER.SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + } +}; + +void CScreen::RenderD3DXMesh(LPD3DXMESH lpMesh, const D3DXMATRIX * c_pmatWorld, float fx, float fy, float fz, float fRadius, D3DFILLMODE d3dFillMode) +{ + D3DXMATRIX matTranslation; + D3DXMATRIX matScaling; + + D3DXMatrixTranslation(&matTranslation, fx, fy, fz); + D3DXMatrixScaling(&matScaling, fRadius, fRadius, fRadius); + + D3DXMATRIX matWorld; + matWorld = matScaling * matTranslation; + + if (c_pmatWorld) + { + matWorld *= *c_pmatWorld; + } + + CD3DXMeshRenderingOption SetRenderingOption(d3dFillMode, matWorld); + LPDIRECT3DINDEXBUFFER8 lpIndexBuffer; + LPDIRECT3DVERTEXBUFFER8 lpVertexBuffer; + lpMesh->GetIndexBuffer(&lpIndexBuffer); + lpMesh->GetVertexBuffer(&lpVertexBuffer); + STATEMANAGER.SetVertexShader(lpMesh->GetFVF()); + STATEMANAGER.SetIndices(lpIndexBuffer, 0); + STATEMANAGER.SetStreamSource(0, lpVertexBuffer, 24); + STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, lpMesh->GetNumVertices(), 0, lpMesh->GetNumFaces()); } -auto CScreen::RenderBox3d(float, float, float, float, float, float) -> void +void CScreen::RenderSphere(const D3DXMATRIX * c_pmatWorld, float fx, float fy, float fz, float fRadius, D3DFILLMODE d3dFillMode) { - MT_PLATFORM_STUB(); + RenderD3DXMesh(ms_lpSphereMesh, c_pmatWorld, fx, fy, fz, fRadius, d3dFillMode); } -auto CScreen::RenderBar3d(float, float, float, float, float, float) -> void +void CScreen::RenderCylinder(const D3DXMATRIX * c_pmatWorld, float fx, float fy, float fz, float fRadius, float /*fLength*/, D3DFILLMODE d3dFillMode) { - MT_PLATFORM_STUB(); + RenderD3DXMesh(ms_lpCylinderMesh, c_pmatWorld, fx, fy, fz, fRadius, d3dFillMode); } -auto CScreen::RenderBar3d(const D3DXVECTOR3 *) -> void +void CScreen::RenderTextureBox(float sx, float sy, float ex, float ey, float z, float su, float sv, float eu, float ev) { - MT_PLATFORM_STUB(); + assert(ms_lpd3dDevice != NULL); + + TPDTVertex vertices[4]; + + vertices[0].position = TPosition(sx, sy, z); + vertices[0].diffuse = ms_diffuseColor; + vertices[0].texCoord = TTextureCoordinate(su, sv); + + vertices[1].position = TPosition(ex, sy, z); + vertices[1].diffuse = ms_diffuseColor; + vertices[1].texCoord = TTextureCoordinate(eu, sv); + + vertices[2].position = TPosition(sx, ey, z); + vertices[2].diffuse = ms_diffuseColor; + vertices[2].texCoord = TTextureCoordinate(su, ev); + + vertices[3].position = TPosition(ex, ey, z); + vertices[3].diffuse = ms_diffuseColor; + vertices[3].texCoord = TTextureCoordinate(eu, ev); + +#ifdef WORLD_EDITOR + STATEMANAGER.SetTransform(D3DTS_WORLD, ms_lpd3dMatStack->GetTop()); +#endif + STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); + + // 2004.11.18.myevan.DrawIndexPrimitiveUP -> DynamicVertexBuffer + SetDefaultIndexBuffer(DEFAULT_IB_FILL_RECT); + if (SetPDTStream(vertices, 4)) + STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 4, 0, 2); + //OLD: STATEMANAGER.DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &ms_fillRectIdxVector[0], D3DFMT_INDEX16, vertices, sizeof(TPDTVertex)); } -auto CScreen::RenderGradationBar3d(float, float, float, float, float, float, DWORD, DWORD) -> void + +void CScreen::RenderBillboard(D3DXVECTOR3 * Position, D3DXCOLOR & Color) { - MT_PLATFORM_STUB(); + assert(ms_lpd3dDevice != NULL); + + TPDTVertex vertices[4]; + vertices[0].position = TPosition(Position[0].x, Position[0].y, Position[0].z); + vertices[0].diffuse = Color; + vertices[0].texCoord = TTextureCoordinate(0, 0); + + vertices[1].position = TPosition(Position[1].x, Position[1].y, Position[1].z); + vertices[1].diffuse = Color; + vertices[1].texCoord = TTextureCoordinate(1, 0); + + vertices[2].position = TPosition(Position[2].x, Position[2].y, Position[2].z); + vertices[2].diffuse = Color; + vertices[2].texCoord = TTextureCoordinate(0, 1); + + vertices[3].position = TPosition(Position[3].x, Position[3].y, Position[3].z); + vertices[3].diffuse = Color; + vertices[3].texCoord = TTextureCoordinate(1, 1); + + STATEMANAGER.SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1); + + // 2004.11.18.myevan.DrawIndexPrimitiveUP -> DynamicVertexBuffer + SetDefaultIndexBuffer(DEFAULT_IB_FILL_RECT); + if (SetPDTStream(vertices, 4)) + STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 4, 0, 2); + //OLD: STATEMANAGER.DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &ms_fillRectIdxVector[0], D3DFMT_INDEX16, vertices, sizeof(TPDTVertex)); } -auto CScreen::RenderLineCube(float, float, float, float, float, float) -> void +void CScreen::DrawMinorGrid(float xMin, float yMin, float xMax, float yMax, float xminorStep, float yminorStep, float zPos) { - MT_PLATFORM_STUB(); + float x, y; + + for (y = yMin; y <= yMax; y += yminorStep) + RenderLine2d(xMin, y, xMax, y, zPos); + + for (x = xMin; x <= xMax; x += xminorStep) + RenderLine2d(x, yMin, x, yMax, zPos); } -auto CScreen::RenderCube(float, float, float, float, float, float) -> void +void CScreen::DrawGrid(float xMin, float yMin, float xMax, float yMax, float xmajorStep, float ymajorStep, float xminorStep, float yminorStep, float zPos) { - MT_PLATFORM_STUB(); + xMin*=xminorStep; + xMax*=xminorStep; + yMin*=yminorStep; + yMax*=yminorStep; + xmajorStep*=xminorStep; + ymajorStep*=yminorStep; + + float x, y; + + SetDiffuseColor(0.5f, 0.5f, 0.5f); + DrawMinorGrid(xMin, yMin, xMax, yMax, xminorStep, yminorStep, zPos); + + SetDiffuseColor(0.7f, 0.7f, 0.7f); + for (y = 0.0f; y >= yMin; y -= ymajorStep) + RenderLine2d(xMin, y, xMax, y, zPos); + + for (y = 0.0f; y <= yMax; y += ymajorStep) + RenderLine2d(xMin, y, xMax, y, zPos); + + for (x = 0.0f; x >= xMin; x -= xmajorStep) + RenderLine2d(x, yMin, x, yMax, zPos); + + for (x = 0.0f; x <= yMax; x += xmajorStep) + RenderLine2d(x, yMin, x, yMax, zPos); + + SetDiffuseColor(1.0f, 1.0f, 1.0f); + RenderLine2d(xMin, 0.0f, xMax, 0.0f, zPos); + RenderLine2d(0.0f, yMin, 0.0f, yMax, zPos); } -auto CScreen::RenderCube(float, float, float, float, float, float, D3DXMATRIX) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::RenderTextureBox(float, float, float, float, float, float, float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::RenderBillboard(D3DXVECTOR3 *, D3DXCOLOR &) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::DrawMinorGrid(float, float, float, float, float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::DrawGrid(float, float, float, float, float, float, float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::RenderD3DXMesh(LPD3DXMESH, const D3DXMATRIX *, float, float, float, float, D3DFILLMODE) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::RenderSphere(const D3DXMATRIX *, float, float, float, float, D3DFILLMODE) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::RenderCylinder(const D3DXMATRIX *, float, float, float, float, float, D3DFILLMODE) -> void -{ - MT_PLATFORM_STUB(); -} - -// 40250 GrpScreen.cpp -void CScreen::SetColorOperation() -{ - STATEMANAGER.SetTexture(0, NULL); - STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); - STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); - STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); -} - -// 40250 GrpScreen.cpp -void CScreen::SetDiffuseOperation() -{ - STATEMANAGER.SetTexture(0, NULL); - STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - - STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); -} - -// 40250 GrpScreen.cpp -void CScreen::SetBlendOperation() -{ - STATEMANAGER.SetTexture(0, NULL); - STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); - STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT); - STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); -} - -auto CScreen::SetOneColorOperation(D3DXCOLOR &) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::SetAddColorOperation(D3DXCOLOR &) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::SetDiffuseColor(DWORD color) -> void -{ - ms_diffuseColor = color; -} - -auto CScreen::SetDiffuseColor(float r, float g, float b, float a) -> void -{ - auto channel = [](float value) -> DWORD { - return static_cast(std::clamp(value, 0.0f, 1.0f) * 255.0f + 0.5f); - }; - ms_diffuseColor = (channel(a) << 24) | (channel(r) << 16) | (channel(g) << 8) | channel(b); -} - -auto CScreen::SetClearColor(float, float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::SetClearDepth(float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CScreen::SetClearStencil(DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -// 40250 GrpScreen.cpp:487, verbatim: the pick ray through the cursor. void CScreen::SetCursorPosition(int x, int y, int hres, int vres) { D3DXVECTOR3 v; @@ -266,7 +514,7 @@ void CScreen::SetCursorPosition(int x, int y, int hres, int vres) D3DXMATRIX matViewInverse=ms_matInverseView; //D3DXMatrixInverse(&matViewInverse, NULL, &ms_matView); - ms_vtPickRayDir.x = v.x * matViewInverse._11 + + ms_vtPickRayDir.x = v.x * matViewInverse._11 + v.y * matViewInverse._21 + v.z * matViewInverse._31; @@ -281,27 +529,60 @@ void CScreen::SetCursorPosition(int x, int y, int hres, int vres) ms_vtPickRayOrig.x = matViewInverse._41; ms_vtPickRayOrig.y = matViewInverse._42; ms_vtPickRayOrig.z = matViewInverse._43; - + +// // 2003. 9. 9 동현 추가 +// // 지형 picking을 위한 뻘짓... ㅡㅡ; 위에 것과 통합 필요... ms_Ray.SetStartPoint(ms_vtPickRayOrig); ms_Ray.SetDirection(-ms_vtPickRayDir, 51200.0f); +// // 2003. 9. 9 동현 추가 } -auto CScreen::GetCursorPosition(float * px, float * py, float * pz) -> bool +bool CScreen::GetCursorPosition(float* px, float* py, float* pz) { if (!GetCursorXYPosition(px, py)) return false; if (!GetCursorZPosition(pz)) return false; + return true; } -auto CScreen::GetCursorXYPosition(float * px, float * py) -> bool +bool CScreen::GetCursorXYPosition(float* px, float* py) { D3DXVECTOR3 v3Eye = CCameraManager::Instance().GetCurrentCamera()->GetEye(); TPosition posVertices[4]; - posVertices[0] = TPosition(v3Eye.x - 90000000.0f, v3Eye.y + 90000000.0f, 0.0f); - posVertices[1] = TPosition(v3Eye.x - 90000000.0f, v3Eye.y - 90000000.0f, 0.0f); - posVertices[2] = TPosition(v3Eye.x + 90000000.0f, v3Eye.y + 90000000.0f, 0.0f); - posVertices[3] = TPosition(v3Eye.x + 90000000.0f, v3Eye.y - 90000000.0f, 0.0f); + posVertices[0] = TPosition(v3Eye.x-90000000.0f, v3Eye.y+90000000.0f, 0.0f); + posVertices[1] = TPosition(v3Eye.x-90000000.0f, v3Eye.y-90000000.0f, 0.0f); + posVertices[2] = TPosition(v3Eye.x+90000000.0f, v3Eye.y+90000000.0f, 0.0f); + posVertices[3] = TPosition(v3Eye.x+90000000.0f, v3Eye.y-90000000.0f, 0.0f); + + static const WORD sc_awFillRectIndices[6] = { 0, 2, 1, 2, 3, 1, }; + + float u, v, t; + for (int i = 0; i < 2; ++i) + { + if (IntersectTriangle(ms_vtPickRayOrig, ms_vtPickRayDir, + posVertices[sc_awFillRectIndices[i*3+0]], + posVertices[sc_awFillRectIndices[i*3+1]], + posVertices[sc_awFillRectIndices[i*3+2]], + &u, &v, &t)) + { + *px = ms_vtPickRayOrig.x + ms_vtPickRayDir.x * t; + *py = ms_vtPickRayOrig.y + ms_vtPickRayDir.y * t; + return true; + } + } + return false; +} + +bool CScreen::GetCursorZPosition(float* pz) +{ + D3DXVECTOR3 v3Eye = CCameraManager::Instance().GetCurrentCamera()->GetEye(); + + TPosition posVertices[4]; + posVertices[0] = TPosition(v3Eye.x-90000000.0f, 0.0f, v3Eye.z+90000000.0f); + posVertices[1] = TPosition(v3Eye.x-90000000.0f, 0.0f, v3Eye.z-90000000.0f); + posVertices[2] = TPosition(v3Eye.x+90000000.0f, 0.0f, v3Eye.z+90000000.0f); + posVertices[3] = TPosition(v3Eye.x+90000000.0f, 0.0f, v3Eye.z-90000000.0f); static const WORD sc_awFillRectIndices[6] = { 0, 2, 1, 2, 3, 1, }; @@ -309,60 +590,190 @@ auto CScreen::GetCursorXYPosition(float * px, float * py) -> bool for (int i = 0; i < 2; ++i) { if (IntersectTriangle(ms_vtPickRayOrig, ms_vtPickRayDir, - posVertices[sc_awFillRectIndices[i * 3]], - posVertices[sc_awFillRectIndices[i * 3 + 1]], - posVertices[sc_awFillRectIndices[i * 3 + 2]], - &u, &v, &t)) + posVertices[sc_awFillRectIndices[i*3+0]], + posVertices[sc_awFillRectIndices[i*3+1]], + posVertices[sc_awFillRectIndices[i*3+2]], + &u, &v, &t)) { - *px = u; - *py = v; + *pz = ms_vtPickRayOrig.z + ms_vtPickRayDir.z * t; return true; } } return false; } -auto CScreen::GetCursorZPosition(float * pz) -> bool -{ - D3DXVECTOR3 v3Eye = CCameraManager::Instance().GetCurrentCamera()->GetEye(); - - TPosition posVertices[4]; - posVertices[0] = TPosition(v3Eye.x - 90000000.0f, 0.0f, v3Eye.z + 90000000.0f); - posVertices[1] = TPosition(v3Eye.x - 90000000.0f, 0.0f, v3Eye.z - 90000000.0f); - posVertices[2] = TPosition(v3Eye.x + 90000000.0f, 0.0f, v3Eye.z + 90000000.0f); - posVertices[3] = TPosition(v3Eye.x + 90000000.0f, 0.0f, v3Eye.z - 90000000.0f); - - static const WORD sc_awFillRectIndices[6] = { 0, 2, 1, 2, 3, 1, }; - - float u, v, t; - for (int i = 0; i < 2; ++i) - { - if (IntersectTriangle(ms_vtPickRayOrig, ms_vtPickRayDir, - posVertices[sc_awFillRectIndices[i * 3]], - posVertices[sc_awFillRectIndices[i * 3 + 1]], - posVertices[sc_awFillRectIndices[i * 3 + 2]], - &u, &v, &t)) - { - *pz = t; - return true; - } - } - return false; -} - -auto CScreen::GetPickingPosition(float t, float * x, float * y, float * z) -> void +void CScreen::GetPickingPosition(float t, float* x, float* y, float* z) { *x = ms_vtPickRayOrig.x + ms_vtPickRayDir.x * t; *y = ms_vtPickRayOrig.y + ms_vtPickRayDir.y * t; *z = ms_vtPickRayOrig.z + ms_vtPickRayDir.z * t; } -// 40250 GrpScreen.cpp:749-779. +void CScreen::SetDiffuseColor(DWORD diffuseColor) +{ + ms_diffuseColor = diffuseColor; +} + +void CScreen::SetDiffuseColor(float r, float g, float b, float a) +{ + ms_diffuseColor = GetColor(r, g, b, a); +} + +void CScreen::SetClearColor(float r, float g, float b, float a) +{ + ms_clearColor = GetColor(r, g, b, a); +} + +void CScreen::SetClearDepth(float depth) +{ + ms_clearDepth = depth; +} + +void CScreen::SetClearStencil(DWORD stencil) +{ + ms_clearStencil = stencil; +} + +void CScreen::ClearDepthBuffer() +{ + assert(ms_lpd3dDevice != NULL); + ms_lpd3dDevice->Clear(0L, NULL, D3DCLEAR_ZBUFFER, ms_clearColor, ms_clearDepth, ms_clearStencil); +} + +void CScreen::Clear() +{ + assert(ms_lpd3dDevice != NULL); + ms_lpd3dDevice->Clear(0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, ms_clearColor, ms_clearDepth, ms_clearStencil); +} + +BOOL CScreen::IsLostDevice() +{ + if (!ms_lpd3dDevice) + return TRUE; + + IDirect3DDevice8 & rkD3DDev = *ms_lpd3dDevice; + HRESULT hrTestCooperativeLevel = rkD3DDev.TestCooperativeLevel(); + if (FAILED(hrTestCooperativeLevel)) + return TRUE; + + return FALSE; +} + +BOOL CScreen::RestoreDevice() +{ + if (!ms_lpd3dDevice) + return FALSE; + + UINT iD3DAdapterInfo = ms_iD3DAdapterInfo; + IDirect3D8 & rkD3D = *ms_lpd3d; + IDirect3DDevice8 & rkD3DDev = *ms_lpd3dDevice; + D3DPRESENT_PARAMETERS & rkD3DPP = ms_d3dPresentParameter; + D3D_CDisplayModeAutoDetector & rkD3DDetector = ms_kD3DDetector; + + HRESULT hrTestCooperativeLevel = rkD3DDev.TestCooperativeLevel(); + + if (FAILED(hrTestCooperativeLevel)) + { + if (D3DERR_DEVICELOST == hrTestCooperativeLevel) + { + return FALSE; + } + + if (D3DERR_DEVICENOTRESET == hrTestCooperativeLevel) + { + D3D_CAdapterInfo* pkD3DAdapterInfo = rkD3DDetector.GetD3DAdapterInfop(ms_iD3DAdapterInfo); + + if (!pkD3DAdapterInfo) + return FALSE; + + D3DDISPLAYMODE & rkD3DDMDesktop = pkD3DAdapterInfo->GetDesktopD3DDisplayModer(); + + if (FAILED(rkD3D.GetAdapterDisplayMode(iD3DAdapterInfo, &rkD3DDMDesktop))) + return FALSE; + + rkD3DPP.BackBufferFormat = rkD3DDMDesktop.Format; + + HRESULT hrReset = rkD3DDev.Reset(&rkD3DPP); + + if (FAILED(hrReset)) + { + return FALSE; + } + + STATEMANAGER.SetDefaultState(); + } + } + + return TRUE; + +} + +bool CScreen::Begin() +{ + assert(ms_lpd3dDevice != NULL); + ResetFaceCount(); + + if (!STATEMANAGER.BeginScene()) + { + Tracenf("BeginScene FAILED\n"); + return false; + } + + return true; +} + +void CScreen::End() +{ + STATEMANAGER.EndScene(); +} + +// PORT: 40250 declares these extern (UserInterface, the in-game web page); PythonApplicationWebPage is +// DIVERGENT here, so the page is never open and Show presents the whole back buffer. +static const bool g_isBrowserMode = false; +static RECT g_rcBrowser = {}; + +void CScreen::Show(HWND hWnd) +{ + assert(ms_lpd3dDevice != NULL); + + if (g_isBrowserMode) + { + // PORT: static_cast for 40250's static_cast: RECT's LONG is 32-bit, long is 64-bit on LP64. + RECT rcTop={ static_cast(0), static_cast(0), static_cast(ms_d3dPresentParameter.BackBufferWidth), static_cast(g_rcBrowser.top)}; + RECT rcBottom={0, g_rcBrowser.bottom, static_cast(ms_d3dPresentParameter.BackBufferWidth), static_cast(ms_d3dPresentParameter.BackBufferHeight)}; + RECT rcLeft={0, g_rcBrowser.top, g_rcBrowser.left, g_rcBrowser.bottom}; + RECT rcRight={g_rcBrowser.right, g_rcBrowser.top, static_cast(ms_d3dPresentParameter.BackBufferWidth), g_rcBrowser.bottom}; + + ms_lpd3dDevice->Present(&rcTop, &rcTop, hWnd, NULL); + ms_lpd3dDevice->Present(&rcBottom, &rcBottom, hWnd, NULL); + ms_lpd3dDevice->Present(&rcLeft, &rcLeft, hWnd, NULL); + ms_lpd3dDevice->Present(&rcRight, &rcRight, hWnd, NULL); + } + else + { + HRESULT hr=ms_lpd3dDevice->Present(NULL, NULL, hWnd, NULL); + if (D3DERR_DEVICELOST == hr) + RestoreDevice(); + } +} + +void CScreen::Show(RECT * pSrcRect) +{ + assert(ms_lpd3dDevice != NULL); + ms_lpd3dDevice->Present(pSrcRect, NULL, NULL, NULL); +} + +void CScreen::Show(RECT * pSrcRect, HWND hWnd) +{ + assert(ms_lpd3dDevice != NULL); + ms_lpd3dDevice->Present(pSrcRect, NULL, hWnd, NULL); +} + void CScreen::ProjectPosition(float x, float y, float z, float * pfX, float * pfY) { D3DXVECTOR3 Input(x, y, z); D3DXVECTOR3 Output; - D3DXVec3Project(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matIdentity); + D3DXVec3Project(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matWorld); *pfX = Output.x; *pfY = Output.y; @@ -372,7 +783,7 @@ void CScreen::ProjectPosition(float x, float y, float z, float * pfX, float * pf { D3DXVECTOR3 Input(x, y, z); D3DXVECTOR3 Output; - D3DXVec3Project(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matIdentity); + D3DXVec3Project(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matWorld); *pfX = Output.x; *pfY = Output.y; @@ -383,32 +794,83 @@ void CScreen::UnprojectPosition(float x, float y, float z, float * pfX, float * { D3DXVECTOR3 Input(x, y, z); D3DXVECTOR3 Output; - D3DXVec3Unproject(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matIdentity); + D3DXVec3Unproject(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matWorld); *pfX = Output.x; *pfY = Output.y; *pfZ = Output.z; } -auto CScreen::IsLostDevice() -> BOOL +void CScreen::SetColorOperation() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); } -auto CScreen::RestoreDevice() -> BOOL +void CScreen::SetDiffuseOperation() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); } -auto CScreen::BuildViewFrustum() -> void +void CScreen::SetBlendOperation() { - CCamera* pkCamera = CCameraManager::Instance().GetCurrentCamera(); - if (!pkCamera) - return; - const D3DXVECTOR3& c_rv3Eye = pkCamera->GetEye(); - const D3DXVECTOR3& c_rv3View = pkCamera->GetView(); + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); +} + +void CScreen::SetOneColorOperation(D3DXCOLOR & rColor) +{ + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + + STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, rColor); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); +} + +void CScreen::SetAddColorOperation(D3DXCOLOR & rColor) +{ + STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, rColor); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_ADD); +} + +void CScreen::Identity() +{ + STATEMANAGER.SetTransform(D3DTS_WORLD, &ms_matIdentity); +} + +CScreen::CScreen() +{ +} + +CScreen::~CScreen() +{ +} +//void BuildViewFrustum() { ms_frustum.BuildViewFrustum(ms_matView*ms_matProj); } + +void CScreen::BuildViewFrustum() +{ + const D3DXVECTOR3& c_rv3Eye=CCameraManager::Instance().GetCurrentCamera()->GetEye(); + const D3DXVECTOR3& c_rv3View=CCameraManager::Instance().GetCurrentCamera()->GetView(); auto vv = ms_matView * ms_matProj; ms_frustum.BuildViewFrustum2( vv, @@ -418,18 +880,3 @@ auto CScreen::BuildViewFrustum() -> void ms_fAspect, c_rv3Eye, c_rv3View); } - -auto CScreen::Identity() -> void -{ - STATEMANAGER.SetTransform(D3DTS_WORLD, &ms_matIdentity); -} - -decltype(CScreen::ms_diffuseColor) CScreen::ms_diffuseColor = 0xffffffff; - -decltype(CScreen::ms_clearColor) CScreen::ms_clearColor{}; - -decltype(CScreen::ms_clearStencil) CScreen::ms_clearStencil{}; - -decltype(CScreen::ms_clearDepth) CScreen::ms_clearDepth = 1.0f; - -decltype(CScreen::ms_frustum) CScreen::ms_frustum{}; diff --git a/src/platform/EterLib/RecordingDevice.cpp b/src/platform/EterLib/RecordingDevice.cpp index 7d02caab..f6c67782 100644 --- a/src/platform/EterLib/RecordingDevice.cpp +++ b/src/platform/EterLib/RecordingDevice.cpp @@ -328,6 +328,11 @@ public: // The caps leave out D3DCAPS2_FULLSCREENGAMMA (the frame goes to a window, where D3D8 ignores the // ramp too), so 40250 CPythonGraphic::SetGamma returns before it gets here. void SetGammaRamp(DWORD, const D3DGAMMARAMP*) override {} + // PORT: the host owns the swapchain (Vulkan / canvas): the recorded device is never lost, Reset keeps + // the recording size, and the host presents the recorded frame after CPythonApplication::Process. + HRESULT TestCooperativeLevel() override { return D3D_OK; } + HRESULT Reset(D3DPRESENT_PARAMETERS*) override { return D3D_OK; } + HRESULT Present(const RECT*, const RECT*, HWND, const RGNDATA*) override { return D3D_OK; } HRESULT BeginScene() override { return S_OK; } HRESULT EndScene() override { return S_OK; } @@ -504,6 +509,11 @@ public: } // PORT: fixed function only; CGraphicDevice's stream "shaders" are the FVFs they describe. HRESULT SetVertexShader(DWORD handle) override { m_fvf = handle; return S_OK; } + HRESULT GetVertexShader(DWORD* pHandle) override + { + *pHandle = m_fvf; + return S_OK; + } HRESULT SetPixelShader(DWORD) override { return S_OK; } // PORT: no programmable vertex shaders; 40250 falls back to its FVF when creation fails. HRESULT CreateVertexShader(const DWORD*, const DWORD*, DWORD* pHandle, DWORD) override diff --git a/src/port/common/D3D8Types.h b/src/port/common/D3D8Types.h index 4464cf29..ee08c2ab 100644 --- a/src/port/common/D3D8Types.h +++ b/src/port/common/D3D8Types.h @@ -505,6 +505,9 @@ typedef enum _D3DVERTEXBLENDFLAGS { #define D3DFVF_RESERVED2 0xE000 // d3d8.h #define D3D_OK S_OK +// d3d8.h device-lost results (MAKE_D3DHRESULT(2152), (2153)). +#define D3DERR_DEVICELOST ((HRESULT)0x88760868L) +#define D3DERR_DEVICENOTRESET ((HRESULT)0x88760869L) // d3d8types.h vertex shader declaration tokens typedef enum _D3DVSD_TOKENTYPE @@ -801,6 +804,10 @@ struct IDirect3DIndexBuffer8 : IDirect3DResource8 virtual HRESULT Unlock() = 0; }; +// wingdi.h region data; Present's dirty region is only ever NULL here. +struct _RGNDATA; +typedef struct _RGNDATA RGNDATA; + // The device methods the ported code calls (CStateManager), with D3D8's signatures. The platform // implements it (platform/EterLib/RecordingDevice.h) as a device that records draw calls. struct IDirect3DDevice8 @@ -813,6 +820,9 @@ struct IDirect3DDevice8 virtual HRESULT SetViewport(const D3DVIEWPORT8* pViewport) = 0; virtual UINT GetAvailableTextureMem() = 0; virtual void SetGammaRamp(DWORD Flags, const D3DGAMMARAMP* pRamp) = 0; + virtual HRESULT TestCooperativeLevel() = 0; + virtual HRESULT Reset(D3DPRESENT_PARAMETERS* pPresentationParameters) = 0; + virtual HRESULT Present(const RECT* pSourceRect, const RECT* pDestRect, HWND hDestWindowOverride, const RGNDATA* pDirtyRegion) = 0; virtual HRESULT BeginScene() = 0; virtual HRESULT EndScene() = 0; virtual HRESULT SetTransform(D3DTRANSFORMSTATETYPE State, const D3DMATRIX* pMatrix) = 0; @@ -834,6 +844,7 @@ struct IDirect3DDevice8 virtual HRESULT CreateVertexShader(const DWORD* pDeclaration, const DWORD* pFunction, DWORD* pHandle, DWORD Usage) = 0; virtual HRESULT DeleteVertexShader(DWORD Handle) = 0; virtual HRESULT SetVertexShader(DWORD Handle) = 0; + virtual HRESULT GetVertexShader(DWORD* pHandle) = 0; virtual HRESULT SetPixelShader(DWORD Handle) = 0; virtual HRESULT SetVertexShaderConstant(DWORD Register, const void* pConstantData, DWORD ConstantCount) = 0; virtual HRESULT SetPixelShaderConstant(DWORD Register, const void* pConstantData, DWORD ConstantCount) = 0; diff --git a/src/port/common/shim/sdk/d3dx8.h b/src/port/common/shim/sdk/d3dx8.h index d6ed3222..220fb254 100644 --- a/src/port/common/shim/sdk/d3dx8.h +++ b/src/port/common/shim/sdk/d3dx8.h @@ -24,7 +24,17 @@ inline HRESULT D3DXAssembleShader(const void*, UINT, DWORD, LPD3DXBUFFER* ppCons return E_FAIL; } -struct ID3DXMesh; +// d3dx8mesh.h ID3DXMesh: the members CScreen::RenderD3DXMesh reads. +struct ID3DXMesh +{ + virtual ~ID3DXMesh() = default; + virtual ULONG Release() = 0; + virtual DWORD GetNumFaces() = 0; + virtual DWORD GetNumVertices() = 0; + virtual DWORD GetFVF() = 0; + virtual HRESULT GetVertexBuffer(LPDIRECT3DVERTEXBUFFER8* ppVB) = 0; + virtual HRESULT GetIndexBuffer(LPDIRECT3DINDEXBUFFER8* ppIB) = 0; +}; typedef ID3DXMesh* LPD3DXMESH; struct ID3DXMatrixStack; typedef ID3DXMatrixStack* LPD3DXMATRIXSTACK; diff --git a/tests/port/port_app_loop_test.cpp b/tests/port/port_app_loop_test.cpp index 8ae97978..79bead34 100644 --- a/tests/port/port_app_loop_test.cpp +++ b/tests/port/port_app_loop_test.cpp @@ -20,7 +20,9 @@ #include "../../src/platform/ScriptLib/PythonHost.h" #include "../../src/platform/UserInterface/UserInterface.h" #include "../../src/platform/EterLib/UIRenderCommands.h" +#include "../../src/platform/EterLib/RenderCommands3D.h" #include "EterLib/GrpScreen.h" +#include "EterLib/StateManager.h" #include "EterPythonLib/PythonGraphic.h" #include // DIK_ESCAPE @@ -289,6 +291,33 @@ int main(int argc, char** argv) frames(1); CHECK(py("assert not _stream.popupWindow.IsShow() and _popup_closed == [1]")); + // CScreen's 3D primitives (40250 GrpScreen.cpp, verbatim) go through the device's dynamic PDT stream: + // under a perspective projection RenderLine3d is one line-list draw, RenderBar3d a two-triangle strip, + // both in the current diffuse colour. The device is lost-free (TestCooperativeLevel is D3D_OK). + { + CScreen screen; + CHECK(!screen.IsLostDevice() && screen.RestoreDevice()); + D3DXMATRIX proj; + D3DXMatrixPerspectiveFovRH(&proj, D3DX_PI * 0.25f, 4.0f / 3.0f, 10.0f, 1000.0f); + CHECK(screen.Begin()); // CStateManager hands transforms to the device only inside the scene + STATEMANAGER.SaveTransform(D3DTS_PROJECTION, &proj); + Render3DBeginFrame(); + screen.SetDiffuseColor(0.0f, 1.0f, 0.0f); + screen.RenderLine3d(0, 0, -100, 10, 0, -100); + screen.RenderBar3d(0, 0, -100, 10, 10, -100); + STATEMANAGER.RestoreTransform(D3DTS_PROJECTION); + screen.End(); + const auto& draws = Render3DDraws(); + CHECK(draws.size() == 2); + if (draws.size() == 2) + { + CHECK(draws[0].lines && draws[0].positions.size() == 6 && near(draws[0].positions[3], 10)); + CHECK(!draws[1].lines && draws[1].positions.size() == 12); + CHECK(!draws[0].diffuse.empty() && draws[0].diffuse[0] == 0xFF00FF00u); + } + Render3DBeginFrame(); + } + // ExpandedImageBox (CGraphicExpandedImageInstance::OnRender): scale + rendering rect, then rotation. CHECK(py("import ui\n" "_ex = ui.ExpandedImageBox()\n"