From b1763a8f4a26dc7ea95ed7599652410304a7648f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 17 Sep 2019 19:03:42 +0200 Subject: [PATCH] - hooked up the texture management. Not in active use yet! --- platform/Windows/build.vcxproj | 2 + platform/Windows/build.vcxproj.filters | 6 ++ source/build/src/polymost.cpp | 52 ++++--------- source/glbackend/gl_hwtexture.cpp | 103 +++++++++++++++++++++++++ source/glbackend/gl_hwtexture.h | 29 +++++++ source/glbackend/gl_samplers.cpp | 4 +- source/glbackend/glbackend.cpp | 39 +++++++++- source/glbackend/glbackend.h | 20 +++++ 8 files changed, 212 insertions(+), 43 deletions(-) create mode 100644 source/glbackend/gl_hwtexture.cpp create mode 100644 source/glbackend/gl_hwtexture.h diff --git a/platform/Windows/build.vcxproj b/platform/Windows/build.vcxproj index 977965d81..dcc131bba 100644 --- a/platform/Windows/build.vcxproj +++ b/platform/Windows/build.vcxproj @@ -308,6 +308,7 @@ + @@ -380,6 +381,7 @@ + diff --git a/platform/Windows/build.vcxproj.filters b/platform/Windows/build.vcxproj.filters index 65cea2d77..bf97d82b5 100644 --- a/platform/Windows/build.vcxproj.filters +++ b/platform/Windows/build.vcxproj.filters @@ -200,6 +200,9 @@ GL Interface + + GL Interface + @@ -412,6 +415,9 @@ GL Interface + + GL Interface + diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index 1196a1f29..2d1d3680a 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -222,21 +222,10 @@ int32_t r_parallaxskypanning = 1; #define MIN_CACHETIME_PRINT 10 -static const int THCACHESIZE = 200; -static GLuint TextureHandleCache[THCACHESIZE]; -static int currentindex = THCACHESIZE; void GetTextureHandle(GLuint *handle) { - // Generating large numbers of texture IDs piece by piece does not work well on modern NVidia drivers. - - if (currentindex == THCACHESIZE) - { - currentindex = 0; - glGenTextures(THCACHESIZE, TextureHandleCache); - } - else currentindex++; - *handle = TextureHandleCache[currentindex]; + *handle = GLInstance.GetTextureID(); } @@ -786,16 +775,11 @@ void polymost_activeTexture(GLenum texture) //POGOTODO: replace this and polymost_activeTexture with proper draw call organization void polymost_bindTexture(GLenum target, uint32_t textureID) { - if (currentTextureID != textureID || - textureID == 0 || - currentActiveTexture != GL_TEXTURE0 || - videoGetRenderMode() != REND_POLYMOST) + glBindSampler(currentActiveTexture - GL_TEXTURE0, 0); + glad_glBindTexture(target, textureID); + if (currentActiveTexture == GL_TEXTURE0) { - glad_glBindTexture(target, textureID); - if (currentActiveTexture == GL_TEXTURE0) - { - currentTextureID = textureID; - } + currentTextureID = textureID; } } @@ -847,11 +831,9 @@ void polymost_glinit() //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); //glEnable(GL_LINE_SMOOTH); - if (r_useindexedcolortextures == -1) - { - //POGO: r_useindexedcolortextures has never been set, so force it to be enabled - gltexfiltermode = 0; - } + GLInterface.Init(); + GLInterface.mSamplers->SetTextureFilterMode(gltexfiltermode, glanisotropy); + #ifdef USE_GLEXT if (glmultisample > 0 && glinfo.multisample) @@ -7517,6 +7499,7 @@ static int32_t gltexturemode(osdcmdptr_t parm) gltexfiltermode = m; gltexapplyprops(); + GLInterface.mSamplers->SetTextureFilterMode(gltexfiltermode, glanisotropy); OSD_Printf("Texture filtering mode changed to %s\n", glfiltermodes[gltexfiltermode].name); @@ -7559,22 +7542,15 @@ static int osdcmd_cvar_set_polymost(osdcmdptr_t parm) r_downsizevar = r_downsize; } - else if (!Bstrcasecmp(parm->name, "r_anisotropy")) - gltexapplyprops(); + else if (!Bstrcasecmp(parm->name, "r_anisotropy")) + { + GLInterface.mSamplers->SetTextureFilterMode(gltexfiltermode, glanisotropy); + gltexapplyprops(); + } else if (!Bstrcasecmp(parm->name, "r_texfilter")) gltexturemode(parm); else if (!Bstrcasecmp(parm->name, "r_usenewshading")) glFogi(GL_FOG_MODE, (r_usenewshading < 2) ? GL_EXP2 : GL_LINEAR); -#ifdef POLYMER - else if (!Bstrcasecmp(parm->name, "r_pr_maxlightpasses")) - { - if (pr_maxlightpasses != r_pr_maxlightpasses) - { - polymer_invalidatelights(); - pr_maxlightpasses = r_pr_maxlightpasses; - } - } -#endif } return r; diff --git a/source/glbackend/gl_hwtexture.cpp b/source/glbackend/gl_hwtexture.cpp new file mode 100644 index 000000000..7015c1ca5 --- /dev/null +++ b/source/glbackend/gl_hwtexture.cpp @@ -0,0 +1,103 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2004-2016 Christoph Oelckers +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// + +#include "glad/glad.h" +#include "glbackend.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 + + + +//=========================================================================== +// +// Allocates an empty texture +// +//=========================================================================== + +unsigned int FHardwareTexture::CreateTexture(int w, int h, bool eightbit, bool mipmapped) +{ + glTexID = GLInterface.GetTextureID(); + glActiveTexture(GL_TEXTURE15); + glBindTexture(GL_TEXTURE_2D, glTexID); + int size = std::max(w, h); + int bits = 0; + while (size) bits++, size >>= 1; + glTextureBytes = eightbit? 1 : 4; + if (eightbit) mipmapped = false; + mWidth = w; + mHeight = h; + + glTexStorage2D(GL_TEXTURE_2D, mipmapped? bits : 1, eightbit? GL_R8 : GL_RGBA8, 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(unsigned char * buffer) +{ + if (glTexID == 0) return 0; + + int srcformat = glTextureBytes == 1? GL_R8 : GL_RGBA8;// TexFormat[gl_texture_format]; + GLenum srctype = glTextureBytes == 1 ? GL_UNSIGNED_BYTE : (B_BIG_ENDIAN? GL_UNSIGNED_INT_8_8_8_8 : GL_UNSIGNED_INT_8_8_8_8_REV); + + glActiveTexture(GL_TEXTURE15); + glBindTexture(GL_TEXTURE_2D, glTexID); + + if (glTextureBytes < 4) glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mWidth, mHeight, srcformat, srctype, buffer); + if (mipmapped) glGenerateMipmap(GL_TEXTURE_2D); + + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0); + return glTexID; +} + + +//=========================================================================== +// +// Destroys the texture +// +//=========================================================================== +FHardwareTexture::~FHardwareTexture() +{ + if (glTexID != 0) glDeleteTextures(1, &glTexID); +} + + +unsigned int FHardwareTexture::GetTextureHandle() +{ + return glTexID; +} + + diff --git a/source/glbackend/gl_hwtexture.h b/source/glbackend/gl_hwtexture.h new file mode 100644 index 000000000..8942ab73c --- /dev/null +++ b/source/glbackend/gl_hwtexture.h @@ -0,0 +1,29 @@ + +#ifndef __GLTEXTURE_H +#define __GLTEXTURE_H + + +class FHardwareTexture //: public IHardwareTexture +{ +public: + +private: + + unsigned int glTexID = 0; + int glTextureBytes = 4; + bool mipmapped = true; + int mWidth = 0, mHeight = 0; + +public: + + ~FHardwareTexture(); + + unsigned int Bind(int texunit, bool needmipmap); + //bool BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags); + + unsigned int CreateTexture(int w, int h, bool eightbit, bool mipmapped); + unsigned int LoadTexture(unsigned char * buffer); + unsigned int GetTextureHandle(); +}; + +#endif diff --git a/source/glbackend/gl_samplers.cpp b/source/glbackend/gl_samplers.cpp index c6ffc079d..0028468df 100644 --- a/source/glbackend/gl_samplers.cpp +++ b/source/glbackend/gl_samplers.cpp @@ -21,7 +21,7 @@ // #include "glad/glad.h" -#include "gl_samplers.h" +#include "glbackend.h" struct TexFilter_s { @@ -44,7 +44,7 @@ TexFilter_s TexFilter[]={ FSamplerManager::FSamplerManager() { glGenSamplers(NumSamplers, mSamplers); - SetTextureFilterMode(); + SetTextureFilterMode(0); glSamplerParameteri(mSamplers[5], GL_TEXTURE_MIN_FILTER, GL_NEAREST); glSamplerParameteri(mSamplers[5], GL_TEXTURE_MAG_FILTER, GL_NEAREST); glSamplerParameterf(mSamplers[5], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp index 1966fcf8e..486f94d49 100644 --- a/source/glbackend/glbackend.cpp +++ b/source/glbackend/glbackend.cpp @@ -7,6 +7,7 @@ GLInstance GLInterface; void GLInstance::Init() { mSamplers = new FSamplerManager; + memset(LastBoundTextures, 0, sizeof(LastBoundTextures)); } void GLInstance::Deinit() @@ -41,12 +42,44 @@ void GLInstance::Draw(EDrawType type, size_t start, size_t count) glEnd(); } +int GLInstance::GetTextureID() +{ + // Generating large numbers of texture IDs piece by piece does not work well on modern NVidia drivers. + + if (currentindex == THCACHESIZE) + { + currentindex = 0; + glGenTextures(THCACHESIZE, TextureHandleCache); + } + else currentindex++; + return TextureHandleCache[currentindex]; +} void GLInstance::BindTexture(int texunit, int tex, int sampler) { - glActiveTexture(GL_TEXTURE0 + texunit); + if (texunit != 0) glActiveTexture(GL_TEXTURE0 + texunit); glBindTexture(GL_TEXTURE_2D, tex); if (sampler != NoSampler) mSamplers->Bind(texunit, sampler, 0); else glBindSampler(texunit, 0); - glActiveTexture(GL_TEXTURE0); -} \ No newline at end of file + if (texunit != 0) glActiveTexture(GL_TEXTURE0); + LastBoundTextures[texunit] = tex; +} + +void GLInstance::UnbindTexture(int texunit) +{ + if (LastBoundTextures[texunit] != 0) + { + if (texunit != 0) glActiveTexture(GL_TEXTURE0+texunit); + glBindTexture(GL_TEXTURE_2D, 0); + if (texunit != 0) glActiveTexture(GL_TEXTURE0); + LastBoundTextures[texunit] = 0; + } +} + +void GLInstance::UnbindAllTextures() +{ + for(int texunit = 0; texunit < MAX_TEXTURES; texunit++) + { + UnbindTexture(texunit); + } +} diff --git a/source/glbackend/glbackend.h b/source/glbackend/glbackend.h index 3413c5fdf..a9df4bc81 100644 --- a/source/glbackend/glbackend.h +++ b/source/glbackend/glbackend.h @@ -2,7 +2,9 @@ #include #include #include +#include #include "gl_samplers.h" +#include "gl_hwtexture.h" class FSamplerManager; @@ -45,18 +47,36 @@ enum EDrawType class GLInstance { + enum + { + MAX_TEXTURES = 15, // slot 15 is used internally and not available. + THCACHESIZE = 200, + }; std::vector Buffer; // cheap-ass implementation. The primary purpose is to get the GL accesses out of polymost.cpp, not writing something performant right away. + unsigned int LastBoundTextures[MAX_TEXTURES]; + unsigned TextureHandleCache[THCACHESIZE]; + int currentindex = THCACHESIZE; + public: FSamplerManager *mSamplers; void Init(); void Deinit(); + + static int GetTexDimension(int value) + { + //if (value > gl.max_texturesize) return gl.max_texturesize; + return value; + } std::pair AllocVertices(size_t num); void Draw(EDrawType type, size_t start, size_t count); + int GetTextureID(); void BindTexture(int texunit, int texid, int sampler = NoSampler); + void UnbindTexture(int texunit); + void UnbindAllTextures(); };