diff --git a/drape/gpu_program.cpp b/drape/gpu_program.cpp index 4ce50a0e82..919b3ce95a 100644 --- a/drape/gpu_program.cpp +++ b/drape/gpu_program.cpp @@ -1,5 +1,6 @@ #include "drape/gpu_program.hpp" #include "drape/glfunctions.hpp" +#include "drape/support_manager.hpp" #include "base/assert.hpp" #include "base/logging.hpp" @@ -12,10 +13,12 @@ namespace dp { GpuProgram::GpuProgram(ref_ptr vertexShader, ref_ptr fragmentShader) + : m_vertexShader(vertexShader) + , m_fragmentShader(fragmentShader) { m_programID = GLFunctions::glCreateProgram(); - GLFunctions::glAttachShader(m_programID, vertexShader->GetID()); - GLFunctions::glAttachShader(m_programID, fragmentShader->GetID()); + GLFunctions::glAttachShader(m_programID, m_vertexShader->GetID()); + GLFunctions::glAttachShader(m_programID, m_fragmentShader->GetID()); string errorLog; if (!GLFunctions::glLinkProgram(m_programID, errorLog)) @@ -25,13 +28,25 @@ GpuProgram::GpuProgram(ref_ptr vertexShader, ref_ptr fragmentSha // on Tegra3, glGetActiveUniform will not work if you detach shaders after linking LoadUniformLocations(); - GLFunctions::glDetachShader(m_programID, vertexShader->GetID()); - GLFunctions::glDetachShader(m_programID, fragmentShader->GetID()); + // On Tegra2 we cannot detach shaders at all. + // https://devtalk.nvidia.com/default/topic/528941/alpha-blending-not-working-on-t20-and-t30-under-ice-cream-sandwich/ + if (!SupportManager::Instance().IsTegraDevice()) + { + GLFunctions::glDetachShader(m_programID, m_vertexShader->GetID()); + GLFunctions::glDetachShader(m_programID, m_fragmentShader->GetID()); + } } GpuProgram::~GpuProgram() { Unbind(); + + if (SupportManager::Instance().IsTegraDevice()) + { + GLFunctions::glDetachShader(m_programID, m_vertexShader->GetID()); + GLFunctions::glDetachShader(m_programID, m_fragmentShader->GetID()); + } + GLFunctions::glDeleteProgram(m_programID); } diff --git a/drape/gpu_program.hpp b/drape/gpu_program.hpp index 4092dfaefd..ce118a35a6 100644 --- a/drape/gpu_program.hpp +++ b/drape/gpu_program.hpp @@ -32,6 +32,9 @@ private: private: uint32_t m_programID; + ref_ptr m_vertexShader; + ref_ptr m_fragmentShader; + using TUniformLocations = map; TUniformLocations m_uniforms; }; diff --git a/drape/support_manager.cpp b/drape/support_manager.cpp index d5a7376ea9..3aad71859a 100644 --- a/drape/support_manager.cpp +++ b/drape/support_manager.cpp @@ -29,6 +29,10 @@ void SupportManager::Init() } } } + + m_isTegra = (renderer.find("Tegra") != string::npos); + if (m_isTegra) + LOG(LINFO, ("NVidia Tegra device detected.")); } bool SupportManager::IsSamsungGoogleNexus() const @@ -41,6 +45,11 @@ bool SupportManager::IsAdreno200Device() const return m_isAdreno200; } +bool SupportManager::IsTegraDevice() const +{ + return m_isTegra; +} + SupportManager & SupportManager::Instance() { static SupportManager manager; diff --git a/drape/support_manager.hpp b/drape/support_manager.hpp index d2d95b2f07..ec45097d84 100644 --- a/drape/support_manager.hpp +++ b/drape/support_manager.hpp @@ -15,6 +15,7 @@ public: bool IsSamsungGoogleNexus() const; bool IsAdreno200Device() const; + bool IsTegraDevice() const; private: SupportManager() = default; @@ -22,6 +23,7 @@ private: bool m_isSamsungGoogleNexus = false; bool m_isAdreno200 = false; + bool m_isTegra = false; }; } // namespace dp