Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorr.kuznetsov <r.kuznetsov@corp.mail.ru>2017-05-12 10:20:09 +0300
committerr.kuznetsov <r.kuznetsov@corp.mail.ru>2017-05-25 15:28:18 +0300
commitc21d5a7854ee6f4c270cb6242cba581cef07479f (patch)
treea3cdcc2a1be7158aed1b7dc12e92a5c4017f7049
parent3a00a30e65e65c9120b7ee076bd809f5ac800fee (diff)
Added Subpixel Morphological Antialiasing (SMAA)
-rw-r--r--data/resources-default/smaa-area.pngbin0 -> 63887 bytes
-rw-r--r--data/resources-default/smaa-search.pngbin0 -> 598 bytes
-rw-r--r--drape/drape_global.hpp2
-rw-r--r--drape/drape_tests/glfunctions.cpp4
-rw-r--r--drape/drape_tests/static_texture_tests.cpp20
-rw-r--r--drape/framebuffer.cpp143
-rw-r--r--drape/framebuffer.hpp40
-rw-r--r--drape/glconstants.cpp17
-rw-r--r--drape/glconstants.hpp19
-rw-r--r--drape/glfunctions.cpp39
-rw-r--r--drape/glfunctions.hpp6
-rw-r--r--drape/hw_texture.cpp11
-rw-r--r--drape/static_texture.cpp86
-rw-r--r--drape/static_texture.hpp22
-rw-r--r--drape/support_manager.cpp61
-rw-r--r--drape/support_manager.hpp23
-rw-r--r--drape/texture_manager.cpp111
-rw-r--r--drape/texture_manager.hpp8
-rw-r--r--drape_frontend/CMakeLists.txt8
-rw-r--r--drape_frontend/backend_renderer.cpp12
-rw-r--r--drape_frontend/drape_engine.cpp109
-rw-r--r--drape_frontend/drape_engine.hpp37
-rwxr-xr-xdrape_frontend/drape_frontend.pro8
-rwxr-xr-xdrape_frontend/frontend_renderer.cpp300
-rwxr-xr-xdrape_frontend/frontend_renderer.hpp114
-rw-r--r--drape_frontend/message.hpp4
-rw-r--r--drape_frontend/message_subclasses.hpp40
-rw-r--r--drape_frontend/postprocess_renderer.cpp416
-rw-r--r--drape_frontend/postprocess_renderer.hpp83
-rw-r--r--drape_frontend/screen_quad_renderer.cpp118
-rw-r--r--drape_frontend/screen_quad_renderer.hpp28
-rw-r--r--drape_frontend/shaders/shader_index.txt3
-rw-r--r--drape_frontend/shaders/smaa_blending_weight.fsh.glsl189
-rw-r--r--drape_frontend/shaders/smaa_blending_weight.vsh.glsl28
-rw-r--r--drape_frontend/shaders/smaa_edges.fsh.glsl65
-rw-r--r--drape_frontend/shaders/smaa_edges.vsh.glsl21
-rw-r--r--drape_frontend/shaders/smaa_final.fsh.glsl51
-rw-r--r--drape_frontend/shaders/smaa_final.vsh.glsl16
-rw-r--r--geometry/rect2d.hpp11
-rw-r--r--indexer/map_style_reader.cpp39
-rw-r--r--indexer/map_style_reader.hpp5
-rw-r--r--map/framework.cpp25
-rw-r--r--qt/qt_common/map_widget.cpp21
-rw-r--r--qt/qt_common/map_widget.hpp3
-rw-r--r--xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj8
45 files changed, 1897 insertions, 477 deletions
diff --git a/data/resources-default/smaa-area.png b/data/resources-default/smaa-area.png
new file mode 100644
index 0000000000..a11af5907a
--- /dev/null
+++ b/data/resources-default/smaa-area.png
Binary files differ
diff --git a/data/resources-default/smaa-search.png b/data/resources-default/smaa-search.png
new file mode 100644
index 0000000000..25873d346f
--- /dev/null
+++ b/data/resources-default/smaa-search.png
Binary files differ
diff --git a/drape/drape_global.hpp b/drape/drape_global.hpp
index d3933057d0..8511bd8cf4 100644
--- a/drape/drape_global.hpp
+++ b/drape/drape_global.hpp
@@ -16,6 +16,7 @@ enum TextureFormat
{
RGBA8,
ALPHA,
+ RED_GREEN,
UNSPECIFIED
};
@@ -26,6 +27,7 @@ inline uint8_t GetBytesPerPixel(TextureFormat format)
{
case RGBA8: result = 4; break;
case ALPHA: result = 1; break;
+ case RED_GREEN: result = 2; break;
default: ASSERT(false, ()); break;
}
return result;
diff --git a/drape/drape_tests/glfunctions.cpp b/drape/drape_tests/glfunctions.cpp
index 0b345dbd34..4143744bf0 100644
--- a/drape/drape_tests/glfunctions.cpp
+++ b/drape/drape_tests/glfunctions.cpp
@@ -318,6 +318,10 @@ void GLFunctions::glDrawArrays(glConst mode, int32_t first, uint32_t count) {}
void GLFunctions::glPixelStore(glConst name, uint32_t value) {}
+void GLFunctions::glStencilOpSeparate(glConst face, glConst sfail, glConst dpfail, glConst dppass) {}
+
+void GLFunctions::glStencilFuncSeparate(glConst face, glConst func, int ref, uint32_t mask) {}
+
int32_t GLFunctions::glGetBufferParameter(glConst target, glConst name)
{
return MOCK_CALL(glGetBufferParameter(target, name));
diff --git a/drape/drape_tests/static_texture_tests.cpp b/drape/drape_tests/static_texture_tests.cpp
index 6d8c726755..b4bce9fd37 100644
--- a/drape/drape_tests/static_texture_tests.cpp
+++ b/drape/drape_tests/static_texture_tests.cpp
@@ -1,5 +1,8 @@
#include "testing/testing.hpp"
+#include "indexer/map_style.hpp"
+#include "indexer/map_style_reader.hpp"
+
#include "drape/static_texture.hpp"
#include <string>
@@ -8,9 +11,20 @@
UNIT_TEST(CheckTrafficArrowTextures)
{
static std::vector<std::string> skinPaths = {"6plus", "mdpi", "hdpi", "xhdpi", "xxhdpi"};
- for (size_t i = 0; i < skinPaths.size(); ++i)
+ static std::vector<MapStyle> styles = {MapStyle::MapStyleClear, MapStyle::MapStyleDark,
+ MapStyle::MapStyleVehicleClear,
+ MapStyle::MapStyleVehicleDark};
+
+ for (auto const & style : styles)
{
- dp::StaticTexture texture("traffic-arrow", skinPaths[i], nullptr);
- TEST(texture.IsLoadingCorrect(), ());
+ GetStyleReader().SetCurrentStyle(style);
+ for (size_t i = 0; i < skinPaths.size(); ++i)
+ {
+ dp::StaticTexture texture("traffic-arrow", skinPaths[i], dp::RGBA8, nullptr);
+ TEST(texture.IsLoadingCorrect(), ());
+
+ dp::StaticTexture texture2("area-hatching", skinPaths[i], dp::RGBA8, nullptr);
+ TEST(texture2.IsLoadingCorrect(), ());
+ }
}
}
diff --git a/drape/framebuffer.cpp b/drape/framebuffer.cpp
index 73d79173f5..39759deee7 100644
--- a/drape/framebuffer.cpp
+++ b/drape/framebuffer.cpp
@@ -1,7 +1,5 @@
#include "drape/framebuffer.hpp"
-
#include "drape/glfunctions.hpp"
-#include "drape/oglcontext.hpp"
#include "base/assert.hpp"
#include "base/logging.hpp"
@@ -9,7 +7,82 @@
namespace dp
{
+Framebuffer::DepthStencil::DepthStencil(bool stencilEnabled)
+ : m_stencilEnabled(stencilEnabled)
+{
+ if (m_stencilEnabled)
+ {
+ m_layout = gl_const::GLDepthStencil;
+ m_pixelType = gl_const::GLUnsignedInt24_8Type;
+ }
+ else
+ {
+ m_layout = gl_const::GLDepthComponent;
+ m_pixelType = gl_const::GLUnsignedIntType;
+ }
+}
+
+Framebuffer::DepthStencil::~DepthStencil()
+{
+ Destroy();
+}
+
+void Framebuffer::DepthStencil::SetSize(uint32_t width, uint32_t height)
+{
+ Destroy();
+
+ m_textureId = GLFunctions::glGenTexture();
+ GLFunctions::glBindTexture(m_textureId);
+ GLFunctions::glTexImage2D(width, height, m_layout, m_pixelType, nullptr);
+ if (GLFunctions::CurrentApiVersion == dp::ApiVersion::OpenGLES3)
+ {
+ GLFunctions::glTexParameter(gl_const::GLMagFilter, gl_const::GLNearest);
+ GLFunctions::glTexParameter(gl_const::GLMinFilter, gl_const::GLNearest);
+ GLFunctions::glTexParameter(gl_const::GLWrapT, gl_const::GLClampToEdge);
+ GLFunctions::glTexParameter(gl_const::GLWrapS, gl_const::GLClampToEdge);
+ }
+}
+
+void Framebuffer::DepthStencil::Destroy()
+{
+ if (m_textureId != 0)
+ {
+ GLFunctions::glDeleteTexture(m_textureId);
+ m_textureId = 0;
+ }
+}
+
+uint32_t Framebuffer::DepthStencil::GetDepthAttachmentId() const
+{
+ return m_textureId;
+}
+
+uint32_t Framebuffer::DepthStencil::GetStencilAttachmentId() const
+{
+ return m_stencilEnabled ? m_textureId : 0;
+}
+
+Framebuffer::Framebuffer()
+ : m_colorFormat(gl_const::GLRGBA)
+{
+ ApplyOwnDepthStencil();
+}
+
+Framebuffer::Framebuffer(uint32_t colorFormat)
+ : m_colorFormat(colorFormat)
+{
+ ApplyOwnDepthStencil();
+}
+
+Framebuffer::Framebuffer(uint32_t colorFormat, bool stencilEnabled)
+ : m_colorFormat(colorFormat)
+ , m_depthStencil(make_unique_dp<dp::Framebuffer::DepthStencil>(stencilEnabled))
+{
+ ApplyOwnDepthStencil();
+}
+
Framebuffer::~Framebuffer() { Destroy(); }
+
void Framebuffer::Destroy()
{
if (m_colorTextureId != 0)
@@ -18,11 +91,8 @@ void Framebuffer::Destroy()
m_colorTextureId = 0;
}
- if (m_depthTextureId != 0)
- {
- GLFunctions::glDeleteTexture(m_depthTextureId);
- m_depthTextureId = 0;
- }
+ if (m_depthStencil != nullptr)
+ m_depthStencil->Destroy();
if (m_framebufferId != 0)
{
@@ -31,19 +101,21 @@ void Framebuffer::Destroy()
}
}
-void Framebuffer::SetDefaultContext(dp::OGLContext * context) { m_defaultContext = context; }
-void Framebuffer::SetSize(uint32_t width, uint32_t height)
+void Framebuffer::SetFramebufferFallback(FramebufferFallback && fallback)
{
- ASSERT(m_defaultContext, ());
+ m_framebufferFallback = std::move(fallback);
+}
+void Framebuffer::SetSize(uint32_t width, uint32_t height)
+{
if (!m_isSupported)
return;
if (m_width == width && m_height == height)
return;
- m_height = height;
m_width = width;
+ m_height = height;
Destroy();
@@ -56,16 +128,14 @@ void Framebuffer::SetSize(uint32_t width, uint32_t height)
GLFunctions::glTexParameter(gl_const::GLWrapT, gl_const::GLClampToEdge);
GLFunctions::glTexParameter(gl_const::GLWrapS, gl_const::GLClampToEdge);
- m_depthTextureId = GLFunctions::glGenTexture();
- GLFunctions::glBindTexture(m_depthTextureId);
- GLFunctions::glTexImage2D(m_width, m_height, gl_const::GLDepthComponent,
- gl_const::GLUnsignedIntType, nullptr);
- if (GLFunctions::CurrentApiVersion == dp::ApiVersion::OpenGLES3)
+ glConst depthAttachmentId = 0;
+ glConst stencilAttachmentId = 0;
+ if (m_depthStencilRef != nullptr)
{
- GLFunctions::glTexParameter(gl_const::GLMagFilter, gl_const::GLNearest);
- GLFunctions::glTexParameter(gl_const::GLMinFilter, gl_const::GLNearest);
- GLFunctions::glTexParameter(gl_const::GLWrapT, gl_const::GLClampToEdge);
- GLFunctions::glTexParameter(gl_const::GLWrapS, gl_const::GLClampToEdge);
+ if (m_depthStencilRef == m_depthStencil.get())
+ m_depthStencilRef->SetSize(m_width, m_height);
+ depthAttachmentId = m_depthStencilRef->GetDepthAttachmentId();
+ stencilAttachmentId = m_depthStencilRef->GetStencilAttachmentId();
}
GLFunctions::glBindTexture(0);
@@ -74,8 +144,15 @@ void Framebuffer::SetSize(uint32_t width, uint32_t height)
GLFunctions::glBindFramebuffer(m_framebufferId);
GLFunctions::glFramebufferTexture2D(gl_const::GLColorAttachment, m_colorTextureId);
- GLFunctions::glFramebufferTexture2D(gl_const::GLDepthAttachment, m_depthTextureId);
- GLFunctions::glFramebufferTexture2D(gl_const::GLStencilAttachment, 0);
+ if (depthAttachmentId != stencilAttachmentId)
+ {
+ GLFunctions::glFramebufferTexture2D(gl_const::GLDepthAttachment, depthAttachmentId);
+ GLFunctions::glFramebufferTexture2D(gl_const::GLStencilAttachment, stencilAttachmentId);
+ }
+ else
+ {
+ GLFunctions::glFramebufferTexture2D(gl_const::GLDepthStencilAttachment, depthAttachmentId);
+ }
uint32_t const status = GLFunctions::glCheckFramebufferStatus();
if (status != gl_const::GLFramebufferComplete)
@@ -85,7 +162,18 @@ void Framebuffer::SetSize(uint32_t width, uint32_t height)
LOG(LWARNING, ("Framebuffer is unsupported. Framebuffer status =", status));
}
- m_defaultContext->setDefaultFramebuffer();
+ if (m_framebufferFallback != nullptr)
+ m_framebufferFallback();
+}
+
+void Framebuffer::SetDepthStencilRef(ref_ptr<DepthStencil> depthStencilRef)
+{
+ m_depthStencilRef = depthStencilRef;
+}
+
+void Framebuffer::ApplyOwnDepthStencil()
+{
+ m_depthStencilRef = make_ref(m_depthStencil);
}
void Framebuffer::Enable()
@@ -96,10 +184,15 @@ void Framebuffer::Enable()
void Framebuffer::Disable()
{
- ASSERT(m_defaultContext, ());
ASSERT(m_isSupported, ());
- m_defaultContext->setDefaultFramebuffer();
+ if (m_framebufferFallback != nullptr)
+ m_framebufferFallback();
}
uint32_t Framebuffer::GetTextureId() const { return m_colorTextureId; }
+
+ref_ptr<Framebuffer::DepthStencil> Framebuffer::GetDepthStencilRef() const
+{
+ return m_depthStencilRef;
+}
} // namespace dp
diff --git a/drape/framebuffer.hpp b/drape/framebuffer.hpp
index 39de064799..96a95c2dcb 100644
--- a/drape/framebuffer.hpp
+++ b/drape/framebuffer.hpp
@@ -1,37 +1,61 @@
#pragma once
+#include "drape/pointers.hpp"
+
#include <cstdint>
+#include <functional>
namespace dp
{
-class OGLContext;
+using FramebufferFallback = std::function<void()>;
class Framebuffer
{
public:
- Framebuffer() = default;
+ class DepthStencil
+ {
+ public:
+ DepthStencil(bool stencilEnabled);
+ ~DepthStencil();
+ void SetSize(uint32_t width, uint32_t height);
+ void Destroy();
+ uint32_t GetDepthAttachmentId() const;
+ uint32_t GetStencilAttachmentId() const;
+ private:
+ bool const m_stencilEnabled = false;
+ uint32_t m_layout = 0;
+ uint32_t m_pixelType = 0;
+ uint32_t m_textureId = 0;
+ };
+
+ Framebuffer();
+ Framebuffer(uint32_t colorFormat);
+ Framebuffer(uint32_t colorFormat, bool stencilEnabled);
~Framebuffer();
- void SetDefaultContext(dp::OGLContext * context);
+ void SetFramebufferFallback(FramebufferFallback && fallback);
void SetSize(uint32_t width, uint32_t height);
+ void SetDepthStencilRef(ref_ptr<DepthStencil> depthStencilRef);
+ void ApplyOwnDepthStencil();
void Enable();
void Disable();
uint32_t GetTextureId() const;
+ ref_ptr<DepthStencil> GetDepthStencilRef() const;
+
bool IsSupported() const { return m_isSupported; }
private:
void Destroy();
+ drape_ptr<DepthStencil> m_depthStencil;
+ ref_ptr<DepthStencil> m_depthStencilRef;
uint32_t m_width = 0;
uint32_t m_height = 0;
-
uint32_t m_colorTextureId = 0;
- uint32_t m_depthTextureId = 0;
uint32_t m_framebufferId = 0;
-
- dp::OGLContext * m_defaultContext = 0;
-
+ uint32_t m_colorFormat;
+ FramebufferFallback m_framebufferFallback;
bool m_isSupported = true;
};
} // namespace dp
diff --git a/drape/glconstants.cpp b/drape/glconstants.cpp
index 2d4d6a8adc..dfd0c6d2ca 100644
--- a/drape/glconstants.cpp
+++ b/drape/glconstants.cpp
@@ -104,6 +104,10 @@ const glConst GLRenderer = GL_RENDERER;
const glConst GLVendor = GL_VENDOR;
const glConst GLVersion = GL_VERSION;
+const glConst GLColorBit = GL_COLOR_BUFFER_BIT;
+const glConst GLDepthBit = GL_DEPTH_BUFFER_BIT;
+const glConst GLStencilBit = GL_STENCIL_BUFFER_BIT;
+
const glConst GLMaxFragmentTextures = GL_MAX_TEXTURE_IMAGE_UNITS;
const glConst GLMaxVertexTextures = GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS;
const glConst GLMaxTextureSize = GL_MAX_TEXTURE_SIZE;
@@ -138,6 +142,7 @@ const glConst GLAlpha = GL_ALPHA;
const glConst GLLuminance = GL_LUMINANCE;
const glConst GLAlphaLuminance = GL_LUMINANCE_ALPHA;
const glConst GLDepthComponent = GL_DEPTH_COMPONENT;
+const glConst GLDepthStencil = GL_DEPTH_STENCIL;
const glConst GLRGBA8 = GL_RGBA8_OES;
const glConst GLRGBA4 = GL_RGBA4_OES;
@@ -146,6 +151,7 @@ const glConst GLLuminance8 = GL_LUMINANCE8_OES;
const glConst GLAlphaLuminance8 = GL_LUMINANCE8_ALPHA8_OES;
const glConst GLAlphaLuminance4 = GL_LUMINANCE8_ALPHA4_OES;
const glConst GLRed = GL_RED;
+const glConst GLRedGreen = GL_RG;
const glConst GL8BitOnChannel = GL_UNSIGNED_BYTE;
const glConst GL4BitOnChannel = GL_UNSIGNED_SHORT_4_4_4_4;
@@ -173,6 +179,7 @@ const glConst GLUnsignedShortType = GL_UNSIGNED_SHORT;
const glConst GLIntType = GL_INT;
const glConst GLUnsignedIntType = GL_UNSIGNED_INT;
const glConst GLFloatType = GL_FLOAT;
+const glConst GLUnsignedInt24_8Type = GL_UNSIGNED_INT_24_8;
const glConst GLFloatVec2 = GL_FLOAT_VEC2;
const glConst GLFloatVec3 = GL_FLOAT_VEC3;
@@ -203,6 +210,7 @@ const glConst GLDepthTest = GL_DEPTH_TEST;
const glConst GLBlending = GL_BLEND;
const glConst GLCullFace = GL_CULL_FACE;
const glConst GLScissorTest = GL_SCISSOR_TEST;
+const glConst GLStencilTest = GL_STENCIL_TEST;
const glConst GLClockwise = GL_CW;
const glConst GLCounterClockwise = GL_CCW;
@@ -220,6 +228,14 @@ const glConst GLNotEqual = GL_NOTEQUAL;
const glConst GLGreatOrEqual = GL_GEQUAL;
const glConst GLAlways = GL_ALWAYS;
+const glConst GLKeep = GL_KEEP;
+const glConst GLIncr = GL_INCR;
+const glConst GLDecr = GL_DECR;
+const glConst GLInvert = GL_INVERT;
+const glConst GLReplace = GL_REPLACE;
+const glConst GLIncrWrap = GL_INCR_WRAP;
+const glConst GLDecrWrap = GL_DECR_WRAP;
+
const glConst GLActiveUniforms = GL_ACTIVE_UNIFORMS;
const glConst GLLines = GL_LINES;
@@ -230,6 +246,7 @@ const glConst GLTriangleStrip = GL_TRIANGLE_STRIP;
const glConst GLColorAttachment = GL_COLOR_ATTACHMENT0;
const glConst GLDepthAttachment = GL_DEPTH_ATTACHMENT;
const glConst GLStencilAttachment = GL_STENCIL_ATTACHMENT;
+const glConst GLDepthStencilAttachment = GL_DEPTH_STENCIL_ATTACHMENT;
const glConst GLFramebufferComplete = GL_FRAMEBUFFER_COMPLETE;
diff --git a/drape/glconstants.hpp b/drape/glconstants.hpp
index c67c181fa9..e44bd5656a 100644
--- a/drape/glconstants.hpp
+++ b/drape/glconstants.hpp
@@ -12,6 +12,11 @@ extern const glConst GLRenderer;
extern const glConst GLVendor;
extern const glConst GLVersion;
+/// Clear bits
+extern const glConst GLColorBit;
+extern const glConst GLDepthBit;
+extern const glConst GLStencilBit;
+
/// Hardware specific params
extern const glConst GLMaxFragmentTextures;
extern const glConst GLMaxVertexTextures;
@@ -54,6 +59,7 @@ extern const glConst GLAlpha;
extern const glConst GLLuminance;
extern const glConst GLAlphaLuminance;
extern const glConst GLDepthComponent;
+extern const glConst GLDepthStencil;
/// Texture layout size
extern const glConst GLRGBA8;
@@ -63,6 +69,7 @@ extern const glConst GLLuminance8;
extern const glConst GLAlphaLuminance8;
extern const glConst GLAlphaLuminance4;
extern const glConst GLRed;
+extern const glConst GLRedGreen;
/// Pixel type for texture upload
extern const glConst GL8BitOnChannel;
@@ -97,6 +104,7 @@ extern const glConst GLUnsignedShortType;
extern const glConst GLIntType;
extern const glConst GLUnsignedIntType;
extern const glConst GLFloatType;
+extern const glConst GLUnsignedInt24_8Type;
extern const glConst GLFloatVec2;
extern const glConst GLFloatVec3;
@@ -130,6 +138,7 @@ extern const glConst GLDepthTest;
extern const glConst GLBlending;
extern const glConst GLCullFace;
extern const glConst GLScissorTest;
+extern const glConst GLStencilTest;
/// Triangle faces order
extern const glConst GLClockwise;
@@ -150,6 +159,15 @@ extern const glConst GLNotEqual;
extern const glConst GLGreatOrEqual;
extern const glConst GLAlways;
+/// OpenGL stencil functions
+extern const glConst GLKeep;
+extern const glConst GLIncr;
+extern const glConst GLDecr;
+extern const glConst GLInvert;
+extern const glConst GLReplace;
+extern const glConst GLIncrWrap;
+extern const glConst GLDecrWrap;
+
/// Program object parameter names
extern const glConst GLActiveUniforms;
@@ -163,6 +181,7 @@ extern const glConst GLTriangleStrip;
extern const glConst GLColorAttachment;
extern const glConst GLDepthAttachment;
extern const glConst GLStencilAttachment;
+extern const glConst GLDepthStencilAttachment;
/// Framebuffer status
extern const glConst GLFramebufferComplete;
diff --git a/drape/glfunctions.cpp b/drape/glfunctions.cpp
index 55c003194a..4cdc153b63 100644
--- a/drape/glfunctions.cpp
+++ b/drape/glfunctions.cpp
@@ -427,16 +427,10 @@ void GLFunctions::glClearColor(float r, float g, float b, float a)
GLCHECK(glClearColorFn(r, g, b, a));
}
-void GLFunctions::glClear()
+void GLFunctions::glClear(uint32_t clearBits)
{
ASSERT(glClearFn != nullptr, ());
- GLCHECK(glClearFn(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
-}
-
-void GLFunctions::glClearDepth()
-{
- ASSERT(glClearFn != nullptr, ());
- GLCHECK(glClearFn(GL_DEPTH_BUFFER_BIT));
+ GLCHECK(glClearFn(clearBits));
}
void GLFunctions::glViewport(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
@@ -458,8 +452,21 @@ void GLFunctions::glFlush()
}
void GLFunctions::glFinish() { GLCHECK(::glFinish()); }
+
void GLFunctions::glFrontFace(glConst mode) { GLCHECK(::glFrontFace(mode)); }
+
void GLFunctions::glCullFace(glConst face) { GLCHECK(::glCullFace(face)); }
+
+void GLFunctions::glStencilOpSeparate(glConst face, glConst sfail, glConst dpfail, glConst dppass)
+{
+ GLCHECK(::glStencilOpSeparate(face, sfail, dpfail, dppass));
+}
+
+void GLFunctions::glStencilFuncSeparate(glConst face, glConst func, int ref, uint32_t mask)
+{
+ GLCHECK(::glStencilFuncSeparate(face, func, ref, mask));
+}
+
void GLFunctions::glPixelStore(glConst name, uint32_t value)
{
GLCHECK(::glPixelStorei(name, value));
@@ -900,8 +907,10 @@ void GLFunctions::glTexImage2D(int width, int height, glConst layout, glConst pi
{
// In OpenGL ES3:
// - we can't create unsized GL_RED texture, so we use GL_R8;
+ // - we can't create unsized GL_RG texture, so we use GL_RG8;
// - we can't create unsized GL_DEPTH_COMPONENT texture, so we use GL_DEPTH_COMPONENT16
- // or GL_DEPTH_COMPONENT24 or GL_DEPTH_COMPONENT32F.
+ // or GL_DEPTH_COMPONENT24 or GL_DEPTH_COMPONENT32F;
+ // - we can't create unsized GL_DEPTH_STENCIL texture, so we use GL_DEPTH24_STENCIL8.
glConst internalFormat = layout;
if (CurrentApiVersion == dp::ApiVersion::OpenGLES3)
{
@@ -909,6 +918,10 @@ void GLFunctions::glTexImage2D(int width, int height, glConst layout, glConst pi
{
internalFormat = GL_R8;
}
+ else if (layout == gl_const::GLRedGreen)
+ {
+ internalFormat = GL_RG8;
+ }
else if (layout == gl_const::GLDepthComponent)
{
internalFormat = GL_DEPTH_COMPONENT16;
@@ -917,10 +930,14 @@ void GLFunctions::glTexImage2D(int width, int height, glConst layout, glConst pi
else if (pixelType == gl_const::GLFloatType)
internalFormat = GL_DEPTH_COMPONENT32F;
}
+ else if (layout == gl_const::GLDepthStencil)
+ {
+ internalFormat = GL_DEPTH24_STENCIL8;
+ }
}
- GLCHECK(
- ::glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, layout, pixelType, data));
+ GLCHECK(::glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
+ 0, layout, pixelType, data));
}
void GLFunctions::glTexSubImage2D(int x, int y, int width, int height, glConst layout,
diff --git a/drape/glfunctions.hpp b/drape/glfunctions.hpp
index 4c3e87c4d5..c950203e62 100644
--- a/drape/glfunctions.hpp
+++ b/drape/glfunctions.hpp
@@ -19,8 +19,7 @@ public:
static bool glHasExtension(std::string const & name);
static void glClearColor(float r, float g, float b, float a);
- static void glClear();
- static void glClearDepth();
+ static void glClear(uint32_t clearBits);
static void glViewport(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
static void glScissor(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
static void glFlush();
@@ -29,6 +28,9 @@ public:
static void glFrontFace(glConst mode);
static void glCullFace(glConst face);
+ static void glStencilOpSeparate(glConst face, glConst sfail, glConst dpfail, glConst dppass);
+ static void glStencilFuncSeparate(glConst face, glConst func, int ref, uint32_t mask);
+
static void glPixelStore(glConst name, uint32_t value);
static int32_t glGetInteger(glConst pname);
diff --git a/drape/hw_texture.cpp b/drape/hw_texture.cpp
index 06a6c580b7..3fde271920 100644
--- a/drape/hw_texture.cpp
+++ b/drape/hw_texture.cpp
@@ -75,17 +75,23 @@ float HWTexture::GetT(uint32_t y) const
void HWTexture::UnpackFormat(TextureFormat format, glConst & layout, glConst & pixelType)
{
+ // Now we support only 1-byte-per-channel textures.
+ pixelType = gl_const::GL8BitOnChannel;
+
switch (format)
{
case RGBA8:
layout = gl_const::GLRGBA;
- pixelType = gl_const::GL8BitOnChannel;
break;
case ALPHA:
// On OpenGL ES3 GLAlpha is not supported, we use GLRed instead.
layout = GLFunctions::CurrentApiVersion == dp::ApiVersion::OpenGLES2 ? gl_const::GLAlpha
: gl_const::GLRed;
- pixelType = gl_const::GL8BitOnChannel;
+ break;
+ case RED_GREEN:
+ // On OpenGL ES2 2-channel textures are not supported.
+ layout = GLFunctions::CurrentApiVersion == dp::ApiVersion::OpenGLES2 ? gl_const::GLRGBA
+ : gl_const::GLRedGreen;
break;
default: ASSERT(false, ()); break;
}
@@ -109,6 +115,7 @@ void HWTexture::SetFilter(glConst filter)
}
int32_t HWTexture::GetID() const { return m_textureID; }
+
OpenGLHWTexture::~OpenGLHWTexture()
{
if (m_textureID != -1)
diff --git a/drape/static_texture.cpp b/drape/static_texture.cpp
index f131129b03..8638787e20 100644
--- a/drape/static_texture.cpp
+++ b/drape/static_texture.cpp
@@ -4,8 +4,8 @@
#include "platform/platform.hpp"
-#include "coding/reader.hpp"
#include "coding/parse_xml.hpp"
+#include "coding/reader.hpp"
#include "base/string_utils.hpp"
@@ -14,26 +14,32 @@
#endif
#include "3party/stb_image/stb_image.h"
+#include <vector>
+
namespace dp
{
+std::string const StaticTexture::kDefaultResource = "default";
namespace
{
-
using TLoadingCompletion = function<void(unsigned char *, uint32_t, uint32_t)>;
-using TLoadingFailure = function<void(string const &)>;
+using TLoadingFailure = function<void(std::string const &)>;
-bool LoadData(string const & textureName, string const & skinPathName,
- TLoadingCompletion const & completionHandler,
+bool LoadData(std::string const & textureName, std::string const & skinPathName,
+ uint8_t bytesPerPixel, TLoadingCompletion const & completionHandler,
TLoadingFailure const & failureHandler)
{
ASSERT(completionHandler != nullptr, ());
ASSERT(failureHandler != nullptr, ());
- vector<unsigned char> rawData;
+ std::vector<unsigned char> rawData;
try
{
- ReaderPtr<Reader> reader = GetStyleReader().GetResourceReader(textureName + ".png", skinPathName);
+ std::string const fullName = textureName + ".png";
+ ReaderPtr<Reader> reader = skinPathName == StaticTexture::kDefaultResource ?
+ GetStyleReader().GetDefaultResourceReader(fullName) :
+ GetStyleReader().GetResourceReader(fullName, skinPathName);
+
CHECK_LESS(reader.Size(), static_cast<uint64_t>(numeric_limits<size_t>::max()), ());
size_t const size = static_cast<size_t>(reader.Size());
rawData.resize(size);
@@ -46,12 +52,30 @@ bool LoadData(string const & textureName, string const & skinPathName,
}
int w, h, bpp;
- unsigned char * data = stbi_load_from_memory(&rawData[0], static_cast<int>(rawData.size()), &w, &h, &bpp, 0);
- ASSERT_EQUAL(bpp, 4, ("Incorrect texture format"));
+ unsigned char * data =
+ stbi_load_from_memory(&rawData[0], static_cast<int>(rawData.size()), &w, &h, &bpp, 0);
+
+ uint8_t constexpr kSupportedBPP = 4;
+ CHECK_EQUAL(bpp, kSupportedBPP, ("Incorrect texture format"));
ASSERT(glm::isPowerOfTwo(w), (w));
ASSERT(glm::isPowerOfTwo(h), (h));
- completionHandler(data, static_cast<uint32_t>(w), static_cast<uint32_t>(h));
+ if (bytesPerPixel != bpp)
+ {
+ std::vector<unsigned char> convertedData(static_cast<size_t>(w * h * bytesPerPixel));
+ uint32_t const pixelsCount = static_cast<uint32_t>(w * h);
+ for (uint32_t i = 0; i < pixelsCount; i++)
+ {
+ unsigned char const * p = data + i * bpp;
+ convertedData[i * bytesPerPixel] = p[0];
+ convertedData[i * bytesPerPixel + 1] = p[1];
+ }
+ stbi_image_free(data);
+ completionHandler(convertedData.data(), static_cast<uint32_t>(w), static_cast<uint32_t>(h));
+ return true;
+ }
+
+ completionHandler(data, static_cast<uint32_t>(w), static_cast<uint32_t>(h));
stbi_image_free(data);
return true;
}
@@ -60,28 +84,29 @@ class StaticResourceInfo : public Texture::ResourceInfo
{
public:
StaticResourceInfo() : Texture::ResourceInfo(m2::RectF(0.0f, 0.0f, 1.0f, 1.0f)) {}
- virtual ~StaticResourceInfo(){}
-
+ virtual ~StaticResourceInfo() {}
Texture::ResourceType GetType() const override { return Texture::Static; }
};
+} // namespace
-} // namespace
-
-StaticTexture::StaticTexture(string const & textureName, string const & skinPathName,
- ref_ptr<HWTextureAllocator> allocator)
+StaticTexture::StaticTexture(std::string const & textureName, std::string const & skinPathName,
+ dp::TextureFormat format, ref_ptr<HWTextureAllocator> allocator)
: m_textureName(textureName)
+ , m_skinPathName(skinPathName)
+ , m_format(format)
, m_info(make_unique_dp<StaticResourceInfo>())
{
- m_isLoadingCorrect = Load(skinPathName, allocator);
+ m_isLoadingCorrect = Load(allocator);
}
-bool StaticTexture::Load(string const & skinPathName, ref_ptr<HWTextureAllocator> allocator)
+bool StaticTexture::Load(ref_ptr<HWTextureAllocator> allocator)
{
- auto completionHandler = [this, &allocator](unsigned char * data, uint32_t width, uint32_t height)
+ auto completionHandler = [this, &allocator](unsigned char * data, uint32_t width,
+ uint32_t height)
{
Texture::Params p;
p.m_allocator = allocator;
- p.m_format = dp::RGBA8;
+ p.m_format = m_format;
p.m_width = width;
p.m_height = height;
p.m_wrapSMode = gl_const::GLRepeate;
@@ -90,22 +115,25 @@ bool StaticTexture::Load(string const & skinPathName, ref_ptr<HWTextureAllocator
Create(p, make_ref(data));
};
- auto failureHandler = [this](string const & reason)
+ auto failureHandler = [this](std::string const & reason)
{
LOG(LERROR, (reason));
Fail();
};
- return LoadData(m_textureName, skinPathName, completionHandler, failureHandler);
+ uint8_t const bytesPerPixel = GetBytesPerPixel(m_format);
+ return LoadData(m_textureName, m_skinPathName, bytesPerPixel,
+ completionHandler, failureHandler);
}
-void StaticTexture::Invalidate(string const & skinPathName, ref_ptr<HWTextureAllocator> allocator)
+void StaticTexture::Invalidate(ref_ptr<HWTextureAllocator> allocator)
{
Destroy();
- m_isLoadingCorrect = Load(skinPathName, allocator);
+ m_isLoadingCorrect = Load(allocator);
}
-ref_ptr<Texture::ResourceInfo> StaticTexture::FindResource(Texture::Key const & key, bool & newResource)
+ref_ptr<Texture::ResourceInfo> StaticTexture::FindResource(Texture::Key const & key,
+ bool & newResource)
{
newResource = false;
if (key.GetType() != Texture::Static)
@@ -115,14 +143,12 @@ ref_ptr<Texture::ResourceInfo> StaticTexture::FindResource(Texture::Key const &
void StaticTexture::Fail()
{
- int32_t alfaTexture = 0;
+ int32_t alphaTexture = 0;
Texture::Params p;
p.m_allocator = GetDefaultAllocator();
p.m_format = dp::RGBA8;
p.m_width = 1;
p.m_height = 1;
-
- Create(p, make_ref(&alfaTexture));
+ Create(p, make_ref(&alphaTexture));
}
-
-} // namespace dp
+} // namespace dp
diff --git a/drape/static_texture.hpp b/drape/static_texture.hpp
index aa2aa7e4c5..d7a6950445 100644
--- a/drape/static_texture.hpp
+++ b/drape/static_texture.hpp
@@ -2,11 +2,10 @@
#include "drape/texture.hpp"
-#include "std/string.hpp"
+#include <string>
namespace dp
{
-
class StaticTexture : public Texture
{
public:
@@ -16,23 +15,26 @@ public:
ResourceType GetType() const override { return ResourceType::Static; }
};
- StaticTexture(string const & textureName, string const & skinPathName,
- ref_ptr<HWTextureAllocator> allocator);
+ static std::string const kDefaultResource;
+
+ StaticTexture(std::string const & textureName, std::string const & skinPathName,
+ dp::TextureFormat format, ref_ptr<HWTextureAllocator> allocator);
ref_ptr<ResourceInfo> FindResource(Key const & key, bool & newResource) override;
- void Invalidate(string const & skinPathName, ref_ptr<HWTextureAllocator> allocator);
+ void Invalidate(ref_ptr<HWTextureAllocator> allocator);
bool IsLoadingCorrect() const { return m_isLoadingCorrect; }
-
private:
void Fail();
- bool Load(string const & skinPathName, ref_ptr<HWTextureAllocator> allocator);
+ bool Load(ref_ptr<HWTextureAllocator> allocator);
+
+ std::string const m_textureName;
+ std::string const m_skinPathName;
+ dp::TextureFormat const m_format;
- string m_textureName;
drape_ptr<Texture::ResourceInfo> m_info;
bool m_isLoadingCorrect;
};
-
-} // namespace dp
+} // namespace dp
diff --git a/drape/support_manager.cpp b/drape/support_manager.cpp
index 6a68449086..bd745335f4 100644
--- a/drape/support_manager.cpp
+++ b/drape/support_manager.cpp
@@ -1,20 +1,24 @@
#include "drape/support_manager.hpp"
#include "drape/glfunctions.hpp"
-#include "base/logging.hpp"
+#include "platform/settings.hpp"
-#include "std/algorithm.hpp"
-#include "std/vector.hpp"
+#include "base/logging.hpp"
#include "3party/Alohalytics/src/alohalytics.h"
+#include <algorithm>
+#include <string>
+#include <vector>
+
namespace dp
{
+char const * kSupportedAntialiasing = "Antialiasing";
void SupportManager::Init()
{
- string const renderer = GLFunctions::glGetString(gl_const::GLRenderer);
- string const version = GLFunctions::glGetString(gl_const::GLVersion);
+ std::string const renderer = GLFunctions::glGetString(gl_const::GLRenderer);
+ std::string const version = GLFunctions::glGetString(gl_const::GLVersion);
LOG(LINFO, ("Renderer =", renderer, "Api =", GLFunctions::CurrentApiVersion, "Driver version =", version));
// On Android the engine may be recreated. Here we guarantee that GPU info is sent once per session.
@@ -29,12 +33,12 @@ void SupportManager::Init()
if (m_isSamsungGoogleNexus)
LOG(LINFO, ("Samsung Google Nexus detected."));
- if (renderer.find("Adreno") != string::npos)
+ if (renderer.find("Adreno") != std::string::npos)
{
- vector<string> const models = { "200", "203", "205", "220", "225" };
+ std::vector<std::string> const models = { "200", "203", "205", "220", "225" };
for (auto const & model : models)
{
- if (renderer.find(model) != string::npos)
+ if (renderer.find(model) != std::string::npos)
{
LOG(LINFO, ("Adreno 200 device detected."));
m_isAdreno200 = true;
@@ -43,32 +47,28 @@ void SupportManager::Init()
}
}
- m_isTegra = (renderer.find("Tegra") != string::npos);
+ m_isTegra = (renderer.find("Tegra") != std::string::npos);
if (m_isTegra)
LOG(LINFO, ("NVidia Tegra device detected."));
- m_maxLineWidth = max(1, GLFunctions::glGetMaxLineWidth());
+ m_maxLineWidth = std::max(1, GLFunctions::glGetMaxLineWidth());
LOG(LINFO, ("Max line width =", m_maxLineWidth));
-}
-bool SupportManager::IsSamsungGoogleNexus() const
-{
- return m_isSamsungGoogleNexus;
-}
-
-bool SupportManager::IsAdreno200Device() const
-{
- return m_isAdreno200;
-}
-
-bool SupportManager::IsTegraDevice() const
-{
- return m_isTegra;
-}
-
-int SupportManager::GetMaxLineWidth() const
-{
- return m_maxLineWidth;
+ // Set up default antialiasing value.
+ bool val;
+ if (!settings::Get(kSupportedAntialiasing, val))
+ {
+#ifdef OMIM_OS_ANDROID
+ std::vector<std::string> const models = {"Mali-G71", "Mali-T880",
+ "Adreno (TM) 540", "Adreno (TM) 530",
+ "Adreno (TM) 430", "Adreno (TM) 330"};
+ m_isAntialiasingEnabledByDefault =
+ (std::find(models.begin(), models.end(), renderer) != models.end());
+#else
+ m_isAntialiasingEnabledByDefault = true;
+#endif
+ settings::Set(kSupportedAntialiasing, m_isAntialiasingEnabledByDefault);
+ }
}
SupportManager & SupportManager::Instance()
@@ -76,5 +76,4 @@ SupportManager & SupportManager::Instance()
static SupportManager manager;
return manager;
}
-
-} // namespace dp
+} // namespace dp
diff --git a/drape/support_manager.hpp b/drape/support_manager.hpp
index c59fdbcbbe..e7a9df6aa9 100644
--- a/drape/support_manager.hpp
+++ b/drape/support_manager.hpp
@@ -1,11 +1,12 @@
#pragma once
-#include "std/noncopyable.hpp"
+#include "base/macros.hpp"
namespace dp
{
+extern char const * kSupportedAntialiasing;
-class SupportManager : public noncopyable
+class SupportManager
{
public:
// This singleton must be available only from rendering threads.
@@ -14,21 +15,21 @@ public:
// Initialization must be called only when OpenGL context is created.
void Init();
- bool IsSamsungGoogleNexus() const;
- bool IsAdreno200Device() const;
- bool IsTegraDevice() const;
-
- int GetMaxLineWidth() const;
+ bool IsSamsungGoogleNexus() const { return m_isSamsungGoogleNexus; }
+ bool IsAdreno200Device() const { return m_isAdreno200; }
+ bool IsTegraDevice() const { return m_isTegra; }
+ int GetMaxLineWidth() const { return m_maxLineWidth; }
+ bool IsAntialiasingEnabledByDefault() const { return m_isAntialiasingEnabledByDefault; }
private:
SupportManager() = default;
- ~SupportManager() = default;
bool m_isSamsungGoogleNexus = false;
bool m_isAdreno200 = false;
bool m_isTegra = false;
-
int m_maxLineWidth = 1;
-};
+ bool m_isAntialiasingEnabledByDefault = false;
-} // namespace dp
+ DISALLOW_COPY_AND_MOVE(SupportManager);
+};
+} // namespace dp
diff --git a/drape/texture_manager.cpp b/drape/texture_manager.cpp
index 2811e4fa22..6c6acc5554 100644
--- a/drape/texture_manager.cpp
+++ b/drape/texture_manager.cpp
@@ -19,6 +19,8 @@
#include "std/vector.hpp"
#include "std/bind.hpp"
+#include <algorithm>
+
namespace dp
{
@@ -43,7 +45,6 @@ uint32_t const kDefaultSymbolsIndex = 0;
namespace
{
-
void MultilineTextToUniString(TextureManager::TMultilineText const & text, strings::UniString & outString)
{
size_t cnt = 0;
@@ -117,8 +118,23 @@ void ParsePatternsList(string const & patternsFile, ToDo toDo)
toDo(pattern);
});
}
+m2::PointU StipplePenTextureSize(size_t patternsCount, uint32_t maxTextureSize)
+{
+ uint32_t const sz = my::NextPowOf2(static_cast<uint32_t>(patternsCount) + kReservedPatterns);
+ uint32_t const stippleTextureHeight =
+ std::min(maxTextureSize, std::max(sz, kMinStippleTextureHeight));
+ return m2::PointU(kStippleTextureWidth, stippleTextureHeight);
+}
-} // namespace
+m2::PointU ColorTextureSize(size_t colorsCount, uint32_t maxTextureSize)
+{
+ uint32_t const sz = static_cast<uint32_t>(floor(sqrt(colorsCount + kReservedColors)));
+ uint32_t colorTextureSize = std::max(my::NextPowOf2(sz), kMinColorTextureSize);
+ colorTextureSize *= ColorTexture::GetColorSizeInPixels();
+ colorTextureSize = std::min(maxTextureSize, colorTextureSize);
+ return m2::PointU(colorTextureSize, colorTextureSize);
+}
+} // namespace
TextureManager::TextureManager()
: m_maxTextureSize(0)
@@ -178,8 +194,7 @@ m2::RectF const & TextureManager::BaseRegion::GetTexRect() const
TextureManager::GlyphRegion::GlyphRegion()
: BaseRegion()
-{
-}
+{}
float TextureManager::GlyphRegion::GetOffsetX() const
{
@@ -228,6 +243,8 @@ void TextureManager::Release()
m_trafficArrowTexture.reset();
m_hatchingTexture.reset();
+ m_smaaAreaTexture.reset();
+ m_smaaSearchTexture.reset();
m_glyphTextures.clear();
@@ -390,39 +407,46 @@ size_t TextureManager::FindHybridGlyphsGroup(TMultilineText const & text, int fi
void TextureManager::Init(Params const & params)
{
+ m_resPostfix = params.m_resPostfix;
m_textureAllocator = CreateAllocator();
- m_maxTextureSize = min(kMaxTextureSize, (uint32_t)GLFunctions::glGetInteger(gl_const::GLMaxTextureSize));
+ m_maxTextureSize = std::min(kMaxTextureSize,
+ static_cast<uint32_t>(GLFunctions::glGetInteger(gl_const::GLMaxTextureSize)));
GLFunctions::glPixelStore(gl_const::GLUnpackAlignment, 1);
+ // Initialize symbols.
for (size_t i = 0; i < ARRAY_SIZE(kSymbolTextures); ++i)
{
- m_symbolTextures.push_back(make_unique_dp<SymbolsTexture>(params.m_resPostfix, kSymbolTextures[i],
+ m_symbolTextures.push_back(make_unique_dp<SymbolsTexture>(m_resPostfix, kSymbolTextures[i],
make_ref(m_textureAllocator)));
}
- m_trafficArrowTexture = make_unique_dp<StaticTexture>("traffic-arrow", params.m_resPostfix,
- make_ref(m_textureAllocator));
+ // Initialize static textures.
+ m_trafficArrowTexture = make_unique_dp<StaticTexture>("traffic-arrow", m_resPostfix,
+ dp::RGBA8, make_ref(m_textureAllocator));
+ m_hatchingTexture = make_unique_dp<StaticTexture>("area-hatching", m_resPostfix,
+ dp::RGBA8, make_ref(m_textureAllocator));
- m_hatchingTexture = make_unique_dp<StaticTexture>("area-hatching", params.m_resPostfix,
- make_ref(m_textureAllocator));
+ if (GLFunctions::CurrentApiVersion == dp::ApiVersion::OpenGLES3)
+ {
+ m_smaaAreaTexture = make_unique_dp<StaticTexture>("smaa-area", StaticTexture::kDefaultResource,
+ dp::RED_GREEN, make_ref(m_textureAllocator));
+ m_smaaSearchTexture = make_unique_dp<StaticTexture>("smaa-search", StaticTexture::kDefaultResource,
+ dp::ALPHA, make_ref(m_textureAllocator));
+ }
- // initialize patterns
+ // Initialize patterns.
buffer_vector<buffer_vector<uint8_t, 8>, 64> patterns;
double const visualScale = params.m_visualScale;
ParsePatternsList(params.m_patterns, [&patterns, visualScale](buffer_vector<double, 8> const & pattern)
{
buffer_vector<uint8_t, 8> p;
for (size_t i = 0; i < pattern.size(); i++)
- p.push_back(pattern[i] * visualScale);
+ p.push_back(static_cast<uint8_t>(pattern[i] * visualScale));
patterns.push_back(move(p));
});
-
- uint32_t stippleTextureHeight = max(my::NextPowOf2(static_cast<uint32_t>(patterns.size()) + kReservedPatterns),
- kMinStippleTextureHeight);
- stippleTextureHeight = min(m_maxTextureSize, stippleTextureHeight);
- m_stipplePenTexture = make_unique_dp<StipplePenTexture>(m2::PointU(kStippleTextureWidth, stippleTextureHeight),
+ m_stipplePenTexture = make_unique_dp<StipplePenTexture>(StipplePenTextureSize(patterns.size(), m_maxTextureSize),
make_ref(m_textureAllocator));
LOG(LDEBUG, ("Patterns texture size = ", m_stipplePenTexture->GetWidth(), m_stipplePenTexture->GetHeight()));
@@ -430,17 +454,13 @@ void TextureManager::Init(Params const & params)
for (auto it = patterns.begin(); it != patterns.end(); ++it)
stipplePenTextureTex->ReservePattern(*it);
- // initialize colors
+ // Initialize colors.
buffer_vector<dp::Color, 256> colors;
ParseColorsList(params.m_colors, [&colors](dp::Color const & color)
{
colors.push_back(color);
});
-
- uint32_t colorTextureSize = max(my::NextPowOf2(floor(sqrt(colors.size() + kReservedColors))), kMinColorTextureSize);
- colorTextureSize *= ColorTexture::GetColorSizeInPixels();
- colorTextureSize = min(m_maxTextureSize, colorTextureSize);
- m_colorTexture = make_unique_dp<ColorTexture>(m2::PointU(colorTextureSize, colorTextureSize),
+ m_colorTexture = make_unique_dp<ColorTexture>(ColorTextureSize(colors.size(), m_maxTextureSize),
make_ref(m_textureAllocator));
LOG(LDEBUG, ("Colors texture size = ", m_colorTexture->GetWidth(), m_colorTexture->GetHeight()));
@@ -448,15 +468,16 @@ void TextureManager::Init(Params const & params)
for (auto it = colors.begin(); it != colors.end(); ++it)
colorTex->ReserveColor(*it);
- // initialize glyphs
+ // Initialize glyphs.
m_glyphManager = make_unique_dp<GlyphManager>(params.m_glyphMngParams);
uint32_t const textureSquare = m_maxTextureSize * m_maxTextureSize;
- uint32_t const baseGlyphHeight = params.m_glyphMngParams.m_baseGlyphHeight * kGlyphAreaMultiplier;
- uint32_t const avarageGlyphSquare = baseGlyphHeight * baseGlyphHeight;
+ uint32_t const baseGlyphHeight =
+ static_cast<uint32_t>(params.m_glyphMngParams.m_baseGlyphHeight * kGlyphAreaMultiplier);
+ uint32_t const averageGlyphSquare = baseGlyphHeight * baseGlyphHeight;
m_glyphGroups.push_back(GlyphGroup());
- m_maxGlypsCount = ceil(kGlyphAreaCoverage * textureSquare / avarageGlyphSquare);
+ m_maxGlypsCount = static_cast<uint32_t>(ceil(kGlyphAreaCoverage * textureSquare / averageGlyphSquare));
m_glyphManager->ForEachUnicodeBlock([this](strings::UniChar const & start, strings::UniChar const & end)
{
if (m_glyphGroups.empty())
@@ -475,22 +496,27 @@ void TextureManager::Init(Params const & params)
});
}
-void TextureManager::Invalidate(string const & resPostfix)
+void TextureManager::OnSwitchMapStyle()
{
+ // Here we need invalidate only textures which can be changed in map style switch.
for (size_t i = 0; i < m_symbolTextures.size(); ++i)
{
ASSERT(m_symbolTextures[i] != nullptr, ());
+ ASSERT(dynamic_cast<SymbolsTexture *>(m_symbolTextures[i].get()) != nullptr, ());
ref_ptr<SymbolsTexture> symbolsTexture = make_ref(m_symbolTextures[i]);
- symbolsTexture->Invalidate(resPostfix, make_ref(m_textureAllocator));
+ symbolsTexture->Invalidate(m_resPostfix, make_ref(m_textureAllocator));
}
- ASSERT(m_trafficArrowTexture != nullptr, ());
- ref_ptr<StaticTexture> trafficArrowTexture = make_ref(m_trafficArrowTexture);
- trafficArrowTexture->Invalidate(resPostfix, make_ref(m_textureAllocator));
-
- ASSERT(m_hatchingTexture != nullptr, ());
- ref_ptr<StaticTexture> hatchingTexture = make_ref(m_hatchingTexture);
- hatchingTexture->Invalidate(resPostfix, make_ref(m_textureAllocator));
+ // Uncomment if static textures can be changed.
+ //ref_ptr<Texture> staticTextures[] = {make_ref(m_trafficArrowTexture),
+ // make_ref(m_hatchingTexture)};
+ //for (uint32_t i = 0; i < ARRAY_SIZE(staticTextures); i++)
+ //{
+ // ASSERT(staticTextures[i] != nullptr, ());
+ // ASSERT(dynamic_cast<StaticTexture *>(staticTextures[i].get()) != nullptr, ());
+ // ref_ptr<StaticTexture> t = staticTextures[i];
+ // t->Invalidate(make_ref(m_textureAllocator));
+ //}
}
void TextureManager::GetSymbolRegion(string const & symbolName, SymbolRegion & region)
@@ -569,9 +595,18 @@ ref_ptr<Texture> TextureManager::GetHatchingTexture() const
return make_ref(m_hatchingTexture);
}
+ref_ptr<Texture> TextureManager::GetSMAAAreaTexture() const
+{
+ return make_ref(m_smaaAreaTexture);
+}
+
+ref_ptr<Texture> TextureManager::GetSMAASearchTexture() const
+{
+ return make_ref(m_smaaSearchTexture);
+}
+
constexpr size_t TextureManager::GetInvalidGlyphGroup()
{
return kInvalidGlyphGroup;
}
-
-} // namespace dp
+} // namespace dp
diff --git a/drape/texture_manager.hpp b/drape/texture_manager.hpp
index c0a9a74a9d..fa9edb7167 100644
--- a/drape/texture_manager.hpp
+++ b/drape/texture_manager.hpp
@@ -10,6 +10,7 @@
#include <atomic>
#include <list>
+#include <string>
#include <vector>
namespace dp
@@ -81,7 +82,7 @@ public:
void Release();
void Init(Params const & params);
- void Invalidate(string const & resPostfix);
+ void OnSwitchMapStyle();
void GetSymbolRegion(string const & symbolName, SymbolRegion & region);
@@ -107,6 +108,8 @@ public:
ref_ptr<Texture> GetSymbolsTexture() const;
ref_ptr<Texture> GetTrafficArrowTexture() const;
ref_ptr<Texture> GetHatchingTexture() const;
+ ref_ptr<Texture> GetSMAAAreaTexture() const;
+ ref_ptr<Texture> GetSMAASearchTexture() const;
private:
struct GlyphGroup
@@ -239,6 +242,7 @@ private:
static constexpr size_t GetInvalidGlyphGroup();
private:
+ std::string m_resPostfix;
std::vector<drape_ptr<Texture>> m_symbolTextures;
drape_ptr<Texture> m_stipplePenTexture;
drape_ptr<Texture> m_colorTexture;
@@ -246,6 +250,8 @@ private:
drape_ptr<Texture> m_trafficArrowTexture;
drape_ptr<Texture> m_hatchingTexture;
+ drape_ptr<Texture> m_smaaAreaTexture;
+ drape_ptr<Texture> m_smaaSearchTexture;
drape_ptr<GlyphManager> m_glyphManager;
drape_ptr<HWTextureAllocator> m_textureAllocator;
diff --git a/drape_frontend/CMakeLists.txt b/drape_frontend/CMakeLists.txt
index 3a130ac449..7b3f68f7bc 100644
--- a/drape_frontend/CMakeLists.txt
+++ b/drape_frontend/CMakeLists.txt
@@ -145,6 +145,8 @@ set(
path_text_shape.hpp
poi_symbol_shape.cpp
poi_symbol_shape.hpp
+ postprocess_renderer.cpp
+ postprocess_renderer.hpp
read_manager.cpp
read_manager.hpp
read_mwm_task.cpp
@@ -274,6 +276,12 @@ set(
shaders/screen_quad.vsh.glsl
shaders/shader_index.txt
shaders/shaders_lib.glsl
+ shaders/smaa_blending_weight.fsh.glsl
+ shaders/smaa_blending_weight.vsh.glsl
+ shaders/smaa_edges.fsh.glsl
+ shaders/smaa_edges.vsh.glsl
+ shaders/smaa_final.fsh.glsl
+ shaders/smaa_final.vsh.glsl
shaders/solid_color.fsh.glsl
shaders/text.fsh.glsl
shaders/text.vsh.glsl
diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp
index 0f6d844711..edc94f2874 100644
--- a/drape_frontend/backend_renderer.cpp
+++ b/drape_frontend/backend_renderer.cpp
@@ -308,9 +308,9 @@ void BackendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
}
- case Message::InvalidateTextures:
+ case Message::SwitchMapStyle:
{
- m_texMng->Invalidate(VisualParams::Instance().GetResourcePostfix());
+ m_texMng->OnSwitchMapStyle();
RecacheMapShapes();
m_trafficGenerator->InvalidateTexturesCache();
break;
@@ -536,6 +536,14 @@ void BackendRenderer::InitGLDependentResource()
GetPlatform().GetFontNames(params.m_glyphMngParams.m_fonts);
m_texMng->Init(params);
+
+ // Send some textures to frontend renderer.
+ drape_ptr<PostprocessStaticTextures> textures = make_unique_dp<PostprocessStaticTextures>();
+ textures->m_smaaAreaTexture = m_texMng->GetSMAAAreaTexture();
+ textures->m_smaaSearchTexture = m_texMng->GetSMAASearchTexture();
+ m_commutator->PostMessage(ThreadsCommutator::RenderThread,
+ make_unique_dp<SetPostprocessStaticTexturesMessage>(std::move(textures)),
+ MessagePriority::High);
}
void BackendRenderer::RecacheMapShapes()
diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp
index 115e0fade9..c95d101565 100644
--- a/drape_frontend/drape_engine.cpp
+++ b/drape_frontend/drape_engine.cpp
@@ -1,17 +1,19 @@
#include "drape_frontend/drape_engine.hpp"
+
#include "drape_frontend/message_subclasses.hpp"
-#include "drape_frontend/visual_params.hpp"
+#include "drape_frontend/gui/drape_gui.hpp"
#include "drape_frontend/my_position_controller.hpp"
+#include "drape_frontend/visual_params.hpp"
-#include "drape_frontend/gui/drape_gui.hpp"
+#include "drape/support_manager.hpp"
#include "platform/settings.hpp"
namespace df
{
DrapeEngine::DrapeEngine(Params && params)
- : m_myPositionModeChanged(move(params.m_myPositionModeChanged))
- , m_viewport(move(params.m_viewport))
+ : m_myPositionModeChanged(std::move(params.m_myPositionModeChanged))
+ , m_viewport(std::move(params.m_viewport))
{
VisualParams::Init(params.m_vs, df::CalculateTileSize(m_viewport.GetWidth(), m_viewport.GetHeight()));
@@ -32,8 +34,8 @@ DrapeEngine::DrapeEngine(Params && params)
}
else if (mode == location::FollowAndRotate)
{
- // If the screen rect setting in follow and rotate mode is missing or invalid, it could cause invalid animations,
- // so the follow and rotate mode should be discarded.
+ // If the screen rect setting in follow and rotate mode is missing or invalid, it could cause
+ // invalid animations, so the follow and rotate mode should be discarded.
m2::AnyRectD rect;
if (!(settings::Get("ScreenClipRect", rect) && df::GetWorldRect().IsRectInside(rect.GetGlobalRect())))
mode = location::Follow;
@@ -44,6 +46,18 @@ DrapeEngine::DrapeEngine(Params && params)
if (settings::Get("LastEnterBackground", lastEnterBackground))
timeInBackground = my::Timer::LocalTime() - lastEnterBackground;
+ std::vector<PostprocessRenderer::Effect> effects;
+
+ bool enabledAntialiasing;
+ if (!settings::Get(dp::kSupportedAntialiasing, enabledAntialiasing))
+ enabledAntialiasing = false;
+
+ if (enabledAntialiasing)
+ {
+ LOG(LINFO, ("Antialiasing is enabled"));
+ effects.push_back(PostprocessRenderer::Antialiasing);
+ }
+
MyPositionController::Params mpParams(mode,
timeInBackground,
params.m_hints,
@@ -55,18 +69,19 @@ DrapeEngine::DrapeEngine(Params && params)
make_ref(m_threadCommutator),
params.m_factory,
make_ref(m_textureManager),
- move(mpParams),
+ std::move(mpParams),
m_viewport,
bind(&DrapeEngine::ModelViewChanged, this, _1),
bind(&DrapeEngine::TapEvent, this, _1),
bind(&DrapeEngine::UserPositionChanged, this, _1),
make_ref(m_requestedTiles),
- move(params.m_overlaysShowStatsCallback),
+ std::move(params.m_overlaysShowStatsCallback),
params.m_allow3dBuildings,
params.m_trafficEnabled,
- params.m_blockTapEvents);
+ params.m_blockTapEvents,
+ std::move(effects));
- m_frontend = make_unique_dp<FrontendRenderer>(move(frParams));
+ m_frontend = make_unique_dp<FrontendRenderer>(std::move(frParams));
BackendRenderer::Params brParams(params.m_apiVersion,
frParams.m_commutator,
@@ -79,15 +94,15 @@ DrapeEngine::DrapeEngine(Params && params)
params.m_trafficEnabled,
params.m_simplifiedTrafficColors);
- m_backend = make_unique_dp<BackendRenderer>(move(brParams));
+ m_backend = make_unique_dp<BackendRenderer>(std::move(brParams));
- m_widgetsInfo = move(params.m_info);
+ m_widgetsInfo = std::move(params.m_info);
RecacheGui(false);
RecacheMapShapes();
if (params.m_showChoosePositionMark)
- EnableChoosePositionMode(true, move(params.m_boundAreaTriangles), false, m2::PointD());
+ EnableChoosePositionMode(true, std::move(params.m_boundAreaTriangles), false, m2::PointD());
ResizeImpl(m_viewport.GetWidth(), m_viewport.GetHeight());
}
@@ -251,7 +266,7 @@ void DrapeEngine::RecacheGui(bool needResetOldGui)
void DrapeEngine::AddUserEvent(drape_ptr<UserEvent> && e)
{
- m_frontend->AddUserEvent(move(e));
+ m_frontend->AddUserEvent(std::move(e));
}
void DrapeEngine::ModelViewChanged(ScreenBase const & screen)
@@ -293,7 +308,8 @@ void DrapeEngine::SetCompassInfo(location::CompassInfo const & info)
MessagePriority::High);
}
-void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable, const location::RouteMatchingInfo & routeInfo)
+void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable,
+ const location::RouteMatchingInfo & routeInfo)
{
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<GpsInfoMessage>(info, isNavigable, routeInfo),
@@ -302,45 +318,49 @@ void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable, c
void DrapeEngine::SwitchMyPositionNextMode()
{
+ using Mode = ChangeMyPositionModeMessage::EChangeType;
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
- make_unique_dp<ChangeMyPositionModeMessage>(ChangeMyPositionModeMessage::SwitchNextMode),
+ make_unique_dp<ChangeMyPositionModeMessage>(Mode::SwitchNextMode),
MessagePriority::High);
}
void DrapeEngine::LoseLocation()
{
+ using Mode = ChangeMyPositionModeMessage::EChangeType;
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
- make_unique_dp<ChangeMyPositionModeMessage>(ChangeMyPositionModeMessage::LoseLocation),
+ make_unique_dp<ChangeMyPositionModeMessage>(Mode::LoseLocation),
MessagePriority::High);
}
void DrapeEngine::StopLocationFollow()
{
+ using Mode = ChangeMyPositionModeMessage::EChangeType;
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
- make_unique_dp<ChangeMyPositionModeMessage>(ChangeMyPositionModeMessage::StopFollowing),
+ make_unique_dp<ChangeMyPositionModeMessage>(Mode::StopFollowing),
MessagePriority::High);
}
void DrapeEngine::FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d, bool enableAutoZoom)
{
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
- make_unique_dp<FollowRouteMessage>(preferredZoomLevel, preferredZoomLevel3d, enableAutoZoom),
+ make_unique_dp<FollowRouteMessage>(preferredZoomLevel,
+ preferredZoomLevel3d, enableAutoZoom),
MessagePriority::High);
}
void DrapeEngine::SetModelViewListener(TModelViewListenerFn && fn)
{
- m_modelViewChanged = move(fn);
+ m_modelViewChanged = std::move(fn);
}
void DrapeEngine::SetTapEventInfoListener(TTapEventInfoFn && fn)
{
- m_tapListener = move(fn);
+ m_tapListener = std::move(fn);
}
void DrapeEngine::SetUserPositionListener(TUserPositionChangedFn && fn)
{
- m_userPositionChanged = move(fn);
+ m_userPositionChanged = std::move(fn);
}
FeatureID DrapeEngine::GetVisiblePOI(m2::PointD const & glbPoint)
@@ -355,7 +375,8 @@ FeatureID DrapeEngine::GetVisiblePOI(m2::PointD const & glbPoint)
return result;
}
-void DrapeEngine::SelectObject(SelectionShape::ESelectedObject obj, m2::PointD const & pt, FeatureID const & featureId, bool isAnim)
+void DrapeEngine::SelectObject(SelectionShape::ESelectedObject obj, m2::PointD const & pt,
+ FeatureID const & featureId, bool isAnim)
{
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<SelectObjectMessage>(obj, pt, featureId, isAnim),
@@ -393,12 +414,13 @@ bool DrapeEngine::GetMyPosition(m2::PointD & myPosition)
return hasPosition;
}
-void DrapeEngine::AddRoute(m2::PolylineD const & routePolyline, vector<double> const & turns,
- df::ColorConstant color, vector<traffic::SpeedGroup> const & traffic,
+void DrapeEngine::AddRoute(m2::PolylineD const & routePolyline, std::vector<double> const & turns,
+ df::ColorConstant color, std::vector<traffic::SpeedGroup> const & traffic,
df::RoutePattern pattern)
{
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
- make_unique_dp<AddRouteMessage>(routePolyline, turns, color, traffic, pattern),
+ make_unique_dp<AddRouteMessage>(routePolyline, turns,
+ color, traffic, pattern),
MessagePriority::Normal);
}
@@ -425,7 +447,7 @@ void DrapeEngine::SetRoutePoint(m2::PointD const & position, bool isStart, bool
void DrapeEngine::SetWidgetLayout(gui::TWidgetsLayoutInfo && info)
{
- m_widgetsLayout = move(info);
+ m_widgetsLayout = std::move(info);
for (auto const & layout : m_widgetsLayout)
{
auto const itInfo = m_widgetsInfo.find(layout.first);
@@ -451,7 +473,8 @@ void DrapeEngine::Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBui
MessagePriority::Normal);
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
- make_unique_dp<Allow3dModeMessage>(allowPerspectiveInNavigation, allow3dBuildings),
+ make_unique_dp<Allow3dModeMessage>(allowPerspectiveInNavigation,
+ allow3dBuildings),
MessagePriority::Normal);
}
@@ -462,10 +485,12 @@ void DrapeEngine::EnablePerspective()
MessagePriority::Normal);
}
-void DrapeEngine::UpdateGpsTrackPoints(vector<df::GpsTrackPoint> && toAdd, vector<uint32_t> && toRemove)
+void DrapeEngine::UpdateGpsTrackPoints(std::vector<df::GpsTrackPoint> && toAdd,
+ std::vector<uint32_t> && toRemove)
{
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
- make_unique_dp<UpdateGpsTrackPointsMessage>(move(toAdd), move(toRemove)),
+ make_unique_dp<UpdateGpsTrackPointsMessage>(std::move(toAdd),
+ std::move(toRemove)),
MessagePriority::Normal);
}
@@ -476,7 +501,7 @@ void DrapeEngine::ClearGpsTrackPoints()
MessagePriority::Normal);
}
-void DrapeEngine::EnableChoosePositionMode(bool enable, vector<m2::TriangleD> && boundAreaTriangles,
+void DrapeEngine::EnableChoosePositionMode(bool enable, std::vector<m2::TriangleD> && boundAreaTriangles,
bool hasPosition, m2::PointD const & position)
{
m_choosePositionMode = enable;
@@ -494,7 +519,7 @@ void DrapeEngine::EnableChoosePositionMode(bool enable, vector<m2::TriangleD> &&
RecacheGui(true);
}
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
- make_unique_dp<SetAddNewPlaceModeMessage>(enable, move(boundAreaTriangles),
+ make_unique_dp<SetAddNewPlaceModeMessage>(enable, std::move(boundAreaTriangles),
kineticScroll, hasPosition, position),
MessagePriority::High);
}
@@ -531,7 +556,7 @@ void DrapeEngine::SetDisplacementMode(int mode)
MessagePriority::Normal);
}
-void DrapeEngine::RequestSymbolsSize(vector<string> const & symbols,
+void DrapeEngine::RequestSymbolsSize(std::vector<string> const & symbols,
TRequestSymbolsSizeCallback const & callback)
{
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
@@ -560,7 +585,7 @@ void DrapeEngine::UpdateTraffic(traffic::TrafficInfo const & info)
segmentsColoring.emplace(info.GetMwmId(), info.GetColoring());
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
- make_unique_dp<UpdateTrafficMessage>(move(segmentsColoring)),
+ make_unique_dp<UpdateTrafficMessage>(std::move(segmentsColoring)),
MessagePriority::Normal);
}
@@ -594,7 +619,7 @@ void DrapeEngine::RunScenario(ScenarioManager::ScenarioData && scenarioData,
{
auto const & manager = m_frontend->GetScenarioManager();
if (manager != nullptr)
- manager->RunScenario(move(scenarioData), onStartFn, onFinishFn);
+ manager->RunScenario(std::move(scenarioData), onStartFn, onFinishFn);
}
void DrapeEngine::AddCustomSymbols(CustomSymbols && symbols)
@@ -618,4 +643,16 @@ void DrapeEngine::RemoveAllCustomSymbols()
MessagePriority::Normal);
}
-} // namespace df
+void DrapeEngine::SetPosteffectEnabled(PostprocessRenderer::Effect effect, bool enabled)
+{
+ if (effect == df::PostprocessRenderer::Antialiasing)
+ {
+ LOG(LINFO, ("Antialiasing is", (enabled ? "enabled" : "disabled")));
+ settings::Set(dp::kSupportedAntialiasing, enabled);
+ }
+
+ m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
+ make_unique_dp<SetPosteffectEnabledMessage>(effect, enabled),
+ MessagePriority::Normal);
+}
+} // namespace df
diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp
index 64e9b5924e..debfbc2494 100644
--- a/drape_frontend/drape_engine.hpp
+++ b/drape_frontend/drape_engine.hpp
@@ -7,6 +7,7 @@
#include "drape_frontend/frontend_renderer.hpp"
#include "drape_frontend/route_shape.hpp"
#include "drape_frontend/overlays_tracker.hpp"
+#include "drape_frontend/postprocess_renderer.hpp"
#include "drape_frontend/scenario_manager.hpp"
#include "drape_frontend/selection_shape.hpp"
#include "drape_frontend/threads_commutator.hpp"
@@ -25,8 +26,8 @@
#include "base/strings_bundle.hpp"
-#include "std/map.hpp"
-#include "std/mutex.hpp"
+#include <functional>
+#include <vector>
namespace dp
{
@@ -58,7 +59,7 @@ public:
bool trafficEnabled,
bool blockTapEvents,
bool showChoosePositionMark,
- vector<m2::TriangleD> && boundAreaTriangles,
+ std::vector<m2::TriangleD> && boundAreaTriangles,
bool isRoutingActive,
bool isAutozoomEnabled,
bool simplifiedTrafficColors,
@@ -71,18 +72,18 @@ public:
, m_hints(hints)
, m_vs(vs)
, m_fontsScaleFactor(fontsScaleFactor)
- , m_info(move(info))
+ , m_info(std::move(info))
, m_initialMyPositionMode(initialMyPositionMode)
- , m_myPositionModeChanged(move(myPositionModeChanged))
+ , m_myPositionModeChanged(std::move(myPositionModeChanged))
, m_allow3dBuildings(allow3dBuildings)
, m_trafficEnabled(trafficEnabled)
, m_blockTapEvents(blockTapEvents)
, m_showChoosePositionMark(showChoosePositionMark)
- , m_boundAreaTriangles(move(boundAreaTriangles))
+ , m_boundAreaTriangles(std::move(boundAreaTriangles))
, m_isRoutingActive(isRoutingActive)
, m_isAutozoomEnabled(isAutozoomEnabled)
, m_simplifiedTrafficColors(simplifiedTrafficColors)
- , m_overlaysShowStatsCallback(move(overlaysShowStatsCallback))
+ , m_overlaysShowStatsCallback(std::move(overlaysShowStatsCallback))
{}
dp::ApiVersion m_apiVersion;
@@ -100,7 +101,7 @@ public:
bool m_trafficEnabled;
bool m_blockTapEvents;
bool m_showChoosePositionMark;
- vector<m2::TriangleD> m_boundAreaTriangles;
+ std::vector<m2::TriangleD> m_boundAreaTriangles;
bool m_isRoutingActive;
bool m_isAutozoomEnabled;
bool m_simplifiedTrafficColors;
@@ -120,7 +121,7 @@ public:
void AddTouchEvent(TouchEvent const & event);
void Scale(double factor, m2::PointD const & pxPoint, bool isAnim);
- /// if zoom == -1, then current zoom will not change
+ // If zoom == -1 then current zoom will not be changed.
void SetModelViewCenter(m2::PointD const & centerPt, int zoom, bool isAnim);
void SetModelViewRect(m2::RectD const & rect, bool applyRotation, int zoom, bool isAnim);
void SetModelViewAnyRect(m2::AnyRectD const & rect, bool isAnim);
@@ -149,13 +150,14 @@ public:
void SetUserPositionListener(TUserPositionChangedFn && fn);
FeatureID GetVisiblePOI(m2::PointD const & glbPoint);
- void SelectObject(SelectionShape::ESelectedObject obj, m2::PointD const & pt, FeatureID const & featureID, bool isAnim);
+ void SelectObject(SelectionShape::ESelectedObject obj, m2::PointD const & pt,
+ FeatureID const & featureID, bool isAnim);
void DeselectObject();
bool GetMyPosition(m2::PointD & myPosition);
SelectionShape::ESelectedObject GetSelectedObject();
- void AddRoute(m2::PolylineD const & routePolyline, vector<double> const & turns,
- df::ColorConstant color, vector<traffic::SpeedGroup> const & traffic,
+ void AddRoute(m2::PolylineD const & routePolyline, std::vector<double> const & turns,
+ df::ColorConstant color, std::vector<traffic::SpeedGroup> const & traffic,
df::RoutePattern pattern = df::RoutePattern());
void RemoveRoute(bool deactivateFollowing);
void FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d, bool enableAutoZoom);
@@ -169,10 +171,11 @@ public:
void Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBuildings);
void EnablePerspective();
- void UpdateGpsTrackPoints(vector<df::GpsTrackPoint> && toAdd, vector<uint32_t> && toRemove);
+ void UpdateGpsTrackPoints(std::vector<df::GpsTrackPoint> && toAdd,
+ std::vector<uint32_t> && toRemove);
void ClearGpsTrackPoints();
- void EnableChoosePositionMode(bool enable, vector<m2::TriangleD> && boundAreaTriangles,
+ void EnableChoosePositionMode(bool enable, std::vector<m2::TriangleD> && boundAreaTriangles,
bool hasPosition, m2::PointD const & position);
void BlockTapEvents(bool block);
@@ -182,9 +185,9 @@ public:
void SetDisplacementMode(int mode);
- using TRequestSymbolsSizeCallback = function<void(vector<m2::PointF> const &)>;
+ using TRequestSymbolsSizeCallback = std::function<void(std::vector<m2::PointF> const &)>;
- void RequestSymbolsSize(vector<string> const & symbols,
+ void RequestSymbolsSize(std::vector<string> const & symbols,
TRequestSymbolsSizeCallback const & callback);
void EnableTraffic(bool trafficEnabled);
@@ -202,6 +205,8 @@ public:
void RemoveCustomSymbols(MwmSet::MwmId const & mwmId);
void RemoveAllCustomSymbols();
+ void SetPosteffectEnabled(PostprocessRenderer::Effect effect, bool enabled);
+
private:
void AddUserEvent(drape_ptr<UserEvent> && e);
void ModelViewChanged(ScreenBase const & screen);
diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro
index 15e0f007bc..51077eb59f 100755
--- a/drape_frontend/drape_frontend.pro
+++ b/drape_frontend/drape_frontend.pro
@@ -71,6 +71,7 @@ SOURCES += \
path_symbol_shape.cpp \
path_text_shape.cpp \
poi_symbol_shape.cpp \
+ postprocess_renderer.cpp \
read_manager.cpp \
read_mwm_task.cpp \
render_group.cpp \
@@ -179,6 +180,7 @@ HEADERS += \
path_symbol_shape.hpp \
path_text_shape.hpp \
poi_symbol_shape.hpp \
+ postprocess_renderer.hpp \
read_manager.hpp \
read_mwm_task.hpp \
render_group.hpp \
@@ -267,6 +269,12 @@ OTHER_FILES += \
shaders/screen_quad.vsh.glsl \
shaders/shader_index.txt \
shaders/shaders_lib.glsl \
+ shaders/smaa_blending_weight.fsh.glsl \
+ shaders/smaa_blending_weight.vsh.glsl \
+ shaders/smaa_edges.fsh.glsl \
+ shaders/smaa_edges.vsh.glsl \
+ shaders/smaa_final.fsh.glsl \
+ shaders/smaa_final.vsh.glsl \
shaders/solid_color.fsh.glsl \
shaders/text.fsh.glsl \
shaders/text.vsh.glsl \
diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp
index ee52189864..fb9c01c920 100755
--- a/drape_frontend/frontend_renderer.cpp
+++ b/drape_frontend/frontend_renderer.cpp
@@ -6,6 +6,7 @@
#include "drape_frontend/gui/drape_gui.hpp"
#include "drape_frontend/gui/ruler_helper.hpp"
#include "drape_frontend/message_subclasses.hpp"
+#include "drape_frontend/postprocess_renderer.hpp"
#include "drape_frontend/scenario_manager.hpp"
#include "drape_frontend/screen_operations.hpp"
#include "drape_frontend/screen_quad_renderer.hpp"
@@ -31,10 +32,9 @@
#include "base/logging.hpp"
#include "base/stl_add.hpp"
-#include "std/algorithm.hpp"
-#include "std/bind.hpp"
-#include "std/cmath.hpp"
-#include "std/chrono.hpp"
+#include <algorithm>
+#include <cmath>
+#include <chrono>
namespace df
{
@@ -62,7 +62,7 @@ struct MergedGroupKey
};
template <typename ToDo>
-bool RemoveGroups(ToDo & filter, vector<drape_ptr<RenderGroup>> & groups,
+bool RemoveGroups(ToDo & filter, std::vector<drape_ptr<RenderGroup>> & groups,
ref_ptr<dp::OverlayTree> tree)
{
size_t startCount = groups.size();
@@ -90,9 +90,9 @@ bool RemoveGroups(ToDo & filter, vector<drape_ptr<RenderGroup>> & groups,
struct RemoveTilePredicate
{
mutable bool m_deletionMark = false;
- function<bool(drape_ptr<RenderGroup> const &)> const & m_predicate;
+ std::function<bool(drape_ptr<RenderGroup> const &)> const & m_predicate;
- RemoveTilePredicate(function<bool(drape_ptr<RenderGroup> const &)> const & predicate)
+ RemoveTilePredicate(std::function<bool(drape_ptr<RenderGroup> const &)> const & predicate)
: m_predicate(predicate)
{}
@@ -108,7 +108,6 @@ struct RemoveTilePredicate
return false;
}
};
-
} // namespace
FrontendRenderer::FrontendRenderer(Params && params)
@@ -116,10 +115,8 @@ FrontendRenderer::FrontendRenderer(Params && params)
, m_gpuProgramManager(new dp::GpuProgramManager())
, m_routeRenderer(new RouteRenderer())
, m_trafficRenderer(new TrafficRenderer())
- , m_framebuffer(new dp::Framebuffer())
- , m_screenQuadRenderer(new ScreenQuadRenderer())
, m_gpsTrackRenderer(
- new GpsTrackRenderer(bind(&FrontendRenderer::PrepareGpsTrackPoints, this, _1)))
+ new GpsTrackRenderer(std::bind(&FrontendRenderer::PrepareGpsTrackPoints, this, _1)))
, m_drapeApiRenderer(new DrapeApiRenderer())
, m_overlayTree(new dp::OverlayTree())
, m_enablePerspectiveInNavigation(false)
@@ -136,8 +133,9 @@ FrontendRenderer::FrontendRenderer(Params && params)
, m_needRestoreSize(false)
, m_trafficEnabled(params.m_trafficEnabled)
, m_overlaysTracker(new OverlaysTracker())
- , m_overlaysShowStatsCallback(move(params.m_overlaysShowStatsCallback))
+ , m_overlaysShowStatsCallback(std::move(params.m_overlaysShowStatsCallback))
, m_forceUpdateScene(false)
+ , m_postprocessRenderer(new PostprocessRenderer())
#ifdef SCENARIO_ENABLE
, m_scenarioManager(new ScenarioManager(this))
#endif
@@ -149,7 +147,11 @@ FrontendRenderer::FrontendRenderer(Params && params)
ASSERT(m_tapEventInfoFn, ());
ASSERT(m_userPositionChangedFn, ());
- m_myPositionController.reset(new MyPositionController(move(params.m_myPositionParams)));
+ m_myPositionController.reset(new MyPositionController(std::move(params.m_myPositionParams)));
+
+ for (auto const & effect : params.m_enabledEffects)
+ m_postprocessRenderer->SetEffectEnabled(effect, true /* enabled */);
+
StartThread();
}
@@ -171,7 +173,7 @@ void FrontendRenderer::UpdateCanBeDeletedStatus()
{
m2::RectD const & screenRect = m_userEventStream.GetCurrentScreen().ClipRect();
- vector<m2::RectD> notFinishedTileRects;
+ std::vector<m2::RectD> notFinishedTileRects;
notFinishedTileRects.reserve(m_notFinishedTiles.size());
for (auto const & tileKey : m_notFinishedTiles)
notFinishedTileRects.push_back(tileKey.GetGlobalRect());
@@ -180,26 +182,18 @@ void FrontendRenderer::UpdateCanBeDeletedStatus()
{
for (auto & group : layer.m_renderGroups)
{
- if (group->IsPendingOnDelete())
+ if (!group->IsPendingOnDelete())
+ continue;
+
+ bool canBeDeleted = true;
+ if (!notFinishedTileRects.empty())
{
- bool canBeDeleted = true;
- if (!notFinishedTileRects.empty())
- {
- m2::RectD const tileRect = group->GetTileKey().GetGlobalRect();
- if (tileRect.IsIntersect(screenRect))
- {
- for (auto const & notFinishedRect : notFinishedTileRects)
- {
- if (notFinishedRect.IsIntersect(tileRect))
- {
- canBeDeleted = false;
- break;
- }
- }
- }
- }
- layer.m_isDirty |= group->UpdateCanBeDeletedStatus(canBeDeleted, m_currentZoomLevel, make_ref(m_overlayTree));
+ m2::RectD const tileRect = group->GetTileKey().GetGlobalRect();
+ if (tileRect.IsIntersect(screenRect))
+ canBeDeleted = !HasIntersection(tileRect, notFinishedTileRects);
}
+ layer.m_isDirty |= group->UpdateCanBeDeletedStatus(canBeDeleted, m_currentZoomLevel,
+ make_ref(m_overlayTree));
}
}
}
@@ -217,7 +211,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
if (key.m_zoomLevel == m_currentZoomLevel && CheckTileGenerations(key))
{
PrepareBucket(state, bucket);
- AddToRenderGroup(state, move(bucket), key);
+ AddToRenderGroup(state, std::move(bucket), key);
}
break;
}
@@ -232,7 +226,8 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
CheckTileGenerations(overlayRenderData.m_tileKey))
{
PrepareBucket(overlayRenderData.m_state, overlayRenderData.m_bucket);
- AddToRenderGroup(overlayRenderData.m_state, move(overlayRenderData.m_bucket), overlayRenderData.m_tileKey);
+ AddToRenderGroup(overlayRenderData.m_state, std::move(overlayRenderData.m_bucket),
+ overlayRenderData.m_tileKey);
}
}
UpdateCanBeDeletedStatus();
@@ -285,8 +280,8 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
auto program = m_gpuProgramManager->GetProgram(shape.m_state.GetProgramIndex());
auto program3d = m_gpuProgramManager->GetProgram(shape.m_state.GetProgram3dIndex());
auto group = make_unique_dp<UserMarkRenderGroup>(layerId, shape.m_state, shape.m_tileKey,
- move(shape.m_bucket));
- m_userMarkRenderGroups.push_back(move(group));
+ std::move(shape.m_bucket));
+ m_userMarkRenderGroups.push_back(std::move(group));
m_userMarkRenderGroups.back()->SetRenderParams(program, program3d, make_ref(&m_generalUniforms));
}
break;
@@ -301,9 +296,9 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
return g->GetLayerId() == layerId;
};
- auto const iter = remove_if(m_userMarkRenderGroups.begin(),
- m_userMarkRenderGroups.end(),
- functor);
+ auto const iter = std::remove_if(m_userMarkRenderGroups.begin(),
+ m_userMarkRenderGroups.end(),
+ functor);
m_userMarkRenderGroups.erase(iter, m_userMarkRenderGroups.end());
break;
}
@@ -321,12 +316,12 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
case Message::GuiLayerRecached:
{
ref_ptr<GuiLayerRecachedMessage> msg = message;
- drape_ptr<gui::LayerRenderer> renderer = move(msg->AcceptRenderer());
+ drape_ptr<gui::LayerRenderer> renderer = std::move(msg->AcceptRenderer());
renderer->Build(make_ref(m_gpuProgramManager));
if (msg->NeedResetOldGui())
m_guiRenderer.release();
if (m_guiRenderer == nullptr)
- m_guiRenderer = move(renderer);
+ m_guiRenderer = std::move(renderer);
else
m_guiRenderer->Merge(make_ref(renderer));
@@ -410,7 +405,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
m_routeRenderer->UpdateDistanceFromBegin(info.GetDistanceFromBegin());
// Here we have to recache route arrows.
m_routeRenderer->UpdateRoute(m_userEventStream.GetCurrentScreen(),
- bind(&FrontendRenderer::OnCacheRouteArrows, this, _1, _2));
+ std::bind(&FrontendRenderer::OnCacheRouteArrows, this, _1, _2));
}
break;
@@ -467,10 +462,10 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
m2::PointD const finishPoint = routeData->m_sourcePolyline.Back();
- m_routeRenderer->SetRouteData(move(routeData), make_ref(m_gpuProgramManager));
+ m_routeRenderer->SetRouteData(std::move(routeData), make_ref(m_gpuProgramManager));
// Here we have to recache route arrows.
m_routeRenderer->UpdateRoute(m_userEventStream.GetCurrentScreen(),
- bind(&FrontendRenderer::OnCacheRouteArrows, this, _1, _2));
+ std::bind(&FrontendRenderer::OnCacheRouteArrows, this, _1, _2));
if (!m_routeRenderer->GetFinishPoint())
{
@@ -497,7 +492,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
if (routeSignData->m_recacheId > 0 && routeSignData->m_recacheId < m_lastRecacheRouteId)
break;
- m_routeRenderer->SetRouteSign(move(routeSignData), make_ref(m_gpuProgramManager));
+ m_routeRenderer->SetRouteSign(std::move(routeSignData), make_ref(m_gpuProgramManager));
break;
}
@@ -509,7 +504,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
if (routeArrowsData->m_recacheId > 0 && routeArrowsData->m_recacheId < m_lastRecacheRouteId)
break;
- m_routeRenderer->SetRouteArrows(move(routeArrowsData), make_ref(m_gpuProgramManager));
+ m_routeRenderer->SetRouteArrows(std::move(routeArrowsData), make_ref(m_gpuProgramManager));
break;
}
@@ -536,8 +531,9 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
// receive FollowRoute message before FlushRoute message, so we need to postpone its processing.
if (m_routeRenderer->GetRouteData() == nullptr)
{
- m_pendingFollowRoute.reset(new FollowRouteData(msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d(),
- msg->EnableAutoZoom()));
+ m_pendingFollowRoute = my::make_unique<FollowRouteData>(msg->GetPreferredZoomLevel(),
+ msg->GetPreferredZoomLevelIn3d(),
+ msg->EnableAutoZoom());
break;
}
@@ -578,11 +574,11 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
blocker.Wait();
}
- // Invalidate textures and wait for completion.
+ // Notify backend renderer and wait for completion.
{
BaseBlockingMessage::Blocker blocker;
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
- make_unique_dp<InvalidateTexturesMessage>(blocker),
+ make_unique_dp<SwitchMapStyleMessage>(blocker),
MessagePriority::High);
blocker.Wait();
}
@@ -784,6 +780,20 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
}
+ case Message::SetPostprocessStaticTextures:
+ {
+ ref_ptr<SetPostprocessStaticTexturesMessage> msg = message;
+ m_postprocessRenderer->SetStaticTextures(msg->AcceptTextures());
+ break;
+ }
+
+ case Message::SetPosteffectEnabled:
+ {
+ ref_ptr<SetPosteffectEnabledMessage> msg = message;
+ m_postprocessRenderer->SetEffectEnabled(msg->GetEffect(), msg->IsEnabled());
+ break;
+ }
+
default:
ASSERT(false, ());
}
@@ -824,7 +834,7 @@ void FrontendRenderer::UpdateGLResources()
routeData->m_color, routeData->m_traffic,
routeData->m_pattern, m_lastRecacheRouteId);
m_routeRenderer->ClearGLDependentResources();
- m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, move(recacheRouteMsg),
+ m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, std::move(recacheRouteMsg),
MessagePriority::Normal);
}
@@ -833,7 +843,8 @@ void FrontendRenderer::UpdateGLResources()
// Request new tiles.
ScreenBase screen = m_userEventStream.GetCurrentScreen();
m_lastReadedModelView = screen;
- m_requestedTiles->Set(screen, m_isIsometry || screen.isPerspective(), m_forceUpdateScene, ResolveTileKeys(screen));
+ m_requestedTiles->Set(screen, m_isIsometry || screen.isPerspective(),
+ m_forceUpdateScene, ResolveTileKeys(screen));
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<UpdateReadManagerMessage>(),
MessagePriority::UberHighSingleton);
@@ -841,10 +852,12 @@ void FrontendRenderer::UpdateGLResources()
m_gpsTrackRenderer->Update();
}
-void FrontendRenderer::FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d, bool enableAutoZoom)
+void FrontendRenderer::FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d,
+ bool enableAutoZoom)
{
- m_myPositionController->ActivateRouting(!m_enablePerspectiveInNavigation ? preferredZoomLevel : preferredZoomLevelIn3d,
- enableAutoZoom);
+ m_myPositionController->ActivateRouting(
+ !m_enablePerspectiveInNavigation ? preferredZoomLevel : preferredZoomLevelIn3d,
+ enableAutoZoom);
if (m_enablePerspectiveInNavigation)
AddUserEvent(make_unique_dp<SetAutoPerspectiveEvent>(true /* isAutoPerspective */));
@@ -904,16 +917,20 @@ void FrontendRenderer::OnResize(ScreenBase const & screen)
m_myPositionController->OnUpdateScreen(screen);
+ uint32_t const sx = static_cast<uint32_t>(viewportRect.SizeX());
+ uint32_t const sy = static_cast<uint32_t>(viewportRect.SizeY());
+
if (viewportChanged)
{
m_myPositionController->UpdatePosition();
- m_viewport.SetViewport(0, 0, viewportRect.SizeX(), viewportRect.SizeY());
+ m_viewport.SetViewport(0, 0, sx, sy);
}
if (viewportChanged || m_needRestoreSize)
{
- m_contextFactory->getDrawContext()->resize(viewportRect.SizeX(), viewportRect.SizeY());
- m_framebuffer->SetSize(viewportRect.SizeX(), viewportRect.SizeY());
+ m_contextFactory->getDrawContext()->resize(sx, sy);
+ m_buildingsFramebuffer->SetSize(sx, sy);
+ m_postprocessRenderer->Resize(sx, sy);
m_needRestoreSize = false;
}
@@ -932,7 +949,7 @@ void FrontendRenderer::AddToRenderGroup(dp::GLState const & state,
{
if (!g->IsPendingOnDelete() && g->GetState() == state && g->GetTileKey().EqualStrict(newTile))
{
- g->AddBucket(move(renderBucket));
+ g->AddBucket(std::move(renderBucket));
layer.m_isDirty = true;
return;
}
@@ -942,7 +959,7 @@ void FrontendRenderer::AddToRenderGroup(dp::GLState const & state,
ref_ptr<dp::GpuProgram> program = m_gpuProgramManager->GetProgram(state.GetProgramIndex());
ref_ptr<dp::GpuProgram> program3d = m_gpuProgramManager->GetProgram(state.GetProgram3dIndex());
group->SetRenderParams(program, program3d, make_ref(&m_generalUniforms));
- group->AddBucket(move(renderBucket));
+ group->AddBucket(std::move(renderBucket));
layer.m_renderGroups.push_back(move(group));
layer.m_isDirty = true;
@@ -1102,14 +1119,16 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
DrapeMeasurer::Instance().BeforeRenderFrame();
#endif
+ m_postprocessRenderer->BeginFrame();
+
GLFunctions::glEnable(gl_const::GLDepthTest);
m_viewport.Apply();
RefreshBgColor();
- GLFunctions::glClear();
+ GLFunctions::glClear(gl_const::GLColorBit | gl_const::GLDepthBit | gl_const::GLStencilBit);
Render2dLayer(modelView);
- if (m_framebuffer->IsSupported())
+ if (m_buildingsFramebuffer->IsSupported())
{
RenderTrafficAndRouteLayer(modelView);
Render3dLayer(modelView, true /* useFramebuffer */);
@@ -1122,7 +1141,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
// After this line we do not use (almost) depth buffer.
GLFunctions::glDisable(gl_const::GLDepthTest);
- GLFunctions::glClearDepth();
+ GLFunctions::glClear(gl_const::GLDepthBit);
if (m_selectionShape != nullptr)
{
@@ -1131,38 +1150,56 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
{
ASSERT(m_myPositionController->IsModeHasPosition(), ());
m_selectionShape->SetPosition(m_myPositionController->Position());
- m_selectionShape->Render(modelView, m_currentZoomLevel,
- make_ref(m_gpuProgramManager), m_generalUniforms);
+ m_selectionShape->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager),
+ m_generalUniforms);
}
else if (selectedObject == SelectionShape::OBJECT_POI)
{
- m_selectionShape->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), m_generalUniforms);
+ m_selectionShape->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager),
+ m_generalUniforms);
}
}
- RenderOverlayLayer(modelView);
-
- m_gpsTrackRenderer->RenderTrack(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), m_generalUniforms);
+ {
+ StencilWriterGuard guard(make_ref(m_postprocessRenderer));
+ RenderOverlayLayer(modelView);
+ }
- if (m_selectionShape != nullptr && m_selectionShape->GetSelectedObject() == SelectionShape::OBJECT_USER_MARK)
- m_selectionShape->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), m_generalUniforms);
+ m_gpsTrackRenderer->RenderTrack(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager),
+ m_generalUniforms);
- RenderUserMarksLayer(modelView);
+ if (m_selectionShape != nullptr &&
+ m_selectionShape->GetSelectedObject() == SelectionShape::OBJECT_USER_MARK)
+ {
+ m_selectionShape->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager),
+ m_generalUniforms);
+ }
- m_routeRenderer->RenderRouteSigns(modelView, make_ref(m_gpuProgramManager), m_generalUniforms);
+ {
+ StencilWriterGuard guard(make_ref(m_postprocessRenderer));
+ RenderUserMarksLayer(modelView);
+ m_routeRenderer->RenderRouteSigns(modelView, make_ref(m_gpuProgramManager), m_generalUniforms);
+ }
- m_myPositionController->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), m_generalUniforms);
+ m_myPositionController->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager),
+ m_generalUniforms);
m_drapeApiRenderer->Render(modelView, make_ref(m_gpuProgramManager), m_generalUniforms);
if (m_guiRenderer != nullptr)
- m_guiRenderer->Render(make_ref(m_gpuProgramManager), m_myPositionController->IsInRouting(), modelView);
+ {
+ StencilWriterGuard guard(make_ref(m_postprocessRenderer));
+ m_guiRenderer->Render(make_ref(m_gpuProgramManager), m_myPositionController->IsInRouting(),
+ modelView);
+ }
#if defined(RENDER_DEBUG_RECTS) && defined(COLLECT_DISPLACEMENT_INFO)
for (auto const & arrow : m_overlayTree->GetDisplacementInfo())
dp::DebugRectRenderer::Instance().DrawArrow(modelView, arrow);
#endif
+ m_postprocessRenderer->EndFrame(make_ref(m_gpuProgramManager));
+
#if defined(DRAPE_MEASURER) && (defined(RENDER_STATISTIC) || defined(TRACK_GPU_MEM))
DrapeMeasurer::Instance().AfterRenderFrame();
#endif
@@ -1184,13 +1221,13 @@ void FrontendRenderer::Render3dLayer(ScreenBase const & modelView, bool useFrame
float const kOpacity = 0.7f;
if (useFramebuffer)
{
- ASSERT(m_framebuffer->IsSupported(), ());
- m_framebuffer->Enable();
+ ASSERT(m_buildingsFramebuffer->IsSupported(), ());
+ m_buildingsFramebuffer->Enable();
GLFunctions::glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- GLFunctions::glClear();
+ GLFunctions::glClear(gl_const::GLColorBit);
}
- GLFunctions::glClearDepth();
+ GLFunctions::glClear(gl_const::GLDepthBit);
GLFunctions::glEnable(gl_const::GLDepthTest);
RenderLayer & layer = m_layers[RenderLayer::Geometry3dID];
layer.Sort(make_ref(m_overlayTree));
@@ -1199,10 +1236,10 @@ void FrontendRenderer::Render3dLayer(ScreenBase const & modelView, bool useFrame
if (useFramebuffer)
{
- m_framebuffer->Disable();
- GLFunctions::glDisable(gl_const::GLDepthTest);
- m_screenQuadRenderer->RenderTexture(m_framebuffer->GetTextureId(),
- make_ref(m_gpuProgramManager), kOpacity);
+ m_buildingsFramebuffer->Disable();
+ m_screenQuadRenderer->RenderTexture(make_ref(m_gpuProgramManager),
+ m_buildingsFramebuffer->GetTextureId(),
+ kOpacity);
}
}
@@ -1216,14 +1253,14 @@ void FrontendRenderer::RenderOverlayLayer(ScreenBase const & modelView)
void FrontendRenderer::RenderTrafficAndRouteLayer(ScreenBase const & modelView)
{
- GLFunctions::glClearDepth();
+ GLFunctions::glClear(gl_const::GLDepthBit);
GLFunctions::glEnable(gl_const::GLDepthTest);
if (m_trafficRenderer->HasRenderData())
{
m_trafficRenderer->RenderTraffic(modelView, m_currentZoomLevel, 1.0f /* opacity */,
make_ref(m_gpuProgramManager), m_generalUniforms);
}
- GLFunctions::glClearDepth();
+ GLFunctions::glClear(gl_const::GLDepthBit);
m_routeRenderer->RenderRoute(modelView, m_trafficRenderer->HasRenderData(),
make_ref(m_gpuProgramManager), m_generalUniforms);
}
@@ -1282,10 +1319,10 @@ void FrontendRenderer::MergeBuckets()
if (layer.m_renderGroups.empty())
return;
- using TGroupMap = map<MergedGroupKey, vector<drape_ptr<RenderGroup>>>;
+ using TGroupMap = map<MergedGroupKey, std::vector<drape_ptr<RenderGroup>>>;
TGroupMap forMerge;
- vector<drape_ptr<RenderGroup>> newGroups;
+ std::vector<drape_ptr<RenderGroup>> newGroups;
newGroups.reserve(layer.m_renderGroups.size());
size_t groupsCount = layer.m_renderGroups.size();
@@ -1296,23 +1333,24 @@ void FrontendRenderer::MergeBuckets()
{
dp::GLState state = group->GetState();
ASSERT_EQUAL(state.GetDepthLayer(), dp::GLState::GeometryLayer, ());
- forMerge[MergedGroupKey(state, group->GetTileKey())].push_back(move(layer.m_renderGroups[i]));
+ MergedGroupKey const k(state, group->GetTileKey());
+ forMerge[k].push_back(std::move(layer.m_renderGroups[i]));
}
else
{
- newGroups.push_back(move(layer.m_renderGroups[i]));
+ newGroups.push_back(std::move(layer.m_renderGroups[i]));
}
}
for (TGroupMap::value_type & node : forMerge)
{
if (node.second.size() < 2)
- newGroups.emplace_back(move(node.second.front()));
+ newGroups.emplace_back(std::move(node.second.front()));
else
BatchMergeHelper::MergeBatches(node.second, newGroups, isPerspective);
}
- layer.m_renderGroups = move(newGroups);
+ layer.m_renderGroups = std::move(newGroups);
layer.m_isDirty = true;
};
@@ -1321,11 +1359,6 @@ void FrontendRenderer::MergeBuckets()
mergeFn(m_layers[RenderLayer::Geometry3dID], isPerspective);
}
-bool FrontendRenderer::IsPerspective() const
-{
- return m_userEventStream.GetCurrentScreen().isPerspective();
-}
-
void FrontendRenderer::RenderSingleGroup(ScreenBase const & modelView, ref_ptr<BaseRenderGroup> group)
{
group->UpdateAnimation();
@@ -1334,15 +1367,14 @@ void FrontendRenderer::RenderSingleGroup(ScreenBase const & modelView, ref_ptr<B
void FrontendRenderer::RefreshProjection(ScreenBase const & screen)
{
- array<float, 16> m;
-
+ std::array<float, 16> m;
dp::MakeProjection(m, 0.0f, screen.GetWidth(), screen.GetHeight(), 0.0f);
m_generalUniforms.SetMatrix4x4Value("projection", m.data());
}
void FrontendRenderer::RefreshZScale(ScreenBase const & screen)
{
- m_generalUniforms.SetFloatValue("zScale", screen.GetZScale());
+ m_generalUniforms.SetFloatValue("zScale", static_cast<float>(screen.GetZScale()));
}
void FrontendRenderer::RefreshPivotTransform(ScreenBase const & screen)
@@ -1355,7 +1387,7 @@ void FrontendRenderer::RefreshPivotTransform(ScreenBase const & screen)
else if (m_isIsometry)
{
math::Matrix<float, 4, 4> transform(math::Identity<float, 4>());
- transform(2, 1) = -1.0f / tan(kIsometryAngle);
+ transform(2, 1) = -1.0f / static_cast<float>(tan(kIsometryAngle));
transform(2, 2) = 1.0f / screen.GetHeight();
m_generalUniforms.SetMatrix4x4Value("pivotTransform", transform.m_data);
}
@@ -1449,7 +1481,7 @@ void FrontendRenderer::OnTwoFingersTap()
bool FrontendRenderer::OnSingleTouchFiltrate(m2::PointD const & pt, TouchEvent::ETouchType type)
{
- // This method can be called before gui rendererer initialization.
+ // This method can be called before gui renderer initialization.
if (m_guiRenderer == nullptr)
return false;
@@ -1526,11 +1558,12 @@ void FrontendRenderer::OnTouchMapAction()
{
m_myPositionController->ResetRoutingNotFollowTimer();
}
-
-bool FrontendRenderer::OnNewVisibleViewport(m2::RectD const & oldViewport, m2::RectD const & newViewport, m2::PointD & gOffset)
+bool FrontendRenderer::OnNewVisibleViewport(m2::RectD const & oldViewport,
+ m2::RectD const & newViewport, m2::PointD & gOffset)
{
gOffset = m2::PointD(0, 0);
- if (m_myPositionController->IsModeChangeViewport() || m_selectionShape == nullptr || oldViewport == newViewport)
+ if (m_myPositionController->IsModeChangeViewport() || m_selectionShape == nullptr ||
+ oldViewport == newViewport)
return false;
ScreenBase const & screen = m_userEventStream.GetCurrentScreen();
@@ -1611,7 +1644,7 @@ TTilesCollection FrontendRenderer::ResolveTileKeys(ScreenBase const & screen)
return group->GetTileKey().m_zoomLevel == m_currentZoomLevel &&
(key.m_x < result.m_minTileX || key.m_x >= result.m_maxTileX ||
key.m_y < result.m_minTileY || key.m_y >= result.m_maxTileY ||
- find(tilesToDelete.begin(), tilesToDelete.end(), key) != tilesToDelete.end());
+ std::find(tilesToDelete.begin(), tilesToDelete.end(), key) != tilesToDelete.end());
};
for (RenderLayer & layer : m_layers)
layer.m_isDirty |= RemoveGroups(removePredicate, layer.m_renderGroups, make_ref(m_overlayTree));
@@ -1647,7 +1680,7 @@ void FrontendRenderer::OnContextDestroy()
m_userMarkRenderGroups.clear();
m_guiRenderer.reset();
m_selectionShape.reset();
- m_framebuffer.reset();
+ m_buildingsFramebuffer.reset();
m_screenQuadRenderer.reset();
m_myPositionController->ResetRenderShape();
@@ -1655,6 +1688,7 @@ void FrontendRenderer::OnContextDestroy()
m_gpsTrackRenderer->ClearRenderData();
m_trafficRenderer->ClearGLDependentResources();
m_drapeApiRenderer->Clear();
+ m_postprocessRenderer->ClearGLDependentResources();
#ifdef RENDER_DEBUG_RECTS
dp::DebugRectRenderer::Instance().Destroy();
@@ -1700,11 +1734,19 @@ void FrontendRenderer::OnContextCreate()
dp::DebugRectRenderer::Instance().Init(make_ref(m_gpuProgramManager), gpu::DEBUG_RECT_PROGRAM);
#endif
- // resources recovering
- m_framebuffer.reset(new dp::Framebuffer());
- m_framebuffer->SetDefaultContext(context);
-
+ // Resources recovering.
m_screenQuadRenderer.reset(new ScreenQuadRenderer());
+
+ m_postprocessRenderer->Init([context]() { context->setDefaultFramebuffer(); });
+ m_postprocessRenderer->SetEnabled(m_apiVersion == dp::ApiVersion::OpenGLES3);
+ if (dp::SupportManager::Instance().IsAntialiasingEnabledByDefault())
+ m_postprocessRenderer->SetEffectEnabled(PostprocessRenderer::Antialiasing, true);
+
+ m_buildingsFramebuffer.reset(new dp::Framebuffer(gl_const::GLRGBA, false /* stencilEnabled */));
+ m_buildingsFramebuffer->SetFramebufferFallback([this]()
+ {
+ m_postprocessRenderer->OnFramebufferFallback();
+ });
}
FrontendRenderer::Routine::Routine(FrontendRenderer & renderer) : m_renderer(renderer) {}
@@ -1713,7 +1755,7 @@ void FrontendRenderer::Routine::Do()
{
LOG(LINFO, ("Start routine."));
- gui::DrapeGui::Instance().ConnectOnCompassTappedHandler(bind(&FrontendRenderer::OnCompassTapped, &m_renderer));
+ gui::DrapeGui::Instance().ConnectOnCompassTappedHandler(std::bind(&FrontendRenderer::OnCompassTapped, &m_renderer));
m_renderer.m_myPositionController->SetListener(ref_ptr<MyPositionController::Listener>(&m_renderer));
m_renderer.m_userEventStream.SetListener(ref_ptr<UserEventStream::Listener>(&m_renderer));
@@ -1738,8 +1780,6 @@ void FrontendRenderer::Routine::Do()
if (viewportChanged)
m_renderer.OnResize(modelView);
- context->setDefaultFramebuffer();
-
if (modelViewChanged || viewportChanged)
m_renderer.PrepareScene(modelView);
@@ -1783,7 +1823,7 @@ void FrontendRenderer::Routine::Do()
activityTimer.Reset();
availableTime = kVSyncInterval - timer.ElapsedSeconds();
}
- while (availableTime > 0);
+ while (availableTime > 0.0);
}
context->present();
@@ -1796,7 +1836,7 @@ void FrontendRenderer::Routine::Do()
m_renderer.m_myPositionController->IsRouteFollowingActive() && frameTime < kFrameTime)
{
uint32_t const ms = static_cast<uint32_t>((kFrameTime - frameTime) * 1000);
- this_thread::sleep_for(milliseconds(ms));
+ this_thread::sleep_for(std::chrono::milliseconds(ms));
}
if (m_renderer.m_overlaysTracker->IsValid() &&
@@ -1828,9 +1868,10 @@ void FrontendRenderer::ReleaseResources()
m_myPositionController.reset();
m_selectionShape.release();
m_routeRenderer.reset();
- m_framebuffer.reset();
+ m_buildingsFramebuffer.reset();
m_screenQuadRenderer.reset();
m_trafficRenderer.reset();
+ m_postprocessRenderer.reset();
m_gpuProgramManager.reset();
m_contextFactory->getDrawContext()->doneCurrent();
@@ -1842,7 +1883,7 @@ void FrontendRenderer::AddUserEvent(drape_ptr<UserEvent> && event)
if (m_scenarioManager->IsRunning() && event->GetType() == UserEvent::EventType::Touch)
return;
#endif
- m_userEventStream.AddEvent(move(event));
+ m_userEventStream.AddEvent(std::move(event));
if (IsInInfinityWaiting())
CancelMessageWaiting();
}
@@ -1852,17 +1893,20 @@ void FrontendRenderer::PositionChanged(m2::PointD const & position)
m_userPositionChangedFn(position);
}
-void FrontendRenderer::ChangeModelView(m2::PointD const & center, int zoomLevel, TAnimationCreator const & parallelAnimCreator)
+void FrontendRenderer::ChangeModelView(m2::PointD const & center, int zoomLevel,
+ TAnimationCreator const & parallelAnimCreator)
{
AddUserEvent(make_unique_dp<SetCenterEvent>(center, zoomLevel, true, parallelAnimCreator));
}
-void FrontendRenderer::ChangeModelView(double azimuth, TAnimationCreator const & parallelAnimCreator)
+void FrontendRenderer::ChangeModelView(double azimuth,
+ TAnimationCreator const & parallelAnimCreator)
{
AddUserEvent(make_unique_dp<RotateEvent>(azimuth, parallelAnimCreator));
}
-void FrontendRenderer::ChangeModelView(m2::RectD const & rect, TAnimationCreator const & parallelAnimCreator)
+void FrontendRenderer::ChangeModelView(m2::RectD const & rect,
+ TAnimationCreator const & parallelAnimCreator)
{
AddUserEvent(make_unique_dp<SetRectEvent>(rect, true, kDoNotChangeZoom, true, parallelAnimCreator));
}
@@ -1871,13 +1915,16 @@ void FrontendRenderer::ChangeModelView(m2::PointD const & userPos, double azimut
m2::PointD const & pxZero, int preferredZoomLevel,
TAnimationCreator const & parallelAnimCreator)
{
- AddUserEvent(make_unique_dp<FollowAndRotateEvent>(userPos, pxZero, azimuth, preferredZoomLevel, true, parallelAnimCreator));
+ AddUserEvent(make_unique_dp<FollowAndRotateEvent>(userPos, pxZero, azimuth, preferredZoomLevel,
+ true, parallelAnimCreator));
}
-void FrontendRenderer::ChangeModelView(double autoScale, m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero,
+void FrontendRenderer::ChangeModelView(double autoScale, m2::PointD const & userPos, double azimuth,
+ m2::PointD const & pxZero,
TAnimationCreator const & parallelAnimCreator)
{
- AddUserEvent(make_unique_dp<FollowAndRotateEvent>(userPos, pxZero, azimuth, autoScale, parallelAnimCreator));
+ AddUserEvent(make_unique_dp<FollowAndRotateEvent>(userPos, pxZero, azimuth, autoScale,
+ parallelAnimCreator));
}
ScreenBase const & FrontendRenderer::ProcessEvents(bool & modelViewChanged, bool & viewportChanged)
@@ -1894,7 +1941,7 @@ void FrontendRenderer::PrepareScene(ScreenBase const & modelView)
RefreshPivotTransform(modelView);
m_myPositionController->OnUpdateScreen(modelView);
- m_routeRenderer->UpdateRoute(modelView, bind(&FrontendRenderer::OnCacheRouteArrows, this, _1, _2));
+ m_routeRenderer->UpdateRoute(modelView, std::bind(&FrontendRenderer::OnCacheRouteArrows, this, _1, _2));
}
void FrontendRenderer::UpdateScene(ScreenBase const & modelView)
@@ -1931,7 +1978,7 @@ void FrontendRenderer::EmitModelViewChanged(ScreenBase const & modelView) const
m_modelViewChangedFn(modelView);
}
-void FrontendRenderer::OnCacheRouteArrows(int routeIndex, vector<ArrowBorders> const & borders)
+void FrontendRenderer::OnCacheRouteArrows(int routeIndex, std::vector<ArrowBorders> const & borders)
{
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<CacheRouteArrowsMessage>(routeIndex, borders),
@@ -1954,7 +2001,8 @@ FrontendRenderer::RenderLayer::RenderLayerID FrontendRenderer::RenderLayer::GetL
if (state.GetDepthLayer() == dp::GLState::OverlayLayer)
return OverlayID;
- if (state.GetProgram3dIndex() == gpu::AREA_3D_PROGRAM || state.GetProgram3dIndex() == gpu::AREA_3D_OUTLINE_PROGRAM)
+ if (state.GetProgram3dIndex() == gpu::AREA_3D_PROGRAM ||
+ state.GetProgram3dIndex() == gpu::AREA_3D_OUTLINE_PROGRAM)
return Geometry3dID;
return Geometry2dID;
diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp
index 3fa2cebb33..309e7e6acc 100755
--- a/drape_frontend/frontend_renderer.hpp
+++ b/drape_frontend/frontend_renderer.hpp
@@ -14,27 +14,28 @@
#include "drape_frontend/render_group.hpp"
#include "drape_frontend/requested_tiles.hpp"
#include "drape_frontend/route_renderer.hpp"
+#include "drape_frontend/postprocess_renderer.hpp"
#include "drape_frontend/threads_commutator.hpp"
#include "drape_frontend/tile_info.hpp"
#include "drape_frontend/traffic_renderer.hpp"
#include "drape_frontend/user_event_stream.hpp"
-#include "drape/pointers.hpp"
#include "drape/glstate.hpp"
-#include "drape/vertex_array_buffer.hpp"
#include "drape/gpu_program_manager.hpp"
#include "drape/overlay_tree.hpp"
+#include "drape/pointers.hpp"
#include "drape/uniform_values_storage.hpp"
+#include "drape/vertex_array_buffer.hpp"
#include "platform/location.hpp"
#include "geometry/screenbase.hpp"
#include "geometry/triangle2d.hpp"
-#include "std/function.hpp"
-#include "std/map.hpp"
-#include "std/array.hpp"
-#include "std/unordered_set.hpp"
+#include <array>
+#include <functional>
+#include <unordered_set>
+#include <vector>
namespace dp
{
@@ -58,42 +59,37 @@ struct TapInfo
FeatureID const m_featureTapped;
};
-class FrontendRenderer : public BaseRenderer
- , public MyPositionController::Listener
- , public UserEventStream::Listener
+class FrontendRenderer : public BaseRenderer,
+ public MyPositionController::Listener,
+ public UserEventStream::Listener
{
public:
- using TModelViewChanged = function<void (ScreenBase const & screen)>;
- using TTapEventInfoFn = function<void (TapInfo const &)>;
- using TUserPositionChangedFn = function<void (m2::PointD const & pt)>;
+ using TModelViewChanged = std::function<void(ScreenBase const & screen)>;
+ using TTapEventInfoFn = std::function<void(TapInfo const &)>;
+ using TUserPositionChangedFn = std::function<void(m2::PointD const & pt)>;
struct Params : BaseRenderer::Params
{
- Params(dp::ApiVersion apiVersion,
- ref_ptr<ThreadsCommutator> commutator,
- ref_ptr<dp::OGLContextFactory> factory,
- ref_ptr<dp::TextureManager> texMng,
- MyPositionController::Params && myPositionParams,
- dp::Viewport viewport,
- TModelViewChanged const & modelViewChangedFn,
- TTapEventInfoFn const & tapEventFn,
- TUserPositionChangedFn const & positionChangedFn,
- ref_ptr<RequestedTiles> requestedTiles,
+ Params(dp::ApiVersion apiVersion, ref_ptr<ThreadsCommutator> commutator,
+ ref_ptr<dp::OGLContextFactory> factory, ref_ptr<dp::TextureManager> texMng,
+ MyPositionController::Params && myPositionParams, dp::Viewport viewport,
+ TModelViewChanged const & modelViewChangedFn, TTapEventInfoFn const & tapEventFn,
+ TUserPositionChangedFn const & positionChangedFn, ref_ptr<RequestedTiles> requestedTiles,
OverlaysShowStatsCallback && overlaysShowStatsCallback,
- bool allow3dBuildings,
- bool trafficEnabled,
- bool blockTapEvents)
+ bool allow3dBuildings, bool trafficEnabled, bool blockTapEvents,
+ std::vector<PostprocessRenderer::Effect> && enabledEffects)
: BaseRenderer::Params(apiVersion, commutator, factory, texMng)
- , m_myPositionParams(move(myPositionParams))
+ , m_myPositionParams(std::move(myPositionParams))
, m_viewport(viewport)
, m_modelViewChangedFn(modelViewChangedFn)
, m_tapEventFn(tapEventFn)
, m_positionChangedFn(positionChangedFn)
, m_requestedTiles(requestedTiles)
- , m_overlaysShowStatsCallback(move(overlaysShowStatsCallback))
+ , m_overlaysShowStatsCallback(std::move(overlaysShowStatsCallback))
, m_allow3dBuildings(allow3dBuildings)
, m_trafficEnabled(trafficEnabled)
, m_blockTapEvents(blockTapEvents)
+ , m_enabledEffects(std::move(enabledEffects))
{}
MyPositionController::Params m_myPositionParams;
@@ -101,18 +97,12 @@ public:
TModelViewChanged m_modelViewChangedFn;
TTapEventInfoFn m_tapEventFn;
TUserPositionChangedFn m_positionChangedFn;
- location::TMyPositionModeChanged m_myPositionModeCallback;
- location::EMyPositionMode m_initMyPositionMode;
ref_ptr<RequestedTiles> m_requestedTiles;
OverlaysShowStatsCallback m_overlaysShowStatsCallback;
- double m_timeInBackground;
bool m_allow3dBuildings;
bool m_trafficEnabled;
bool m_blockTapEvents;
- bool m_firstLaunch;
- bool m_isLaunchByDeepLink;
- bool m_isRoutingActive;
- bool m_isAutozoomEnabled;
+ std::vector<PostprocessRenderer::Effect> m_enabledEffects;
};
FrontendRenderer(Params && params);
@@ -122,14 +112,18 @@ public:
void AddUserEvent(drape_ptr<UserEvent> && event);
- /// MyPositionController::Listener
+ // MyPositionController::Listener
void PositionChanged(m2::PointD const & position) override;
- void ChangeModelView(m2::PointD const & center, int zoomLevel, TAnimationCreator const & parallelAnimCreator) override;
+ void ChangeModelView(m2::PointD const & center, int zoomLevel,
+ TAnimationCreator const & parallelAnimCreator) override;
void ChangeModelView(double azimuth, TAnimationCreator const & parallelAnimCreator) override;
- void ChangeModelView(m2::RectD const & rect, TAnimationCreator const & parallelAnimCreator) override;
+ void ChangeModelView(m2::RectD const & rect,
+ TAnimationCreator const & parallelAnimCreator) override;
void ChangeModelView(m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero,
- int preferredZoomLevel, TAnimationCreator const & parallelAnimCreator) override;
- void ChangeModelView(double autoScale, m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero,
+ int preferredZoomLevel,
+ TAnimationCreator const & parallelAnimCreator) override;
+ void ChangeModelView(double autoScale, m2::PointD const & userPos, double azimuth,
+ m2::PointD const & pxZero,
TAnimationCreator const & parallelAnimCreator) override;
drape_ptr<ScenarioManager> const & GetScenarioManager() const;
@@ -151,14 +145,13 @@ private:
void RefreshPivotTransform(ScreenBase const & screen);
void RefreshBgColor();
- //////
- /// Render part of scene
+ // Render part of scene
void Render2dLayer(ScreenBase const & modelView);
void Render3dLayer(ScreenBase const & modelView, bool useFramebuffer);
void RenderOverlayLayer(ScreenBase const & modelView);
void RenderUserMarksLayer(ScreenBase const & modelView);
void RenderTrafficAndRouteLayer(ScreenBase const & modelView);
- //////
+
ScreenBase const & ProcessEvents(bool & modelViewChanged, bool & viewportChanged);
void PrepareScene(ScreenBase const & modelView);
void UpdateScene(ScreenBase const & modelView);
@@ -189,14 +182,13 @@ private:
void OnScaleEnded() override;
void OnAnimatedScaleEnded() override;
void OnTouchMapAction() override;
- bool OnNewVisibleViewport(m2::RectD const & oldViewport, m2::RectD const & newViewport, m2::PointD & gOffset) override;
+ bool OnNewVisibleViewport(m2::RectD const & oldViewport, m2::RectD const & newViewport,
+ m2::PointD & gOffset) override;
class Routine : public threads::IRoutine
{
public:
Routine(FrontendRenderer & renderer);
-
- // threads::IRoutine overrides:
void Do() override;
private:
@@ -210,11 +202,10 @@ private:
void UpdateOverlayTree(ScreenBase const & modelView, drape_ptr<RenderGroup> & renderGroup);
void EndUpdateOverlayTree();
- void AddToRenderGroup(dp::GLState const & state,
- drape_ptr<dp::RenderBucket> && renderBucket,
+ void AddToRenderGroup(dp::GLState const & state, drape_ptr<dp::RenderBucket> && renderBucket,
TileKey const & newTile);
- using TRenderGroupRemovePredicate = function<bool(drape_ptr<RenderGroup> const &)>;
+ using TRenderGroupRemovePredicate = std::function<bool(drape_ptr<RenderGroup> const &)>;
void RemoveRenderGroupsLater(TRenderGroupRemovePredicate const & predicate);
void FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d, bool enableAutoZoom);
@@ -227,15 +218,13 @@ private:
FeatureID GetVisiblePOI(m2::PointD const & pixelPoint);
FeatureID GetVisiblePOI(m2::RectD const & pixelRect);
- bool IsPerspective() const;
-
void PrepareGpsTrackPoints(uint32_t pointsCount);
void PullToBoundArea(bool randomPlace, bool applyZoom);
void ProcessSelection(ref_ptr<SelectObjectMessage> msg);
- void OnCacheRouteArrows(int routeIndex, vector<ArrowBorders> const & borders);
+ void OnCacheRouteArrows(int routeIndex, std::vector<ArrowBorders> const & borders);
void CollectShowOverlaysEvents();
@@ -253,22 +242,22 @@ private:
static RenderLayerID GetLayerID(dp::GLState const & renderGroup);
- vector<drape_ptr<RenderGroup>> m_renderGroups;
+ std::vector<drape_ptr<RenderGroup>> m_renderGroups;
bool m_isDirty = false;
void Sort(ref_ptr<dp::OverlayTree> overlayTree);
};
- array<RenderLayer, RenderLayer::LayerCountID> m_layers;
- vector<drape_ptr<UserMarkRenderGroup>> m_userMarkRenderGroups;
- unordered_set<size_t> m_userMarkVisibility;
+ std::array<RenderLayer, RenderLayer::LayerCountID> m_layers;
+ std::vector<drape_ptr<UserMarkRenderGroup>> m_userMarkRenderGroups;
+ std::unordered_set<size_t> m_userMarkVisibility;
drape_ptr<gui::LayerRenderer> m_guiRenderer;
drape_ptr<MyPositionController> m_myPositionController;
drape_ptr<SelectionShape> m_selectionShape;
drape_ptr<RouteRenderer> m_routeRenderer;
drape_ptr<TrafficRenderer> m_trafficRenderer;
- drape_ptr<dp::Framebuffer> m_framebuffer;
+ drape_ptr<dp::Framebuffer> m_buildingsFramebuffer;
drape_ptr<ScreenQuadRenderer> m_screenQuadRenderer;
drape_ptr<GpsTrackRenderer> m_gpsTrackRenderer;
drape_ptr<DrapeApiRenderer> m_drapeApiRenderer;
@@ -295,7 +284,7 @@ private:
TTilesCollection m_notFinishedTiles;
int m_currentZoomLevel = -1;
-
+
ref_ptr<RequestedTiles> m_requestedTiles;
uint64_t m_maxGeneration;
int m_mergeBucketsCounter = 0;
@@ -304,9 +293,7 @@ private:
struct FollowRouteData
{
- FollowRouteData(int preferredZoomLevel,
- int preferredZoomLevelIn3d,
- bool enableAutoZoom)
+ FollowRouteData(int preferredZoomLevel, int preferredZoomLevelIn3d, bool enableAutoZoom)
: m_preferredZoomLevel(preferredZoomLevel)
, m_preferredZoomLevelIn3d(preferredZoomLevelIn3d)
, m_enableAutoZoom(enableAutoZoom)
@@ -319,7 +306,7 @@ private:
unique_ptr<FollowRouteData> m_pendingFollowRoute;
- vector<m2::TriangleD> m_dragBoundArea;
+ std::vector<m2::TriangleD> m_dragBoundArea;
drape_ptr<SelectObjectMessage> m_selectObjectMessage;
@@ -332,11 +319,12 @@ private:
bool m_forceUpdateScene;
+ drape_ptr<PostprocessRenderer> m_postprocessRenderer;
+
drape_ptr<ScenarioManager> m_scenarioManager;
#ifdef DEBUG
bool m_isTeardowned;
#endif
};
-
-} // namespace df
+} // namespace df
diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp
index 69ee6c4172..048f167290 100644
--- a/drape_frontend/message.hpp
+++ b/drape_frontend/message.hpp
@@ -46,7 +46,7 @@ public:
FollowRoute,
DeactivateRouteFollowing,
UpdateMapStyle,
- InvalidateTextures,
+ SwitchMapStyle,
Invalidate,
Allow3dMode,
Allow3dBuildings,
@@ -78,6 +78,8 @@ public:
AddCustomSymbols,
RemoveCustomSymbols,
UpdateCustomSymbols,
+ SetPostprocessStaticTextures,
+ SetPosteffectEnabled,
};
virtual ~Message() {}
diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp
index 17b9ea5c3d..d322832e69 100644
--- a/drape_frontend/message_subclasses.hpp
+++ b/drape_frontend/message_subclasses.hpp
@@ -12,6 +12,7 @@
#include "drape_frontend/message.hpp"
#include "drape_frontend/my_position.hpp"
#include "drape_frontend/overlay_batcher.hpp"
+#include "drape_frontend/postprocess_renderer.hpp"
#include "drape_frontend/route_builder.hpp"
#include "drape_frontend/selection_shape.hpp"
#include "drape_frontend/tile_utils.hpp"
@@ -785,14 +786,14 @@ private:
bool const m_enableAutoZoom;
};
-class InvalidateTexturesMessage : public BaseBlockingMessage
+class SwitchMapStyleMessage : public BaseBlockingMessage
{
public:
- InvalidateTexturesMessage(Blocker & blocker)
+ SwitchMapStyleMessage(Blocker & blocker)
: BaseBlockingMessage(blocker)
{}
- Type GetType() const override { return Message::InvalidateTextures; }
+ Type GetType() const override { return Message::SwitchMapStyle; }
};
class InvalidateMessage : public Message
@@ -1198,4 +1199,35 @@ private:
std::vector<FeatureID> m_symbolsFeatures;
};
-} // namespace df
+class SetPostprocessStaticTexturesMessage : public Message
+{
+public:
+ explicit SetPostprocessStaticTexturesMessage(drape_ptr<PostprocessStaticTextures> && textures)
+ : m_textures(std::move(textures))
+ {}
+
+ Type GetType() const override { return Message::SetPostprocessStaticTextures; }
+
+ drape_ptr<PostprocessStaticTextures> && AcceptTextures() { return std::move(m_textures); }
+
+private:
+ drape_ptr<PostprocessStaticTextures> m_textures;
+};
+
+class SetPosteffectEnabledMessage : public Message
+{
+public:
+ SetPosteffectEnabledMessage(PostprocessRenderer::Effect effect, bool enabled)
+ : m_effect(effect)
+ , m_enabled(enabled)
+ {}
+
+ Type GetType() const override { return Message::SetPosteffectEnabled; }
+ PostprocessRenderer::Effect GetEffect() const { return m_effect; }
+ bool IsEnabled() const { return m_enabled; }
+
+private:
+ PostprocessRenderer::Effect const m_effect;
+ bool const m_enabled;
+};
+} // namespace df
diff --git a/drape_frontend/postprocess_renderer.cpp b/drape_frontend/postprocess_renderer.cpp
new file mode 100644
index 0000000000..37d77fc5dc
--- /dev/null
+++ b/drape_frontend/postprocess_renderer.cpp
@@ -0,0 +1,416 @@
+#include "drape_frontend/postprocess_renderer.hpp"
+#include "drape_frontend/screen_quad_renderer.hpp"
+#include "drape_frontend/shader_def.hpp"
+
+#include "drape/glfunctions.hpp"
+#include "drape/glstate.hpp"
+#include "drape/gpu_program_manager.hpp"
+#include "drape/texture_manager.hpp"
+#include "drape/uniform_values_storage.hpp"
+
+#include "base/assert.hpp"
+
+namespace df
+{
+namespace
+{
+class SMAABaseRendererContext : public RendererContext
+{
+protected:
+ void ApplyFramebufferMetrics(ref_ptr<dp::GpuProgram> prg)
+ {
+ dp::UniformValuesStorage uniforms;
+ uniforms.SetFloatValue("u_framebufferMetrics", 1.0f / m_width, 1.0f / m_height,
+ m_width, m_height);
+ dp::ApplyUniforms(uniforms, prg);
+ }
+
+ float m_width = 1.0f;
+ float m_height = 1.0f;
+};
+
+class EdgesRendererContext : public SMAABaseRendererContext
+{
+public:
+ int GetGpuProgram() const override { return gpu::SMAA_EDGES_PROGRAM; }
+
+ void PreRender(ref_ptr<dp::GpuProgram> prg) override
+ {
+ GLFunctions::glClear(gl_const::GLColorBit);
+
+ BindTexture(m_textureId, prg, "u_colorTex", 0 /* slotIndex */,
+ gl_const::GLLinear, gl_const::GLClampToEdge);
+ ApplyFramebufferMetrics(prg);
+
+ GLFunctions::glDisable(gl_const::GLDepthTest);
+ GLFunctions::glDisable(gl_const::GLBlending);
+ }
+
+ void SetParams(uint32_t textureId, uint32_t width, uint32_t height)
+ {
+ m_textureId = textureId;
+ m_width = static_cast<float>(width);
+ m_height = static_cast<float>(height);
+ }
+
+protected:
+ uint32_t m_textureId = 0;
+};
+
+class BlendingWeightRendererContext : public SMAABaseRendererContext
+{
+public:
+ int GetGpuProgram() const override { return gpu::SMAA_BLENDING_WEIGHT_PROGRAM; }
+
+ void PreRender(ref_ptr<dp::GpuProgram> prg) override
+ {
+ GLFunctions::glClear(gl_const::GLColorBit);
+
+ BindTexture(m_edgesTextureId, prg, "u_colorTex", 0 /* slotIndex */,
+ gl_const::GLLinear, gl_const::GLClampToEdge);
+ BindTexture(m_areaTextureId, prg, "u_smaaArea", 1 /* slotIndex */,
+ gl_const::GLLinear, gl_const::GLClampToEdge);
+ BindTexture(m_searchTextureId, prg, "u_smaaSearch", 2 /* slotIndex */,
+ gl_const::GLLinear, gl_const::GLClampToEdge);
+ ApplyFramebufferMetrics(prg);
+
+ GLFunctions::glDisable(gl_const::GLDepthTest);
+ GLFunctions::glDisable(gl_const::GLBlending);
+ }
+
+ void PostRender() override
+ {
+ GLFunctions::glActiveTexture(gl_const::GLTexture0 + 2);
+ GLFunctions::glBindTexture(0);
+ }
+
+ void SetParams(uint32_t edgesTextureId, uint32_t areaTextureId, uint32_t searchTextureId,
+ uint32_t width, uint32_t height)
+ {
+ m_edgesTextureId = edgesTextureId;
+ m_areaTextureId = areaTextureId;
+ m_searchTextureId = searchTextureId;
+ m_width = static_cast<float>(width);
+ m_height = static_cast<float>(height);
+ }
+
+private:
+ uint32_t m_edgesTextureId = 0;
+ uint32_t m_areaTextureId = 0;
+ uint32_t m_searchTextureId = 0;
+};
+
+class SMAAFinalRendererContext : public SMAABaseRendererContext
+{
+public:
+ int GetGpuProgram() const override { return gpu::SMAA_FINAL_PROGRAM; }
+
+ void PreRender(ref_ptr<dp::GpuProgram> prg) override
+ {
+ GLFunctions::glClear(gl_const::GLColorBit);
+
+ BindTexture(m_colorTextureId, prg, "u_colorTex", 0 /* slotIndex */,
+ gl_const::GLLinear, gl_const::GLClampToEdge);
+ BindTexture(m_blendingWeightTextureId, prg, "u_blendingWeightTex", 1 /* slotIndex */,
+ gl_const::GLLinear, gl_const::GLClampToEdge);
+ ApplyFramebufferMetrics(prg);
+
+ GLFunctions::glDisable(gl_const::GLDepthTest);
+ GLFunctions::glDisable(gl_const::GLBlending);
+ }
+
+ void PostRender() override
+ {
+ GLFunctions::glActiveTexture(gl_const::GLTexture0 + 1);
+ GLFunctions::glBindTexture(0);
+ GLFunctions::glActiveTexture(gl_const::GLTexture0);
+ GLFunctions::glBindTexture(0);
+ }
+
+ void SetParams(uint32_t colorTextureId, uint32_t blendingWeightTextureId, uint32_t width,
+ uint32_t height)
+ {
+ m_colorTextureId = colorTextureId;
+ m_blendingWeightTextureId = blendingWeightTextureId;
+ m_width = static_cast<float>(width);
+ m_height = static_cast<float>(height);
+ }
+
+private:
+ uint32_t m_colorTextureId = 0;
+ uint32_t m_blendingWeightTextureId = 0;
+};
+
+void InitFramebuffer(drape_ptr<dp::Framebuffer> & framebuffer, uint32_t width, uint32_t height)
+{
+ if (framebuffer == nullptr)
+ framebuffer.reset(new dp::Framebuffer(gl_const::GLRGBA, true /* stencilEnabled */));
+ framebuffer->SetSize(width, height);
+}
+
+void InitFramebuffer(drape_ptr<dp::Framebuffer> & framebuffer, uint32_t colorFormat,
+ ref_ptr<dp::Framebuffer::DepthStencil> depthStencilRef,
+ uint32_t width, uint32_t height)
+{
+ if (framebuffer == nullptr)
+ framebuffer.reset(new dp::Framebuffer(colorFormat));
+ framebuffer->SetDepthStencilRef(depthStencilRef);
+ framebuffer->SetSize(width, height);
+}
+
+bool IsSupported(drape_ptr<dp::Framebuffer> const & framebuffer)
+{
+ return framebuffer != nullptr && framebuffer->IsSupported();
+}
+} // namespace
+
+PostprocessRenderer::PostprocessRenderer()
+ : m_isEnabled(false)
+ , m_effects(0)
+ , m_width(0)
+ , m_height(0)
+ , m_edgesRendererContext(make_unique_dp<EdgesRendererContext>())
+ , m_bwRendererContext(make_unique_dp<BlendingWeightRendererContext>())
+ , m_smaaFinalRendererContext(make_unique_dp<SMAAFinalRendererContext>())
+ , m_frameStarted(false)
+{}
+
+PostprocessRenderer::~PostprocessRenderer()
+{
+ ClearGLDependentResources();
+}
+
+void PostprocessRenderer::Init(dp::FramebufferFallback && fallback)
+{
+ m_screenQuadRenderer.reset(new ScreenQuadRenderer());
+ m_framebufferFallback = std::move(fallback);
+ ASSERT(m_framebufferFallback != nullptr, ());
+}
+
+void PostprocessRenderer::ClearGLDependentResources()
+{
+ m_screenQuadRenderer.reset();
+ m_framebufferFallback = nullptr;
+ m_staticTextures.reset();
+
+ m_mainFramebuffer.reset();
+ m_edgesFramebuffer.reset();
+ m_blendingWeightFramebuffer.reset();
+}
+
+void PostprocessRenderer::Resize(uint32_t width, uint32_t height)
+{
+ m_width = width;
+ m_height = height;
+
+ UpdateFramebuffers(m_width, m_height);
+}
+
+void PostprocessRenderer::SetStaticTextures(drape_ptr<PostprocessStaticTextures> && textures)
+{
+ m_staticTextures = std::move(textures);
+}
+
+void PostprocessRenderer::SetEnabled(bool enabled)
+{
+ m_isEnabled = enabled;
+ if (m_isEnabled && m_width != 0 && m_height != 0)
+ UpdateFramebuffers(m_width, m_height);
+}
+
+bool PostprocessRenderer::IsEnabled() const
+{
+ if (!m_isEnabled || m_effects == 0 || m_staticTextures == nullptr)
+ return false;
+
+ if (!IsSupported(m_mainFramebuffer))
+ return false;
+
+ if (IsEffectEnabled(Effect::Antialiasing) &&
+ (!IsSupported(m_edgesFramebuffer) || !IsSupported(m_blendingWeightFramebuffer)))
+ {
+ return false;
+ }
+
+ // Insert checking new effects here.
+
+ return true;
+}
+
+void PostprocessRenderer::SetEffectEnabled(Effect effect, bool enabled)
+{
+ uint32_t const oldValue = m_effects;
+ uint32_t const effectMask = static_cast<uint32_t>(effect);
+ m_effects = (m_effects & ~effectMask) | (enabled ? effectMask : 0);
+
+ if (m_width != 0 && m_height != 0 && oldValue != m_effects)
+ UpdateFramebuffers(m_width, m_height);
+}
+
+bool PostprocessRenderer::IsEffectEnabled(Effect effect) const
+{
+ return (m_effects & static_cast<uint32_t>(effect)) > 0;
+}
+
+void PostprocessRenderer::BeginFrame()
+{
+ if (!IsEnabled())
+ {
+ m_framebufferFallback();
+ return;
+ }
+
+ // Check if Subpixel Morphological Antialiasing (SMAA) is unavailable.
+ ASSERT(m_staticTextures != nullptr, ());
+ if (m_staticTextures->m_smaaSearchTexture == nullptr ||
+ m_staticTextures->m_smaaAreaTexture == nullptr ||
+ m_staticTextures->m_smaaAreaTexture->GetID() < 0 ||
+ m_staticTextures->m_smaaSearchTexture->GetID() < 0)
+ {
+ SetEffectEnabled(Effect::Antialiasing, false);
+ }
+
+ m_mainFramebuffer->Enable();
+ m_frameStarted = true;
+
+ GLFunctions::glDisable(gl_const::GLStencilTest);
+}
+
+void PostprocessRenderer::EndFrame(ref_ptr<dp::GpuProgramManager> gpuProgramManager)
+{
+ if (!IsEnabled() && !m_frameStarted)
+ return;
+
+ bool wasPostEffect = false;
+
+ // Subpixel Morphological Antialiasing (SMAA).
+ if (IsEffectEnabled(Effect::Antialiasing))
+ {
+ wasPostEffect = true;
+
+ ASSERT(m_staticTextures->m_smaaAreaTexture != nullptr, ());
+ ASSERT_GREATER_OR_EQUAL(m_staticTextures->m_smaaAreaTexture->GetID(), 0, ());
+
+ ASSERT(m_staticTextures->m_smaaSearchTexture != nullptr, ());
+ ASSERT_GREATER_OR_EQUAL(m_staticTextures->m_smaaSearchTexture->GetID(), 0, ());
+
+ GLFunctions::glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ GLFunctions::glEnable(gl_const::GLStencilTest);
+
+ // Render edges to texture.
+ {
+ m_edgesFramebuffer->Enable();
+
+ GLFunctions::glStencilFuncSeparate(gl_const::GLFrontAndBack, gl_const::GLNotEqual, 1, 1);
+ GLFunctions::glStencilOpSeparate(gl_const::GLFrontAndBack, gl_const::GLZero,
+ gl_const::GLZero, gl_const::GLReplace);
+
+ ASSERT(dynamic_cast<EdgesRendererContext *>(m_edgesRendererContext.get()) != nullptr, ());
+ auto context = static_cast<EdgesRendererContext *>(m_edgesRendererContext.get());
+ context->SetParams(m_mainFramebuffer->GetTextureId(), m_width, m_height);
+ m_screenQuadRenderer->Render(gpuProgramManager, make_ref(m_edgesRendererContext));
+ }
+
+ // Render blending weight to texture.
+ {
+ m_blendingWeightFramebuffer->Enable();
+
+ GLFunctions::glStencilFuncSeparate(gl_const::GLFrontAndBack, gl_const::GLEqual, 1, 1);
+ GLFunctions::glStencilOpSeparate(gl_const::GLFrontAndBack, gl_const::GLKeep,
+ gl_const::GLKeep, gl_const::GLKeep);
+
+ ASSERT(dynamic_cast<BlendingWeightRendererContext *>(m_bwRendererContext.get()) != nullptr, ());
+ auto context = static_cast<BlendingWeightRendererContext *>(m_bwRendererContext.get());
+ context->SetParams(m_edgesFramebuffer->GetTextureId(),
+ static_cast<uint32_t>(m_staticTextures->m_smaaAreaTexture->GetID()),
+ static_cast<uint32_t>(m_staticTextures->m_smaaSearchTexture->GetID()),
+ m_width, m_height);
+ m_screenQuadRenderer->Render(gpuProgramManager, make_ref(m_bwRendererContext));
+ }
+
+ // SMAA final pass.
+ GLFunctions::glDisable(gl_const::GLStencilTest);
+ {
+ m_framebufferFallback();
+ ASSERT(dynamic_cast<SMAAFinalRendererContext *>(m_smaaFinalRendererContext.get()) != nullptr, ());
+ auto context = static_cast<SMAAFinalRendererContext *>(m_smaaFinalRendererContext.get());
+ context->SetParams(m_mainFramebuffer->GetTextureId(),
+ m_blendingWeightFramebuffer->GetTextureId(),
+ m_width, m_height);
+ m_screenQuadRenderer->Render(gpuProgramManager, make_ref(m_smaaFinalRendererContext));
+ }
+ }
+
+ if (!wasPostEffect)
+ {
+ m_framebufferFallback();
+ GLFunctions::glClear(gl_const::GLColorBit);
+ m_screenQuadRenderer->RenderTexture(gpuProgramManager, m_mainFramebuffer->GetTextureId(),
+ 1.0f /* opacity */);
+ }
+ m_frameStarted = false;
+}
+
+void PostprocessRenderer::EnableWritingToStencil() const
+{
+ if (!m_frameStarted)
+ return;
+ GLFunctions::glEnable(gl_const::GLStencilTest);
+ GLFunctions::glStencilFuncSeparate(gl_const::GLFrontAndBack, gl_const::GLAlways, 1, 1);
+ GLFunctions::glStencilOpSeparate(gl_const::GLFrontAndBack, gl_const::GLKeep,
+ gl_const::GLKeep, gl_const::GLReplace);
+}
+
+void PostprocessRenderer::DisableWritingToStencil() const
+{
+ if (!m_frameStarted)
+ return;
+ GLFunctions::glDisable(gl_const::GLStencilTest);
+}
+
+void PostprocessRenderer::UpdateFramebuffers(uint32_t width, uint32_t height)
+{
+ ASSERT_NOT_EQUAL(width, 0, ());
+ ASSERT_NOT_EQUAL(height, 0, ());
+
+ if (m_effects != 0)
+ InitFramebuffer(m_mainFramebuffer, width, height);
+ else
+ m_mainFramebuffer.reset();
+
+ if (IsEffectEnabled(Effect::Antialiasing))
+ {
+ InitFramebuffer(m_edgesFramebuffer, gl_const::GLRedGreen,
+ m_mainFramebuffer->GetDepthStencilRef(),
+ width, height);
+ InitFramebuffer(m_blendingWeightFramebuffer, gl_const::GLRGBA,
+ m_mainFramebuffer->GetDepthStencilRef(),
+ width, height);
+ }
+ else
+ {
+ m_edgesFramebuffer.reset();
+ m_blendingWeightFramebuffer.reset();
+ }
+}
+
+void PostprocessRenderer::OnFramebufferFallback()
+{
+ if (m_frameStarted)
+ m_mainFramebuffer->Enable();
+ else
+ m_framebufferFallback();
+}
+
+StencilWriterGuard::StencilWriterGuard(ref_ptr<PostprocessRenderer> renderer)
+ : m_renderer(renderer)
+{
+ ASSERT(m_renderer != nullptr, ());
+ m_renderer->EnableWritingToStencil();
+}
+
+StencilWriterGuard::~StencilWriterGuard()
+{
+ m_renderer->DisableWritingToStencil();
+}
+} // namespace df
diff --git a/drape_frontend/postprocess_renderer.hpp b/drape_frontend/postprocess_renderer.hpp
new file mode 100644
index 0000000000..ce926218cf
--- /dev/null
+++ b/drape_frontend/postprocess_renderer.hpp
@@ -0,0 +1,83 @@
+#pragma once
+
+#include "drape/framebuffer.hpp"
+#include "drape/pointers.hpp"
+
+namespace dp
+{
+class GpuProgramManager;
+class Texture;
+} // namespace dp
+
+namespace df
+{
+class ScreenQuadRenderer;
+class RendererContext;
+
+struct PostprocessStaticTextures
+{
+ ref_ptr<dp::Texture> m_smaaAreaTexture;
+ ref_ptr<dp::Texture> m_smaaSearchTexture;
+};
+
+class PostprocessRenderer
+{
+public:
+ enum Effect
+ {
+ Antialiasing = 1
+ };
+
+ PostprocessRenderer();
+ ~PostprocessRenderer();
+
+ void Init(dp::FramebufferFallback && fallback);
+ void ClearGLDependentResources();
+ void Resize(uint32_t width, uint32_t height);
+ void SetStaticTextures(drape_ptr<PostprocessStaticTextures> && textures);
+
+ void SetEnabled(bool enabled);
+ bool IsEnabled() const;
+ void SetEffectEnabled(Effect effect, bool enabled);
+ bool IsEffectEnabled(Effect effect) const;
+
+ void OnFramebufferFallback();
+
+ void BeginFrame();
+ void EndFrame(ref_ptr<dp::GpuProgramManager> gpuProgramManager);
+
+ void EnableWritingToStencil() const;
+ void DisableWritingToStencil() const;
+
+private:
+ void UpdateFramebuffers(uint32_t width, uint32_t height);
+
+ bool m_isEnabled;
+ uint32_t m_effects;
+
+ drape_ptr<ScreenQuadRenderer> m_screenQuadRenderer;
+ dp::FramebufferFallback m_framebufferFallback;
+ drape_ptr<PostprocessStaticTextures> m_staticTextures;
+ uint32_t m_width;
+ uint32_t m_height;
+
+ drape_ptr<dp::Framebuffer> m_mainFramebuffer;
+ drape_ptr<dp::Framebuffer> m_edgesFramebuffer;
+ drape_ptr<dp::Framebuffer> m_blendingWeightFramebuffer;
+
+ drape_ptr<RendererContext> m_edgesRendererContext;
+ drape_ptr<RendererContext> m_bwRendererContext;
+ drape_ptr<RendererContext> m_smaaFinalRendererContext;
+
+ bool m_frameStarted;
+};
+
+class StencilWriterGuard
+{
+public:
+ StencilWriterGuard(ref_ptr<PostprocessRenderer> renderer);
+ ~StencilWriterGuard();
+private:
+ ref_ptr<PostprocessRenderer> const m_renderer;
+};
+} // namespace df
diff --git a/drape_frontend/screen_quad_renderer.cpp b/drape_frontend/screen_quad_renderer.cpp
index 22818bd365..7da2089685 100644
--- a/drape_frontend/screen_quad_renderer.cpp
+++ b/drape_frontend/screen_quad_renderer.cpp
@@ -13,10 +13,73 @@
namespace df
{
+namespace
+{
+class TextureRendererContext : public RendererContext
+{
+public:
+ int GetGpuProgram() const override { return gpu::SCREEN_QUAD_PROGRAM; }
+
+ void PreRender(ref_ptr<dp::GpuProgram> prg) override
+ {
+ BindTexture(m_textureId, prg, "u_colorTex", 0 /* slotIndex */,
+ gl_const::GLLinear, gl_const::GLClampToEdge);
+
+ dp::UniformValuesStorage uniforms;
+ uniforms.SetFloatValue("u_opacity", m_opacity);
+ dp::ApplyUniforms(uniforms, prg);
+
+ GLFunctions::glDisable(gl_const::GLDepthTest);
+ GLFunctions::glEnable(gl_const::GLBlending);
+ }
+
+ void PostRender() override
+ {
+ GLFunctions::glDisable(gl_const::GLBlending);
+ GLFunctions::glBindTexture(0);
+ }
+
+ void SetParams(uint32_t textureId, float opacity)
+ {
+ m_textureId = textureId;
+ m_opacity = opacity;
+ }
+
+private:
+ uint32_t m_textureId = 0;
+ float m_opacity = 1.0f;
+};
+} // namespace
+
+void RendererContext::BindTexture(uint32_t textureId, ref_ptr<dp::GpuProgram> prg,
+ std::string const & uniformName, uint8_t slotIndex,
+ uint32_t filteringMode, uint32_t wrappingMode)
+{
+ int8_t const textureLocation = prg->GetUniformLocation(uniformName);
+ ASSERT_NOT_EQUAL(textureLocation, -1, ());
+ if (textureLocation < 0)
+ return;
+
+ GLFunctions::glActiveTexture(gl_const::GLTexture0 + slotIndex);
+ GLFunctions::glBindTexture(textureId);
+ GLFunctions::glUniformValuei(textureLocation, slotIndex);
+ GLFunctions::glTexParameter(gl_const::GLMinFilter, filteringMode);
+ GLFunctions::glTexParameter(gl_const::GLMagFilter, filteringMode);
+ GLFunctions::glTexParameter(gl_const::GLWrapS, wrappingMode);
+ GLFunctions::glTexParameter(gl_const::GLWrapT, wrappingMode);
+}
+
+ScreenQuadRenderer::ScreenQuadRenderer()
+ : m_textureRendererContext(make_unique_dp<TextureRendererContext>())
+{}
+
ScreenQuadRenderer::~ScreenQuadRenderer()
{
if (m_bufferId != 0)
GLFunctions::glDeleteBuffer(m_bufferId);
+
+ if (m_VAO != 0)
+ GLFunctions::glDeleteVertexArray(m_VAO);
}
void ScreenQuadRenderer::Build(ref_ptr<dp::GpuProgram> prg)
@@ -31,10 +94,7 @@ void ScreenQuadRenderer::Build(ref_ptr<dp::GpuProgram> prg)
m_attributeTexCoord = prg->GetAttributeLocation("a_tcoord");
ASSERT_NOT_EQUAL(m_attributeTexCoord, -1, ());
-
- m_textureLocation = prg->GetUniformLocation("u_colorTex");
- ASSERT_NOT_EQUAL(m_textureLocation, -1, ());
-
+
std::vector<float> vertices = {-1.0f, 1.0f, m_textureRect.minX(), m_textureRect.maxY(),
1.0f, 1.0f, m_textureRect.maxX(), m_textureRect.maxY(),
-1.0f, -1.0f, m_textureRect.minX(), m_textureRect.minY(),
@@ -50,29 +110,17 @@ void ScreenQuadRenderer::Build(ref_ptr<dp::GpuProgram> prg)
GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer);
}
-void ScreenQuadRenderer::RenderTexture(uint32_t textureId, ref_ptr<dp::GpuProgramManager> mng,
- float opacity)
+void ScreenQuadRenderer::Render(ref_ptr<dp::GpuProgramManager> mng, ref_ptr<RendererContext> context)
{
- ref_ptr<dp::GpuProgram> prg = mng->GetProgram(gpu::SCREEN_QUAD_PROGRAM);
+ ref_ptr<dp::GpuProgram> prg = mng->GetProgram(context->GetGpuProgram());
prg->Bind();
if (m_bufferId == 0)
Build(prg);
- if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject))
+ if (m_VAO != 0)
GLFunctions::glBindVertexArray(m_VAO);
- if (m_textureLocation >= 0)
- {
- GLFunctions::glActiveTexture(gl_const::GLTexture0);
- GLFunctions::glBindTexture(textureId);
- GLFunctions::glUniformValuei(m_textureLocation, 0);
- GLFunctions::glTexParameter(gl_const::GLMinFilter, gl_const::GLLinear);
- GLFunctions::glTexParameter(gl_const::GLMagFilter, gl_const::GLLinear);
- GLFunctions::glTexParameter(gl_const::GLWrapS, gl_const::GLClampToEdge);
- GLFunctions::glTexParameter(gl_const::GLWrapT, gl_const::GLClampToEdge);
- }
-
GLFunctions::glBindBuffer(m_bufferId, gl_const::GLArrayBuffer);
GLFunctions::glEnableVertexAttribute(m_attributePosition);
@@ -82,29 +130,39 @@ void ScreenQuadRenderer::RenderTexture(uint32_t textureId, ref_ptr<dp::GpuProgra
GLFunctions::glVertexAttributePointer(m_attributeTexCoord, 2, gl_const::GLFloatType, false,
sizeof(float) * 4, sizeof(float) * 2);
- dp::UniformValuesStorage uniforms;
- uniforms.SetFloatValue("u_opacity", opacity);
- dp::ApplyUniforms(uniforms, prg);
-
- GLFunctions::glEnable(gl_const::GLBlending);
+ context->PreRender(prg);
GLFunctions::glDrawArrays(gl_const::GLTriangleStrip, 0, 4);
- GLFunctions::glDisable(gl_const::GLBlending);
+ context->PostRender();
prg->Unbind();
- if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject))
- GLFunctions::glBindVertexArray(0);
- GLFunctions::glBindTexture(0);
GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer);
+
+ if (m_VAO != 0)
+ GLFunctions::glBindVertexArray(0);
+}
+
+void ScreenQuadRenderer::RenderTexture(ref_ptr<dp::GpuProgramManager> mng, uint32_t textureId,
+ float opacity)
+{
+ ASSERT(dynamic_cast<TextureRendererContext *>(m_textureRendererContext.get()) != nullptr, ());
+
+ auto context = static_cast<TextureRendererContext *>(m_textureRendererContext.get());
+ context->SetParams(textureId, opacity);
+
+ Render(mng, make_ref(m_textureRendererContext));
}
-void ScreenQuadRenderer::SetTextureRect(m2::RectF const & rect, ref_ptr<dp::GpuProgramManager> mng)
+void ScreenQuadRenderer::SetTextureRect(m2::RectF const & rect, ref_ptr<dp::GpuProgram> prg)
{
m_textureRect = rect;
+ Rebuild(prg);
+}
+void ScreenQuadRenderer::Rebuild(ref_ptr<dp::GpuProgram> prg)
+{
if (m_bufferId != 0)
GLFunctions::glDeleteBuffer(m_bufferId);
- ref_ptr<dp::GpuProgram> prg = mng->GetProgram(gpu::SCREEN_QUAD_PROGRAM);
prg->Bind();
Build(prg);
prg->Unbind();
diff --git a/drape_frontend/screen_quad_renderer.hpp b/drape_frontend/screen_quad_renderer.hpp
index 2231aab638..512ed29d89 100644
--- a/drape_frontend/screen_quad_renderer.hpp
+++ b/drape_frontend/screen_quad_renderer.hpp
@@ -4,6 +4,8 @@
#include "geometry/rect2d.hpp"
+#include <string>
+
namespace dp
{
class GpuProgram;
@@ -12,16 +14,33 @@ class GpuProgramManager;
namespace df
{
+class RendererContext
+{
+public:
+ virtual ~RendererContext() {}
+ virtual int GetGpuProgram() const = 0;
+ virtual void PreRender(ref_ptr<dp::GpuProgram> prg) {}
+ virtual void PostRender() {}
+protected:
+ void BindTexture(uint32_t textureId, ref_ptr<dp::GpuProgram> prg,
+ std::string const & uniformName, uint8_t slotIndex,
+ uint32_t filteringMode, uint32_t wrappingMode);
+};
+
class ScreenQuadRenderer
{
public:
- ScreenQuadRenderer() = default;
+ ScreenQuadRenderer();
~ScreenQuadRenderer();
- void SetTextureRect(m2::RectF const & rect, ref_ptr<dp::GpuProgramManager> mng);
+ void SetTextureRect(m2::RectF const & rect, ref_ptr<dp::GpuProgram> prg);
+ void Rebuild(ref_ptr<dp::GpuProgram> prg);
+
bool IsInitialized() const { return m_bufferId != 0; }
m2::RectF const & GetTextureRect() const { return m_textureRect; }
- void RenderTexture(uint32_t textureId, ref_ptr<dp::GpuProgramManager> mng, float opacity);
+
+ void Render(ref_ptr<dp::GpuProgramManager> mng, ref_ptr<RendererContext> context);
+ void RenderTexture(ref_ptr<dp::GpuProgramManager> mng, uint32_t textureId, float opacity);
private:
void Build(ref_ptr<dp::GpuProgram> prg);
@@ -30,7 +49,8 @@ private:
uint32_t m_VAO = 0;
int8_t m_attributePosition = -1;
int8_t m_attributeTexCoord = -1;
- int8_t m_textureLocation = -1;
m2::RectF m_textureRect = m2::RectF(0.0f, 0.0f, 1.0f, 1.0f);
+
+ drape_ptr<RendererContext> m_textureRendererContext;
};
} // namespace df
diff --git a/drape_frontend/shaders/shader_index.txt b/drape_frontend/shaders/shader_index.txt
index e0dea148f2..d3eabfc6c8 100644
--- a/drape_frontend/shaders/shader_index.txt
+++ b/drape_frontend/shaders/shader_index.txt
@@ -37,3 +37,6 @@ TEXT_FIXED_BILLBOARD_PROGRAM text_billboard.vsh.glsl text_fixed.fsh.glsl
BOOKMARK_BILLBOARD_PROGRAM user_mark_billboard.vsh.glsl texturing.fsh.glsl
TRAFFIC_PROGRAM traffic.vsh.glsl traffic.fsh.glsl
TRAFFIC_LINE_PROGRAM traffic_line.vsh.glsl traffic_line.fsh.glsl
+SMAA_EDGES_PROGRAM smaa_edges.vsh.glsl smaa_edges.fsh.glsl
+SMAA_BLENDING_WEIGHT_PROGRAM smaa_blending_weight.vsh.glsl smaa_blending_weight.fsh.glsl
+SMAA_FINAL_PROGRAM smaa_final.vsh.glsl smaa_final.fsh.glsl
diff --git a/drape_frontend/shaders/smaa_blending_weight.fsh.glsl b/drape_frontend/shaders/smaa_blending_weight.fsh.glsl
new file mode 100644
index 0000000000..284fe0a48d
--- /dev/null
+++ b/drape_frontend/shaders/smaa_blending_weight.fsh.glsl
@@ -0,0 +1,189 @@
+// Implementation of Subpixel Morphological Antialiasing (SMAA) is based on https://github.com/iryoku/smaa
+
+uniform sampler2D u_colorTex;
+uniform sampler2D u_smaaArea;
+uniform sampler2D u_smaaSearch;
+
+uniform vec4 u_framebufferMetrics;
+
+varying vec4 v_coords;
+varying vec4 v_offset0;
+varying vec4 v_offset1;
+varying vec4 v_offset2;
+
+#define SMAA_SEARCHTEX_SIZE vec2(66.0, 33.0)
+#define SMAA_SEARCHTEX_PACKED_SIZE vec2(64.0, 16.0)
+#define SMAA_AREATEX_MAX_DISTANCE 16.0
+#define SMAA_AREATEX_PIXEL_SIZE (vec2(1.0 / 256.0, 1.0 / 1024.0))
+
+#ifdef GLES3
+ #define SMAALoopBegin(condition) while (condition) {
+ #define SMAALoopEnd }
+ #define SMAASampleLevelZero(tex, coord) textureLod(tex, coord, 0.0)
+ #define SMAASampleLevelZeroOffset(tex, coord, offset) textureLodOffset(tex, coord, 0.0, offset)
+ #define SMAARound(v) round((v))
+ #define SMAAOffset(x,y) ivec2(x,y)
+#else
+ #define SMAA_MAX_SEARCH_STEPS 8
+ #define SMAALoopBegin(condition) for (int i = 0; i < SMAA_MAX_SEARCH_STEPS; i++) { if (!(condition)) break;
+ #define SMAALoopEnd }
+ #define SMAASampleLevelZero(tex, coord) texture2D(tex, coord)
+ #define SMAASampleLevelZeroOffset(tex, coord, offset) texture2D(tex, coord + vec2(offset) * u_framebufferMetrics.xy)
+ #define SMAARound(v) floor((v) + 0.5)
+ #define SMAAOffset(x,y) vec2(x,y)
+#endif
+
+const vec2 kAreaTexMaxDistance = vec2(SMAA_AREATEX_MAX_DISTANCE, SMAA_AREATEX_MAX_DISTANCE);
+const float kActivationThreshold = 0.8281;
+
+float SMAASearchLength(vec2 e, float offset)
+{
+ // The texture is flipped vertically, with left and right cases taking half
+ // of the space horizontally.
+ vec2 scale = SMAA_SEARCHTEX_SIZE * vec2(0.5, -1.0);
+ vec2 bias = SMAA_SEARCHTEX_SIZE * vec2(offset, 1.0);
+
+ // Scale and bias to access texel centers.
+ scale += vec2(-1.0, 1.0);
+ bias += vec2( 0.5, -0.5);
+
+ // Convert from pixel coordinates to texcoords.
+ // (We use SMAA_SEARCHTEX_PACKED_SIZE because the texture is cropped).
+ scale *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE;
+ bias *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE;
+
+ // Lookup the search texture.
+#ifdef GLES3
+ return SMAASampleLevelZero(u_smaaSearch, scale * e + bias).r;
+#else
+ return SMAASampleLevelZero(u_smaaSearch, scale * e + bias).a;
+#endif
+}
+
+float SMAASearchXLeft(vec2 texcoord, float end)
+{
+ vec2 e = vec2(0.0, 1.0);
+ SMAALoopBegin(texcoord.x > end && e.g > kActivationThreshold && e.r == 0.0)
+ e = SMAASampleLevelZero(u_colorTex, texcoord).rg;
+ texcoord = vec2(-2.0, 0.0) * u_framebufferMetrics.xy + texcoord;
+ SMAALoopEnd
+ float offset = 3.25 - (255.0 / 127.0) * SMAASearchLength(e, 0.0);
+ return u_framebufferMetrics.x * offset + texcoord.x;
+}
+
+float SMAASearchXRight(vec2 texcoord, float end)
+{
+ vec2 e = vec2(0.0, 1.0);
+ SMAALoopBegin(texcoord.x < end && e.g > kActivationThreshold && e.r == 0.0)
+ e = SMAASampleLevelZero(u_colorTex, texcoord).rg;
+ texcoord = vec2(2.0, 0.0) * u_framebufferMetrics.xy + texcoord;
+ SMAALoopEnd
+ float offset = 3.25 - (255.0 / 127.0) * SMAASearchLength(e, 0.5);
+ return -u_framebufferMetrics.x * offset + texcoord.x;
+}
+
+float SMAASearchYUp(vec2 texcoord, float end)
+{
+ vec2 e = vec2(1.0, 0.0);
+ SMAALoopBegin(texcoord.y > end && e.r > kActivationThreshold && e.g == 0.0)
+ e = SMAASampleLevelZero(u_colorTex, texcoord).rg;
+ texcoord = vec2(0.0, -2.0) * u_framebufferMetrics.xy + texcoord;
+ SMAALoopEnd
+ float offset = 3.25 - (255.0 / 127.0) * SMAASearchLength(e.gr, 0.0);
+ return u_framebufferMetrics.y * offset + texcoord.y;
+}
+
+float SMAASearchYDown(vec2 texcoord, float end)
+{
+ vec2 e = vec2(1.0, 0.0);
+ SMAALoopBegin(texcoord.y < end && e.r > kActivationThreshold && e.g == 0.0)
+ e = SMAASampleLevelZero(u_colorTex, texcoord).rg;
+ texcoord = vec2(0.0, 2.0) * u_framebufferMetrics.xy + texcoord;
+ SMAALoopEnd
+ float offset = 3.25 - (255.0 / 127.0) * SMAASearchLength(e.gr, 0.5);
+ return -u_framebufferMetrics.y * offset + texcoord.y;
+}
+
+// Here, we have the distance and both crossing edges. So, what are the areas
+// at each side of current edge?
+vec2 SMAAArea(vec2 dist, float e1, float e2)
+{
+ // Rounding prevents precision errors of bilinear filtering.
+ vec2 texcoord = kAreaTexMaxDistance * SMAARound(4.0 * vec2(e1, e2)) + dist;
+ // We do a scale and bias for mapping to texel space.
+ texcoord = SMAA_AREATEX_PIXEL_SIZE * (texcoord + 0.5);
+ return SMAASampleLevelZero(u_smaaArea, texcoord).rg;
+}
+
+void main()
+{
+ vec4 weights = vec4(0.0, 0.0, 0.0, 0.0);
+ vec2 e = texture2D(u_colorTex, v_coords.xy).rg;
+
+ if (e.g > 0.0) // Edge at north
+ {
+ vec2 d;
+
+ // Find the distance to the left.
+ vec3 coords;
+ coords.x = SMAASearchXLeft(v_offset0.xy, v_offset2.x);
+ coords.y = v_offset1.y;
+ d.x = coords.x;
+
+ // Now fetch the left crossing edges, two at a time using bilinear
+ // filtering. Sampling at -0.25 enables to discern what value each edge has.
+ float e1 = SMAASampleLevelZero(u_colorTex, coords.xy).r;
+
+ // Find the distance to the right.
+ coords.z = SMAASearchXRight(v_offset0.zw, v_offset2.y);
+ d.y = coords.z;
+
+ // We want the distances to be in pixel units (doing this here allow to
+ // better interleave arithmetic and memory accesses).
+ d = abs(SMAARound(u_framebufferMetrics.zz * d - v_coords.zz));
+
+ // SMAAArea below needs a sqrt, as the areas texture is compressed
+ // quadratically.
+ vec2 sqrt_d = sqrt(d);
+
+ // Fetch the right crossing edges.
+ float e2 = SMAASampleLevelZeroOffset(u_colorTex, coords.zy, SMAAOffset(1, 0)).r;
+
+ // Here we know how this pattern looks like, now it is time for getting
+ // the actual area.
+ weights.rg = SMAAArea(sqrt_d, e1, e2);
+ }
+
+ if (e.r > 0.0) // Edge at west
+ {
+ vec2 d;
+
+ // Find the distance to the top.
+ vec3 coords;
+ coords.y = SMAASearchYUp(v_offset1.xy, v_offset2.z);
+ coords.x = v_offset0.x;
+ d.x = coords.y;
+
+ // Fetch the top crossing edges.
+ float e1 = SMAASampleLevelZero(u_colorTex, coords.xy).g;
+
+ // Find the distance to the bottom.
+ coords.z = SMAASearchYDown(v_offset1.zw, v_offset2.w);
+ d.y = coords.z;
+
+ // We want the distances to be in pixel units.
+ d = abs(SMAARound(u_framebufferMetrics.ww * d - v_coords.ww));
+
+ // SMAAArea below needs a sqrt, as the areas texture is compressed
+ // quadratically.
+ vec2 sqrt_d = sqrt(d);
+
+ // Fetch the bottom crossing edges.
+ float e2 = SMAASampleLevelZeroOffset(u_colorTex, coords.xz, SMAAOffset(0, 1)).g;
+
+ // Get the area for this direction.
+ weights.ba = SMAAArea(sqrt_d, e1, e2);
+ }
+
+ gl_FragColor = weights;
+}
diff --git a/drape_frontend/shaders/smaa_blending_weight.vsh.glsl b/drape_frontend/shaders/smaa_blending_weight.vsh.glsl
new file mode 100644
index 0000000000..621cd2a332
--- /dev/null
+++ b/drape_frontend/shaders/smaa_blending_weight.vsh.glsl
@@ -0,0 +1,28 @@
+// Implementation of Subpixel Morphological Antialiasing (SMAA) is based on https://github.com/iryoku/smaa
+
+attribute vec2 a_pos;
+attribute vec2 a_tcoord;
+
+uniform vec4 u_framebufferMetrics;
+
+varying vec4 v_coords;
+varying vec4 v_offset0;
+varying vec4 v_offset1;
+varying vec4 v_offset2;
+
+// SMAA_MAX_SEARCH_STEPS specifies the maximum steps performed in the
+// horizontal/vertical pattern searches, at each side of the pixel.
+#define SMAA_MAX_SEARCH_STEPS 8.0
+const vec4 kMaxSearchSteps = vec4(-2.0 * SMAA_MAX_SEARCH_STEPS, 2.0 * SMAA_MAX_SEARCH_STEPS,
+ -2.0 * SMAA_MAX_SEARCH_STEPS, 2.0 * SMAA_MAX_SEARCH_STEPS);
+
+void main()
+{
+ v_coords = vec4(a_tcoord, a_tcoord * u_framebufferMetrics.zw);
+ // We will use these offsets for the searches.
+ v_offset0 = u_framebufferMetrics.xyxy * vec4(-0.25, -0.125, 1.25, -0.125) + a_tcoord.xyxy;
+ v_offset1 = u_framebufferMetrics.xyxy * vec4(-0.125, -0.25, -0.125, 1.25) + a_tcoord.xyxy;
+ // And these for the searches, they indicate the ends of the loops.
+ v_offset2 = u_framebufferMetrics.xxyy * kMaxSearchSteps + vec4(v_offset0.xz, v_offset1.yw);
+ gl_Position = vec4(a_pos, 0.0, 1.0);
+}
diff --git a/drape_frontend/shaders/smaa_edges.fsh.glsl b/drape_frontend/shaders/smaa_edges.fsh.glsl
new file mode 100644
index 0000000000..69322a954d
--- /dev/null
+++ b/drape_frontend/shaders/smaa_edges.fsh.glsl
@@ -0,0 +1,65 @@
+// Implementation of Subpixel Morphological Antialiasing (SMAA) is based on https://github.com/iryoku/smaa
+
+uniform sampler2D u_colorTex;
+
+varying vec2 v_colorTexCoords;
+varying vec4 v_offset0;
+varying vec4 v_offset1;
+varying vec4 v_offset2;
+
+// SMAA_THRESHOLD specifies the threshold or sensitivity to edges.
+// Lowering this value you will be able to detect more edges at the expense of
+// performance.
+// Range: [0, 0.5]
+// 0.1 is a reasonable value, and allows to catch most visible edges.
+// 0.05 is a rather overkill value, that allows to catch 'em all.
+#define SMAA_THRESHOLD 0.05
+const vec2 kThreshold = vec2(SMAA_THRESHOLD, SMAA_THRESHOLD);
+
+// If there is an neighbor edge that has SMAA_LOCAL_CONTRAST_FACTOR times
+// bigger contrast than current edge, current edge will be discarded.
+// This allows to eliminate spurious crossing edges, and is based on the fact
+// that, if there is too much contrast in a direction, that will hide
+// perceptually contrast in the other neighbors.
+#define SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR 2.0
+
+// Standard relative luminance weights.
+// https://en.wikipedia.org/wiki/Relative_luminance
+const vec3 kWeights = vec3(0.2126, 0.7152, 0.0722);
+
+void main()
+{
+ // Calculate lumas.
+ float L = dot(texture2D(u_colorTex, v_colorTexCoords).rgb, kWeights);
+ float Lleft = dot(texture2D(u_colorTex, v_offset0.xy).rgb, kWeights);
+ float Ltop = dot(texture2D(u_colorTex, v_offset0.zw).rgb, kWeights);
+
+ // We do the usual threshold.
+ vec4 delta;
+ delta.xy = abs(L - vec2(Lleft, Ltop));
+ vec2 edges = step(kThreshold, delta.xy);
+ if (dot(edges, vec2(1.0, 1.0)) == 0.0)
+ discard;
+
+ // Calculate right and bottom deltas.
+ float Lright = dot(texture2D(u_colorTex, v_offset1.xy).rgb, kWeights);
+ float Lbottom = dot(texture2D(u_colorTex, v_offset1.zw).rgb, kWeights);
+ delta.zw = abs(L - vec2(Lright, Lbottom));
+
+ // Calculate the maximum delta in the direct neighborhood.
+ vec2 maxDelta = max(delta.xy, delta.zw);
+
+ // Calculate left-left and top-top deltas.
+ float Lleftleft = dot(texture2D(u_colorTex, v_offset2.xy).rgb, kWeights);
+ float Ltoptop = dot(texture2D(u_colorTex, v_offset2.zw).rgb, kWeights);
+ delta.zw = abs(vec2(Lleft, Ltop) - vec2(Lleftleft, Ltoptop));
+
+ // Calculate the final maximum delta.
+ maxDelta = max(maxDelta.xy, delta.zw);
+ float finalDelta = max(maxDelta.x, maxDelta.y);
+
+ // Local contrast adaptation
+ edges *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy);
+
+ gl_FragColor = vec4(edges, 0.0, 1.0);
+}
diff --git a/drape_frontend/shaders/smaa_edges.vsh.glsl b/drape_frontend/shaders/smaa_edges.vsh.glsl
new file mode 100644
index 0000000000..efcd5e118d
--- /dev/null
+++ b/drape_frontend/shaders/smaa_edges.vsh.glsl
@@ -0,0 +1,21 @@
+// Implementation of Subpixel Morphological Antialiasing (SMAA) is based on https://github.com/iryoku/smaa
+
+attribute vec2 a_pos;
+attribute vec2 a_tcoord;
+
+uniform vec4 u_framebufferMetrics;
+
+varying vec2 v_colorTexCoords;
+varying vec4 v_offset0;
+varying vec4 v_offset1;
+varying vec4 v_offset2;
+
+void main()
+{
+ v_colorTexCoords = a_tcoord;
+ v_offset0 = u_framebufferMetrics.xyxy * vec4(-1.0, 0.0, 0.0, -1.0) + a_tcoord.xyxy;
+ v_offset1 = u_framebufferMetrics.xyxy * vec4( 1.0, 0.0, 0.0, 1.0) + a_tcoord.xyxy;
+ v_offset2 = u_framebufferMetrics.xyxy * vec4(-2.0, 0.0, 0.0, -2.0) + a_tcoord.xyxy;
+ gl_Position = vec4(a_pos, 0.0, 1.0);
+}
+
diff --git a/drape_frontend/shaders/smaa_final.fsh.glsl b/drape_frontend/shaders/smaa_final.fsh.glsl
new file mode 100644
index 0000000000..01054dedb4
--- /dev/null
+++ b/drape_frontend/shaders/smaa_final.fsh.glsl
@@ -0,0 +1,51 @@
+// Implementation of Subpixel Morphological Antialiasing (SMAA) is based on https://github.com/iryoku/smaa
+
+uniform sampler2D u_colorTex;
+uniform sampler2D u_blendingWeightTex;
+
+uniform vec4 u_framebufferMetrics;
+
+varying vec2 v_colorTexCoords;
+varying vec4 v_offset;
+
+#ifdef GLES3
+ #define SMAASampleLevelZero(tex, coord) textureLod(tex, coord, 0.0)
+#else
+ #define SMAASampleLevelZero(tex, coord) texture2D(tex, coord)
+#endif
+
+void main()
+{
+ // Fetch the blending weights for current pixel.
+ vec4 a;
+ a.x = texture2D(u_blendingWeightTex, v_offset.xy).a; // Right
+ a.y = texture2D(u_blendingWeightTex, v_offset.zw).g; // Top
+ a.wz = texture2D(u_blendingWeightTex, v_colorTexCoords).xz; // Bottom / Left
+
+ // Is there any blending weight with a value greater than 0.0?
+ if (dot(a, vec4(1.0, 1.0, 1.0, 1.0)) < 1e-5)
+ {
+ gl_FragColor = texture2D(u_colorTex, v_colorTexCoords);
+ }
+ else
+ {
+ // Calculate the blending offsets.
+ vec4 blendingOffset = vec4(0.0, a.y, 0.0, a.w);
+ vec2 blendingWeight = a.yw;
+ if (max(a.x, a.z) > max(a.y, a.w))
+ {
+ blendingOffset = vec4(a.x, 0.0, a.z, 0.0);
+ blendingWeight = a.xz;
+ }
+ blendingWeight /= dot(blendingWeight, vec2(1.0, 1.0));
+
+ // Calculate the texture coordinates.
+ vec4 bc = blendingOffset * vec4(u_framebufferMetrics.xy, -u_framebufferMetrics.xy);
+ bc += v_colorTexCoords.xyxy;
+
+ // We exploit bilinear filtering to mix current pixel with the chosen neighbor.
+ vec4 color = blendingWeight.x * SMAASampleLevelZero(u_colorTex, bc.xy);
+ color += blendingWeight.y * SMAASampleLevelZero(u_colorTex, bc.zw);
+ gl_FragColor = color;
+ }
+}
diff --git a/drape_frontend/shaders/smaa_final.vsh.glsl b/drape_frontend/shaders/smaa_final.vsh.glsl
new file mode 100644
index 0000000000..7f872d4f1d
--- /dev/null
+++ b/drape_frontend/shaders/smaa_final.vsh.glsl
@@ -0,0 +1,16 @@
+// Implementation of Subpixel Morphological Antialiasing (SMAA) is based on https://github.com/iryoku/smaa
+
+attribute vec2 a_pos;
+attribute vec2 a_tcoord;
+
+uniform vec4 u_framebufferMetrics;
+
+varying vec2 v_colorTexCoords;
+varying vec4 v_offset;
+
+void main()
+{
+ v_colorTexCoords = a_tcoord;
+ v_offset = u_framebufferMetrics.xyxy * vec4(1.0, 0.0, 0.0, 1.0) + a_tcoord.xyxy;
+ gl_Position = vec4(a_pos, 0.0, 1.0);
+}
diff --git a/geometry/rect2d.hpp b/geometry/rect2d.hpp
index 4eb42e75a4..bb77e21a49 100644
--- a/geometry/rect2d.hpp
+++ b/geometry/rect2d.hpp
@@ -355,6 +355,17 @@ namespace m2
);
}
+ template <typename T, typename TCollection>
+ inline bool HasIntersection(m2::Rect<T> const & rect, TCollection const & geometry)
+ {
+ for (auto const & g : geometry)
+ {
+ if (rect.IsIntersect(g))
+ return true;
+ }
+ return false;
+ };
+
template <class TArchive, class PointT>
TArchive & operator >> (TArchive & ar, m2::Rect<PointT> & rect)
{
diff --git a/indexer/map_style_reader.cpp b/indexer/map_style_reader.cpp
index 68f38a7213..1ebedfaccb 100644
--- a/indexer/map_style_reader.cpp
+++ b/indexer/map_style_reader.cpp
@@ -1,16 +1,13 @@
#include "map_style_reader.hpp"
-#include "base/logging.hpp"
-
#include "coding/file_name_utils.hpp"
#include "platform/platform.hpp"
-#include <string>
+#include "base/logging.hpp"
namespace
{
-
std::string const kSuffixDark = "_dark";
std::string const kSuffixClear = "_clear";
std::string const kSuffixVehicleDark = "_vehicle_dark";
@@ -18,7 +15,7 @@ std::string const kSuffixVehicleClear = "_vehicle_clear";
std::string const kStylesOverrideDir = "styles";
-string GetStyleRulesSuffix(MapStyle mapStyle)
+std::string GetStyleRulesSuffix(MapStyle mapStyle)
{
switch (mapStyle)
{
@@ -31,7 +28,7 @@ string GetStyleRulesSuffix(MapStyle mapStyle)
case MapStyleVehicleClear:
return kSuffixVehicleClear;
case MapStyleMerged:
- return string();
+ return std::string();
case MapStyleCount:
break;
@@ -40,7 +37,7 @@ string GetStyleRulesSuffix(MapStyle mapStyle)
return kSuffixClear;
}
-string GetStyleResourcesSuffix(MapStyle mapStyle)
+std::string GetStyleResourcesSuffix(MapStyle mapStyle)
{
// We use the same resources for default and vehicle styles
// to avoid textures duplication and package size increasing.
@@ -53,7 +50,7 @@ string GetStyleResourcesSuffix(MapStyle mapStyle)
case MapStyleVehicleClear:
return kSuffixClear;
case MapStyleMerged:
- return string();
+ return std::string();
case MapStyleCount:
break;
@@ -61,13 +58,11 @@ string GetStyleResourcesSuffix(MapStyle mapStyle)
LOG(LWARNING, ("Unknown map style", mapStyle));
return kSuffixClear;
}
-
} // namespace
StyleReader::StyleReader()
: m_mapStyle(kDefaultMapStyle)
-{
-}
+{}
void StyleReader::SetCurrentStyle(MapStyle mapStyle)
{
@@ -81,27 +76,37 @@ MapStyle StyleReader::GetCurrentStyle()
ReaderPtr<Reader> StyleReader::GetDrawingRulesReader()
{
- string rulesFile = string("drules_proto") + GetStyleRulesSuffix(GetCurrentStyle()) + ".bin";
+ std::string rulesFile =
+ std::string("drules_proto") + GetStyleRulesSuffix(GetCurrentStyle()) + ".bin";
- auto overriddenRulesFile = my::JoinFoldersToPath({GetPlatform().WritableDir(), kStylesOverrideDir}, rulesFile);
+ auto overriddenRulesFile =
+ my::JoinFoldersToPath({GetPlatform().WritableDir(), kStylesOverrideDir}, rulesFile);
if (GetPlatform().IsFileExistsByFullPath(overriddenRulesFile))
rulesFile = overriddenRulesFile;
return GetPlatform().GetReader(rulesFile);
}
-ReaderPtr<Reader> StyleReader::GetResourceReader(string const & file, string const & density)
+ReaderPtr<Reader> StyleReader::GetResourceReader(std::string const & file,
+ std::string const & density)
{
- string const resourceDir = string("resources-") + density + GetStyleResourcesSuffix(GetCurrentStyle());
- string resFile = my::JoinFoldersToPath(resourceDir, file);
+ std::string const resourceDir =
+ std::string("resources-") + density + GetStyleResourcesSuffix(GetCurrentStyle());
+ std::string resFile = my::JoinFoldersToPath(resourceDir, file);
- auto overriddenResFile = my::JoinFoldersToPath({GetPlatform().WritableDir(), kStylesOverrideDir}, resFile);
+ auto overriddenResFile =
+ my::JoinFoldersToPath({GetPlatform().WritableDir(), kStylesOverrideDir}, resFile);
if (GetPlatform().IsFileExistsByFullPath(overriddenResFile))
resFile = overriddenResFile;
return GetPlatform().GetReader(resFile);
}
+ReaderPtr<Reader> StyleReader::GetDefaultResourceReader(std::string const & file)
+{
+ return GetPlatform().GetReader(my::JoinFoldersToPath("resources-default", file));
+}
+
StyleReader & GetStyleReader()
{
static StyleReader instance;
diff --git a/indexer/map_style_reader.hpp b/indexer/map_style_reader.hpp
index 63ff46a47a..5c488614d3 100644
--- a/indexer/map_style_reader.hpp
+++ b/indexer/map_style_reader.hpp
@@ -4,6 +4,8 @@
#include "map_style.hpp"
+#include <string>
+
class StyleReader
{
public:
@@ -14,7 +16,8 @@ public:
ReaderPtr<Reader> GetDrawingRulesReader();
- ReaderPtr<Reader> GetResourceReader(string const & file, string const & density);
+ ReaderPtr<Reader> GetResourceReader(std::string const & file, std::string const & density);
+ ReaderPtr<Reader> GetDefaultResourceReader(std::string const & file);
private:
MapStyle m_mapStyle;
diff --git a/map/framework.cpp b/map/framework.cpp
index 969cd06b19..15caf2ccab 100644
--- a/map/framework.cpp
+++ b/map/framework.cpp
@@ -3072,16 +3072,31 @@ bool Framework::ParseDrapeDebugCommand(std::string const & query)
desiredStyle = MapStyleVehicleDark;
else if (query == "?vlight" || query == "mapstyle:vehicle_light")
desiredStyle = MapStyleVehicleClear;
- else
- return false;
+ if (desiredStyle != MapStyleCount)
+ {
#if defined(OMIM_OS_ANDROID)
- MarkMapStyle(desiredStyle);
+ MarkMapStyle(desiredStyle);
#else
- SetMapStyle(desiredStyle);
+ SetMapStyle(desiredStyle);
#endif
+ return true;
+ }
- return true;
+ if (query == "?aa" || query == "effect:antialiasing")
+ {
+ m_drapeEngine->SetPosteffectEnabled(df::PostprocessRenderer::Antialiasing,
+ true /* enabled */);
+ return true;
+ }
+ else if (query == "?no-aa" || query == "effect:no-antialiasing")
+ {
+ m_drapeEngine->SetPosteffectEnabled(df::PostprocessRenderer::Antialiasing,
+ false /* enabled */);
+ return true;
+ }
+
+ return false;
}
bool Framework::ParseEditorDebugCommand(search::SearchParams const & params)
diff --git a/qt/qt_common/map_widget.cpp b/qt/qt_common/map_widget.cpp
index 4af959574b..bd2746a890 100644
--- a/qt/qt_common/map_widget.cpp
+++ b/qt/qt_common/map_widget.cpp
@@ -21,6 +21,8 @@ namespace qt
{
namespace common
{
+//#define ENABLE_AA_SWITCH
+
MapWidget::MapWidget(Framework & framework, bool apiOpenGLES3, QWidget * parent)
: QOpenGLWidget(parent)
, m_framework(framework)
@@ -54,6 +56,11 @@ void MapWidget::BindHotkeys(QWidget & parent)
{Qt::Key_Minus, SLOT(ScaleMinus())},
{Qt::ALT + Qt::Key_Equal, SLOT(ScalePlusLight())},
{Qt::ALT + Qt::Key_Minus, SLOT(ScaleMinusLight())},
+ {Qt::ALT + Qt::Key_Minus, SLOT(ScaleMinusLight())},
+#ifdef ENABLE_AA_SWITCH
+ {Qt::ALT + Qt::Key_A, SLOT(AntialiasingOn())},
+ {Qt::ALT + Qt::Key_S, SLOT(AntialiasingOff())},
+#endif
};
for (auto const & hotkey : hotkeys)
@@ -104,6 +111,20 @@ void MapWidget::ScalePlusLight() { m_framework.Scale(Framework::SCALE_MAG_LIGHT,
void MapWidget::ScaleMinusLight() { m_framework.Scale(Framework::SCALE_MIN_LIGHT, true); }
+void MapWidget::AntialiasingOn()
+{
+ auto engine = m_framework.GetDrapeEngine();
+ if (engine != nullptr)
+ engine->SetPosteffectEnabled(df::PostprocessRenderer::Antialiasing, true);
+}
+
+void MapWidget::AntialiasingOff()
+{
+ auto engine = m_framework.GetDrapeEngine();
+ if (engine != nullptr)
+ engine->SetPosteffectEnabled(df::PostprocessRenderer::Antialiasing, false);
+}
+
void MapWidget::ScaleChanged(int action)
{
if (!m_slider)
diff --git a/qt/qt_common/map_widget.hpp b/qt/qt_common/map_widget.hpp
index ce37dcf09e..4956b592a8 100644
--- a/qt/qt_common/map_widget.hpp
+++ b/qt/qt_common/map_widget.hpp
@@ -46,6 +46,9 @@ public Q_SLOTS:
void SliderPressed();
void SliderReleased();
+ void AntialiasingOn();
+ void AntialiasingOff();
+
public:
Q_SIGNAL void BeforeEngineCreation();
diff --git a/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj b/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj
index 40fb7faddc..bd30acd56a 100644
--- a/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj
+++ b/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj
@@ -45,6 +45,8 @@
454C19BD1CCE3EC0002A2C86 /* animation_system.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 454C19BA1CCE3EC0002A2C86 /* animation_system.hpp */; };
45580ABA1E28DB2600CD535D /* scenario_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45580AB81E28DB2600CD535D /* scenario_manager.cpp */; };
45580ABB1E28DB2600CD535D /* scenario_manager.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45580AB91E28DB2600CD535D /* scenario_manager.hpp */; };
+ 456B3F991ED464FE009B3D1F /* postprocess_renderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 456B3F971ED464FE009B3D1F /* postprocess_renderer.cpp */; };
+ 456B3F9A1ED464FE009B3D1F /* postprocess_renderer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 456B3F981ED464FE009B3D1F /* postprocess_renderer.hpp */; };
457D89251E7AE89500049500 /* custom_symbol.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 457D89241E7AE89500049500 /* custom_symbol.hpp */; };
45B4B8CB1CF5C16B00A54761 /* screen_animations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45B4B8C71CF5C16B00A54761 /* screen_animations.cpp */; };
45B4B8CC1CF5C16B00A54761 /* screen_animations.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45B4B8C81CF5C16B00A54761 /* screen_animations.hpp */; };
@@ -275,6 +277,8 @@
45580AB81E28DB2600CD535D /* scenario_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scenario_manager.cpp; sourceTree = "<group>"; };
45580AB91E28DB2600CD535D /* scenario_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = scenario_manager.hpp; sourceTree = "<group>"; };
4560692B1EB9F9D2009AB7B7 /* shaders_lib.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = shaders_lib.glsl; path = shaders/shaders_lib.glsl; sourceTree = "<group>"; };
+ 456B3F971ED464FE009B3D1F /* postprocess_renderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = postprocess_renderer.cpp; sourceTree = "<group>"; };
+ 456B3F981ED464FE009B3D1F /* postprocess_renderer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = postprocess_renderer.hpp; sourceTree = "<group>"; };
457D89241E7AE89500049500 /* custom_symbol.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = custom_symbol.hpp; sourceTree = "<group>"; };
45B4B8C71CF5C16B00A54761 /* screen_animations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = screen_animations.cpp; sourceTree = "<group>"; };
45B4B8C81CF5C16B00A54761 /* screen_animations.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = screen_animations.hpp; sourceTree = "<group>"; };
@@ -605,6 +609,8 @@
670947411BDF9B99005014C0 /* drape_frontend */ = {
isa = PBXGroup;
children = (
+ 456B3F971ED464FE009B3D1F /* postprocess_renderer.cpp */,
+ 456B3F981ED464FE009B3D1F /* postprocess_renderer.hpp */,
45BB025B1EB8BE5200FE5C0C /* shader_def.cpp */,
45BB025C1EB8BE5200FE5C0C /* shader_def.hpp */,
45BB02221EB8BE1400FE5C0C /* shaders */,
@@ -859,6 +865,7 @@
6709486A1BDF9C7F005014C0 /* brush_info.hpp in Headers */,
675D218E1BFB871D00717E4F /* rect.h in Headers */,
670948191BDF9C39005014C0 /* interpolations.hpp in Headers */,
+ 456B3F9A1ED464FE009B3D1F /* postprocess_renderer.hpp in Headers */,
670947CB1BDF9BE1005014C0 /* threads_commutator.hpp in Headers */,
347F52121DC2334A0064B273 /* drape_api.hpp in Headers */,
670948701BDF9C7F005014C0 /* feature_processor.hpp in Headers */,
@@ -1106,6 +1113,7 @@
347F52111DC2334A0064B273 /* drape_api.cpp in Sources */,
347F520F1DC2334A0064B273 /* drape_api_renderer.cpp in Sources */,
347F520D1DC2334A0064B273 /* drape_api_builder.cpp in Sources */,
+ 456B3F991ED464FE009B3D1F /* postprocess_renderer.cpp in Sources */,
670947CA1BDF9BE1005014C0 /* threads_commutator.cpp in Sources */,
670947981BDF9BE1005014C0 /* map_data_provider.cpp in Sources */,
670948181BDF9C39005014C0 /* interpolations.cpp in Sources */,