diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 4080768ec..0340bb082 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -712,8 +712,6 @@ set( FASTMATH_SOURCES set (PCH_SOURCES - glbackend/gl_hwtexture.cpp - #glbackend/gl_samplers.cpp glbackend/gl_shader.cpp glbackend/glbackend.cpp glbackend/gl_palmanager.cpp @@ -867,6 +865,7 @@ set (PCH_SOURCES common/objects/dobjtype.cpp common/rendering/gl_load/gl_interface.cpp common/rendering/gl/gl_debug.cpp + common/rendering/gl/gl_hwtexture.cpp common/rendering/gl/gl_samplers.cpp common/scripting/core/dictionary.cpp common/scripting/core/dynarrays.cpp diff --git a/source/build/include/mdsprite.h b/source/build/include/mdsprite.h index 7b6c8e9e6..5e89c8957 100644 --- a/source/build/include/mdsprite.h +++ b/source/build/include/mdsprite.h @@ -3,7 +3,7 @@ #ifdef USE_OPENGL #include "hightile.h" -#include "glbackend/gl_hwtexture.h" +#include "gl_hwtexture.h" #if defined(_M_IX86) || defined(_M_AMD64) || defined(__i386) || defined(__x86_64) #define SHIFTMOD32(a) (a) @@ -15,7 +15,6 @@ #define IDP3_MAGIC 0x33504449 class FGameTexture; -class FHardwareTexture; struct mdmodel_t { @@ -195,7 +194,7 @@ struct voxmodel_t : public mdmodel_t vec3_t siz; vec3f_t piv; int32_t is8bit; - TMap *texIds; + TMap *texIds; }; EXTERN mdmodel_t **models; diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index 7fb1f4457..b5c832a47 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -150,7 +150,7 @@ void gltexapplyprops(void) gl_texture_filter_anisotropic = (int32_t)GLInterface.glinfo.maxanisotropy; } - GLInterface.mSamplers->SetTextureFilterMode(); + screen->SetTextureFilterMode(); } //-------------------------------------------------------------------------------------------------- diff --git a/source/build/src/voxmodel.cpp b/source/build/src/voxmodel.cpp index 6221ba0cb..f0192be5d 100644 --- a/source/build/src/voxmodel.cpp +++ b/source/build/src/voxmodel.cpp @@ -35,7 +35,7 @@ static voxmodel_t *gvox; //pitch must equal xsiz*4 -static FHardwareTexture *gloadtex(const int32_t *picbuf, int32_t xsiz, int32_t ysiz, int32_t is8bit, const PalEntry *paldata) +static OpenGLRenderer::FHardwareTexture *gloadtex(const int32_t *picbuf, int32_t xsiz, int32_t ysiz, int32_t is8bit, const PalEntry *paldata) { // Correct for GL's RGB order; also apply gamma here: const coltype *const pic = (const coltype *)picbuf; @@ -64,9 +64,8 @@ static FHardwareTexture *gloadtex(const int32_t *picbuf, int32_t xsiz, int32_t y } } - auto tex = GLInterface.NewTexture(); - tex->CreateTexture(xsiz, ysiz, FHardwareTexture::TrueColor, false); - tex->LoadTexture((uint8_t*)pic2); + auto tex = GLInterface.NewTexture(4); + tex->CreateTexture((uint8_t*)pic2, xsiz, ysiz, 15, true, "Voxel"); // Mipmap should be false for this but currently this causes render errors because the proper sampler cannot be selected. Xfree(pic2); return tex; @@ -843,8 +842,8 @@ void voxfree(voxmodel_t *m) if (m->texIds) { - TMap::Iterator it(*m->texIds); - TMap::Pair* pair; + TMap::Iterator it(*m->texIds); + TMap::Pair* pair; while (it.NextPair(pair)) { if (pair->Value) delete pair->Value; @@ -1137,9 +1136,9 @@ int32_t polymost_voxdraw(voxmodel_t *m, tspriteptr_t const tspr) #if 1 int palId = TRANSLATION(Translation_Remap + curbasepal, globalpal); auto palette = GPalette.TranslationToTable(palId); - if (!m->texIds) m->texIds = new TMap; + if (!m->texIds) m->texIds = new TMap; auto pTex = m->texIds->CheckKey(palId); - FHardwareTexture* htex; + OpenGLRenderer::FHardwareTexture* htex; if (!pTex) { htex = gloadtex(m->mytex, m->mytexx, m->mytexy, m->is8bit, palette->Palette); diff --git a/source/common/rendering/gl/gl_hwtexture.cpp b/source/common/rendering/gl/gl_hwtexture.cpp new file mode 100644 index 000000000..31e104cfe --- /dev/null +++ b/source/common/rendering/gl/gl_hwtexture.cpp @@ -0,0 +1,338 @@ +/* +** gl_hwtexture.cpp +** GL texture abstraction +** +**--------------------------------------------------------------------------- +** Copyright 2019 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +*/ + +#include "gl_system.h" +#include "templates.h" +#include "c_cvars.h" +#include "hw_material.h" + +#include "gl_interface.h" +#include "hw_cvars.h" +#include "gl_debug.h" +#include "gl_renderer.h" +#include "gl_samplers.h" +#include "gl_hwtexture.h" + +namespace OpenGLRenderer +{ + + +TexFilter_s TexFilter[] = { + {GL_NEAREST, GL_NEAREST, false}, + {GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST, true}, + {GL_LINEAR, GL_LINEAR, false}, + {GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, true}, + {GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, true}, + {GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST, true}, + {GL_LINEAR_MIPMAP_LINEAR, GL_NEAREST, true}, +}; + +//=========================================================================== +// +// Static texture data +// +//=========================================================================== +unsigned int FHardwareTexture::lastbound[FHardwareTexture::MAX_TEXTURES]; + +//=========================================================================== +// +// Loads the texture image into the hardware +// +// NOTE: For some strange reason I was unable to find the source buffer +// should be one line higher than the actual texture. I got extremely +// strange crashes deep inside the GL driver when I didn't do it! +// +//=========================================================================== + +unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, const char *name) +{ + int rh,rw; + int texformat = GL_RGBA8;// TexFormat[gl_texture_format]; + bool deletebuffer=false; + + /* + if (forcenocompression) + { + texformat = GL_RGBA8; + } + */ + bool firstCall = glTexID == 0; + if (firstCall) + { + glGenTextures(1, &glTexID); + } + + int textureBinding = UINT_MAX; + if (texunit == -1) glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding); + if (texunit > 0) glActiveTexture(GL_TEXTURE0+texunit); + if (texunit >= 0) lastbound[texunit] = glTexID; + glBindTexture(GL_TEXTURE_2D, glTexID); + + FGLDebug::LabelObject(GL_TEXTURE, glTexID, name); + + rw = GetTexDimension(w); + rh = GetTexDimension(h); + if (glBufferID > 0) + { + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + buffer = nullptr; + } + else if (!buffer) + { + // The texture must at least be initialized if no data is present. + mipmapped = false; + buffer=(unsigned char *)calloc(4,rw * (rh+1)); + deletebuffer=true; + //texheight=-h; + } + else + { + if (rw < w || rh < h) + { + // The texture is larger than what the hardware can handle so scale it down. + unsigned char * scaledbuffer=(unsigned char *)calloc(4,rw * (rh+1)); + if (scaledbuffer) + { + Resize(w, h, rw, rh, buffer, scaledbuffer); + deletebuffer=true; + buffer=scaledbuffer; + } + } + } + // store the physical size. + + int sourcetype; + if (glTextureBytes > 0) + { + if (glTextureBytes < 4) glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + static const int ITypes[] = { GL_R8, GL_RG8, GL_RGB8, GL_RGBA8 }; + static const int STypes[] = { GL_RED, GL_RG, GL_BGR, GL_BGRA }; + + texformat = ITypes[glTextureBytes - 1]; + sourcetype = STypes[glTextureBytes - 1]; + } + else + { + sourcetype = GL_BGRA; + } + + if (!firstCall && glBufferID > 0) + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rw, rh, sourcetype, GL_UNSIGNED_BYTE, buffer); + else + glTexImage2D(GL_TEXTURE_2D, 0, texformat, rw, rh, 0, sourcetype, GL_UNSIGNED_BYTE, buffer); + + if (deletebuffer && buffer) free(buffer); + else if (glBufferID) + { + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + } + + if (mipmap && TexFilter[gl_texture_filter].mipmapping) + { + glGenerateMipmap(GL_TEXTURE_2D); + mipmapped = true; + } + + if (texunit > 0) glActiveTexture(GL_TEXTURE0); + else if (texunit == -1) glBindTexture(GL_TEXTURE_2D, textureBinding); + return glTexID; +} + + +//=========================================================================== +// +// +// +//=========================================================================== +void FHardwareTexture::AllocateBuffer(int w, int h, int texelsize) +{ + int rw = GetTexDimension(w); + int rh = GetTexDimension(h); + if (texelsize < 1 || texelsize > 4) texelsize = 4; + glTextureBytes = texelsize; + bufferpitch = w; + if (rw == w || rh == h) + { + glGenBuffers(1, &glBufferID); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glBufferID); + glBufferData(GL_PIXEL_UNPACK_BUFFER, w*h*texelsize, nullptr, GL_STREAM_DRAW); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + } +} + + +uint8_t *FHardwareTexture::MapBuffer() +{ + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glBufferID); + return (uint8_t*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); +} + +//=========================================================================== +// +// Destroys the texture +// +//=========================================================================== +FHardwareTexture::~FHardwareTexture() +{ + if (glTexID != 0) glDeleteTextures(1, &glTexID); + if (glBufferID != 0) glDeleteBuffers(1, &glBufferID); +} + + +//=========================================================================== +// +// Binds this patch +// +//=========================================================================== +unsigned int FHardwareTexture::Bind(int texunit, bool needmipmap) +{ + if (glTexID != 0) + { + if (lastbound[texunit] == glTexID) return glTexID; + lastbound[texunit] = glTexID; + if (texunit != 0) glActiveTexture(GL_TEXTURE0 + texunit); + glBindTexture(GL_TEXTURE_2D, glTexID); + // Check if we need mipmaps on a texture that was creted without them. + if (needmipmap && !mipmapped && TexFilter[gl_texture_filter].mipmapping) + { + glGenerateMipmap(GL_TEXTURE_2D); + mipmapped = true; + } + if (texunit != 0) glActiveTexture(GL_TEXTURE0); + return glTexID; + } + return 0; +} + +void FHardwareTexture::Unbind(int texunit) +{ + if (lastbound[texunit] != 0) + { + if (texunit != 0) glActiveTexture(GL_TEXTURE0+texunit); + glBindTexture(GL_TEXTURE_2D, 0); + if (texunit != 0) glActiveTexture(GL_TEXTURE0); + lastbound[texunit] = 0; + } +} + +void FHardwareTexture::UnbindAll() +{ + for(int texunit = 0; texunit < 16; texunit++) + { + Unbind(texunit); + } +} + +//=========================================================================== +// +// Creates a depth buffer for this texture +// +//=========================================================================== + +int FHardwareTexture::GetDepthBuffer(int width, int height) +{ + if (glDepthID == 0) + { + glGenRenderbuffers(1, &glDepthID); + glBindRenderbuffer(GL_RENDERBUFFER, glDepthID); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, + GetTexDimension(width), GetTexDimension(height)); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + return glDepthID; +} + + +//=========================================================================== +// +// Binds this texture's surfaces to the current framrbuffer +// +//=========================================================================== + +void FHardwareTexture::BindToFrameBuffer(int width, int height) +{ + width = GetTexDimension(width); + height = GetTexDimension(height); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glTexID, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, GetDepthBuffer(width, height)); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, GetDepthBuffer(width, height)); +} + + +//=========================================================================== +// +// Binds a texture to the renderer +// +//=========================================================================== + +bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags) +{ + int usebright = false; + + bool needmipmap = (clampmode <= CLAMP_XY); + + // Bind it to the system. + if (!Bind(texunit, needmipmap)) + { + + int w = 0, h = 0; + + // Create this texture + + FTextureBuffer texbuffer; + + if (!tex->isHardwareCanvas()) + { + texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData); + w = texbuffer.mWidth; + h = texbuffer.mHeight; + } + else + { + w = tex->GetWidth(); + h = tex->GetHeight(); + } + if (!CreateTexture(texbuffer.mBuffer, w, h, texunit, needmipmap, "FHardwareTexture.BindOrCreate")) + { + // could not create texture + return false; + } + } + GLRenderer->mSamplerManager->Bind(texunit, clampmode, 255); + return true; +} + +} diff --git a/source/common/rendering/gl/gl_hwtexture.h b/source/common/rendering/gl/gl_hwtexture.h new file mode 100644 index 000000000..1b3cdff2c --- /dev/null +++ b/source/common/rendering/gl/gl_hwtexture.h @@ -0,0 +1,80 @@ +#pragma once +class FBitmap; +class FTexture; + +#include "tarray.h" +#include "hw_ihwtexture.h" + + +#ifdef LoadImage +#undef LoadImage +#endif + +#define SHADED_TEXTURE -1 +#define DIRECT_PALETTE -2 + +#include "tarray.h" +#include "gl_interface.h" +#include "hw_ihwtexture.h" + +class FCanvasTexture; + +namespace OpenGLRenderer +{ + +class FHardwareTexture : public IHardwareTexture +{ +public: + + static unsigned int lastbound[MAX_TEXTURES]; + + static int GetTexDimension(int value) + { + if (value > gl.max_texturesize) return gl.max_texturesize; + return value; + } + + static void InitGlobalState() { for (int i = 0; i < MAX_TEXTURES; i++) lastbound[i] = 0; } + +private: + + bool forcenofilter; + + unsigned int glTexID = 0; + unsigned int glDepthID = 0; // only used by camera textures + unsigned int glBufferID = 0; + int glTextureBytes; + bool mipmapped = false; + + int GetDepthBuffer(int w, int h); + +public: + FHardwareTexture(int numchannels = 4, bool disablefilter = false) + { + forcenofilter = disablefilter; + glTextureBytes = numchannels; + } + + ~FHardwareTexture(); + + static void Unbind(int texunit); + static void UnbindAll(); + + void BindToFrameBuffer(int w, int h); + + unsigned int Bind(int texunit, bool needmipmap); + bool BindOrCreate(FTexture* tex, int texunit, int clampmode, int translation, int flags); + + void AllocateBuffer(int w, int h, int texelsize); + uint8_t* MapBuffer(); + + unsigned int CreateTexture(unsigned char* buffer, int w, int h, int texunit, bool mipmap, const char* name); + unsigned int GetTextureHandle() + { + return glTexID; + } + + int numChannels() { return glTextureBytes; } +}; + +} diff --git a/source/core/rendering/gl/renderer/gl_renderer.cpp b/source/core/rendering/gl/renderer/gl_renderer.cpp index 6af6e6d0b..4089b1a5d 100644 --- a/source/core/rendering/gl/renderer/gl_renderer.cpp +++ b/source/core/rendering/gl/renderer/gl_renderer.cpp @@ -52,7 +52,7 @@ #include "gl/renderer/gl_renderbuffers.h" #include "gl/shaders/gl_shaderprogram.h" //#include "hwrenderer/data/flatvertices.h" -//#include "gl/textures/gl_samplers.h" +#include "gl_samplers.h" //#include "hwrenderer/dynlights/hw_lightbuffer.h" //#include "hwrenderer/data/hw_viewpointbuffer.h" #include "r_videoscale.h" @@ -108,7 +108,7 @@ void FGLRenderer::Initialize(int width, int height) mOldFBID = 0; //mShaderManager = new FShaderManager; - //mSamplerManager = new FSamplerManager; + mSamplerManager = new FSamplerManager; } FGLRenderer::~FGLRenderer() @@ -116,7 +116,7 @@ FGLRenderer::~FGLRenderer() //FlushModels(); //TexMan.FlushAll(); //if (mShaderManager != nullptr) delete mShaderManager; - //if (mSamplerManager != nullptr) delete mSamplerManager; + if (mSamplerManager != nullptr) delete mSamplerManager; if (mFBID != 0) glDeleteFramebuffers(1, &mFBID); if (mVAOID != 0) { @@ -172,13 +172,13 @@ void FGLRenderer::EndOffscreen() void FGLRenderer::BindToFrameBuffer(FGameTexture *mat) { auto pBaseLayer = mat->GetTexture()->SystemTextures.GetHardwareTexture(0, false); - auto BaseLayer = pBaseLayer ? (::FHardwareTexture*)pBaseLayer : nullptr; + auto BaseLayer = pBaseLayer ? (OpenGLRenderer::FHardwareTexture*)pBaseLayer : nullptr; if (BaseLayer == nullptr) { // must create the hardware texture first - BaseLayer = new ::FHardwareTexture; - BaseLayer->CreateTexture(mat->GetTexelWidth()*4, mat->GetTexelHeight()*4, ::FHardwareTexture::TrueColor, false); + BaseLayer = new FHardwareTexture(4); + BaseLayer->CreateTexture(nullptr, mat->GetTexelWidth() * 4, mat->GetTexelHeight() * 4, 15, false, "Camtex"); mat->GetTexture()->SystemTextures.AddHardwareTexture(0, false, BaseLayer); } BaseLayer->BindToFrameBuffer(mat->GetTexelWidth()*4, mat->GetTexelHeight()*4); diff --git a/source/core/rendering/gl/renderer/gl_renderer.h b/source/core/rendering/gl/renderer/gl_renderer.h index 89a0aeb2e..a635b37d5 100644 --- a/source/core/rendering/gl/renderer/gl_renderer.h +++ b/source/core/rendering/gl/renderer/gl_renderer.h @@ -21,7 +21,6 @@ class FLightBuffer; class DPSprite; class FGLRenderBuffers; class FGL2DDrawer; -class FHardwareTexture; class SWSceneDrawer; class HWViewpointBuffer; struct FRenderViewpoint; @@ -44,7 +43,7 @@ public: int mMirrorCount = 0; int mPlaneMirrorCount = 0; //FShaderManager *mShaderManager = nullptr; - //FSamplerManager *mSamplerManager = nullptr; + FSamplerManager *mSamplerManager = nullptr; unsigned int mFBID; unsigned int mVAOID; //unsigned int PortalQueryObject; diff --git a/source/core/rendering/gl/system/gl_framebuffer.cpp b/source/core/rendering/gl/system/gl_framebuffer.cpp index 259561508..316fb18d6 100644 --- a/source/core/rendering/gl/system/gl_framebuffer.cpp +++ b/source/core/rendering/gl/system/gl_framebuffer.cpp @@ -94,10 +94,11 @@ OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, bool fullscreen) : // SetVSync needs to be at the very top to workaround a bug in Nvidia's OpenGL driver. // If wglSwapIntervalEXT is called after glBindFramebuffer in a frame the setting is not changed! Super::SetVSync(vid_vsync); + FHardwareTexture::InitGlobalState(); #ifdef IMPLEMENT_IT // Make sure all global variables tracking OpenGL context state are reset.. - FHardwareTexture::InitGlobalState(); + gl_RenderState.Reset(); #endif @@ -248,7 +249,7 @@ void OpenGLFrameBuffer::Swap() if (!swapbefore) glFinish(); //Finish.Unclock(); camtexcount = 0; - //FHardwareTexture::UnbindAll(); + FHardwareTexture::UnbindAll(); mDebug->Update(); } @@ -282,17 +283,19 @@ void OpenGLFrameBuffer::CleanForRestart() { } -#ifdef IMPLEMENT_IT -void OpenGLFrameBuffer::SetTextureFilterMode() -{ - //if (GLRenderer != nullptr && GLRenderer->mSamplerManager != nullptr) GLRenderer->mSamplerManager->SetTextureFilterMode(); -} - IHardwareTexture *OpenGLFrameBuffer::CreateHardwareTexture(int numchannels) { - return nullptr;// new FHardwareTexture(true/*tex->bNoCompress*/); + return new FHardwareTexture(numchannels); } +void OpenGLFrameBuffer::SetTextureFilterMode() +{ + if (GLRenderer != nullptr && GLRenderer->mSamplerManager != nullptr) GLRenderer->mSamplerManager->SetTextureFilterMode(); +} + +#ifdef IMPLEMENT_IT + + void OpenGLFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) { auto tex = mat->tex; @@ -337,13 +340,6 @@ IDataBuffer *OpenGLFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo, bo return new GLDataBuffer(bindingpoint, ssbo); } -#ifdef IMPLEMENT_IT -void OpenGLFrameBuffer::TextureFilterChanged() -{ - if (GLRenderer != NULL && GLRenderer->mSamplerManager != NULL) GLRenderer->mSamplerManager->SetTextureFilterMode(); -} -#endif - void OpenGLFrameBuffer::BlurScene(float amount) { GLRenderer->BlurScene(amount); diff --git a/source/core/rendering/gl/system/gl_framebuffer.h b/source/core/rendering/gl/system/gl_framebuffer.h index ba4dd0071..0f1944734 100644 --- a/source/core/rendering/gl/system/gl_framebuffer.h +++ b/source/core/rendering/gl/system/gl_framebuffer.h @@ -27,12 +27,12 @@ public: void CleanForRestart() override; const char* DeviceName() const override; void WriteSavePic(FileWriter* file, int width, int height) override; -#ifdef IMPLEMENT_IT - void SetTextureFilterMode() override; IHardwareTexture *CreateHardwareTexture(int numchannels) override; + void SetTextureFilterMode() override; + +#ifdef IMPLEMENT_IT void PrecacheMaterial(FMaterial *mat, int translation) override; FModelRenderer *CreateModelRenderer(int mli) override; - void TextureFilterChanged() override; #endif void BeginFrame() override; //void SetViewportRects(IntRect *bounds) override; diff --git a/source/core/rendering/v_video.cpp b/source/core/rendering/v_video.cpp index 11f34433e..eccdb4376 100644 --- a/source/core/rendering/v_video.cpp +++ b/source/core/rendering/v_video.cpp @@ -396,7 +396,7 @@ void V_Init2() Polymost_Startup(); GLInterface.Init(SCREENHEIGHT); GLInterface.InitGLState(4, 4/*glmultisample*/); - GLInterface.mSamplers->SetTextureFilterMode(); + screen->SetTextureFilterMode(); //setsizeneeded = true; } diff --git a/source/core/rendering/v_video.h b/source/core/rendering/v_video.h index c0809513c..3094fe1a5 100644 --- a/source/core/rendering/v_video.h +++ b/source/core/rendering/v_video.h @@ -233,7 +233,6 @@ public: virtual IHardwareTexture *CreateHardwareTexture(int numchannels) { return nullptr; } virtual void PrecacheMaterial(FMaterial *mat, int translation) {} virtual FModelRenderer *CreateModelRenderer(int mli) { return nullptr; } - virtual void TextureFilterChanged() {} virtual void BeginFrame() {} virtual void SetWindowSize(int w, int h) {} virtual void StartPrecaching() {} diff --git a/source/glbackend/gl_hwtexture.cpp b/source/glbackend/gl_hwtexture.cpp deleted file mode 100644 index 6288c93c9..000000000 --- a/source/glbackend/gl_hwtexture.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* -** gl_hwtexture.cpp -** GL texture abstraction -** -**--------------------------------------------------------------------------- -** Copyright 2019 Christoph Oelckers -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -** -*/ - -#include -#include "gl_load.h" -#include "glbackend.h" -#include "bitmap.h" -#include "c_dispatch.h" -#include "printf.h" -#include "gl_interface.h" -//#include "compat.h" - -// Workaround to avoid including the dirty 'compat.h' header. This will hopefully not be needed anymore once the texture format uses something better. -# define B_LITTLE_ENDIAN 1 -# define B_BIG_ENDIAN 0 - -uint64_t alltexturesize; - -CCMD(alltexturesize) -{ - Printf("All textures are %llu bytes\n", alltexturesize); -} - - -//=========================================================================== -// -// Allocates an empty texture -// -//=========================================================================== - -unsigned int FHardwareTexture::CreateTexture(int w, int h, int type, bool mipmapped) -{ - static int gltypes[] = { GL_R8, GL_RGBA8, GL_RGB5_A1, GL_RGBA2 }; - static uint8_t bytes[] = { 1, 4, 2, 1 }; - glGenTextures(1, &glTexID); - glActiveTexture(GL_TEXTURE15); - glBindTexture(GL_TEXTURE_2D, glTexID); - int size = std::max(w, h); - int bits = 0; - while (size) bits++, size >>= 1; - internalType = type; - if (type == Indexed) mipmapped = false; - mWidth = w; - mHeight = h; - - allocated = w * h; - if (mipmapped) - { - - for (auto mip = allocated>>2; mip > 0; mip >>= 2) - { - allocated += mip; - } - } - allocated *= bytes[type]; - alltexturesize += allocated; - - glTexStorage2D(GL_TEXTURE_2D, mipmapped? bits : 1, gltypes[type], w, h); - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); - this->mipmapped = mipmapped; - return glTexID; -} - - -//=========================================================================== -// -// Loads the texture image into the hardware -// -//=========================================================================== - -unsigned int FHardwareTexture::LoadTexture(const unsigned char * buffer) -{ - return LoadTexturePart(buffer, 0, 0, mWidth, mHeight); -} - -unsigned int FHardwareTexture::LoadTexture(FBitmap& bmp) -{ - return LoadTexture(bmp.GetPixels()); -} - -//=========================================================================== -// -// Loads the texture image into the hardware -// -//=========================================================================== - -unsigned int FHardwareTexture::LoadTexturePart(const unsigned char* buffer, int x, int y, int w, int h) -{ - if (glTexID == 0) return 0; - - int srcformat = internalType == Indexed ? GL_RED : GL_BGRA;// TexFormat[gl_texture_format]; - - glActiveTexture(GL_TEXTURE15); - glBindTexture(GL_TEXTURE_2D, glTexID); - - if (internalType == Indexed) glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, srcformat, GL_UNSIGNED_BYTE, buffer); - if (mipmapped) glGenerateMipmap(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); - if (internalType == Indexed) glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - return glTexID; -} - -//=========================================================================== -// -// Destroys the texture -// -//=========================================================================== -FHardwareTexture::~FHardwareTexture() -{ - alltexturesize -= allocated; - if (glTexID != 0) glDeleteTextures(1, &glTexID); - if (glBufferID != 0) glDeleteBuffers(1, &glBufferID); -} - - -unsigned int FHardwareTexture::GetTextureHandle() -{ - return glTexID; -} - -static int GetTexDimension(int value) -{ - if (value > gl.max_texturesize) return gl.max_texturesize; - return value; -} - -//=========================================================================== -// -// Creates a depth buffer for this texture -// -//=========================================================================== - -int FHardwareTexture::GetDepthBuffer(int width, int height) -{ - if (glDepthID == 0) - { - glGenRenderbuffers(1, &glDepthID); - glBindRenderbuffer(GL_RENDERBUFFER, glDepthID); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - } - return glDepthID; -} - - -//=========================================================================== -// -// Binds this texture's surfaces to the current framrbuffer -// -//=========================================================================== - -void FHardwareTexture::BindToFrameBuffer(int width, int height) -{ - width = GetTexDimension(width); - height = GetTexDimension(height); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glTexID, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, GetDepthBuffer(width, height)); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, GetDepthBuffer(width, height)); -} - - diff --git a/source/glbackend/gl_hwtexture.h b/source/glbackend/gl_hwtexture.h deleted file mode 100644 index b2cb6051e..000000000 --- a/source/glbackend/gl_hwtexture.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once -class FBitmap; -class FTexture; - -#include "tarray.h" -#include "hw_ihwtexture.h" - -class FHardwareTexture : public IHardwareTexture -{ -public: - enum - { - Indexed, - TrueColor, - HighColor, // 16 bit - Can be used to save space in memory constrained scenarios at the cost of visual accuracy. - Brightmap, // This can be stored as RGBA2 to save space, it also doesn't really need a mipmap. - }; - -private: - - unsigned int glTexID = 0; - unsigned int glDepthID = 0; // only used by camera textures - unsigned int glBufferID = 0; - int internalType = TrueColor; - bool mipmapped = true; - int mWidth = 0, mHeight = 0; - int colorId = 0; - uint32_t allocated = 0; - - int GetDepthBuffer(int w, int h); - -public: - - ~FHardwareTexture(); - - // Satisfy the virtual interface - currently this isn't being used. - virtual void AllocateBuffer(int w, int h, int texelsize) {} - virtual uint8_t* MapBuffer() { return nullptr; } - virtual unsigned int CreateTexture(unsigned char* buffer, int w, int h, int texunit, bool mipmap, const char* name) { return 0; } - - //bool BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags); - - unsigned int CreateTexture(int w, int h, bool type, bool mipmapped) = delete; - unsigned int CreateTexture(int w, int h, int type, bool mipmapped); - unsigned int LoadTexture(const unsigned char * buffer); - unsigned int LoadTexturePart(const unsigned char* buffer, int x, int y, int w, int h); - unsigned int LoadTexture(FBitmap &bmp); - unsigned int GetTextureHandle(); - bool isIndexed() const { return internalType == Indexed; } - void BindToFrameBuffer(int w, int h); - - friend class FGameTexture; -}; - - diff --git a/source/glbackend/gl_palmanager.cpp b/source/glbackend/gl_palmanager.cpp index d4115174d..06d570722 100644 --- a/source/glbackend/gl_palmanager.cpp +++ b/source/glbackend/gl_palmanager.cpp @@ -100,9 +100,8 @@ void PaletteManager::BindPalette(int index) if (palettetextures[index] == nullptr) { - auto p = GLInterface.NewTexture(); - p->CreateTexture(256, 1, FHardwareTexture::TrueColor, false); - p->LoadTexture((uint8_t*)palettedata->Palette); + auto p = GLInterface.NewTexture(4); + p->CreateTexture((uint8_t*)palettedata->Palette, 256, 1, 15, false, "Palette"); palettetextures[index] = p; } inst->BindTexture(2, palettetextures[index], SamplerNoFilterClampXY); @@ -127,8 +126,7 @@ void PaletteManager::BindPalswap(int index) lastsindex = index; if (palswaptextures[index] == nullptr) { - auto p = GLInterface.NewTexture(); - p->CreateTexture(256, numshades, FHardwareTexture::Indexed, false); + auto p = GLInterface.NewTexture(1); // Perform a 0<->255 index swap. The lookup tables are still the original data. TArray lookup(numshades * 256, true); @@ -139,7 +137,7 @@ void PaletteManager::BindPalswap(int index) p[255] = p[0]; p[0] = 0; } - p->LoadTexture(lookup.Data()); + p->CreateTexture(lookup.Data(), 256, numshades, 15, false, "Palette"); palswaptextures[index] = p; } inst->BindTexture(1, palswaptextures[index], SamplerNoFilterClampXY); diff --git a/source/glbackend/gl_texture.cpp b/source/glbackend/gl_texture.cpp index 52e765f05..3c633be7a 100644 --- a/source/glbackend/gl_texture.cpp +++ b/source/glbackend/gl_texture.cpp @@ -67,19 +67,18 @@ void FlipNonSquareBlock(T* dst, const T* src, int x, int y, int srcpitch) // //=========================================================================== -FHardwareTexture* GLInstance::CreateIndexedTexture(FGameTexture* tex) +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(); - glpic->CreateTexture(siz.x, siz.y, FHardwareTexture::Indexed, false); + auto glpic = GLInterface.NewTexture(1); TArray flipped(siz.x * siz.y, true); FlipNonSquareBlock(flipped.Data(), p, siz.y, siz.x, siz.y); - glpic->LoadTexture(flipped.Data()); + glpic->CreateTexture(flipped.Data(), siz.x, siz.y, 15, false, tex->GetName()); return glpic; } @@ -89,7 +88,7 @@ FHardwareTexture* GLInstance::CreateIndexedTexture(FGameTexture* tex) // //=========================================================================== -FHardwareTexture* GLInstance::CreateTrueColorTexture(FGameTexture* tex, int palid, bool checkfulltransparency, bool rgb8bit) +OpenGLRenderer::FHardwareTexture* GLInstance::CreateTrueColorTexture(FGameTexture* tex, int palid, bool checkfulltransparency, bool rgb8bit) { if (tex == TexMan.GameByIndex(0)) return nullptr; @@ -110,12 +109,8 @@ FHardwareTexture* GLInstance::CreateTrueColorTexture(FGameTexture* tex, int pali if (!found) return nullptr; } - auto glpic = GLInterface.NewTexture(); - if (!rgb8bit) - glpic->CreateTexture(texbuffer.mWidth, texbuffer.mHeight, FHardwareTexture::TrueColor, true); - else - glpic->CreateTexture(texbuffer.mWidth, texbuffer.mHeight, FHardwareTexture::Brightmap, false); // Use a more memory friendly format for simple brightmaps. - glpic->LoadTexture(texbuffer.mBuffer); + auto glpic = GLInterface.NewTexture(4); + glpic->CreateTexture(texbuffer.mBuffer, texbuffer.mWidth, texbuffer.mHeight, 15, true, tex->GetName()); return glpic; } @@ -125,13 +120,13 @@ FHardwareTexture* GLInstance::CreateTrueColorTexture(FGameTexture* tex, int pali // //=========================================================================== -FHardwareTexture* GLInstance::LoadTexture(FGameTexture* tex, int textype, int palid) +OpenGLRenderer::FHardwareTexture* GLInstance::LoadTexture(FGameTexture* tex, int textype, int palid) { if (textype == TT_INDEXED) palid = -1; auto phwtex = tex->GetTexture()->SystemTextures.GetHardwareTexture(palid, false); - if (phwtex) return (FHardwareTexture*)phwtex; + if (phwtex) return (OpenGLRenderer::FHardwareTexture*)phwtex; - FHardwareTexture *hwtex = nullptr; + OpenGLRenderer::FHardwareTexture *hwtex = nullptr; if (textype == TT_INDEXED) hwtex = CreateIndexedTexture(tex); else if (!tex->GetTexture()->isHardwareCanvas()) diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp index 8dde82572..65c7064eb 100644 --- a/source/glbackend/glbackend.cpp +++ b/source/glbackend/glbackend.cpp @@ -52,22 +52,6 @@ float shadediv[MAXPALOOKUPS]; -namespace OpenGLRenderer -{ - - - TexFilter_s TexFilter[] = { - {GL_NEAREST, GL_NEAREST, false}, - {GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST, true}, - {GL_LINEAR, GL_LINEAR, false}, - {GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, true}, - {GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, true}, - {GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST, true}, - {GL_LINEAR_MIPMAP_LINEAR, GL_NEAREST, true}, - }; - -} - static int blendstyles[] = { GL_ZERO, GL_ONE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA }; static int renderops[] = { GL_FUNC_ADD, GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT }; int depthf[] = { GL_ALWAYS, GL_LESS, GL_EQUAL, GL_LEQUAL }; @@ -99,11 +83,6 @@ TArray ttf; void GLInstance::Init(int ydim) { - if (!mSamplers) - { - mSamplers = new OpenGLRenderer::FSamplerManager; - } - //glinfo.bufferstorage = !!strstr(glinfo.extensions, "GL_ARB_buffer_storage"); glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glinfo.maxanisotropy); @@ -158,8 +137,6 @@ void GLInstance::Deinit() ImGui::DestroyContext(im_ctx); } #endif - if (mSamplers) delete mSamplers; - mSamplers = nullptr; if (polymostShader) delete polymostShader; polymostShader = nullptr; if (surfaceShader) delete surfaceShader; @@ -169,9 +146,9 @@ void GLInstance::Deinit() lastPalswapIndex = -1; } -FHardwareTexture* GLInstance::NewTexture() +OpenGLRenderer::FHardwareTexture* GLInstance::NewTexture(int numchannels) { - return new FHardwareTexture; + return new OpenGLRenderer::FHardwareTexture(numchannels); } void GLInstance::ResetFrame() @@ -320,7 +297,8 @@ void PolymostRenderState::Apply(PolymostShader* shader, GLState &oldState) reset = true; } glBindTexture(GL_TEXTURE_2D, texIds[i]); - GLInterface.mSamplers->Bind(i, samplerIds[i], -1); + if (OpenGLRenderer::GLRenderer) + OpenGLRenderer::GLRenderer->mSamplerManager->Bind(i, samplerIds[i], -1); oldState.TexId[i] = texIds[i]; oldState.SamplerId[i] = samplerIds[i]; } diff --git a/source/glbackend/glbackend.h b/source/glbackend/glbackend.h index a740d70ae..97661bbd2 100644 --- a/source/glbackend/glbackend.h +++ b/source/glbackend/glbackend.h @@ -10,7 +10,6 @@ #include "palentry.h" #include "renderstyle.h" -class FSamplerManager; class FShader; class PolymostShader; class SurfaceShader; @@ -40,8 +39,8 @@ enum class PaletteManager { - FHardwareTexture* palettetextures[256] = {}; - FHardwareTexture* palswaptextures[256] = {}; + OpenGLRenderer::FHardwareTexture* palettetextures[256] = {}; + OpenGLRenderer::FHardwareTexture* palswaptextures[256] = {}; uint32_t lastindex = ~0u; uint32_t lastsindex = ~0u; @@ -127,7 +126,7 @@ class GLInstance int maxTextureSize; PaletteManager palmanager; int lastPalswapIndex = -1; - FHardwareTexture* texv; + OpenGLRenderer::FHardwareTexture* texv; FGameTexture* currentTexture = nullptr; int TextureType; int MatrixChange = 0; @@ -144,7 +143,6 @@ class GLInstance public: glinfo_t glinfo; - OpenGLRenderer::FSamplerManager *mSamplers; void Init(int y); void InitGLState(int fogmode, int multisample); @@ -166,7 +164,7 @@ public: void DoDraw(); void DrawElement(EDrawType type, size_t start, size_t count, PolymostRenderState& renderState); - FHardwareTexture* NewTexture(); + OpenGLRenderer::FHardwareTexture* NewTexture(int numchannels = 4); void SetVertexBuffer(IVertexBuffer* vb, int offset1, int offset2); void SetIndexBuffer(IIndexBuffer* vb); @@ -363,13 +361,15 @@ public: SetColor(r * (1 / 255.f), g * (1 / 255.f), b * (1 / 255.f), a * (1 / 255.f)); } - void BindTexture(int texunit, FHardwareTexture* tex, int sampler) + void BindTexture(int texunit, OpenGLRenderer::FHardwareTexture* tex, int sampler) { if (!tex) return; if (texunit == 0) { - if (tex->isIndexed()) renderState.Flags |= RF_UsePalette; - else renderState.Flags &= ~RF_UsePalette; + if (tex->numChannels() == 1) + renderState.Flags |= RF_UsePalette; + else + renderState.Flags &= ~RF_UsePalette; } renderState.texIds[texunit] = tex->GetTextureHandle(); renderState.samplerIds[texunit] = sampler; @@ -487,9 +487,9 @@ public: renderState.AlphaThreshold = al; } - FHardwareTexture* CreateIndexedTexture(FGameTexture* tex); - FHardwareTexture* CreateTrueColorTexture(FGameTexture* tex, int palid, bool checkfulltransparency = false, bool rgb8bit = false); - FHardwareTexture *LoadTexture(FGameTexture* tex, int texturetype, int palid); + 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); 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);