diff options
author | r.kuznetsov <r.kuznetsov@corp.mail.ru> | 2016-10-11 17:48:53 +0300 |
---|---|---|
committer | r.kuznetsov <r.kuznetsov@corp.mail.ru> | 2016-10-11 17:48:53 +0300 |
commit | 852dcba6ed0719bd9e8a6409583ff85cd654bcf6 (patch) | |
tree | 8923eddad467d5940fd06d1eff4bc8b9db273d4f /drape | |
parent | 75b38035b7aca2cad9aa9498b70d09972bbebc7e (diff) |
Fixed using of texture slots in shaders
Diffstat (limited to 'drape')
-rw-r--r-- | drape/glstate.cpp | 51 | ||||
-rw-r--r-- | drape/glstate.hpp | 11 | ||||
-rw-r--r-- | drape/gpu_program.cpp | 13 | ||||
-rw-r--r-- | drape/gpu_program.hpp | 4 | ||||
-rw-r--r-- | drape/gpu_program_manager.cpp | 2 |
5 files changed, 46 insertions, 35 deletions
diff --git a/drape/glstate.cpp b/drape/glstate.cpp index a13b8fea7f..9a60a1a680 100644 --- a/drape/glstate.cpp +++ b/drape/glstate.cpp @@ -155,16 +155,12 @@ struct UniformApplyer } // namespace -void ApplyUniforms(UniformValuesStorage const & uniforms, ref_ptr<GpuProgram> program) -{ - static UniformApplyer applyer; - applyer.m_program = program; - uniforms.ForeachValue(applyer); - applyer.m_program = nullptr; -} +uint8_t TextureState::m_usedSlots = 0; -void ApplyTextures(GLState state, ref_ptr<GpuProgram> program) +void TextureState::ApplyTextures(GLState state, ref_ptr<GpuProgram> program) { + m_usedSlots = 0; + ref_ptr<Texture> tex = state.GetColorTexture(); int8_t colorTexLoc = -1; if (tex != nullptr && (colorTexLoc = program->GetUniformLocation("u_colorTex")) >= 0) @@ -173,19 +169,7 @@ void ApplyTextures(GLState state, ref_ptr<GpuProgram> program) tex->Bind(); GLFunctions::glUniformValuei(colorTexLoc, 0); tex->SetFilter(state.GetTextureFilter()); - } - else - { - // Some Android devices (Galaxy Nexus) require to reset texture state explicitly. - // It's caused by a bug in OpenGL driver (for Samsung Nexus, maybe others). Normally - // we don't need to explicitly call glBindTexture(GL_TEXTURE2D, 0) after glUseProgram - // in case of the GPU-program doesn't use textures. Here we have to do it to work around - // graphics artefacts. The overhead isn't significant, we don't know on which devices - // it may happen so do it for all Android devices. -#ifdef OMIM_OS_ANDROID - GLFunctions::glActiveTexture(gl_const::GLTexture0); - GLFunctions::glBindTexture(0); -#endif + m_usedSlots++; } tex = state.GetMaskTexture(); @@ -196,16 +180,21 @@ void ApplyTextures(GLState state, ref_ptr<GpuProgram> program) tex->Bind(); GLFunctions::glUniformValuei(maskTexLoc, 1); tex->SetFilter(state.GetTextureFilter()); + m_usedSlots++; } - else - { - // Some Android devices (Galaxy Nexus) require to reset texture state explicitly. - // See detailed description above. -#ifdef OMIM_OS_ANDROID - GLFunctions::glActiveTexture(gl_const::GLTexture0 + 1); - GLFunctions::glBindTexture(0); -#endif - } +} + +uint8_t TextureState::GetLastUsedSlots() +{ + return m_usedSlots; +} + +void ApplyUniforms(UniformValuesStorage const & uniforms, ref_ptr<GpuProgram> program) +{ + static UniformApplyer applyer; + applyer.m_program = program; + uniforms.ForeachValue(applyer); + applyer.m_program = nullptr; } void ApplyBlending(GLState state, ref_ptr<GpuProgram> program) @@ -215,7 +204,7 @@ void ApplyBlending(GLState state, ref_ptr<GpuProgram> program) void ApplyState(GLState state, ref_ptr<GpuProgram> program) { - ApplyTextures(state, program); + TextureState::ApplyTextures(state, program); ApplyBlending(state, program); GLFunctions::glDepthFunc(state.GetDepthFunction()); GLFunctions::glLineWidth(state.GetLineWidth()); diff --git a/drape/glstate.hpp b/drape/glstate.hpp index cf42cec1e4..27f1b27d31 100644 --- a/drape/glstate.hpp +++ b/drape/glstate.hpp @@ -91,9 +91,18 @@ private: int m_lineWidth; }; +class TextureState +{ +public: + static void ApplyTextures(GLState state, ref_ptr<GpuProgram> program); + static uint8_t GetLastUsedSlots(); + +private: + static uint8_t m_usedSlots; +}; + void ApplyUniforms(UniformValuesStorage const & uniforms, ref_ptr<GpuProgram> program); void ApplyState(GLState state, ref_ptr<GpuProgram> program); -void ApplyTextures(GLState state, ref_ptr<GpuProgram> program); void ApplyBlending(GLState state, ref_ptr<GpuProgram> program); } // namespace dp diff --git a/drape/gpu_program.cpp b/drape/gpu_program.cpp index 919b3ce95a..7bbc23f071 100644 --- a/drape/gpu_program.cpp +++ b/drape/gpu_program.cpp @@ -1,5 +1,7 @@ #include "drape/gpu_program.hpp" #include "drape/glfunctions.hpp" +#include "drape/glstate.hpp" +#include "drape/shader_def.hpp" #include "drape/support_manager.hpp" #include "base/assert.hpp" @@ -12,9 +14,10 @@ namespace dp { -GpuProgram::GpuProgram(ref_ptr<Shader> vertexShader, ref_ptr<Shader> fragmentShader) +GpuProgram::GpuProgram(int programIndex, ref_ptr<Shader> vertexShader, ref_ptr<Shader> fragmentShader) : m_vertexShader(vertexShader) , m_fragmentShader(fragmentShader) + , m_textureSlotsCount(gpu::GetTextureSlotsCount(programIndex)) { m_programID = GLFunctions::glCreateProgram(); GLFunctions::glAttachShader(m_programID, m_vertexShader->GetID()); @@ -52,6 +55,14 @@ GpuProgram::~GpuProgram() void GpuProgram::Bind() { + // Deactivate all unused textures. + uint8_t const usedSlots = TextureState::GetLastUsedSlots(); + for (uint8_t i = m_textureSlotsCount; i < usedSlots; i++) + { + GLFunctions::glActiveTexture(gl_const::GLTexture0 + i); + GLFunctions::glBindTexture(0); + } + GLFunctions::glUseProgram(m_programID); } diff --git a/drape/gpu_program.hpp b/drape/gpu_program.hpp index ce118a35a6..9346309cb3 100644 --- a/drape/gpu_program.hpp +++ b/drape/gpu_program.hpp @@ -16,7 +16,7 @@ namespace dp class GpuProgram { public: - GpuProgram(ref_ptr<Shader> vertexShader, + GpuProgram(int programIndex, ref_ptr<Shader> vertexShader, ref_ptr<Shader> fragmentShader); ~GpuProgram(); @@ -37,6 +37,8 @@ private: using TUniformLocations = map<string, int8_t>; TUniformLocations m_uniforms; + + uint8_t const m_textureSlotsCount; }; } // namespace dp diff --git a/drape/gpu_program_manager.cpp b/drape/gpu_program_manager.cpp index b921ef9e9f..8c51848572 100644 --- a/drape/gpu_program_manager.cpp +++ b/drape/gpu_program_manager.cpp @@ -71,7 +71,7 @@ ref_ptr<GpuProgram> GpuProgramManager::GetProgram(int index) programInfo.m_fragmentSource, Shader::FragmentShader); - drape_ptr<GpuProgram> program = make_unique_dp<GpuProgram>(vertexShader, fragmentShader); + drape_ptr<GpuProgram> program = make_unique_dp<GpuProgram>(index, vertexShader, fragmentShader); ref_ptr<GpuProgram> result = make_ref(program); m_programs.emplace(index, move(program)); |