From c5e81c54a24c30f628a51c70fee54bd19dadf6b6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 16 Apr 2020 00:45:14 +0200 Subject: [PATCH] - Moved the raw texture handling into the texture manager as well. --- .../textures/formats/multipatchtexture.h | 12 +++- src/common/textures/image.h | 3 +- src/common/textures/texture.cpp | 36 ------------ src/common/textures/texturemanager.cpp | 57 ++++++++++++++++++- src/common/textures/texturemanager.h | 6 +- src/common/textures/textures.h | 3 - src/rendering/hwrenderer/scene/hw_walls.cpp | 4 +- .../swrenderer/textures/r_swtexture.cpp | 7 ++- 8 files changed, 80 insertions(+), 48 deletions(-) diff --git a/src/common/textures/formats/multipatchtexture.h b/src/common/textures/formats/multipatchtexture.h index 5c15e8aa0..2f1421a8a 100644 --- a/src/common/textures/formats/multipatchtexture.h +++ b/src/common/textures/formats/multipatchtexture.h @@ -41,8 +41,18 @@ class FMultiPatchTexture : public FImageSource friend class FGameTexture; public: FMultiPatchTexture(int w, int h, const TArray &parts, bool complex, bool textual); - bool SupportRemap0() override; int GetNumParts() const { return NumParts; } + // Query some needed info for texture hack support. + bool SupportRemap0() override; + bool IsRawCompatible() override + { + return NumParts != 1 || Parts[0].OriginY == 0 || bTextual; + } + FImageSource* GetImageForPart(int num) + { + if (num >= 0 && num < NumParts) return Parts[num].Image; + return nullptr; + } protected: int NumParts; diff --git a/src/common/textures/image.h b/src/common/textures/image.h index a72c82eb3..00b541411 100644 --- a/src/common/textures/image.h +++ b/src/common/textures/image.h @@ -57,7 +57,8 @@ protected: public: - virtual bool SupportRemap0() { return false; } // Unfortunate hackery that's needed for Hexen's skies. + virtual bool SupportRemap0() { return false; } // Unfortunate hackery that's needed for Hexen's skies. Only the image can know about the needed parameters + virtual bool IsRawCompatible() { return true; } // Same thing for mid texture compatibility handling. Can only be determined by looking at the composition data which is private to the image. void CopySize(FImageSource &other) { diff --git a/src/common/textures/texture.cpp b/src/common/textures/texture.cpp index 6d19723f5..adb2b60e4 100644 --- a/src/common/textures/texture.cpp +++ b/src/common/textures/texture.cpp @@ -181,42 +181,6 @@ FBitmap FTexture::GetBgraBitmap(const PalEntry *remap, int *ptrans) return bmp; } -//========================================================================== -// -// -// -//========================================================================== - -FGameTexture *FGameTexture::GetRawTexture() -{ - auto tex = GetTexture(); - if (tex->OffsetLess) return tex->OffsetLess; - // Reject anything that cannot have been a single-patch multipatch texture in vanilla. - auto image = static_cast(tex->GetImage()); - if (tex->bMultiPatch != 1 || GetUseType() != ETextureType::Wall || tex->Scale.X != 1 || tex->Scale.Y != 1 || - useWorldPanning() || image == nullptr || image->GetNumParts() != 1 || tex->_TopOffset[0] == 0) - { - tex->OffsetLess = this; - return this; - } - // Set up a new texture that directly references the underlying patch. - // From here we cannot retrieve the original texture made for it, so just create a new one. - FImageSource *source = image->Parts[0].Image; - - // Size must match for this to work as intended - if (source->GetWidth() != GetTexelWidth() || source->GetHeight() != GetTexelHeight()) - { - tex->OffsetLess = this; - return this; - } - - - tex->OffsetLess = MakeGameTexture(new FImageTexture(source, "")); - // todo: This must also copy all layers from the base texture. - TexMan.AddGameTexture(tex->OffsetLess); - return tex->OffsetLess; -} - void FTexture::SetDisplaySize(int fitwidth, int fitheight) { Scale.X = double(Width) / fitwidth; diff --git a/src/common/textures/texturemanager.cpp b/src/common/textures/texturemanager.cpp index 3a25f0a0b..5ffac6fc8 100644 --- a/src/common/textures/texturemanager.cpp +++ b/src/common/textures/texturemanager.cpp @@ -396,7 +396,7 @@ FTextureID FTextureManager::AddGameTexture (FGameTexture *texture, bool addtohas hash = -1; } - TextureHash hasher = { texture, -1, -1, hash }; + TextureHash hasher = { texture, -1, -1, -1, hash }; int trans = Textures.Push (hasher); Translation.Push (trans); if (bucket >= 0) HashFirst[bucket] = trans; @@ -1176,6 +1176,50 @@ void FTextureManager::InitPalettedVersions() } } +//========================================================================== +// +// +// +//========================================================================== + +FTextureID FTextureManager::GetRawTexture(FTextureID texid) +{ + int texidx = texid.GetIndex(); + if ((unsigned)texidx >= Textures.Size()) return texid; + if (Textures[texidx].FrontSkyLayer != -1) return FSetTextureID(Textures[texidx].FrontSkyLayer); + + // Reject anything that cannot have been a front layer for the sky in original Hexen, i.e. it needs to be an unscaled wall texture only using Doom patches. + auto tex = Textures[texidx].Texture; + auto ttex = tex->GetTexture(); + auto image = tex->GetTexture()->GetImage(); + // Reject anything that cannot have been a single-patch multipatch texture in vanilla. + if (image == nullptr || image->IsRawCompatible() || tex->GetUseType() != ETextureType::Wall || tex->GetTexelWidth() != tex->GetDisplayWidth() || + tex->GetTexelHeight() != tex->GetDisplayHeight()) + { + Textures[texidx].RawTexture = texidx; + return texid; + } + + // Let the hackery begin + auto mptimage = static_cast(image); + auto source = mptimage->GetImageForPart(0); + + // Size must match for this to work as intended + if (source->GetWidth() != tex->GetTexelWidth() || source->GetHeight() != tex->GetTexelHeight()) + { + Textures[texidx].RawTexture = texidx; + return texid; + } + + // Todo: later this can just link to the already existing texture for this source graphic, once it can be retrieved through the image's SourceLump index + auto RawTexture = MakeGameTexture(new FImageTexture(source, "")); + texid = TexMan.AddGameTexture(RawTexture); + Textures[texidx].RawTexture = texid.GetIndex(); + Textures[texid.GetIndex()].RawTexture = texid.GetIndex(); + return texid; +} + + //========================================================================== // // Same shit for a different hack, this time Hexen's front sky layers. @@ -1185,7 +1229,7 @@ void FTextureManager::InitPalettedVersions() FTextureID FTextureManager::GetFrontSkyLayer(FTextureID texid) { int texidx = texid.GetIndex(); - if (texidx >= Textures.Size()) return texid; + if ((unsigned)texidx >= Textures.Size()) return texid; if (Textures[texidx].FrontSkyLayer != -1) return FSetTextureID(Textures[texidx].FrontSkyLayer); // Reject anything that cannot have been a front layer for the sky in original Hexen, i.e. it needs to be an unscaled wall texture only using Doom patches. @@ -1199,10 +1243,11 @@ FTextureID FTextureManager::GetFrontSkyLayer(FTextureID texid) } // Set this up so that it serializes to the same info as the base texture - this is needed to restore it on load. + // But do not link the new texture into the hash chain! auto FrontSkyLayer = MakeGameTexture(new FImageTexture(image, tex->GetName())); FrontSkyLayer->SetUseType(tex->GetUseType()); FrontSkyLayer->GetTexture()->bNoRemap0 = true; - texid = TexMan.AddGameTexture(FrontSkyLayer); + texid = TexMan.AddGameTexture(FrontSkyLayer, false); Textures[texidx].FrontSkyLayer = texid.GetIndex(); Textures[texid.GetIndex()].FrontSkyLayer = texid.GetIndex(); // also let it refer to itself as its front sky layer, in case for repeated InitSkyMap calls. return texid; @@ -1443,3 +1488,9 @@ FTextureID FTextureID::operator +(int offset) throw() if (texnum + offset >= TexMan.NumTextures()) return FTextureID(-1); return FTextureID(texnum + offset); } + + +CCMD(texinfo) +{ + Printf("Sizeof texture = %d\n", sizeof(FTexture)); +} diff --git a/src/common/textures/texturemanager.h b/src/common/textures/texturemanager.h index 2b3bb0829..994772edc 100644 --- a/src/common/textures/texturemanager.h +++ b/src/common/textures/texturemanager.h @@ -76,6 +76,7 @@ public: void FlushAll(); FTextureID GetFrontSkyLayer(FTextureID); + FTextureID GetRawTexture(FTextureID); enum @@ -171,8 +172,9 @@ private: struct TextureHash { FGameTexture* Texture; - int Paletted; // redirection to paletted variant - int FrontSkyLayer; + int Paletted; // redirection to paletted variant + int FrontSkyLayer; // and front sky layer, + int RawTexture; int HashNext; bool HasLocalization; }; diff --git a/src/common/textures/textures.h b/src/common/textures/textures.h index ed438e36a..c4841cb81 100644 --- a/src/common/textures/textures.h +++ b/src/common/textures/textures.h @@ -717,9 +717,6 @@ public: wrapped.CopySize(&BaseTexture->wrapped); } - // These substitutions must be done on the material level because their sizes can differ. Substitution must happen before any coordinate calculations take place. - FGameTexture* GetRawTexture(); - // Glowing is a pure material property that should not filter down to the actual texture objects. void GetGlowColor(float* data) { wrapped.GetGlowColor(data); } bool isGlowing() const { return wrapped.isGlowing(); } diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 68ecbae3a..73c19f804 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -2078,7 +2078,9 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ { if (di->Level->i_compatflags & COMPATF_MASKEDMIDTEX) { - tex = tex->GetRawTexture(); + auto rawtexid = TexMan.GetRawTexture(tex->GetID()); + auto rawtex = TexMan.GetGameTexture(rawtexid); + if (rawtex) tex = rawtex; } texture = tex; } diff --git a/src/rendering/swrenderer/textures/r_swtexture.cpp b/src/rendering/swrenderer/textures/r_swtexture.cpp index 5094aa355..4f3a94bc9 100644 --- a/src/rendering/swrenderer/textures/r_swtexture.cpp +++ b/src/rendering/swrenderer/textures/r_swtexture.cpp @@ -617,7 +617,12 @@ FSoftwareTexture* GetPalettedSWTexture(FTextureID texid, bool animate, bool chec bool needpal = !vid_nopalsubstitutions && !V_IsTrueColor(); auto tex = TexMan.GetPalettedTexture(texid, true, needpal); if (tex == nullptr || (!allownull && !tex->isValid())) return nullptr; - if (checkcompat) tex = tex->GetRawTexture(); + if (checkcompat) + { + auto rawtexid = TexMan.GetRawTexture(tex->GetID()); + auto rawtex = TexMan.GetGameTexture(rawtexid); + if (rawtex) tex = rawtex; + } return GetSoftwareTexture(tex); }