From c6514949e33f09f7b93f47f1b8a899eebc288577 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 18 Oct 2019 00:20:27 +0200 Subject: [PATCH] - texture creation WIP. --- source/build/src/polymost.cpp | 2 +- source/build/src/pragmas.cpp | 40 +--- source/build/src/texcache.cpp | 302 ++++++++++++++--------------- source/build/src/voxmodel.cpp | 3 +- source/common/textures/textures.h | 13 ++ source/glbackend/gl_palmanager.cpp | 26 +++ source/glbackend/glbackend.h | 16 +- 7 files changed, 208 insertions(+), 194 deletions(-) diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index 2e8a61a42..ec8687e6d 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -649,7 +649,7 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32 if (drawpoly_srepeat && drawpoly_trepeat) sampleroverride = SamplerRepeat; else if (drawpoly_srepeat) sampleroverride = SamplerClampY; else if (drawpoly_trepeat) sampleroverride = SamplerClampX; - else sampleroverride = -1; + else sampleroverride = SamplerClampXY; bool success = GLInterface.SetTexture(TileFiles.tiles[globalpicnum], globalpal, method, sampleroverride); diff --git a/source/build/src/pragmas.cpp b/source/build/src/pragmas.cpp index d73144a78..219849540 100644 --- a/source/build/src/pragmas.cpp +++ b/source/build/src/pragmas.cpp @@ -129,45 +129,7 @@ void copybufbyte(const void *s, void *d, int32_t c) // *and* x86_64, and the C version otherwise. // XXX: we don't honor NOASM in the x86_64 case. -#if defined(__GNUC__) && defined(__x86_64__) -// NOTE: Almost CODEDUP from x86 GCC assembly version, except that -// - %%esi -> %%rsi -// - %%edi -> %%rdi -// - (dec,inc,sub,add)l suffix removed where necessary -void copybufreverse(const void *S, void *D, int32_t c) -{ - __asm__ __volatile__( - "shrl $1, %%ecx\n\t" - "jnc 0f\n\t" // jnc skipit1 - "movb (%%rsi), %%al\n\t" - "dec %%rsi\n\t" - "movb %%al, (%%rdi)\n\t" - "inc %%rdi\n\t" - "0:\n\t" // skipit1: - "shrl $1, %%ecx\n\t" - "jnc 1f\n\t" // jnc skipit2 - "movw -1(%%rsi), %%ax\n\t" - "sub $2, %%rsi\n\t" - "rorw $8, %%ax\n\t" - "movw %%ax, (%%rdi)\n\t" - "add $2, %%rdi\n\t" - "1:\n\t" // skipit2 - "testl %%ecx, %%ecx\n\t" - "jz 3f\n\t" // jz endloop - "2:\n\t" // begloop - "movl -3(%%rsi), %%eax\n\t" - "sub $4, %%rsi\n\t" - "bswapl %%eax\n\t" - "movl %%eax, (%%rdi)\n\t" - "add $4, %%rdi\n\t" - "decl %%ecx\n\t" - "jnz 2b\n\t" // jnz begloop - "3:" - : "+S"(S), "+D"(D), "+c"(c) : - : "eax", "memory", "cc" - ); -} -#elif !defined pragmas_have_copybufreverse +#if !defined pragmas_have_copybufreverse void copybufreverse(const void *s, void *d, int32_t c) { auto src = (const char *)s; diff --git a/source/build/src/texcache.cpp b/source/build/src/texcache.cpp index 6569af803..c9e4a6ab4 100644 --- a/source/build/src/texcache.cpp +++ b/source/build/src/texcache.cpp @@ -1,4 +1,3 @@ -#ifdef USE_OPENGL #include "baselayer.h" #include "build.h" @@ -15,6 +14,9 @@ #include "bitmap.h" #include "../../glbackend/glbackend.h" +extern int r_detailmapping, r_glowmapping, usehightile, r_useindexedcolortextures; +extern int fixpalette, fixpalswap; + #if 0 void gltexinvalidate(int32_t dapicnum, int32_t dapalnum, int32_t dameth) @@ -99,18 +101,6 @@ static void polymost_setupsampler(FHardwareTexture* tex, const int32_t dameth, i } -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]; - } - } -} - void gloadtile_art(int32_t dapic, int32_t dameth, pthtyp* pth, int32_t doalloc) { vec2_16_t const& tsizart = tilesiz[dapic]; @@ -229,77 +219,8 @@ int32_t gloadtile_hi(int32_t dapic, int32_t dapalnum, int32_t facen, hicreplctyp globaltexcache texcache; -static pthtyp *texcache_tryart(int32_t const dapicnum, int32_t const dapalnum, int32_t const dashade, int32_t dameth) -{ - const int32_t j = dapicnum&(GLTEXCACHEADSIZ-1); - pthtyp *pth; - int32_t tintpalnum = -1; - int32_t searchpalnum = dapalnum; - polytintflags_t const tintflags = hictinting[dapalnum].f; - if (tintflags & (HICTINT_USEONART)) - { - tintpalnum = dapalnum; - if (!(tintflags & HICTINT_APPLYOVERPALSWAP)) - searchpalnum = 0; - } - // load from art - for (pth=texcache.list[j]; pth; pth=pth->next) - if (pth->picnum == dapicnum && ((pth->flags & (PTH_INDEXED|PTH_HIGHTILE)) == PTH_INDEXED)) - { - if (pth->flags & PTH_INVALIDATED) - { - pth->flags &= ~PTH_INVALIDATED; - gloadtile_art(dapicnum, dameth, pth, 0); - pth->palnum = dapalnum; - } - - return pth; - } - - pth = (pthtyp *)Xcalloc(1,sizeof(pthtyp)); - - gloadtile_art(dapicnum, dameth, pth, 1); - - pth->palnum = dapalnum; - pth->next = texcache.list[j]; - texcache.list[j] = pth; - - return pth; -} - -#if 0 -pthtyp *texcache_fetchmulti(pthtyp *pth, hicreplctyp *si, int32_t dapicnum, int32_t dameth) -{ - const int32_t j = dapicnum&(GLTEXCACHEADSIZ-1); - int32_t i; - - for (i = 0; i <= (GLTEXCACHEADSIZ - 1); i++) - { - const pthtyp *pth2; - - for (pth2=texcache.list[i]; pth2; pth2=pth2->next) - { - if (pth2->hicr && pth2->hicr->filename && si->filename && filnamcmp(pth2->hicr->filename, si->filename) == 0) - { - Bmemcpy(pth, pth2, sizeof(pthtyp)); - pth->picnum = dapicnum; - pth->flags = PTH_HIGHTILE | (drawingskybox>0)*PTH_SKYBOX; - if (pth2->flags & PTH_HASALPHA) - pth->flags |= PTH_HASALPHA; - pth->hicr = si; - - pth->next = texcache.list[j]; - texcache.list[j] = pth; - - return pth; - } - } - } - return NULL; -} -#endif // : ignored if not in Polymost+r_usetileshades pthtyp *texcache_fetch(int32_t dapicnum, int32_t dapalnum, int32_t dashade, int32_t dameth) @@ -379,94 +300,171 @@ pthtyp *texcache_fetch(int32_t dapicnum, int32_t dapalnum, int32_t dashade, int3 } -extern int r_detailmapping, r_glowmapping, usehightile; +#endif -bool GLInstance::ApplyTextureProps() + +template +void FlipNonSquareBlock(T* dst, const T* src, int x, int y, int srcpitch) { - int pal = palmanager.ActivePalswap(); - if (currentTexture == nullptr) return false; - auto rep = currentTexture->FindReplacement(pal); - VSMatrix texmat; - bool changed = false; - - // texture scale - if (rep && ((rep->scale.x != 1.0f) || (rep->scale.y != 1.0f))) + for (int i = 0; i < x; ++i) { - texmat.loadIdentity(); - texmat.scale(rep->scale.x, rep->scale.y, 1.0f); - GLInterface.SetMatrix(Matrix_Texture, &texmat); - } - - if (r_detailmapping) - { - auto detailrep = currentTexture->FindReplacement(DETAILPAL); - if (detailrep) + for (int j = 0; j < y; ++j) { - UseDetailMapping(true); - //BindTexture(3, detailrep->faces[0], SamplerRepeat); - - texmat.loadIdentity(); - bool scaled = false; - - if (rep && ((rep->scale.x != 1.0f) || (rep->scale.y != 1.0f))) - { - texmat.scale(rep->scale.x, rep->scale.y, 1.0f); - scaled = true; - } - - if ((detailrep->scale.x != 1.0f) || (detailrep->scale.y != 1.0f)) - { - texmat.scale(detailrep->scale.x, detailrep->scale.y, 1.0f); - scaled = true; - } - - if (scaled) GLInterface.SetMatrix(Matrix_Detail, &texmat); - changed |= scaled; + dst[i * y + j] = src[i + j * srcpitch]; } } - - // glow texture - if (r_glowmapping) - { - auto glowrep = currentTexture->FindReplacement(GLOWPAL); - if (glowrep) - { - UseGlowMapping(true); - //BindTexture(4, glowrep->faces[0], SamplerRepeat); - } - } - - auto brightrep = currentTexture->FindReplacement(BRIGHTPAL); - if (brightrep) - { - //UseGlowMapping(true); - //BindTexture(5, glowrep->faces[0], SamplerRepeat); - } - - return false; // true if the matrices were changed, false otherwise } +//=========================================================================== +// +// Create an indexed version of the requested texture +// +//=========================================================================== -void GLInstance::SetTexture(FTexture* tex, int palette, int method) +FHardwareTexture* CreateIndexedTexture(FTexture* tex) { + auto siz = tex->GetSize(); + bool npoty = false; - GLInterface.SetPalswap(fixpalswap >= 1 ? fixpalswap - 1 : globalpal); - GLInterface.SetPalette(fixpalette >= 1 ? fixpalette - 1 : curbasepal); + const uint8_t* p = tex->Get8BitPixels(); + TArray store(siz.x * siz.y, true); + if (!p) + { + tex->Create8BitPixels(store.Data()); + p = store.Data(); + } + auto glpic = GLInterface.NewTexture(); + glpic->CreateTexture(siz.x, siz.y, true, false); - pthtyp* pth = texcache_fetch(globalpicnum, globalpal, getpalookup(1, globalshade), method | PTH_INDEXED); - GLInterface.BindTexture(0, pth->glpic, mSampler); + TArray flipped(siz.x * siz.y, true); + FlipNonSquareBlock(flipped.Data(), p, siz.y, siz.x, siz.y); + glpic->LoadTexture(flipped.Data()); + return glpic; +} - // Fixme: Alpha test on shaders must be done differently. -// Also: Consider a texture's alpha threshold. - float const al = alphahackarray[globalpicnum] != 0 ? alphahackarray[globalpicnum] * (1.f / 255.f) : - (pth->hicr && pth->hicr->alphacut >= 0.f ? pth->hicr->alphacut : 0.f); +//=========================================================================== +// +// Retrieve the texture to be used. +// +//=========================================================================== +FHardwareTexture* GLInstance::LoadTexture(FTexture* tex, int textype, int palid) +{ + if (textype == TT_TRUECOLOR && palid == 0) textype = TT_HICREPLACE; // true color tiles with the base palette won't get processed. + if (textype == TT_INDEXED) + { + auto hwtex = tex->GetHardwareTexture(-1); + if (hwtex) return hwtex; + else + { + hwtex = CreateIndexedTexture(tex); + tex->SetHardwareTexture(-1, hwtex); + return hwtex; + } + } +} + +//=========================================================================== +// +// Sets a texture for rendering +// +//=========================================================================== + +bool GLInstance::SetTexture(FTexture* tex, int palette, int method, int sampleroverride) +{ + int usepalette = fixpalette >= 1 ? fixpalette - 1 : curbasepal; + int usepalswap = fixpalswap >= 1 ? fixpalswap - 1 : palette; + GLInterface.SetPalette(usepalette); + GLInterface.SetPalswap(usepalswap); + + TextureType = r_useindexedcolortextures? TT_INDEXED : TT_TRUECOLOR; + + int lookuppal = 0; + VSMatrix texmat; + + auto rep = usehightile? currentTexture->FindReplacement(palette) : nullptr; + if (rep) + { + // Hightile replacements have only one texture representation and it is always the base. + tex = rep->faces[0]; + TextureType = TT_HICREPLACE; + } + else + { + // Only look up the palette if we really want to use it (i.e. when creating a true color texture of an ART tile.) + if (!r_useindexedcolortextures) lookuppal = palmanager.LookupPalette(usepalette, usepalswap); + } + + // Load the main texture + auto mtex = LoadTexture(tex, TextureType, lookuppal); + if (mtex) + { + auto sampler = (method & DAMETH_CLAMPED) ? (sampleroverride != -1 ? sampleroverride : SamplerClampXY) : SamplerRepeat; + + BindTexture(0, mtex, sampler); + if (rep && ((rep->scale.x != 1.0f) || (rep->scale.y != 1.0f))) + { + texmat.loadIdentity(); + texmat.scale(rep->scale.x, rep->scale.y, 1.0f); + GLInterface.SetMatrix(Matrix_Texture, &texmat); + MatrixChange |= 1; + } + + // Also load additional layers needed for this texture. + if (r_detailmapping && usehightile) + { + auto drep = currentTexture->FindReplacement(DETAILPAL); + if (drep) + { + auto htex = LoadTexture(drep->faces[0], TT_HICREPLACE, 0); + UseDetailMapping(true); + BindTexture(3, htex, SamplerRepeat); + + texmat.loadIdentity(); + + if (rep && ((rep->scale.x != 1.0f) || (rep->scale.y != 1.0f))) + { + texmat.scale(rep->scale.x, rep->scale.y, 1.0f); + MatrixChange |= 2; + } + + if ((drep->scale.x != 1.0f) || (drep->scale.y != 1.0f)) + { + texmat.scale(drep->scale.x, drep->scale.y, 1.0f); + MatrixChange |= 2; + } + if (MatrixChange & 2) GLInterface.SetMatrix(Matrix_Detail, &texmat); + } + } + if (r_glowmapping && usehightile) + { + auto drep = currentTexture->FindReplacement(GLOWPAL); + if (drep) + { + auto htex = LoadTexture(drep->faces[0], TT_HICREPLACE, 0); + UseGlowMapping(true); + BindTexture(4, htex, SamplerRepeat); + + } + } + auto brep = currentTexture->FindReplacement(BRIGHTPAL); + if (brep) + { + auto htex = LoadTexture(brep->faces[0], TT_HICREPLACE, 0); + BindTexture(5, mtex, sampler); + } + } + + float al = 0; + if (TextureType == TT_HICREPLACE) + { + al = /*alphahackarray[globalpicnum] != 0 ? alphahackarray[globalpicnum] * (1.f / 255.f) :*/ + (tex->alphaThreshold >= 0.f ? tex->alphaThreshold : 0.f); + } GLInterface.SetAlphaThreshold(al); } -#endif -#endif \ No newline at end of file diff --git a/source/build/src/voxmodel.cpp b/source/build/src/voxmodel.cpp index b564518c8..19b51fc30 100644 --- a/source/build/src/voxmodel.cpp +++ b/source/build/src/voxmodel.cpp @@ -1188,7 +1188,8 @@ int32_t polymost_voxdraw(voxmodel_t *m, tspriteptr_t const tspr) } VSMatrix identity(0); GLInterface.SetMatrix(Matrix_ModelView, &identity); - return 1; + GLInterface.SetTinting(0, 0, PalEntry(255, 255, 255)); + return 1; } #endif diff --git a/source/common/textures/textures.h b/source/common/textures/textures.h index 057527e89..708d69602 100644 --- a/source/common/textures/textures.h +++ b/source/common/textures/textures.h @@ -43,6 +43,7 @@ class FImageSource; class FTexture; +class FHardwareTexture; // picanm[].sf: // |bit(1<<7) @@ -249,6 +250,16 @@ public: Hightiles.Clear(); } + void SetHardwareTexture(int palid, FHardwareTexture* htex) + { + HardwareTextures.Insert(palid, htex); + } + FHardwareTexture* GetHardwareTexture(int palid) + { + auto k = HardwareTextures.CheckKey(palid); + return k ? *k : nullptr; + } + HightileReplacement * FindReplacement(int palnum, bool skybox = false); int alphaThreshold = 128; @@ -299,6 +310,8 @@ protected: intptr_t CacheHandle = 0; // For tiles that do not have a static image but get accessed by the software renderer. uint8_t CacheLock = 0; TArray Hightiles; + // Don't waste too much effort on efficient storage here. Polymost performs so many calculations on a single draw call that the minor map lookup hardly matters. + TMap HardwareTextures; // Note: These must be deleted by the backend. When the texture manager is taken down it may already be too late to delete them. FTexture (const char *name = NULL); }; diff --git a/source/glbackend/gl_palmanager.cpp b/source/glbackend/gl_palmanager.cpp index 7c8261e4a..fed8a2cc6 100644 --- a/source/glbackend/gl_palmanager.cpp +++ b/source/glbackend/gl_palmanager.cpp @@ -39,6 +39,7 @@ #include "baselayer.h" #include "resourcefile.h" +#include "imagehelpers.h" //=========================================================================== // @@ -168,6 +169,10 @@ void PaletteManager::SetPalette(int index, const uint8_t* data, bool transient) return; } palettemap[index] = FindPalette(data); + if (index == 0) + { + ImageHelpers::SetPalette((PalEntry*)data); // Palette 0 is always the reference for downconverting images + } } //=========================================================================== @@ -251,3 +256,24 @@ void PaletteManager::BindPalswap(int index) } + +int PaletteManager::LookupPalette(int palette, int palswap) +{ + int realpal = palettemap[palette]; + int realswap = palswapmap[palswap]; + int combined = realpal * 0x10000 + realswap; + int* combinedindex = swappedpalmap.CheckKey(combined); + if (combinedindex) return *combinedindex; + + PaletteData* paldata = &palettes[realpal]; + PalswapData* swapdata = &palswaps[realswap]; + PalEntry swappedpalette[256]; + for (int i = 0; i < 256; i++) + { + int swapi = swapdata->lookup[i]; + swappedpalette[i] = paldata->colors[swapi]; + } + int palid = FindPalette((uint8_t*)swappedpalette); + swappedpalmap.Insert(combined, palid); + return palid; +} diff --git a/source/glbackend/glbackend.h b/source/glbackend/glbackend.h index cc67be78e..90742d8a2 100644 --- a/source/glbackend/glbackend.h +++ b/source/glbackend/glbackend.h @@ -62,6 +62,7 @@ class PaletteManager // All data is being stored in contiguous blocks that can be used as uniform buffers as-is. TArray palettes; TArray palswaps; + TMap swappedpalmap; FHardwareTexture* palswapTexture = nullptr; GLInstance* const inst; @@ -81,6 +82,7 @@ public: void BindPalette(int index); void BindPalswap(int index); int ActivePalswap() const { return lastsindex; } + int LookupPalette(int palette, int palswap); }; @@ -186,6 +188,14 @@ enum EWinding Winding_CCW, Winding_CW }; + +enum ETexType +{ + TT_INDEXED, + TT_TRUECOLOR, + TT_HICREPLACE +}; + class GLInstance { enum @@ -202,6 +212,8 @@ class GLInstance int lastPalswapIndex = -1; FHardwareTexture* texv; FTexture* currentTexture = nullptr; + int TextureType; + int MatrixChange = 0; VSMatrix matrices[NUMMATRICES]; @@ -279,7 +291,7 @@ public: void SetSurfaceShader(); void SetVPXShader(); void SetPalette(int palette); - bool ApplyTextureProps(); + bool ApplyTextureProps(FTexture *tex, int pal); void RestoreTextureProps(); void ReadPixels(int w, int h, uint8_t* buffer); @@ -365,6 +377,8 @@ public: // not yet implemented - only relevant for hires replacements. } + FHardwareTexture* CreateIndexedTexture(FTexture* tex); + FHardwareTexture *LoadTexture(FTexture* tex, int texturetype, int palid); bool SetTexture(FTexture* tex, int palette, int method, int sampleroverride = -1); };