diff --git a/Render/RenderStub.cpp b/Render/RenderStub.cpp index 55c2dff1..e8361f8c 100644 --- a/Render/RenderStub.cpp +++ b/Render/RenderStub.cpp @@ -1,24 +1,39 @@ -// Render-backend stub for the cross-platform build. +// Where the renderer is created, and the seam the D3D9 retirement left behind. // -// The real renderer is the D3D9 backend (Render/D3D/*.cpp), which drives -// IDirect3DDevice9 / IDirect3D9 directly and is therefore Windows-only (gated in -// Render/CMakeLists.txt). Off-Windows the fake d3d9.h only makes the render -// headers parse, not the device-creation call sites, so we provide no-op -// definitions for the render-backend symbols the rest of the engine references. -// The real cross-platform renderer is the SDL GPU backend (Track B); until then -// the game links and runs with a silent renderer. +// CreateIRenderDevice() below is the engine's one entry point into the renderer: it builds +// gb_VisGeneric and the SDL GPU device every platform now draws through. The D3D9 backend it +// replaced is retired -- Render/D3D/*.cpp is compiled nowhere, nothing assigns +// gb_RenderDevice3D, so that pointer is null for the life of the process, on Windows too. +// Every D3D name below resolves through the fake d3d9.h; there is no Direct3D in this build. // -// Only the symbols actually referenced by the compiled (non-WIN32) sources are -// stubbed here — see the undefined-symbol set at the final Game link. +// The rest of the file is what retirement could not reach. Portable engine code still speaks +// D3D9 nouns -- cTexture::CalcTextureSize asks GetTextureFormatSize(D3DFORMAT), +// GrassMap::BuildGrass packs normals with ColorByNormalRGBA, Camera::SetRenderTarget takes an +// IDirect3DSurface9* -- and it still owns classes whose only implementation was D3D9: +// cOcclusionQuery (cObject3dx's silhouette test, the lens flare), sVideoWrite (GameShell's +// movie recorder), cVertexBufferInternal / cQuadBufferInternal (the dynamic buffer family, +// Documents/Render-PORTING.md #15). The call sites are real and have to link; these bodies are +// what they land on. +// +// Two different kinds of body, and the difference matters. The cD3DRender:: helpers are +// unreachable -- every call goes through the null gb_RenderDevice3D, so nothing runs them. +// The rest DO run, and their return values are consumed: GrassMap::BuildGrass writes +// ColorByNormalRGBA's result into every bush (so each one gets a white normal), cOcclusionQuery +// answers IsVisible() = true, GetTextureFormatSize reports 0 bits per pixel. Those are answers +// the game acts on, not silence. Before treating one as inert, check what reads it. +// +// Only the symbols the linker actually asks for are defined here. When a feature above is +// ported -- or the dead D3D9 reference sources go -- delete what goes with it; the way to find +// out what is still owed is to remove a body and relink. #include "StdAfxRD.h" #include "VisGeneric.h" #include "SDLRenderDevice.h" #include "D3DRender.h" -#include "D3DRenderTilemap.h" #include "src/WinVideo.h" // --------------------------------------------------------------------------- -// Globals (defined in D3DRender.cpp / RenderDevice.cpp on Windows). +// Globals. cD3DRender's constructor used to define and own these; it no longer runs +// anywhere, so gb_RenderDevice3D keeps the null it is initialised with here. // --------------------------------------------------------------------------- RENDER_API cInterfaceRenderDevice* gb_RenderDevice = 0; RENDER_API cD3DRender* gb_RenderDevice3D = 0; @@ -31,8 +46,8 @@ RENDER_API SAMPLER_DATA sampler_clamp_linear; RENDER_API SAMPLER_DATA sampler_clamp_anisotropic; // The six samplers the engine names when it calls SetSamplerData/SetSamplerDataVirtual. -// cD3DRender::InitSamplerConstants fills them on Windows; without this they stay zeroed -// off it, and a caller asking for sampler_wrap_linear (the selection frame's tiled centre) +// cD3DRender::InitSamplerConstants used to fill them at device init; without this they stay +// zeroed, and a caller asking for sampler_wrap_linear (the selection frame's tiled centre) // would be asking for address mode 0, which is not a mode at all. static void initSamplerConstants() { @@ -60,21 +75,19 @@ static void initSamplerConstants() sampler_clamp_point.addressv = DX_TADDRESS_CLAMP; sampler_clamp_point.addressw = DX_TADDRESS_CLAMP; - // cD3DRender rounds these to linear until SetAnisotropic(n) raises them, and nothing - // off-Windows raises them yet. + // cD3DRender rounded these to linear until SetAnisotropic(n) raised them, and nothing + // raises them now: cVisGeneric::SetAnisotropic forwards to the null gb_RenderDevice3D. sampler_wrap_anisotropic = sampler_wrap_linear; sampler_clamp_anisotropic = sampler_clamp_linear; } RENDER_API cInterfaceRenderDevice* CreateIRenderDevice(bool multiThread) { - // Half 1 of the real CreateIRenderDevice (RenderDevice.cpp): construct the - // backend-agnostic cVisGeneric so gb_VisGeneric is non-null. Its constructor - // is pure file-IO/config (no GPU device), and VisGeneric.cpp is compiled into - // this library off-Windows, so this links and runs today. + // Half 1, unchanged from the original (RenderDevice.cpp): construct the backend-agnostic + // cVisGeneric so gb_VisGeneric is non-null. Its constructor is pure file-IO/config and + // touches no GPU device. // - // Half 2: the cross-platform render device is the SDL GPU backend - // (cSDLRenderDevice), replacing the Windows-only cD3DRender. + // Half 2 is where the backends part: cSDLRenderDevice, not cD3DRender. initSamplerConstants(); gb_VisGeneric = new cVisGeneric(multiThread); return gb_RenderDevice = new cSDLRenderDevice; @@ -89,7 +102,7 @@ ManagedResource::~ManagedResource() {} // --------------------------------------------------------------------------- // sPtrVertexBuffer / sPtrIndexBuffer — lifetime routes through the interface -// (mirrors the Windows D3DRender.cpp bodies), so the SDL backend owns the GPU +// (the shape the D3DRender.cpp bodies had), so the SDL backend owns the GPU // buffers behind the slot and releases them on Destroy/dtor. // // The gb_RenderDevice guard matters for handles with *static storage duration*: @@ -128,10 +141,10 @@ void sPtrIndexBuffer::CopyAddRef(const sPtrIndexBuffer& from) } // --------------------------------------------------------------------------- -// Vertex-format declaration registration. On Windows this queues (decl,elements) -// pairs for CreateVertexDeclaration at device init; off-Windows there is no D3D -// object, so we point the declaration at its immortal static element table (from -// the BEGIN_VERTEX_DECLARATION macro) so the SDL backend can read the layout. +// Vertex-format declaration registration. The D3D9 original queued (decl,elements) +// pairs for CreateVertexDeclaration at device init; there is no D3D object to create +// now, so the declaration points at its immortal static element table (from the +// BEGIN_VERTEX_DECLARATION macro) and the SDL backend reads the layout straight off it. // The vertex::declaration statics themselves are defined by VertexDeclaration.cpp. // --------------------------------------------------------------------------- void cD3DRender::RegisterVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9& declaration, @@ -146,43 +159,19 @@ void cD3DRender::RegisterVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9& declara } // --------------------------------------------------------------------------- -// DrawStrip / PoolManager -// --------------------------------------------------------------------------- -// DrawStrip has no off-Windows implementation: its Set() is an inline in +// DrawStrip has no implementation, deliberately. Its Set() is an inline in // Render/D3D/VertexBuffer.h that writes straight into a locked cVertexBuffer, and there is -// no such buffer here. These bodies exist only so the class still links -- and they leave -// `buf` null and `pointer` uninitialised, so the first Set() writes through a garbage -// pointer. Every off-Windows caller therefore takes SDLWorldQuadRenderer's triangle route -// instead (cUnkLight::Draw, CircleManager::Layer::drawSpline, Lighting::OneLight::Draw); -// the assert is here to catch a new one before it corrupts the heap. -void DrawStrip::Begin() { xassert(0 && "DrawStrip is Windows-only: use SDLWorldQuadRenderer"); } -void DrawStrip::End() {} - -PoolManager::PoolManager() {} -PoolManager::~PoolManager() {} - -// Pool hierarchy (D3D/PoolManager.cpp): defining Pool's virtual dtor (key -// function) emits its vtable+typeinfo; VertexPool/IndexPool define their full -// override set so their vtables resolve when constructed. -Pool::Pool() : total_pages(0), free_pages(0), free_pages_list(0), parameter(0) {} -Pool::~Pool() {} - -VertexPool::VertexPool() : vb(0), page_size(0), vertex_declaration(0), vertex_size(0) {} -VertexPool::~VertexPool() {} -void VertexPool::Create(const PoolParameter*) {} -void VertexPool::Select(int) {} -void* VertexPool::LockPage(int) { return 0; } -void VertexPool::UnlockPage(int) {} -void VertexPool::GetUsedMemory(int& total, int& free) { total = 0; free = 0; } -void* VertexPool::InternalLockPage(int) { return 0; } - -IndexPool::IndexPool() : ib(0), page_size(0) {} -IndexPool::~IndexPool() {} -void IndexPool::Create(const PoolParameter*) {} -void IndexPool::Select(int) {} -void* IndexPool::LockPage(int) { return 0; } -void IndexPool::UnlockPage(int) {} -void IndexPool::GetUsedMemory(int& total, int& free) { total = 0; free = 0; } +// no such buffer here: a body would leave `buf` null and `pointer` uninitialised, so the +// first Set() would write through a garbage pointer. Every caller takes +// SDLWorldQuadRenderer's triangle route instead (cUnkLight::Draw, +// CircleManager::Layer::drawSpline, Lighting::OneLight::Draw), and a new one now fails at +// link time rather than corrupting the heap at run time. +// +// PoolManager / Pool / VertexPool / IndexPool (the D3D9 tilemap's page allocator), DrawType +// and cTileMapRender were stubbed here for the same reason and are not stubbed any more: +// nothing left in the build references them. They live on in Render/D3D/, which is compiled +// nowhere. +// --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // Render free functions (D3D/*.cpp): logging, format/size queries, debug stats. @@ -217,8 +206,8 @@ void cQuadBufferInternal::EndDraw() {} void* cQuadBufferInternal::Get() { return 0; } void cQuadBufferInternal::SetMatrix(const MatXf& /*m*/) {} -// cSkinVertex (ctor / GetWeight / GetDeclaration / declaration[] / Register) is -// defined by VertexDeclaration.cpp, which is now compiled off-Windows too. +// cSkinVertex (ctor / GetWeight / GetDeclaration / declaration[] / Register) is not stubbed: +// VertexDeclaration.cpp is real, portable, and in the build. // --------------------------------------------------------------------------- // cOcclusionQuery @@ -235,44 +224,18 @@ void cOcclusionQuery::Begin() {} void cOcclusionQuery::End() {} // --------------------------------------------------------------------------- -// DrawType (abstract; only these non-virtual members are referenced — DrawType -// itself is never constructed off-Windows, so no vtable is needed). -// --------------------------------------------------------------------------- -void DrawType::BeginDraw() {} -void DrawType::SetTileColor(Color4f /*color*/) {} - -// --------------------------------------------------------------------------- -// cTileMapRender (polymorphic via ManagedResource; defining the destructor -// emits its vtable + typeinfo, so the pure-virtual overrides are defined too). -// --------------------------------------------------------------------------- -cTileMapRender::cTileMapRender(cTileMap* /*pTileMap*/) {} -cTileMapRender::~cTileMapRender() {} -void cTileMapRender::deleteManagedResource() {} -void cTileMapRender::restoreManagedResource() {} -void cTileMapRender::dumpManagedResource(XBuffer& /*buffer*/) {} -void cTileMapRender::PreDraw(Camera* /*camera*/) {} -void cTileMapRender::DrawBump(Camera* /*camera*/, eBlendMode /*MatMode*/, bool /*shadow*/, bool /*zbuffer*/) {} - -// --------------------------------------------------------------------------- -// cD3DRender — the helper (non-virtual) methods called from compiled code. +// cD3DRender — the helper (non-virtual) methods still named by compiled code. +// Every call reaches them through the permanently null gb_RenderDevice3D, so none of +// these bodies ever runs; they exist so those call sites link. Only the methods the +// linker actually asks for are here — the rest of cD3DRender's helpers went with the +// pools above. // --------------------------------------------------------------------------- -void* cD3DRender::LockTexture(cTexture* /*Texture*/, int& /*Pitch*/) { return 0; } -void* cD3DRender::LockTexture(cTexture* /*Texture*/, int& /*Pitch*/, Vect2i /*lock_min*/, Vect2i /*lock_size*/) { return 0; } -void cD3DRender::UnlockTexture(cTexture* /*Texture*/) {} -void cD3DRender::DrawQuad(float, float, float, float, float, float, float, float, Color4c) {} Mat4f cD3DRender::shadowMatBias() const { return Mat4f(); } -bool cD3DRender::createRenderTargets(int /*xysize*/) { return false; } -void cD3DRender::deleteRenderTargets() {} -bool cD3DRender::CreateFloatTexture(int /*width*/, int /*height*/) { return false; } -void cD3DRender::CreateMirageMap(int /*x*/, int /*y*/, bool /*recreate*/) {} -void cD3DRender::SetAdvance(bool /*is_shadow*/) {} void cD3DRender::SetAnisotropic(int /*level*/) {} int cD3DRender::GetAnisotropic() { return 0; } int cD3DRender::GetMaxAnisotropicLevels() { return 0; } -void cD3DRender::SetBlendState(eBlendMode /*blend*/) {} void cD3DRender::SetBlendStateAlphaRef(eBlendMode /*blend*/) {} void cD3DRender::SetRenderTarget(cTexture* /*target*/, IDirect3DSurface9* /*pZBuffer*/) {} -void cD3DRender::SetRenderTarget1(cTexture* /*target1*/) {} void cD3DRender::RestoreRenderTarget() {} void cD3DRender::FlushPrimitive3DWorld() {} bool cD3DRender::ReinitOcclusion() { return false; }