port: GrpScreen verbatim 40250 (2d draws via UIRender, D3D8 shim device-lost/Present/ID3DXMesh)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-09-30 14:40:57 +09:00
co-authored by Claude Opus 5.5
parent d73f5ea4bd
commit b5d413afa6
7 changed files with 1125 additions and 323 deletions
+1
View File
@@ -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)"}
+350 -56
View File
@@ -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"
]
}
}
}
File diff suppressed because it is too large Load Diff
+10
View File
@@ -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
+11
View File
@@ -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;
+11 -1
View File
@@ -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;
+29
View File
@@ -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 <dinput.h> // 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"