diff --git a/src/gl/system/gl_interface.cpp b/src/gl/system/gl_interface.cpp index 3fd718ff7..3fcb7ced6 100644 --- a/src/gl/system/gl_interface.cpp +++ b/src/gl/system/gl_interface.cpp @@ -128,14 +128,15 @@ void gl_LoadExtensions() gl.vendorstring = (char*)glGetString(GL_VENDOR); - if (gl.version < 3.3f && !CheckExtension("GL_ARB_sampler_objects")) - { - I_FatalError("'GL_ARB_sampler_objects' extension not found. Please update your graphics driver."); - } if (CheckExtension("GL_ARB_texture_compression")) gl.flags|=RFL_TEXTURE_COMPRESSION; if (CheckExtension("GL_EXT_texture_compression_s3tc")) gl.flags|=RFL_TEXTURE_COMPRESSION_S3TC; if (!Args->CheckParm("-gl3")) { + if (gl.version >= 3.3f || CheckExtension("GL_ARB_sampler_objects")) + { + gl.flags |= RFL_SAMPLER_OBJECTS; + } + // don't use GL 4.x features when running in GL 3 emulation mode. if (CheckExtension("GL_ARB_buffer_storage")) { diff --git a/src/gl/system/gl_interface.h b/src/gl/system/gl_interface.h index 6f2fb2bfc..6988f873e 100644 --- a/src/gl/system/gl_interface.h +++ b/src/gl/system/gl_interface.h @@ -10,7 +10,8 @@ enum RenderFlags RFL_TEXTURE_COMPRESSION_S3TC=2, RFL_SHADER_STORAGE_BUFFER = 4, - RFL_BUFFER_STORAGE = 8 + RFL_BUFFER_STORAGE = 8, + RFL_SAMPLER_OBJECTS = 16 }; enum TexMode diff --git a/src/gl/system/gl_wipe.cpp b/src/gl/system/gl_wipe.cpp index 232be87a1..00fc002f3 100644 --- a/src/gl/system/gl_wipe.cpp +++ b/src/gl/system/gl_wipe.cpp @@ -149,8 +149,8 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type) wipestartscreen = new FHardwareTexture(Width, Height, true); wipestartscreen->CreateTexture(NULL, Width, Height, 0, false, 0); - GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER); - GLRenderer->mSamplerManager->Bind(1, CLAMP_NONE); + GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER, -1); + GLRenderer->mSamplerManager->Bind(1, CLAMP_NONE, -1); glFinish(); wipestartscreen->Bind(0, false, false); GLint readbuffer = 0; @@ -176,7 +176,7 @@ void OpenGLFrameBuffer::WipeEndScreen() { wipeendscreen = new FHardwareTexture(Width, Height, true); wipeendscreen->CreateTexture(NULL, Width, Height, 0, false, 0); - GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER); + GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER, -1); glFinish(); wipeendscreen->Bind(0, false, false); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height); diff --git a/src/gl/textures/gl_material.cpp b/src/gl/textures/gl_material.cpp index f5c8f90b3..961a61c04 100644 --- a/src/gl/textures/gl_material.cpp +++ b/src/gl/textures/gl_material.cpp @@ -89,6 +89,7 @@ FGLTexture::FGLTexture(FTexture * tx, bool expandpatches) bHasColorkey = false; bIsTransparent = -1; bExpandFlag = expandpatches; + lastSampler = 254; tex->gl_info.SystemTexture[expandpatches] = this; } @@ -278,7 +279,7 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla if (translation <= 0) translation = -translation; else translation = GLTranslationPalette::GetInternalTranslation(translation); - bool needmipmap = (clampmode <= CLAMP_XY); + bool needmipmap = (clampmode <= CLAMP_XY) || !(gl.flags & RFL_SAMPLER_OBJECTS); FHardwareTexture *hwtex = CreateHwTexture(); @@ -313,9 +314,10 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla } delete[] buffer; } - + if (!needmipmap) clampmode = CLAMP_XY_NOMIP; if (tex->bHasCanvas) static_cast(tex)->NeedUpdate(); - GLRenderer->mSamplerManager->Bind(texunit, clampmode); + if (lastSampler != clampmode) + lastSampler = GLRenderer->mSamplerManager->Bind(texunit, clampmode, lastSampler); return hwtex; } return NULL; diff --git a/src/gl/textures/gl_material.h b/src/gl/textures/gl_material.h index b8a71c7ce..83069049c 100644 --- a/src/gl/textures/gl_material.h +++ b/src/gl/textures/gl_material.h @@ -65,6 +65,7 @@ private: bool bHasColorkey; // only for hires bool bExpandFlag; + BYTE lastSampler; unsigned char * LoadHiresTexture(FTexture *hirescheck, int *width, int *height); diff --git a/src/gl/textures/gl_samplers.cpp b/src/gl/textures/gl_samplers.cpp index 3851d6c71..db0193c69 100644 --- a/src/gl/textures/gl_samplers.cpp +++ b/src/gl/textures/gl_samplers.cpp @@ -44,69 +44,159 @@ #include "gl/system/gl_cvars.h" #include "gl/renderer/gl_renderer.h" #include "gl_samplers.h" +#include "gl_material.h" extern TexFilter_s TexFilter[]; FSamplerManager::FSamplerManager() { - glGenSamplers(7, mSamplers); - SetTextureFilterMode(); - 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); - glSamplerParameterf(mSamplers[4], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); - glSamplerParameterf(mSamplers[6], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); + if (gl.flags & RFL_SAMPLER_OBJECTS) + { + glGenSamplers(7, mSamplers); + SetTextureFilterMode(); + 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); + glSamplerParameterf(mSamplers[4], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); + glSamplerParameterf(mSamplers[6], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); - glSamplerParameteri(mSamplers[1], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameteri(mSamplers[2], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glSamplerParameteri(mSamplers[3], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameteri(mSamplers[3], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glSamplerParameteri(mSamplers[4], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameteri(mSamplers[4], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glSamplerParameteri(mSamplers[1], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glSamplerParameteri(mSamplers[2], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glSamplerParameteri(mSamplers[3], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glSamplerParameteri(mSamplers[3], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glSamplerParameteri(mSamplers[4], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glSamplerParameteri(mSamplers[4], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } } FSamplerManager::~FSamplerManager() { - UnbindAll(); - glDeleteSamplers(7, mSamplers); + if (gl.flags & RFL_SAMPLER_OBJECTS) + { + UnbindAll(); + glDeleteSamplers(7, mSamplers); + } } void FSamplerManager::UnbindAll() { - for (int i = 0; i < FHardwareTexture::MAX_TEXTURES; i++) + if (gl.flags & RFL_SAMPLER_OBJECTS) { - mLastBound[i] = 0; - glBindSampler(i, 0); + for (int i = 0; i < FHardwareTexture::MAX_TEXTURES; i++) + { + mLastBound[i] = 0; + glBindSampler(i, 0); + } } } -void FSamplerManager::Bind(int texunit, int num) +BYTE FSamplerManager::Bind(int texunit, int num, int lastval) { - unsigned int samp = mSamplers[num]; - //if (samp != mLastBound[texunit]) + if (gl.flags & RFL_SAMPLER_OBJECTS) { - glBindSampler(texunit, samp); - mLastBound[texunit] = samp; + unsigned int samp = mSamplers[num]; + //if (samp != mLastBound[texunit]) + { + glBindSampler(texunit, samp); + mLastBound[texunit] = samp; + return 255; + } + } + else + { + glActiveTexture(GL_TEXTURE0 + texunit); + switch (num) + { + case CLAMP_NONE: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + if (lastval > CLAMP_XY_NOMIP) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); + } + break; + + case CLAMP_X: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + if (lastval > CLAMP_XY_NOMIP) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); + } + break; + + case CLAMP_Y: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (lastval > CLAMP_XY_NOMIP) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); + } + break; + + case CLAMP_XY_NOMIP: + case CLAMP_XY: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (lastval > CLAMP_XY_NOMIP) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); + } + break; + + case CLAMP_NOFILTER: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + break; + + case CLAMP_CAMTEX: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + break; + } + glActiveTexture(GL_TEXTURE0); + return num; } } void FSamplerManager::SetTextureFilterMode() { - UnbindAll(); - - for (int i = 0; i < 4; i++) + if (gl.flags & RFL_SAMPLER_OBJECTS) { - glSamplerParameteri(mSamplers[i], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); - glSamplerParameteri(mSamplers[i], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); - glSamplerParameterf(mSamplers[i], GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); + UnbindAll(); + + for (int i = 0; i < 4; i++) + { + glSamplerParameteri(mSamplers[i], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); + glSamplerParameteri(mSamplers[i], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glSamplerParameterf(mSamplers[i], GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); + } + glSamplerParameteri(mSamplers[4], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter); + glSamplerParameteri(mSamplers[4], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glSamplerParameteri(mSamplers[6], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter); + glSamplerParameteri(mSamplers[6], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + } + else + { + GLRenderer->FlushTextures(); } - glSamplerParameteri(mSamplers[4], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter); - glSamplerParameteri(mSamplers[4], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); - glSamplerParameteri(mSamplers[6], GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter); - glSamplerParameteri(mSamplers[6], GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); } diff --git a/src/gl/textures/gl_samplers.h b/src/gl/textures/gl_samplers.h index 26589b4ad..daba65d45 100644 --- a/src/gl/textures/gl_samplers.h +++ b/src/gl/textures/gl_samplers.h @@ -17,7 +17,7 @@ public: FSamplerManager(); ~FSamplerManager(); - void Bind(int texunit, int num); + BYTE Bind(int texunit, int num, int lastval); void SetTextureFilterMode();