diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index 8d0a7c43e..55ba61e4e 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -345,6 +345,26 @@ sector_t *FGLRenderer::RenderView(player_t* player) return retsec; } +//=========================================================================== +// +// +// +//=========================================================================== + +void FGLRenderer::BindToFrameBuffer(FMaterial *mat) +{ + auto BaseLayer = static_cast(mat->GetLayer(0)); + + if (BaseLayer == nullptr) + { + // must create the hardware texture first + BaseLayer->BindOrCreate(mat->sourcetex, 0, 0, 0, 0); + FHardwareTexture::Unbind(0); + gl_RenderState.ClearLastMaterial(); + } + BaseLayer->BindToFrameBuffer(mat->GetWidth(), mat->GetHeight()); +} + //=========================================================================== // // Camera texture rendering @@ -367,7 +387,7 @@ void FGLRenderer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, doub else { StartOffscreen(); - gltex->BindToFrameBuffer(); + BindToFrameBuffer(gltex); } IntRect bounds; diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index a66d5ced2..99e07f1f1 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -177,10 +177,8 @@ public: bool StartOffscreen(); void EndOffscreen(); - void FillSimplePoly(FTexture *texture, FVector2 *points, int npoints, - double originx, double originy, double scalex, double scaley, - DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip); - + void BindToFrameBuffer(FMaterial *mat); + static float GetZNear() { return 5.f; } static float GetZFar() { return 65536.f; } }; diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 9473a057a..550b27c4b 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -36,6 +36,7 @@ #include "gl/renderer/gl_renderer.h" #include "gl/dynlights//gl_lightbuffer.h" #include "gl/renderer/gl_renderbuffers.h" +#include "gl/textures/gl_hwtexture.h" void gl_SetTextureMode(int type); @@ -424,3 +425,65 @@ void FRenderState::SetClipHeight(float height, float direction) glDisable(GL_CLIP_DISTANCE0); // GL_CLIP_PLANE0 is the same value so no need to make a distinction } } + +//=========================================================================== +// +// Binds a texture to the renderer +// +//=========================================================================== + +void FRenderState::SetMaterial(FMaterial *mat, int clampmode, int translation, int overrideshader, bool alphatexture) +{ + // alpha textures need special treatment in the legacy renderer because without shaders they need a different texture. This will also override all other translations. + if (alphatexture && gl.legacyMode) translation = -STRange_AlphaTexture; + + if (mat->tex->bHasCanvas) + { + mTempTM = TM_OPAQUE; + } + else + { + mTempTM = TM_MODULATE; + } + mEffectState = overrideshader >= 0 ? overrideshader : mat->mShaderIndex; + mShaderTimer = mat->tex->shaderspeed; + SetSpecular(mat->tex->Glossiness, mat->tex->SpecularLevel); + + // avoid rebinding the same texture multiple times. + if (mat == lastMaterial && lastClamp == clampmode && translation == lastTranslation) return; + lastMaterial = mat; + lastClamp = clampmode; + lastTranslation = translation; + + int usebright = false; + int maxbound = 0; + auto tex = mat->tex; + + if (tex->UseType == ETextureType::SWCanvas) clampmode = CLAMP_NOFILTER; + if (tex->bHasCanvas) clampmode = CLAMP_CAMTEX; + else if (tex->bWarped && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE; + + // Textures that are already scaled in the texture lump will not get replaced by hires textures. + int flags = mat->isExpanded() ? CTF_Expand : (gl_texture_usehires && tex->Scale.X == 1 && tex->Scale.Y == 1 && clampmode <= CLAMP_XY) ? CTF_CheckHires : 0; + int numLayers = mat->GetLayers(); + auto base = static_cast(mat->GetLayer(0)); + + if (base->BindOrCreate(tex, 0, clampmode, translation, flags)) + { + for (int i = 1; i(mat->GetLayer(i, &layer)); + systex->BindOrCreate(layer, i, clampmode, 0, mat->isExpanded() ? CTF_Expand : 0); + maxbound = i; + } + } + // unbind everything from the last texture that's still active + for (int i = maxbound + 1; i <= maxBoundMaterial; i++) + { + FHardwareTexture::Unbind(i); + maxBoundMaterial = maxbound; + } +} + + diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index 3cd505611..c8211f1c7 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -131,6 +131,13 @@ class FRenderState bool ApplyShader(); + // Texture binding state + FMaterial *lastMaterial = nullptr; + int lastClamp = 0; + int lastTranslation = 0; + int maxBoundMaterial = -1; + + public: VSMatrix mProjectionMatrix; @@ -146,25 +153,13 @@ public: void Reset(); - void SetMaterial(FMaterial *mat, int clampmode, int translation, int overrideshader, bool alphatexture) + void ClearLastMaterial() { - // alpha textures need special treatment in the legacy renderer because without shaders they need a different texture. This will also override all other translations. - if (alphatexture && gl.legacyMode) translation = -STRange_AlphaTexture; - - if (mat->tex->bHasCanvas) - { - mTempTM = TM_OPAQUE; - } - else - { - mTempTM = TM_MODULATE; - } - mEffectState = overrideshader >= 0? overrideshader : mat->mShaderIndex; - mShaderTimer = mat->tex->shaderspeed; - SetSpecular(mat->tex->Glossiness, mat->tex->SpecularLevel); - mat->Bind(clampmode, translation); + lastMaterial = nullptr; } + void SetMaterial(FMaterial *mat, int clampmode, int translation, int overrideshader, bool alphatexture); + void Apply(); void ApplyColorMask(); void ApplyMatrices(); diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index ad8a25a45..5d4774059 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -73,7 +73,6 @@ OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, int width, int height, int // Make sure all global variables tracking OpenGL context state are reset.. FHardwareTexture::InitGlobalState(); - FMaterial::InitGlobalState(); gl_RenderState.Reset(); GLRenderer = new FGLRenderer(this); @@ -355,6 +354,11 @@ IHardwareTexture *OpenGLFrameBuffer::CreateHardwareTexture(FTexture *tex) return new FHardwareTexture(tex->bNoCompress); } +void OpenGLFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) +{ + gl_RenderState.SetMaterial(mat, CLAMP_NONE, translation, false, false); +} + FModelRenderer *OpenGLFrameBuffer::CreateModelRenderer(int mli) { return new FGLModelRenderer(mli); @@ -371,11 +375,6 @@ IShaderProgram *OpenGLFrameBuffer::CreateShaderProgram() } -void OpenGLFrameBuffer::UnbindTexUnit(int no) -{ - FHardwareTexture::Unbind(no); -} - void OpenGLFrameBuffer::FlushTextures() { if (GLRenderer) GLRenderer->FlushTextures(); diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 8aff32906..e9026a737 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -35,8 +35,8 @@ public: sector_t *RenderView(player_t *player) override; void SetTextureFilterMode() override; IHardwareTexture *CreateHardwareTexture(FTexture *tex) override; + void PrecacheMaterial(FMaterial *mat, int translation) override; FModelRenderer *CreateModelRenderer(int mli) override; - void UnbindTexUnit(int no) override; void FlushTextures() override; void TextureFilterChanged() override; void ResetFixedColormap() override; diff --git a/src/gl/system/gl_wipe.cpp b/src/gl/system/gl_wipe.cpp index 84d72bd98..4fe51ec17 100644 --- a/src/gl/system/gl_wipe.cpp +++ b/src/gl/system/gl_wipe.cpp @@ -242,7 +242,7 @@ void OpenGLFrameBuffer::WipeCleanup() delete wipeendscreen; wipeendscreen = NULL; } - FMaterial::ClearLastTexture(); + gl_RenderState.ClearLastMaterial(); } //========================================================================== diff --git a/src/gl/textures/gl_hwtexture.cpp b/src/gl/textures/gl_hwtexture.cpp index ef069114d..77f9da593 100644 --- a/src/gl/textures/gl_hwtexture.cpp +++ b/src/gl/textures/gl_hwtexture.cpp @@ -36,6 +36,7 @@ #include "hwrenderer/utility/hw_cvars.h" #include "gl/system/gl_debug.h" #include "gl/renderer/gl_renderer.h" +#include "gl/renderer/gl_renderstate.h" #include "gl/textures/gl_samplers.h" @@ -481,7 +482,7 @@ void FHardwareTexture::UnbindAll() { Unbind(texunit); } - FMaterial::ClearLastTexture(); + gl_RenderState.ClearLastMaterial(); } //=========================================================================== diff --git a/src/hwrenderer/textures/hw_ihwtexture.h b/src/hwrenderer/textures/hw_ihwtexture.h index ca9d5bfad..b91291806 100644 --- a/src/hwrenderer/textures/hw_ihwtexture.h +++ b/src/hwrenderer/textures/hw_ihwtexture.h @@ -21,8 +21,6 @@ public: IHardwareTexture() {} virtual ~IHardwareTexture() {} - virtual void BindToFrameBuffer(int w, int h) = 0; - virtual bool BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags) = 0; virtual void AllocateBuffer(int w, int h, int texelsize) = 0; virtual uint8_t *MapBuffer() = 0; virtual unsigned int CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, const char *name) = 0; diff --git a/src/hwrenderer/textures/hw_material.cpp b/src/hwrenderer/textures/hw_material.cpp index cca6c9b2a..daeca6d06 100644 --- a/src/hwrenderer/textures/hw_material.cpp +++ b/src/hwrenderer/textures/hw_material.cpp @@ -407,61 +407,6 @@ outl: return true; } - -//=========================================================================== -// -// Binds a texture to the renderer -// -//=========================================================================== - -static FMaterial *last; -static int lastclamp; -static int lasttrans; - -void FMaterial::InitGlobalState() -{ - last = nullptr; - lastclamp = 0; - lasttrans = 0; -} - -void FMaterial::Bind(int clampmode, int translation) -{ - // avoid rebinding the same texture multiple times. - if (this == last && lastclamp == clampmode && translation == lasttrans) return; - last = this; - lastclamp = clampmode; - lasttrans = translation; - - int usebright = false; - int maxbound = 0; - - if (tex->UseType == ETextureType::SWCanvas) clampmode = CLAMP_NOFILTER; - if (tex->bHasCanvas) clampmode = CLAMP_CAMTEX; - else if (tex->bWarped && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE; - - // Textures that are already scaled in the texture lump will not get replaced by hires textures. - int flags = mExpanded? CTF_Expand : (gl_texture_usehires && tex->Scale.X == 1 && tex->Scale.Y == 1 && clampmode <= CLAMP_XY)? CTF_CheckHires : 0; - - if (mBaseLayer->BindOrCreate(tex, 0, clampmode, translation, flags)) - { - for(unsigned i=0;iBindOrCreate(layer, i+1, clampmode, 0, mExpanded ? CTF_Expand : 0); - maxbound = i+1; - } - } - // unbind everything from the last texture that's still active - for(int i=maxbound+1; i<=mMaxBound;i++) - { - screen->UnbindTexUnit(i); - mMaxBound = maxbound; - } -} - - //=========================================================================== // // @@ -469,7 +414,7 @@ void FMaterial::Bind(int clampmode, int translation) //=========================================================================== void FMaterial::Precache() { - Bind(0, 0); + screen->PrecacheMaterial(this, 0); } //=========================================================================== @@ -482,7 +427,7 @@ void FMaterial::PrecacheList(SpriteHits &translations) if (mBaseLayer != nullptr) mBaseLayer->CleanUnused(translations); SpriteHits::Iterator it(translations); SpriteHits::Pair *pair; - while(it.NextPair(pair)) Bind(0, pair->Key); + while(it.NextPair(pair)) screen->PrecacheMaterial(this, pair->Key); } //=========================================================================== @@ -548,24 +493,6 @@ int FMaterial::GetAreas(FloatRect **pAreas) const } } -//=========================================================================== -// -// -// -//=========================================================================== - -void FMaterial::BindToFrameBuffer() -{ - if (mBaseLayer == nullptr) - { - // must create the hardware texture first - mBaseLayer->BindOrCreate(sourcetex, 0, 0, 0, 0); - screen->UnbindTexUnit(0); - ClearLastTexture(); - } - mBaseLayer->BindToFrameBuffer(mWidth, mHeight); -} - //========================================================================== // // Gets a texture from the texture manager and checks its validity for @@ -637,11 +564,6 @@ void FMaterial::FlushAll() } } -void FMaterial::ClearLastTexture() -{ - last = NULL; -} - void FMaterial::Clean(bool f) { // This somehow needs to deal with the other layers as well, but they probably need some form of reference counting to work properly... diff --git a/src/hwrenderer/textures/hw_material.h b/src/hwrenderer/textures/hw_material.h index 7a3b2f391..d334ceaa1 100644 --- a/src/hwrenderer/textures/hw_material.h +++ b/src/hwrenderer/textures/hw_material.h @@ -75,7 +75,6 @@ class FMaterial float mSpriteU[2], mSpriteV[2]; FloatRect mSpriteRect; - IHardwareTexture * ValidateSysTexture(FTexture * tex, bool expand); bool TrimBorders(uint16_t *rect); public: @@ -87,6 +86,7 @@ public: void SetSpriteRect(); void Precache(); void PrecacheList(SpriteHits &translations); + IHardwareTexture * ValidateSysTexture(FTexture * tex, bool expand); void AddTextureLayer(FTexture *tex) { ValidateTexture(tex, false); @@ -96,17 +96,34 @@ public: { return !!sourcetex->bMasked; } + bool isExpanded() const + { + return mExpanded; + } int GetLayers() const { return mTextureLayers.Size() + 1; } - void Bind(int clamp, int translation); + IHardwareTexture *GetLayer(int i, FTexture **pLayer = nullptr) + { + if (i == 0) + { + if (pLayer) *pLayer = tex; + return mBaseLayer; + } + else + { + i--; + FTexture *layer = mTextureLayers[i]; + if (pLayer) *pLayer = layer; + return ValidateSysTexture(layer, isExpanded()); + } + } void Clean(bool f); - void BindToFrameBuffer(); // Patch drawing utilities void GetSpriteRect(FloatRect * r) const @@ -165,9 +182,6 @@ public: static void FlushAll(); static FMaterial *ValidateTexture(FTexture * tex, bool expand); static FMaterial *ValidateTexture(FTextureID no, bool expand, bool trans); - static void ClearLastTexture(); - - static void InitGlobalState(); }; #endif diff --git a/src/v_video.h b/src/v_video.h index e329939ab..ffc9181fa 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -405,6 +405,7 @@ public: virtual void CleanForRestart() {} virtual void SetTextureFilterMode() {} virtual IHardwareTexture *CreateHardwareTexture(FTexture *tex) { return nullptr; } + virtual void PrecacheMaterial(FMaterial *mat, int translation) {} virtual FModelRenderer *CreateModelRenderer(int mli) { return nullptr; } virtual void UnbindTexUnit(int no) {} virtual void FlushTextures() {}