diff --git a/source/common/rendering/gl/gl_hwtexture.cpp b/source/common/rendering/gl/gl_hwtexture.cpp index 31e104cfe..d16af5e8c 100644 --- a/source/common/rendering/gl/gl_hwtexture.cpp +++ b/source/common/rendering/gl/gl_hwtexture.cpp @@ -302,7 +302,7 @@ bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, i { int usebright = false; - bool needmipmap = (clampmode <= CLAMP_XY); + bool needmipmap = (clampmode <= CLAMP_XY) && !forcenofilter; // Bind it to the system. if (!Bind(texunit, needmipmap)) @@ -331,6 +331,7 @@ bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, i return false; } } + if (forcenofilter) clampmode += CLAMP_NOFILTER - CLAMP_NONE; GLRenderer->mSamplerManager->Bind(texunit, clampmode, 255); return true; } diff --git a/source/common/textures/gametexture.cpp b/source/common/textures/gametexture.cpp index 3ab74a5c3..d47ffb733 100644 --- a/source/common/textures/gametexture.cpp +++ b/source/common/textures/gametexture.cpp @@ -187,7 +187,7 @@ void FGameTexture::AddAutoMaterials() void FGameTexture::CreateDefaultBrightmap() { auto tex = GetTexture(); - if (flags & GTexf_BrightmapChecked) + if (!(flags & GTexf_BrightmapChecked)) { flags |= GTexf_BrightmapChecked; // Check for brightmaps diff --git a/source/common/textures/gametexture.h b/source/common/textures/gametexture.h index 38c0908c6..2b8638ea5 100644 --- a/source/common/textures/gametexture.h +++ b/source/common/textures/gametexture.h @@ -305,6 +305,13 @@ public: } } + FTexture* GetBrightmap() + { + if (Brightmap.get() || (flags & GTexf_BrightmapChecked)) return Brightmap.get(); + CreateDefaultBrightmap(); + return Brightmap.get(); + } + }; inline FGameTexture* MakeGameTexture(FTexture* tex, const char *name, ETextureType useType) diff --git a/source/common/textures/hw_texcontainer.h b/source/common/textures/hw_texcontainer.h index c75d42278..a29fc6396 100644 --- a/source/common/textures/hw_texcontainer.h +++ b/source/common/textures/hw_texcontainer.h @@ -14,6 +14,7 @@ enum ECreateTexBufferFlags CTF_CreateMask = 3, // Flags that are relevant for hardware texture creation. CTF_ProcessData = 4, // run postprocessing on the generated buffer. This is only needed when using the data for a hardware texture. CTF_CheckOnly = 8, // Only runs the code to get a content ID but does not create a texture. Can be used to access a caching system for the hardware textures. + CTF_Indexed = 16 // Tell the backend to create an indexed texture. }; class FHardwareTextureContainer diff --git a/source/common/textures/texture.cpp b/source/common/textures/texture.cpp index e8626eaf7..bddd16c23 100644 --- a/source/common/textures/texture.cpp +++ b/source/common/textures/texture.cpp @@ -48,6 +48,7 @@ #include "formats/multipatchtexture.h" #include "texturemanager.h" #include "c_cvars.h" +#include "imagehelpers.h" // Wrappers to keep the definitions of these classes out of here. IHardwareTexture* CreateHardwareTexture(int numchannels); @@ -323,66 +324,82 @@ bool FTexture::ProcessData(unsigned char* buffer, int w, int h, bool ispatch) FTextureBuffer FTexture::CreateTexBuffer(int translation, int flags) { FTextureBuffer result; - - unsigned char* buffer = nullptr; - int W, H; - int isTransparent = -1; - bool checkonly = !!(flags & CTF_CheckOnly); - - int exx = !!(flags & CTF_Expand); - - W = GetWidth() + 2 * exx; - H = GetHeight() + 2 * exx; - - if (!checkonly) + if (flags & CTF_Indexed) { - buffer = new unsigned char[W * (H + 1) * 4]; - memset(buffer, 0, W * (H + 1) * 4); + // Indexed textures will never be translated and never be scaled. + int w = GetWidth(), h = GetHeight(); - auto remap = translation <= 0 ? nullptr : GPalette.TranslationToTable(translation); - if (remap) translation = remap->Index; - FBitmap bmp(buffer, W * 4, W, H); + auto store = Get8BitPixels(false); + const uint8_t* p = store.Data(); - int trans; - auto Pixels = GetBgraBitmap(remap ? remap->Palette : nullptr, &trans); - bmp.Blit(exx, exx, Pixels); + result.mBuffer = new uint8_t[w * h]; + result.mWidth = w; + result.mHeight = h; + result.mContentId = 0; + ImageHelpers::FlipNonSquareBlock(result.mBuffer, p, h, w, h); + } + else + { + unsigned char* buffer = nullptr; + int W, H; + int isTransparent = -1; + bool checkonly = !!(flags & CTF_CheckOnly); - if (remap == nullptr) + int exx = !!(flags & CTF_Expand); + + W = GetWidth() + 2 * exx; + H = GetHeight() + 2 * exx; + + if (!checkonly) { - CheckTrans(buffer, W * H, trans); - isTransparent = bTranslucent; + buffer = new unsigned char[W * (H + 1) * 4]; + memset(buffer, 0, W * (H + 1) * 4); + + auto remap = translation <= 0 ? nullptr : GPalette.TranslationToTable(translation); + if (remap) translation = remap->Index; + FBitmap bmp(buffer, W * 4, W, H); + + int trans; + auto Pixels = GetBgraBitmap(remap ? remap->Palette : nullptr, &trans); + bmp.Blit(exx, exx, Pixels); + + if (remap == nullptr) + { + CheckTrans(buffer, W * H, trans); + isTransparent = bTranslucent; + } + else + { + isTransparent = 0; + // A translated image is not conclusive for setting the texture's transparency info. + } } - else + + if (GetImage()) { - isTransparent = 0; - // A translated image is not conclusive for setting the texture's transparency info. + FContentIdBuilder builder; + builder.id = 0; + builder.imageID = GetImage()->GetId(); + builder.translation = MAX(0, translation); + builder.expand = exx; + result.mContentId = builder.id; + } + else result.mContentId = 0; // for non-image backed textures this has no meaning so leave it at 0. + + result.mBuffer = buffer; + result.mWidth = W; + result.mHeight = H; + + // Only do postprocessing for image-backed textures. (i.e. not for the burn texture which can also pass through here.) + if (GetImage() && flags & CTF_ProcessData) + { + if (flags & CTF_Upscale) CreateUpsampledTextureBuffer(result, !!isTransparent, checkonly); + + if (!checkonly) ProcessData(result.mBuffer, result.mWidth, result.mHeight, false); } } - - if (GetImage()) - { - FContentIdBuilder builder; - builder.id = 0; - builder.imageID = GetImage()->GetId(); - builder.translation = MAX(0, translation); - builder.expand = exx; - result.mContentId = builder.id; - } - else result.mContentId = 0; // for non-image backed textures this has no meaning so leave it at 0. - - result.mBuffer = buffer; - result.mWidth = W; - result.mHeight = H; - - // Only do postprocessing for image-backed textures. (i.e. not for the burn texture which can also pass through here.) - if (GetImage() && flags & CTF_ProcessData) - { - if (flags & CTF_Upscale) CreateUpsampledTextureBuffer(result, !!isTransparent, checkonly); - - if (!checkonly) ProcessData(result.mBuffer, result.mWidth, result.mHeight, false); - } - return result; + } //=========================================================================== diff --git a/source/core/textures/buildtiles.cpp b/source/core/textures/buildtiles.cpp index ad4217257..02cefd3e6 100644 --- a/source/core/textures/buildtiles.cpp +++ b/source/core/textures/buildtiles.cpp @@ -138,7 +138,6 @@ void BuildTiles::Init() tile.picanm = {}; tile.RotTile = { -1,-1 }; tile.replacement = ReplacementType::Art; - tile.NoBrightmapFlag.Zero(); } } @@ -743,7 +742,7 @@ int BuildTiles::findUnusedTile(void) for (; lastUnusedTile >= 0; --lastUnusedTile) { auto tex = tileGetTexture(lastUnusedTile); - if (!tex || tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) return lastUnusedTile; + if (!tex || !tex->isValid()) return lastUnusedTile; } return -1; } diff --git a/source/core/textures/buildtiles.h b/source/core/textures/buildtiles.h index 04a423fcc..9cece50fc 100644 --- a/source/core/textures/buildtiles.h +++ b/source/core/textures/buildtiles.h @@ -265,7 +265,6 @@ struct TileDesc rottile_t RotTile;// = { -1,-1 }; TArray Hightiles; ReplacementType replacement; - FixedBitArray<256> NoBrightmapFlag; }; struct BuildTiles diff --git a/source/glbackend/gl_texture.cpp b/source/glbackend/gl_texture.cpp index da92509f3..605085540 100644 --- a/source/glbackend/gl_texture.cpp +++ b/source/glbackend/gl_texture.cpp @@ -43,98 +43,26 @@ #include "palettecontainer.h" #include "../../glbackend/glbackend.h" #include "texturemanager.h" +#include "v_video.h" // Test CVARs. CVAR(Int, fixpalette, -1, 0) CVAR(Int, fixpalswap, -1, 0) -template -void FlipNonSquareBlock(T* dst, const T* src, int x, int y, int srcpitch) -{ - for (int i = 0; i < x; ++i) - { - for (int j = 0; j < y; ++j) - { - dst[i * y + j] = src[i + j * srcpitch]; - } - } -} - - -//=========================================================================== -// -// Create an indexed version of the requested texture -// -//=========================================================================== - -OpenGLRenderer::FHardwareTexture* GLInstance::CreateIndexedTexture(FGameTexture* tex) -{ - vec2_t siz = { tex->GetTexelWidth(), tex->GetTexelHeight() }; - - auto store = tex->GetTexture()->Get8BitPixels(false); - const uint8_t* p = store.Data(); - - auto glpic = GLInterface.NewTexture(1); - - TArray flipped(siz.x * siz.y, true); - FlipNonSquareBlock(flipped.Data(), p, siz.y, siz.x, siz.y); - glpic->CreateTexture(flipped.Data(), siz.x, siz.y, 15, false, tex->GetName()); - return glpic; -} - -//=========================================================================== -// -// Create a true color version of the requested tile -// -//=========================================================================== - -OpenGLRenderer::FHardwareTexture* GLInstance::CreateTrueColorTexture(FGameTexture* tex, int palid, bool checkfulltransparency, bool rgb8bit) -{ - if (tex == TexMan.GameByIndex(0)) - return nullptr; - auto texbuffer = tex->GetTexture()->CreateTexBuffer(palid, checkfulltransparency? 0: CTF_ProcessData); - // Check if the texture is fully transparent. When creating a brightmap such textures can be discarded. - if (checkfulltransparency) - { - int siz = texbuffer.mWidth * texbuffer.mHeight * 4; - bool found = false; - for (int i = 3; i < siz; i+=4) - { - if (texbuffer.mBuffer[i] > 0) - { - found = true; - break; - } - } - if (!found) return nullptr; - } - - auto glpic = GLInterface.NewTexture(4); - glpic->CreateTexture(texbuffer.mBuffer, texbuffer.mWidth, texbuffer.mHeight, 15, true, tex->GetName()); - return glpic; -} - //=========================================================================== // // Retrieve the texture to be used. // //=========================================================================== -OpenGLRenderer::FHardwareTexture* GLInstance::LoadTexture(FGameTexture* tex, int textype, int palid) +OpenGLRenderer::FHardwareTexture* GLInstance::LoadTexture(FTexture *tex, int textype, int palid) { if (textype == TT_INDEXED) palid = -1; - auto phwtex = tex->GetTexture()->SystemTextures.GetHardwareTexture(palid, false); + auto phwtex = tex->SystemTextures.GetHardwareTexture(palid, false); if (phwtex) return (OpenGLRenderer::FHardwareTexture*)phwtex; - OpenGLRenderer::FHardwareTexture *hwtex = nullptr; - if (textype == TT_INDEXED) - hwtex = CreateIndexedTexture(tex); - else if (!tex->GetTexture()->isHardwareCanvas()) - hwtex = CreateTrueColorTexture(tex, textype == TT_HICREPLACE? -1 : palid, textype == TT_BRIGHTMAP, textype == TT_BRIGHTMAP); - else - hwtex = nullptr; - - if (hwtex) tex->GetTexture()->SystemTextures.AddHardwareTexture(palid, false, hwtex); + auto hwtex = static_cast(screen->CreateHardwareTexture(textype == TT_INDEXED? 1:4)); + if (hwtex) tex->SystemTextures.AddHardwareTexture(palid, false, hwtex); return hwtex; } @@ -203,7 +131,7 @@ TexturePick PickTexture(int tilenum, int basepal, int palette) bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid, int method, int sampleroverride, FGameTexture *det, float detscale, FGameTexture *glow) { - if (tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) return false; + if (!tex->isValid() || tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) return false; int curbasepal = GetTranslationType(paletteid) - Translation_Remap; int palette = GetTranslationIndex(paletteid); int usepalette = fixpalette >= 0 ? fixpalette : curbasepal; @@ -216,6 +144,7 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid TextureType = hw_int_useindexedcolortextures? TT_INDEXED : TT_TRUECOLOR; int lookuppal = 0; + int bindflags = 0; VSMatrix texmat; GLInterface.SetBasepalTint(0xffffff); @@ -241,6 +170,7 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid } if (!rep || rep->palnum != palette || (h.f & HICTINT_APPLYOVERALTPAL)) applytint = true; TextureType = TT_HICREPLACE; + bindflags = CTF_Upscale; } else { @@ -254,7 +184,9 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid if (!(h.f & HICTINT_APPLYOVERPALSWAP)) usepalswap = 0; } lookuppal = TRANSLATION(usepalette + Translation_Remap, usepalswap); + bindflags = CTF_Upscale; } + else bindflags = CTF_Indexed; } // This is intentionally the same value for both parameters. The shader does not use the same uniform for modulation and overlay colors. @@ -264,7 +196,8 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid // Load the main texture - auto mtex = LoadTexture(tex, TextureType, lookuppal); + + auto mtex = LoadTexture(tex->GetTexture(), TextureType, lookuppal); if (mtex) { auto sampler = (method & DAMETH_CLAMPED) ? (sampleroverride != -1 ? sampleroverride : SamplerClampXY) : SamplerRepeat; @@ -280,6 +213,7 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid UseGlowMapping(false); UseBrightmaps(false); + mtex->BindOrCreate(tex->GetTexture(), 0, sampler, lookuppal, bindflags); BindTexture(0, mtex, sampler); // Needs a) testing and b) verification for correctness. This doesn't look like it makes sense. if (rep && (rep->scale.x != 1.0f || rep->scale.y != 1.0f)) @@ -305,8 +239,9 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid } if (det) { - auto htex = LoadTexture(det, TT_HICREPLACE, 0); + auto htex = LoadTexture(det->GetTexture(), TT_HICREPLACE, 0); UseDetailMapping(true); + htex->BindOrCreate(det->GetTexture(), 3, CLAMP_NONE, 0, 0); BindTexture(3, htex, SamplerRepeat); texbound[0] = true; @@ -335,44 +270,38 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid } if (glow) { - auto htex = LoadTexture(glow, TT_HICREPLACE, 0); + auto htex = LoadTexture(glow->GetTexture(), TT_HICREPLACE, 0); UseGlowMapping(true); + htex->BindOrCreate(glow->GetTexture(), 4, sampler, 0, CTF_Upscale); BindTexture(4, htex, SamplerRepeat); texbound[1] = true; } } #if 1 - if (picnum > -1 && !(TileFiles.tiledata[picnum].picanm.sf & PICANM_NOFULLBRIGHT_BIT) && !(globalflags & GLOBAL_NO_GL_FULLBRIGHT) && !TileFiles.tiledata[picnum].NoBrightmapFlag[usepalswap]) + if (picnum > -1 && !(TileFiles.tiledata[picnum].picanm.sf & PICANM_NOFULLBRIGHT_BIT) && !(globalflags & GLOBAL_NO_GL_FULLBRIGHT)) { if (TextureType == TT_HICREPLACE) { auto brep = TileFiles.FindReplacement(picnum, BRIGHTPAL); if (brep) { - LoadTexture(brep->faces[0], TT_HICREPLACE, 0); + auto mtex = LoadTexture(brep->faces[0]->GetTexture(), TT_HICREPLACE, 0); UseBrightmaps(true); + mtex->BindOrCreate(brep->faces[0]->GetTexture(), 5, sampler, 0, CTF_Upscale); BindTexture(5, mtex, sampler); texbound[2] = true; } - else - { - TileFiles.tiledata[picnum].picanm.sf |= PICANM_NOFULLBRIGHT_BIT; - } } else if (TextureType == TT_TRUECOLOR) { - lookuppal = -1;// Needs some work on the texture management first. palmanager.LookupPalette(usepalette, usepalswap, true); - if (lookuppal >= 0) + auto btex = tex->GetBrightmap(); + if (btex) { - auto htex = LoadTexture(tex, TT_BRIGHTMAP, lookuppal); - if (htex == nullptr) - { - // Flag the texture as not being brightmapped for the given palette - TileFiles.tiledata[picnum].NoBrightmapFlag.Set(usepalswap); - } - else + auto htex = LoadTexture(btex, TT_BRIGHTMAP, lookuppal); + if (htex != nullptr) { UseBrightmaps(true); + htex->BindOrCreate(btex, 5, sampler, 0, CTF_Upscale); BindTexture(5, htex, sampler); texbound[2] = true; } @@ -399,23 +328,10 @@ bool GLInstance::SetTextureInternal(int picnum, FGameTexture* tex, int paletteid //=========================================================================== // -// Sets a named texture for 2D rendering. In this case the palette is -// a direct index into the palette map. +// stand-ins for the texture system. Nothing of this is used right now, but needs to be present to satisfy the linker // //=========================================================================== -bool GLInstance::SetNamedTexture(FGameTexture* tex, int palette, int sampler) -{ - auto mtex = LoadTexture(tex, palette>= 0? TT_TRUECOLOR : TT_HICREPLACE, palette); - if (!mtex) return false; - - BindTexture(0, mtex, sampler); - GLInterface.SetAlphaThreshold(tex->GetTranslucency()? 0.f : 0.5f); - return true; -} - -// stand-ins for the texture system. Nothing of this is used right now, but needs to be present to satisfy the linker - int PalCheck(int tex) { return tex; diff --git a/source/glbackend/glbackend.h b/source/glbackend/glbackend.h index 97661bbd2..95df70fa3 100644 --- a/source/glbackend/glbackend.h +++ b/source/glbackend/glbackend.h @@ -487,13 +487,9 @@ public: renderState.AlphaThreshold = al; } - OpenGLRenderer::FHardwareTexture* CreateIndexedTexture(FGameTexture* tex); - OpenGLRenderer::FHardwareTexture* CreateTrueColorTexture(FGameTexture* tex, int palid, bool checkfulltransparency = false, bool rgb8bit = false); - OpenGLRenderer::FHardwareTexture *LoadTexture(FGameTexture* tex, int texturetype, int palid); + OpenGLRenderer::FHardwareTexture *LoadTexture(FTexture* tex, int texturetype, int palid); bool SetTextureInternal(int globalpicnum, FGameTexture* tex, int palette, int method, int sampleroverride, FGameTexture *det, float detscale, FGameTexture *glow); - bool SetNamedTexture(FGameTexture* tex, int palette, int sampleroverride); - bool SetTexture(int globalpicnum, FGameTexture* tex, int palette, int method, int sampleroverride) { return SetTextureInternal(globalpicnum, tex, palette, method, sampleroverride, nullptr, 1, nullptr);