diff --git a/.github/workflows/linux-check.yaml b/.github/workflows/linux-check.yaml
index 17adeecbd2..bce6b20487 100644
--- a/.github/workflows/linux-check.yaml
+++ b/.github/workflows/linux-check.yaml
@@ -61,6 +61,10 @@ jobs:
libgl1-mesa-dev \
libglvnd-dev \
libharfbuzz-dev \
+ libxrandr-dev \
+ libxinerama-dev \
+ libxcursor-dev \
+ libxi-dev \
qt6-base-dev \
libqt6svg6-dev \
qt6-positioning-dev \
@@ -128,6 +132,10 @@ jobs:
libgl1-mesa-dev \
libglvnd-dev \
libharfbuzz-dev \
+ libxrandr-dev \
+ libxinerama-dev \
+ libxcursor-dev \
+ libxi-dev \
qt6-base-dev \
libqt6svg6-dev \
qt6-positioning-dev \
diff --git a/.gitmodules b/.gitmodules
index 7d35fe8264..b059cf9425 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -59,3 +59,12 @@
[submodule "3party/utfcpp"]
path = 3party/utfcpp
url = https://github.com/nemtrif/utfcpp.git
+[submodule "3party/glfw"]
+ path = 3party/glfw
+ url = https://github.com/glfw/glfw.git
+[submodule "3party/CMake-MetalShaderSupport"]
+ path = 3party/CMake-MetalShaderSupport
+ url = https://github.com/dpogue/CMake-MetalShaderSupport.git
+[submodule "3party/imgui/imgui"]
+ path = 3party/imgui/imgui
+ url = https://github.com/ocornut/imgui
diff --git a/3party/CMake-MetalShaderSupport b/3party/CMake-MetalShaderSupport
new file mode 160000
index 0000000000..989857d2e5
--- /dev/null
+++ b/3party/CMake-MetalShaderSupport
@@ -0,0 +1 @@
+Subproject commit 989857d2e5e54869c35ad06fb21a67d12a2dbc67
diff --git a/3party/CMakeLists.txt b/3party/CMakeLists.txt
index 57d0592dc3..d5635d56fb 100644
--- a/3party/CMakeLists.txt
+++ b/3party/CMakeLists.txt
@@ -66,4 +66,19 @@ add_subdirectory(vulkan_wrapper)
if (PLATFORM_DESKTOP)
add_subdirectory(libtess2)
+
+ set(GLFW_BUILD_DOCS OFF CACHE BOOL "")
+ set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "")
+ set(GLFW_BUILD_TESTS OFF CACHE BOOL "")
+ set(GLFW_INSTALL OFF CACHE BOOL "")
+ set(GLFW_VULKAN_STATIC OFF CACHE BOOL "")
+ set(GLFW_BUILD_WAYLAND OFF CACHE BOOL "")
+ # Disable ARC for glfw and re-enable after it because it's globally set in the root CMakeLists.txt
+ set(CMAKE_OBJC_FLAGS "")
+ add_subdirectory(glfw)
+ set_target_properties(glfw PROPERTIES UNITY_BUILD OFF)
+ set_target_properties(glfw PROPERTIES XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC NO)
+ set(CMAKE_OBJC_FLAGS -fobjc-arc)
+
+ add_subdirectory(imgui)
endif()
diff --git a/3party/glfw b/3party/glfw
new file mode 160000
index 0000000000..21fea01161
--- /dev/null
+++ b/3party/glfw
@@ -0,0 +1 @@
+Subproject commit 21fea01161e0d6b70c0c5c1f52dc8e7a7df14a50
diff --git a/3party/imgui/CMakeLists.txt b/3party/imgui/CMakeLists.txt
new file mode 100644
index 0000000000..ebbdde8c48
--- /dev/null
+++ b/3party/imgui/CMakeLists.txt
@@ -0,0 +1,16 @@
+project(imgui)
+
+set(SRC
+ imgui/imgui_draw.cpp
+ imgui/imgui_tables.cpp
+ imgui/imgui_widgets.cpp
+ imgui/imgui.cpp
+ imgui/backends/imgui_impl_glfw.cpp
+)
+
+add_library(${PROJECT_NAME} ${SRC})
+target_include_directories(${PROJECT_NAME}
+ PRIVATE ${OMIM_ROOT}/3party/glfw/include
+ PUBLIC ${OMIM_ROOT}/3party/imgui/imgui
+ PUBLIC .
+)
diff --git a/3party/imgui/imgui b/3party/imgui/imgui
new file mode 160000
index 0000000000..6982ce43f5
--- /dev/null
+++ b/3party/imgui/imgui
@@ -0,0 +1 @@
+Subproject commit 6982ce43f5b143c5dce5fab0ce07dd4867b705ae
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 30c1a0e496..c62396a763 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -90,6 +90,19 @@ else()
message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
endif()
+if(${PLATFORM_MAC})
+ set(XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES)
+
+ # Metal language support
+ list(APPEND CMAKE_MODULE_PATH ${OMIM_ROOT}/3party/CMake-MetalShaderSupport/cmake)
+ include(CheckLanguage)
+ include(MetalShaderSupport)
+ check_language(Metal)
+ if(CMAKE_Metal_COMPILER)
+ enable_language(Metal)
+ endif()
+endif()
+
# Sanitizer
if (PLATFORM_DESKTOP)
# https://clang.llvm.org/docs/UsersManual.html#controlling-code-generation
@@ -394,6 +407,7 @@ if (PLATFORM_DESKTOP)
add_subdirectory(qt)
omim_add_tool_subdirectory(skin_generator)
endif()
+ add_subdirectory(dev_sandbox)
endif()
omim_add_test_subdirectory(qt_tstfrm)
diff --git a/android/app/src/main/cpp/app/organicmaps/Framework.cpp b/android/app/src/main/cpp/app/organicmaps/Framework.cpp
index 905a6b36fe..223aaa3b45 100644
--- a/android/app/src/main/cpp/app/organicmaps/Framework.cpp
+++ b/android/app/src/main/cpp/app/organicmaps/Framework.cpp
@@ -224,8 +224,7 @@ bool Framework::CreateDrapeEngine(JNIEnv * env, jobject jSurface, int densityDpi
LOG(LWARNING, ("Invalid GL context."));
return false;
}
- p.m_apiVersion = oglFactory->IsSupportedOpenGLES3() ? dp::ApiVersion::OpenGLES3 :
- dp::ApiVersion::OpenGLES2;
+ p.m_apiVersion = dp::ApiVersion::OpenGLES3;
p.m_surfaceWidth = oglFactory->GetWidth();
p.m_surfaceHeight = oglFactory->GetHeight();
diff --git a/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontext.cpp b/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontext.cpp
index 0c73761217..bfe5b38410 100644
--- a/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontext.cpp
+++ b/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontext.cpp
@@ -8,20 +8,16 @@
namespace android
{
-static EGLint * getContextAttributesList(bool supportedES3)
+static EGLint * getContextAttributesList()
{
static EGLint contextAttrList[] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE
- };
- static EGLint contextAttrListES3[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
- return supportedES3 ? contextAttrListES3 : contextAttrList;
+ return contextAttrList;
}
-AndroidOGLContext::AndroidOGLContext(bool supportedES3, EGLDisplay display, EGLSurface surface,
+AndroidOGLContext::AndroidOGLContext(EGLDisplay display, EGLSurface surface,
EGLConfig config, AndroidOGLContext * contextToShareWith)
: m_nativeContext(EGL_NO_CONTEXT)
, m_surface(surface)
@@ -32,7 +28,7 @@ AndroidOGLContext::AndroidOGLContext(bool supportedES3, EGLDisplay display, EGLS
ASSERT(m_display != EGL_NO_DISPLAY, ());
EGLContext sharedContext = (contextToShareWith == NULL) ? EGL_NO_CONTEXT : contextToShareWith->m_nativeContext;
- m_nativeContext = eglCreateContext(m_display, config, sharedContext, getContextAttributesList(supportedES3));
+ m_nativeContext = eglCreateContext(m_display, config, sharedContext, getContextAttributesList());
CHECK(m_nativeContext != EGL_NO_CONTEXT, ());
}
diff --git a/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontext.hpp b/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontext.hpp
index 385d801548..6f7885b644 100644
--- a/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontext.hpp
+++ b/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontext.hpp
@@ -10,7 +10,7 @@ namespace android
class AndroidOGLContext : public dp::OGLContext
{
public:
- AndroidOGLContext(bool supportedES3, EGLDisplay display, EGLSurface surface,
+ AndroidOGLContext(EGLDisplay display, EGLSurface surface,
EGLConfig config, AndroidOGLContext * contextToShareWith);
~AndroidOGLContext();
diff --git a/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontextfactory.cpp b/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontextfactory.cpp
index 00f576dbe9..88b0c93911 100644
--- a/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontextfactory.cpp
+++ b/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontextfactory.cpp
@@ -16,26 +16,13 @@
#define EGL_OPENGL_ES3_BIT 0x00000040
-int constexpr kMinSdkVersionForES3 = 21;
-
namespace android
{
namespace
{
-static EGLint * getConfigAttributesListRGB8(bool supportedES3)
+static EGLint * getConfigAttributesListRGB8()
{
static EGLint attr_list[] = {
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 0,
- EGL_STENCIL_SIZE, 0,
- EGL_DEPTH_SIZE, 16,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_SURFACE_TYPE, EGL_PBUFFER_BIT | EGL_WINDOW_BIT,
- EGL_NONE
- };
- static EGLint attr_list_es3[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
@@ -46,33 +33,16 @@ static EGLint * getConfigAttributesListRGB8(bool supportedES3)
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT | EGL_WINDOW_BIT,
EGL_NONE
};
- return supportedES3 ? attr_list_es3 : attr_list;
+ return attr_list;
}
int const kMaxConfigCount = 40;
-static EGLint * getConfigAttributesListR5G6B5()
-{
- // We do not support OpenGL ES3 for R5G6B5, because some Android devices
- // are not able to create OpenGL context in such mode.
- static EGLint attr_list[] = {
- EGL_RED_SIZE, 5,
- EGL_GREEN_SIZE, 6,
- EGL_BLUE_SIZE, 5,
- EGL_STENCIL_SIZE, 0,
- EGL_DEPTH_SIZE, 16,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_SURFACE_TYPE, EGL_PBUFFER_BIT | EGL_WINDOW_BIT,
- EGL_NONE
- };
- return attr_list;
-}
-
-bool IsSupportedRGB8(EGLDisplay display, bool es3)
+bool IsSupportedRGB8(EGLDisplay display)
{
EGLConfig configs[kMaxConfigCount];
int count = 0;
- return eglChooseConfig(display, getConfigAttributesListRGB8(es3), configs,
+ return eglChooseConfig(display, getConfigAttributesListRGB8(), configs,
kMaxConfigCount, &count) == EGL_TRUE && count != 0;
}
@@ -90,7 +60,6 @@ AndroidOGLContextFactory::AndroidOGLContextFactory(JNIEnv * env, jobject jsurfac
, m_surfaceWidth(0)
, m_surfaceHeight(0)
, m_windowSurfaceValid(false)
- , m_supportedES3(false)
{
m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (m_display == EGL_NO_DISPLAY)
@@ -106,10 +75,7 @@ AndroidOGLContextFactory::AndroidOGLContextFactory(JNIEnv * env, jobject jsurfac
return;
}
- // Check ES3 availability.
- bool const isES3Supported = IsSupportedRGB8(m_display, true /* es3 */) &&
- android_get_device_api_level() >= kMinSdkVersionForES3;
- m_supportedES3 = isES3Supported && gl3stubInit();
+ CHECK(gl3stubInit(), ("Could not initialize OpenGL ES3"));
SetSurface(env, jsurface);
@@ -266,7 +232,7 @@ dp::GraphicsContext * AndroidOGLContextFactory::GetDrawContext()
ASSERT(m_windowSurface != EGL_NO_SURFACE, ());
if (m_drawContext == nullptr)
{
- m_drawContext = new AndroidOGLContext(m_supportedES3, m_display, m_windowSurface,
+ m_drawContext = new AndroidOGLContext(m_display, m_windowSurface,
m_config, m_uploadContext);
}
return m_drawContext;
@@ -278,7 +244,7 @@ dp::GraphicsContext * AndroidOGLContextFactory::GetResourcesUploadContext()
ASSERT(m_pixelbufferSurface != EGL_NO_SURFACE, ());
if (m_uploadContext == nullptr)
{
- m_uploadContext = new AndroidOGLContext(m_supportedES3, m_display, m_pixelbufferSurface,
+ m_uploadContext = new AndroidOGLContext(m_display, m_pixelbufferSurface,
m_config, m_drawContext);
}
return m_uploadContext;
@@ -322,17 +288,15 @@ bool AndroidOGLContextFactory::CreateWindowSurface()
{
EGLConfig configs[kMaxConfigCount];
int count = 0;
- if (eglChooseConfig(m_display, getConfigAttributesListRGB8(m_supportedES3), configs,
- kMaxConfigCount, &count) != EGL_TRUE)
+ if (eglChooseConfig(m_display, getConfigAttributesListRGB8(), configs,
+ kMaxConfigCount, &count) == EGL_TRUE)
{
- ASSERT(!m_supportedES3, ());
- VERIFY(eglChooseConfig(m_display, getConfigAttributesListR5G6B5(), configs,
- kMaxConfigCount, &count) == EGL_TRUE, ());
- LOG(LDEBUG, ("Backbuffer format: R5G6B5"));
+ CHECK(IsSupportedRGB8(m_display), ("RGB8 is not suported on this device"));
+ LOG(LDEBUG, ("Backbuffer format: RGB8"));
}
else
{
- LOG(LDEBUG, ("Backbuffer format: RGB8"));
+ CHECK(false, ("OpenGL ES3 is not supported"));
}
ASSERT(count > 0, ("Didn't find any configs."));
diff --git a/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontextfactory.hpp b/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontextfactory.hpp
index 8f886a9c4e..edbc425550 100644
--- a/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontextfactory.hpp
+++ b/android/app/src/main/cpp/app/organicmaps/opengl/androidoglcontextfactory.hpp
@@ -33,8 +33,6 @@ public:
int GetHeight() const;
void UpdateSurfaceSize(int w, int h);
- bool IsSupportedOpenGLES3() const { return m_supportedES3; }
-
private:
bool QuerySurfaceSize();
@@ -56,7 +54,6 @@ private:
int m_surfaceHeight;
bool m_windowSurfaceValid;
- bool m_supportedES3;
bool m_isInitialized = false;
size_t m_initializationCounter = 0;
diff --git a/data/copyright.html b/data/copyright.html
index b83b74ae60..c517a2b17c 100644
--- a/data/copyright.html
+++ b/data/copyright.html
@@ -155,6 +155,12 @@
The FreeType Project License
diff --git a/data/vulkan_shaders/reflection.json b/data/vulkan_shaders/reflection.json
index bca74ae8eb..e2784fb8a2 100644
--- a/data/vulkan_shaders/reflection.json
+++ b/data/vulkan_shaders/reflection.json
@@ -1 +1 @@
-[{"prg":0,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":0,"vs_size":3772,"fs_off":3772,"fs_size":2552},{"prg":1,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":6324,"vs_size":3412,"fs_off":9736,"fs_size":1508},{"prg":2,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1},{"name":"u_maskTex","idx":2,"frag":1}]},"vs_off":11244,"vs_size":3560,"fs_off":14804,"fs_size":1756},{"prg":3,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":16560,"vs_size":4468,"fs_off":21028,"fs_size":2508},{"prg":4,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":23536,"vs_size":4468,"fs_off":28004,"fs_size":2508},{"prg":5,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":30512,"vs_size":4440,"fs_off":34952,"fs_size":2084},{"prg":6,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":37036,"vs_size":3768,"fs_off":40804,"fs_size":2084},{"prg":7,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":42888,"vs_size":3104,"fs_off":45992,"fs_size":1992},{"prg":8,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":47984,"vs_size":3104,"fs_off":51088,"fs_size":1992},{"prg":9,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":53080,"vs_size":3352,"fs_off":56432,"fs_size":1336},{"prg":10,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":57768,"vs_size":3352,"fs_off":61120,"fs_size":1336},{"prg":11,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":62456,"vs_size":3692,"fs_off":66148,"fs_size":1904},{"prg":12,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":68052,"vs_size":2716,"fs_off":70768,"fs_size":1336},{"prg":13,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":72104,"vs_size":5084,"fs_off":77188,"fs_size":1332},{"prg":14,"info":{"vs_uni":0,"fs_uni":-1,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":78520,"vs_size":5436,"fs_off":83956,"fs_size":1800},{"prg":15,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1},{"name":"u_maskTex","idx":2,"frag":1}]},"vs_off":85756,"vs_size":5452,"fs_off":91208,"fs_size":1828},{"prg":16,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":93036,"vs_size":3988,"fs_off":97024,"fs_size":1508},{"prg":17,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":98532,"vs_size":3352,"fs_off":101884,"fs_size":1336},{"prg":18,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":103220,"vs_size":3696,"fs_off":106916,"fs_size":2092},{"prg":19,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":109008,"vs_size":3516,"fs_off":112524,"fs_size":1716},{"prg":20,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":114240,"vs_size":1820,"fs_off":116060,"fs_size":1416},{"prg":21,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":117476,"vs_size":2064,"fs_off":119540,"fs_size":1416},{"prg":22,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":120956,"vs_size":3640,"fs_off":124596,"fs_size":1540},{"prg":23,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":126136,"vs_size":4140,"fs_off":130276,"fs_size":1540},{"prg":24,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":131816,"vs_size":5812,"fs_off":137628,"fs_size":1868},{"prg":25,"info":{"vs_uni":0,"fs_uni":-1,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":139496,"vs_size":4976,"fs_off":144472,"fs_size":832},{"prg":26,"info":{"vs_uni":0,"fs_uni":-1,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":145304,"vs_size":4440,"fs_off":149744,"fs_size":1984},{"prg":27,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":151728,"vs_size":5928,"fs_off":157656,"fs_size":4644},{"prg":28,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":162300,"vs_size":5928,"fs_off":168228,"fs_size":4240},{"prg":29,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":172468,"vs_size":5228,"fs_off":177696,"fs_size":2332},{"prg":30,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":180028,"vs_size":4772,"fs_off":184800,"fs_size":3332},{"prg":31,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":188132,"vs_size":3624,"fs_off":191756,"fs_size":2344},{"prg":32,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":194100,"vs_size":4468,"fs_off":198568,"fs_size":2508},{"prg":33,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":201076,"vs_size":4468,"fs_off":205544,"fs_size":2508},{"prg":34,"info":{"vs_uni":-1,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":208052,"vs_size":1104,"fs_off":209156,"fs_size":992},{"prg":35,"info":{"vs_uni":-1,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":210148,"vs_size":920,"fs_off":211068,"fs_size":1180},{"prg":36,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":212248,"vs_size":2044,"fs_off":214292,"fs_size":1904},{"prg":37,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":216196,"vs_size":2416,"fs_off":218612,"fs_size":1856},{"prg":38,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":220468,"vs_size":1880,"fs_off":222348,"fs_size":1628},{"prg":39,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":223976,"vs_size":1880,"fs_off":225856,"fs_size":1692},{"prg":40,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":227548,"vs_size":4280,"fs_off":231828,"fs_size":2552},{"prg":41,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":234380,"vs_size":4056,"fs_off":238436,"fs_size":1508},{"prg":42,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1},{"name":"u_maskTex","idx":2,"frag":1}]},"vs_off":239944,"vs_size":4204,"fs_off":244148,"fs_size":1756},{"prg":43,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":245904,"vs_size":4904,"fs_off":250808,"fs_size":2508},{"prg":44,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":253316,"vs_size":4904,"fs_off":258220,"fs_size":2508},{"prg":45,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":260728,"vs_size":4904,"fs_off":265632,"fs_size":2508},{"prg":46,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":268140,"vs_size":4904,"fs_off":273044,"fs_size":2508},{"prg":47,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":275552,"vs_size":4928,"fs_off":280480,"fs_size":2084},{"prg":48,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":282564,"vs_size":4412,"fs_off":286976,"fs_size":2084},{"prg":49,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1},{"name":"u_maskTex","idx":2,"frag":1}]},"vs_off":289060,"vs_size":6368,"fs_off":295428,"fs_size":3820},{"prg":50,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":299248,"vs_size":3492,"fs_off":302740,"fs_size":1616},{"prg":51,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":304356,"vs_size":5984,"fs_off":310340,"fs_size":2428},{"prg":52,"info":{"vs_uni":0,"fs_uni":-1,"tex":[{"name":"u_colorTex","idx":1,"frag":1}]},"vs_off":312768,"vs_size":1924,"fs_off":314692,"fs_size":4236},{"prg":53,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1},{"name":"u_smaaArea","idx":2,"frag":1},{"name":"u_smaaSearch","idx":3,"frag":1}]},"vs_off":318928,"vs_size":2300,"fs_off":321228,"fs_size":12356},{"prg":54,"info":{"vs_uni":0,"fs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1},{"name":"u_blendingWeightTex","idx":2,"frag":1}]},"vs_off":333584,"vs_size":1372,"fs_off":334956,"fs_size":3696}]
\ No newline at end of file
+[{"prg":0,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":0,"vs_size":3920,"fs_off":3920,"fs_size":2712},{"prg":1,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":6632,"vs_size":3560,"fs_off":10192,"fs_size":1636},{"prg":2,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":11828,"vs_size":3708,"fs_off":15536,"fs_size":1884},{"prg":3,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":17420,"vs_size":4612,"fs_off":22032,"fs_size":2636},{"prg":4,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":24668,"vs_size":4612,"fs_off":29280,"fs_size":2636},{"prg":5,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":31916,"vs_size":4584,"fs_off":36500,"fs_size":2228},{"prg":6,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":38728,"vs_size":3916,"fs_off":42644,"fs_size":2228},{"prg":7,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":44872,"vs_size":3228,"fs_off":48100,"fs_size":2132},{"prg":8,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":50232,"vs_size":3228,"fs_off":53460,"fs_size":2132},{"prg":9,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":55592,"vs_size":3500,"fs_off":59092,"fs_size":1480},{"prg":10,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":60572,"vs_size":3500,"fs_off":64072,"fs_size":1480},{"prg":11,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":65552,"vs_size":3832,"fs_off":69384,"fs_size":2032},{"prg":12,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":71416,"vs_size":2860,"fs_off":74276,"fs_size":1480},{"prg":13,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":75756,"vs_size":5232,"fs_off":80988,"fs_size":1476},{"prg":14,"info":{"vs_uni":0,"tex":[],"fs_uni":-1},"vs_off":82464,"vs_size":5464,"fs_off":87928,"fs_size":1448},{"prg":15,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":89376,"vs_size":5600,"fs_off":94976,"fs_size":1972},{"prg":16,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":96948,"vs_size":4136,"fs_off":101084,"fs_size":1636},{"prg":17,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":102720,"vs_size":3500,"fs_off":106220,"fs_size":1480},{"prg":18,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":107700,"vs_size":3844,"fs_off":111544,"fs_size":2396},{"prg":19,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":113940,"vs_size":3664,"fs_off":117604,"fs_size":1844},{"prg":20,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":119448,"vs_size":1964,"fs_off":121412,"fs_size":1540},{"prg":21,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":122952,"vs_size":2176,"fs_off":125128,"fs_size":1540},{"prg":22,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":126668,"vs_size":3788,"fs_off":130456,"fs_size":1676},{"prg":23,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":132132,"vs_size":4272,"fs_off":136404,"fs_size":1676},{"prg":24,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":138080,"vs_size":5968,"fs_off":144048,"fs_size":1812},{"prg":25,"info":{"vs_uni":0,"tex":[],"fs_uni":-1},"vs_off":145860,"vs_size":5016,"fs_off":150876,"fs_size":464},{"prg":26,"info":{"vs_uni":0,"tex":[],"fs_uni":-1},"vs_off":151340,"vs_size":4484,"fs_off":155824,"fs_size":1632},{"prg":27,"info":{"vs_uni":0,"tex":[],"fs_uni":0},"vs_off":157456,"vs_size":6080,"fs_off":163536,"fs_size":4432},{"prg":28,"info":{"vs_uni":0,"tex":[],"fs_uni":0},"vs_off":167968,"vs_size":6080,"fs_off":174048,"fs_size":4028},{"prg":29,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":178076,"vs_size":5376,"fs_off":183452,"fs_size":2464},{"prg":30,"info":{"vs_uni":0,"tex":[],"fs_uni":0},"vs_off":185916,"vs_size":4924,"fs_off":190840,"fs_size":3128},{"prg":31,"info":{"vs_uni":0,"tex":[],"fs_uni":0},"vs_off":193968,"vs_size":3772,"fs_off":197740,"fs_size":2120},{"prg":32,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":199860,"vs_size":4612,"fs_off":204472,"fs_size":2636},{"prg":33,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":207108,"vs_size":4612,"fs_off":211720,"fs_size":2636},{"prg":34,"info":{"vs_uni":-1,"tex":[],"fs_uni":0},"vs_off":214356,"vs_size":1104,"fs_off":215460,"fs_size":616},{"prg":35,"info":{"vs_uni":-1,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":216076,"vs_size":920,"fs_off":216996,"fs_size":1152},{"prg":36,"info":{"vs_uni":0,"tex":[],"fs_uni":0},"vs_off":218148,"vs_size":2060,"fs_off":220208,"fs_size":1488},{"prg":37,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":221696,"vs_size":2388,"fs_off":224084,"fs_size":1856},{"prg":38,"info":{"vs_uni":0,"tex":[],"fs_uni":0},"vs_off":225940,"vs_size":1880,"fs_off":227820,"fs_size":1212},{"prg":39,"info":{"vs_uni":0,"tex":[],"fs_uni":0},"vs_off":229032,"vs_size":1880,"fs_off":230912,"fs_size":1276},{"prg":40,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0}],"fs_uni":0},"vs_off":232188,"vs_size":4428,"fs_off":236616,"fs_size":2712},{"prg":41,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":239328,"vs_size":4200,"fs_off":243528,"fs_size":1636},{"prg":42,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":245164,"vs_size":4348,"fs_off":249512,"fs_size":1884},{"prg":43,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":251396,"vs_size":5048,"fs_off":256444,"fs_size":2636},{"prg":44,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":259080,"vs_size":5048,"fs_off":264128,"fs_size":2636},{"prg":45,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":266764,"vs_size":5048,"fs_off":271812,"fs_size":2636},{"prg":46,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":274448,"vs_size":5048,"fs_off":279496,"fs_size":2636},{"prg":47,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":282132,"vs_size":5084,"fs_off":287216,"fs_size":2228},{"prg":48,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":0},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":289444,"vs_size":4556,"fs_off":294000,"fs_size":2228},{"prg":49,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1},{"name":"u_maskTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":296228,"vs_size":6476,"fs_off":302704,"fs_size":3952},{"prg":50,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":306656,"vs_size":3600,"fs_off":310256,"fs_size":1688},{"prg":51,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":0},"vs_off":311944,"vs_size":6012,"fs_off":317956,"fs_size":2532},{"prg":52,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":-1},"vs_off":320488,"vs_size":1916,"fs_off":322404,"fs_size":4236},{"prg":53,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1},{"name":"u_smaaArea","idx":2,"frag":1},{"name":"u_smaaSearch","idx":3,"frag":1}],"fs_uni":0},"vs_off":326640,"vs_size":2292,"fs_off":328932,"fs_size":12348},{"prg":54,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1},{"name":"u_blendingWeightTex","idx":2,"frag":1}],"fs_uni":0},"vs_off":341280,"vs_size":1364,"fs_off":342644,"fs_size":3688},{"prg":55,"info":{"vs_uni":0,"tex":[{"name":"u_colorTex","idx":1,"frag":1}],"fs_uni":-1},"vs_off":346332,"vs_size":1692,"fs_off":348024,"fs_size":892}]
\ No newline at end of file
diff --git a/data/vulkan_shaders/shaders_pack.spv b/data/vulkan_shaders/shaders_pack.spv
index 2e8dcdff7c..cf7b08f3a1 100644
Binary files a/data/vulkan_shaders/shaders_pack.spv and b/data/vulkan_shaders/shaders_pack.spv differ
diff --git a/dev_sandbox/CMakeLists.txt b/dev_sandbox/CMakeLists.txt
new file mode 100644
index 0000000000..4680cfbe5e
--- /dev/null
+++ b/dev_sandbox/CMakeLists.txt
@@ -0,0 +1,144 @@
+project(dev_sandbox)
+
+set(SRC
+ main.cpp
+ imgui_renderer.cpp
+ imgui_renderer.hpp
+)
+
+if (${PLATFORM_MAC})
+ append(SRC
+ main.mm
+ ../iphone/Maps/Classes/MetalContextFactory.h
+ ../iphone/Maps/Classes/MetalContextFactory.mm
+ )
+
+ file(GLOB_RECURSE SHADER_SOURCES_FILES ${OMIM_ROOT}/shaders/Metal/*.metal)
+ add_metal_shader_library(shaders_metal
+ ${SHADER_SOURCES_FILES}
+ )
+endif()
+
+if (${PLATFORM_LINUX})
+ append(SRC
+ main_linux.cpp
+ )
+endif()
+
+omim_add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${SRC})
+
+target_link_libraries(${PROJECT_NAME}
+ generator # For borders::LoadBorders
+ qt_common
+ map
+ gflags::gflags
+ glfw
+ imgui
+)
+
+# Installing Vulkan SDK is optional, however without it Vulkan dynamic libraries
+# should be discovered via system paths and validation layers may not be available
+find_package(Vulkan QUIET)
+if (Vulkan_FOUND)
+ message(STATUS "Vulkan found")
+ target_link_libraries(${PROJECT_NAME} Vulkan::Vulkan)
+endif()
+
+if(PLATFORM_MAC)
+ target_embed_metal_shader_libraries(${PROJECT_NAME} shaders_metal)
+endif()
+
+target_compile_definitions(${PROJECT_NAME} PUBLIC GL_SILENCE_DEPRECATION)
+if (PLATFORM_MAC)
+ set_target_properties(${PROJECT_NAME} PROPERTIES XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES)
+endif()
+
+if (PLATFORM_LINUX)
+ target_compile_definitions(${PROJECT_NAME} PRIVATE VK_USE_PLATFORM_XLIB_KHR)
+endif()
+
+target_include_directories(${PROJECT_NAME} PUBLIC ${OMIM_ROOT}/3party/glfw/include)
+target_include_directories(${PROJECT_NAME} PUBLIC ${OMIM_ROOT}/3party/imgui)
+
+set(BUNDLE_NAME "OMapsDevSandbox")
+set(BUNDLE_DISPLAY_NAME "Organic Maps: Developer Sandbox")
+
+set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${BUNDLE_NAME})
+
+set(BUNDLE_EXECUTABLE ${BUNDLE_NAME})
+
+set(BUNDLE_FOLDER ${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${BUNDLE_NAME}.app)
+set(RESOURCES_FOLDER ${BUNDLE_FOLDER}/Contents/Resources)
+set(DATA_DIR ${OMIM_ROOT}/data)
+
+execute_process(
+ COMMAND mkdir -p ${RESOURCES_FOLDER}/shaders_compiler
+)
+
+function(copy_resources)
+ foreach(file ${ARGN})
+ execute_process(
+ COMMAND cp -r ${DATA_DIR}/${file} ${RESOURCES_FOLDER}
+ )
+ endforeach()
+endfunction()
+
+copy_resources(
+ countries-strings
+ resources-default
+ resources-mdpi_light
+ resources-hdpi_light
+ resources-xhdpi_light
+ resources-xxhdpi_light
+ resources-xxxhdpi_light
+ resources-6plus_light
+
+ categories.txt
+ categories_cuisines.txt
+ classificator.txt
+ colors.txt
+ countries.txt
+ drules_proto_default_light.bin
+ drules_proto_default_dark.bin
+ drules_proto_vehicle_light.bin
+ drules_proto_vehicle_dark.bin
+ editor.config
+ fonts_blacklist.txt
+ fonts_whitelist.txt
+ packed_polygons.bin
+ patterns.txt
+ transit_colors.txt
+ types.txt
+ unicode_blocks.txt
+ World.mwm
+ WorldCoasts.mwm
+
+ 00_NotoNaskhArabic-Regular.ttf
+ 00_NotoSansBengali-Regular.ttf
+ 00_NotoSansHebrew-Regular.ttf
+ 00_NotoSansMalayalam-Regular.ttf
+ 00_NotoSansThai-Regular.ttf
+ 00_NotoSerifDevanagari-Regular.ttf
+ 01_dejavusans.ttf
+ 02_droidsans-fallback.ttf
+ 03_jomolhari-id-a3d.ttf
+ 04_padauk.ttf
+ 05_khmeros.ttf
+ 06_code2000.ttf
+ 07_roboto_medium.ttf
+)
+
+if (NOT PLATFORM_LINUX)
+ # On Linux, ICU data is loaded from the shared library.
+ copy_resources(icudt75l.dat)
+endif()
+
+if (PLATFORM_MAC)
+ execute_process(
+ COMMAND cp -r ${OMIM_ROOT}/tools/shaders_compiler/macos ${RESOURCES_FOLDER}/shaders_compiler
+ )
+elseif (PLATFORM_LINUX)
+ execute_process(
+ COMMAND cp -r ${OMIM_ROOT}/tools/shaders_compiler/linux ${RESOURCES_FOLDER}/shaders_compiler
+ )
+endif()
diff --git a/dev_sandbox/imgui_renderer.cpp b/dev_sandbox/imgui_renderer.cpp
new file mode 100644
index 0000000000..689b2cb471
--- /dev/null
+++ b/dev_sandbox/imgui_renderer.cpp
@@ -0,0 +1,257 @@
+#include "imgui_renderer.hpp"
+
+#include "base/logging.hpp"
+#include "base/macros.hpp"
+
+#include
+
+#include
+
+#include
+
+#include
+#include
+
+ImguiRenderer::ImguiRenderer()
+ : m_state(df::CreateRenderState(gpu::Program::ImGui, df::DepthLayer::GuiLayer))
+{
+ m_state.SetDepthTestEnabled(false);
+ m_state.SetBlending(dp::Blending(true));
+}
+
+void ImguiRenderer::Render(ref_ptr context, ref_ptr textureManager,
+ ref_ptr programManager)
+{
+ std::lock_guard lock(m_bufferMutex);
+ size_t renderDataIndex = (m_updateIndex + 1) % m_uiDataBuffer.size();
+ UiDataBuffer & dataBuffer = m_uiDataBuffer[renderDataIndex];
+
+ auto gpuProgram = programManager->GetProgram(m_state.GetProgram());
+
+ bool needUpdate = true;
+ if (!m_mesh || dataBuffer.m_vertices.size() > m_vertexCount || dataBuffer.m_indices.size() > m_indexCount)
+ {
+ while (dataBuffer.m_vertices.size() > m_vertexCount)
+ m_vertexCount *= 2;
+ while (dataBuffer.m_indices.size() > m_indexCount)
+ m_indexCount *= 2;
+ m_indexCount = std::min(m_indexCount, static_cast(std::numeric_limits::max()));
+
+ dataBuffer.m_vertices.resize(m_vertexCount);
+ dataBuffer.m_indices.resize(m_indexCount);
+
+ m_mesh = make_unique_dp(context, dp::MeshObject::DrawPrimitive::Triangles, "imGui");
+
+ m_mesh->SetBuffer(0, std::move(dataBuffer.m_vertices));
+ m_mesh->SetAttribute("a_position", 0, 0 /* offset */, 2);
+ m_mesh->SetAttribute("a_texCoords", 0, 2 * sizeof(float) /* offset */, 2);
+ m_mesh->SetAttribute("a_color", 0, 4 * sizeof(float) /* offset */, 4);
+ m_mesh->SetIndexBuffer(std::move(dataBuffer.m_indices));
+ m_mesh->Build(context, gpuProgram);
+
+ dataBuffer.m_vertices.clear();
+ dataBuffer.m_indices.clear();
+ needUpdate = false;
+ }
+
+ if (!m_texture)
+ {
+ std::lock_guard lock(m_textureMutex);
+ if (!m_textureData.empty())
+ {
+ m_texture = make_unique_dp();
+ m_texture->Create(context,
+ dp::Texture::Params{
+ .m_width = m_textureWidth,
+ .m_height = m_textureHeight,
+ .m_format = dp::TextureFormat::RGBA8,
+ .m_allocator = textureManager->GetTextureAllocator(),
+ },
+ m_textureData.data());
+ m_textureData.clear();
+ m_state.SetColorTexture(make_ref(m_texture));
+ }
+ else
+ {
+ // Can't render without texture.
+ return;
+ }
+ }
+
+ if (dataBuffer.m_drawCalls.empty())
+ return;
+
+ if (needUpdate && !dataBuffer.m_vertices.empty() && !dataBuffer.m_indices.empty())
+ {
+ m_mesh->UpdateBuffer(context, 0, dataBuffer.m_vertices);
+ m_mesh->UpdateIndexBuffer(context, dataBuffer.m_indices);
+ dataBuffer.m_vertices.clear();
+ dataBuffer.m_indices.clear();
+ }
+
+ gpu::ImGuiProgramParams const params{.m_projection = m_projection};
+ context->PushDebugLabel("ImGui Rendering");
+ m_mesh->Render(context, gpuProgram, m_state, programManager->GetParamsSetter(), params,
+ [&, this]()
+ {
+ context->SetCullingEnabled(false);
+ for (auto const & drawCall : dataBuffer.m_drawCalls)
+ {
+ uint32_t y = drawCall.clipRect.y;
+ if (context->GetApiVersion() == dp::ApiVersion::OpenGLES3)
+ y = dataBuffer.m_height - y - drawCall.clipRect.w;
+ context->SetScissor(drawCall.clipRect.x, y, drawCall.clipRect.z, drawCall.clipRect.w);
+ m_mesh->DrawPrimitivesSubsetIndexed(context, drawCall.indexCount, drawCall.startIndex);
+ }
+ context->SetCullingEnabled(true);
+ context->SetScissor(0, 0, dataBuffer.m_width, dataBuffer.m_height);
+ });
+ context->PopDebugLabel();
+}
+
+void ImguiRenderer::Update(std::function const & uiCallback)
+{
+ CHECK(uiCallback, ());
+ ImGuiIO & io = ImGui::GetIO();
+ if (!io.Fonts->IsBuilt())
+ io.Fonts->Build();
+ if (!m_texture)
+ UpdateTexture();
+
+ ImGui::NewFrame();
+ uiCallback();
+ ImGui::Render();
+ UpdateBuffers();
+}
+
+void ImguiRenderer::Reset()
+{
+ {
+ std::lock_guard lock(m_textureMutex);
+ m_texture.reset();
+ }
+
+ {
+ std::lock_guard lock(m_bufferMutex);
+ m_mesh.reset();
+ }
+}
+
+void ImguiRenderer::UpdateTexture()
+{
+ std::lock_guard lock(m_textureMutex);
+ unsigned char * pixels;
+ int width, height;
+ ImGui::GetIO().Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+
+ auto const sizeInBytes = width * height * sizeof(uint32_t);
+ m_textureData.resize(sizeInBytes);
+ memcpy(m_textureData.data(), pixels, sizeInBytes);
+ m_textureWidth = static_cast(width);
+ m_textureHeight = static_cast(height);
+}
+
+void ImguiRenderer::UpdateBuffers()
+{
+ UiDataBuffer & dataBuffer = m_uiDataBuffer[m_updateIndex];
+ dataBuffer.m_drawCalls.clear();
+
+ ImDrawData * dd = ImGui::GetDrawData();
+ auto const fbWidth = static_cast(dd->DisplaySize.x * dd->FramebufferScale.x);
+ auto const fbHeight = static_cast(dd->DisplaySize.y * dd->FramebufferScale.y);
+ if (fbWidth <= 0 || fbHeight <= 0 || dd->CmdListsCount == 0 || dd->TotalIdxCount == 0 || dd->TotalVtxCount == 0)
+ return;
+ dataBuffer.m_width = static_cast(fbWidth);
+ dataBuffer.m_height = static_cast(fbHeight);
+
+ CHECK(dd->TotalVtxCount <= std::numeric_limits::max(),
+ ("UI is so complex and now requires 32-bit indices. You need to improve dp::MeshObject or simplify UI"));
+
+ CHECK((ImGui::GetIO().BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) == 0, ());
+
+ dataBuffer.m_vertices.resize(dd->TotalVtxCount);
+ dataBuffer.m_indices.resize(dd->TotalIdxCount);
+
+ int totalDrawCallsCount = 0;
+ for (int i = 0; i < dd->CmdListsCount; ++i)
+ totalDrawCallsCount += dd->CmdLists[i]->CmdBuffer.Size;
+ dataBuffer.m_drawCalls.reserve(totalDrawCallsCount);
+
+ ImVec2 const clipOff = dd->DisplayPos;
+ ImVec2 const clipScale = dd->FramebufferScale;
+
+ uint32_t vertexOffset = 0;
+ uint32_t indexOffset = 0;
+ for (int i = 0; i < dd->CmdListsCount; ++i)
+ {
+ ImDrawList const * cmdList = dd->CmdLists[i];
+ for (int j = 0; j < cmdList->VtxBuffer.Size; ++j)
+ {
+ dp::Color color(cmdList->VtxBuffer.Data[j].col);
+ dataBuffer.m_vertices[j + vertexOffset] = {
+ .position = {cmdList->VtxBuffer.Data[j].pos.x, cmdList->VtxBuffer.Data[j].pos.y},
+ .texCoords = {cmdList->VtxBuffer.Data[j].uv.x, cmdList->VtxBuffer.Data[j].uv.y},
+ .color = {color.GetAlphaF(), color.GetBlueF(), color.GetGreenF(),
+ color.GetRedF()} // Byte order is reversed in imGui
+ };
+ }
+
+ static_assert(sizeof(uint16_t) == sizeof(ImDrawIdx));
+ memcpy(dataBuffer.m_indices.data() + indexOffset, cmdList->IdxBuffer.Data,
+ cmdList->IdxBuffer.Size * sizeof(ImDrawIdx));
+ for (int j = 0; j < cmdList->IdxBuffer.Size; ++j)
+ {
+ uint32_t indexValue = dataBuffer.m_indices[j + indexOffset];
+ indexValue += vertexOffset;
+ CHECK(indexValue <= std::numeric_limits::max(), ());
+ dataBuffer.m_indices[j + indexOffset] = static_cast(indexValue);
+ }
+
+ for (int cmdIndex = 0; cmdIndex < cmdList->CmdBuffer.Size; ++cmdIndex)
+ {
+ const ImDrawCmd cmd = cmdList->CmdBuffer[cmdIndex];
+ ImVec2 clipMin((cmd.ClipRect.x - clipOff.x) * clipScale.x, (cmd.ClipRect.y - clipOff.y) * clipScale.y);
+ ImVec2 clipMax((cmd.ClipRect.z - clipOff.x) * clipScale.x, (cmd.ClipRect.w - clipOff.y) * clipScale.y);
+ if (clipMin.x < 0.0f)
+ clipMin.x = 0.0f;
+ if (clipMin.y < 0.0f)
+ clipMin.y = 0.0f;
+ if (clipMax.x > fbWidth)
+ clipMax.x = static_cast(fbWidth);
+ if (clipMax.y > fbHeight)
+ clipMax.y = static_cast(fbHeight);
+ if (clipMax.x <= clipMin.x || clipMax.y <= clipMin.y)
+ continue;
+
+ dataBuffer.m_drawCalls.emplace_back(DrawCall{
+ .indexCount = static_cast(cmd.ElemCount),
+ .startIndex = static_cast(indexOffset + cmd.IdxOffset),
+ .clipRect = {static_cast(clipMin.x), static_cast(clipMin.y),
+ static_cast(clipMax.x - clipMin.x), static_cast(clipMax.y - clipMin.y)}});
+ }
+
+ vertexOffset += static_cast(cmdList->VtxBuffer.Size);
+ indexOffset += static_cast(cmdList->IdxBuffer.Size);
+ }
+ CHECK(vertexOffset == dataBuffer.m_vertices.size(), ());
+ CHECK(indexOffset == dataBuffer.m_indices.size(), ());
+
+ {
+ std::lock_guard lock(m_bufferMutex);
+
+ // Projection
+ float const left = dd->DisplayPos.x;
+ float const right = dd->DisplayPos.x + dd->DisplaySize.x;
+ float const top = dd->DisplayPos.y;
+ float const bottom = dd->DisplayPos.y + dd->DisplaySize.y;
+ m_projection[0][0] = 2.0f / (right - left);
+ m_projection[1][1] = 2.0f / (top - bottom);
+ m_projection[2][2] = -1.0f;
+ m_projection[3][3] = 1.0f;
+ m_projection[0][3] = -(right + left) / (right - left);
+ m_projection[1][3] = -(top + bottom) / (top - bottom);
+
+ // Swap buffers
+ m_updateIndex = (m_updateIndex + 1) % m_uiDataBuffer.size();
+ }
+}
diff --git a/dev_sandbox/imgui_renderer.hpp b/dev_sandbox/imgui_renderer.hpp
new file mode 100644
index 0000000000..6e048c8e0c
--- /dev/null
+++ b/dev_sandbox/imgui_renderer.hpp
@@ -0,0 +1,72 @@
+#pragma once
+
+#include "drape/glsl_types.hpp"
+#include "drape/graphics_context.hpp"
+#include "drape/mesh_object.hpp"
+#include "drape/pointers.hpp"
+#include "drape/render_state.hpp"
+#include "drape/static_texture.hpp"
+#include "drape/texture_manager.hpp"
+
+#include
+#include
+#include
+#include
+#include
+
+class ImguiRenderer
+{
+public:
+ ImguiRenderer();
+ void Render(ref_ptr context,
+ ref_ptr textureManager,
+ ref_ptr programManager);
+ void Update(std::function const & uiCallback);
+ void Reset();
+
+private:
+ void UpdateTexture();
+ void UpdateBuffers();
+
+ struct ImguiVertex
+ {
+ glsl::vec2 position;
+ glsl::vec2 texCoords;
+ glsl::vec4 color;
+ };
+ static_assert(sizeof(ImguiVertex) == 2 * sizeof(glsl::vec4));
+
+ struct DrawCall
+ {
+ uint32_t indexCount = 0;
+ uint32_t startIndex = 0;
+ glsl::uvec4 clipRect{};
+ };
+
+ drape_ptr m_mesh;
+ uint32_t m_vertexCount = 2000;
+ uint32_t m_indexCount = 3000;
+
+ drape_ptr m_texture;
+ std::vector m_textureData;
+ uint32_t m_textureWidth = 0;
+ uint32_t m_textureHeight = 0;
+
+ dp::RenderState m_state;
+
+ struct UiDataBuffer
+ {
+ std::vector m_vertices;
+ std::vector m_indices;
+ std::vector m_drawCalls;
+ uint32_t m_width;
+ uint32_t m_height;
+ };
+ std::array m_uiDataBuffer;
+ size_t m_updateIndex = 0;
+
+ glsl::mat4 m_projection;
+
+ std::mutex m_bufferMutex;
+ std::mutex m_textureMutex;
+};
diff --git a/dev_sandbox/main.cpp b/dev_sandbox/main.cpp
new file mode 100644
index 0000000000..8c66d4c9e2
--- /dev/null
+++ b/dev_sandbox/main.cpp
@@ -0,0 +1,672 @@
+#include "dev_sandbox/imgui_renderer.hpp"
+
+#include "map/framework.hpp"
+
+#include "platform/platform.hpp"
+#include "platform/settings.hpp"
+
+#include "coding/reader.hpp"
+
+#include "base/logging.hpp"
+#include "base/macros.hpp"
+
+#include "std/target_os.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#if defined(OMIM_OS_WINDOWS)
+#define GLFW_EXPOSE_NATIVE_WIN32
+#elif defined(OMIM_OS_LINUX)
+#define GLFW_EXPOSE_NATIVE_X11
+#elif defined(OMIM_OS_MAC)
+#define GLFW_EXPOSE_NATIVE_COCOA
+#else
+#error Unsupported plaform
+#endif
+#define GLFW_INCLUDE_NONE
+#include
+#include
+#include
+#include
+
+DEFINE_string(data_path, "", "Path to data directory.");
+DEFINE_string(log_abort_level, base::ToString(base::GetDefaultLogAbortLevel()),
+ "Log messages severity that causes termination.");
+DEFINE_string(resources_path, "", "Path to resources directory.");
+DEFINE_string(lang, "", "Device language.");
+
+#if defined(OMIM_OS_MAC) || defined(OMIM_OS_LINUX)
+drape_ptr CreateContextFactory(GLFWwindow * window, dp::ApiVersion api, m2::PointU size);
+void PrepareDestroyContextFactory(ref_ptr contextFactory);
+void OnCreateDrapeEngine(GLFWwindow * window, dp::ApiVersion api, ref_ptr contextFactory);
+void UpdateContentScale(GLFWwindow * window, float scale);
+void UpdateSize(ref_ptr contextFactory, int w, int h);
+#endif
+
+#if defined(OMIM_OS_LINUX)
+// Workaround for storage::Status compilation issue:
+// /usr/include/X11/Xlib.h:83:16: note: expanded from macro 'Status'
+#undef Status
+#endif
+
+namespace
+{
+bool ValidateLogAbortLevel(char const * flagname, std::string const & value)
+{
+ if (auto level = base::FromString(value); !level)
+ {
+ std::cerr << "Invalid value for --" << flagname << ": " << value << ", must be one of: ";
+ auto const & names = base::GetLogLevelNames();
+ for (size_t i = 0; i < names.size(); ++i)
+ {
+ if (i != 0)
+ std::cerr << ", ";
+ std::cerr << names[i];
+ }
+ std::cerr << '\n';
+ return false;
+ }
+ return true;
+}
+
+bool const g_logAbortLevelDummy = gflags::RegisterFlagValidator(&FLAGS_log_abort_level, &ValidateLogAbortLevel);
+
+void errorCallback(int error, char const * description) { LOG(LERROR, ("GLFW (", error, "):", description)); }
+
+std::function onResize;
+std::function onMouseButton;
+std::function onMouseMove;
+std::function onScroll;
+std::function onKeyboardButton;
+std::function onContentScale;
+
+df::Touch GetTouch(double x, double y)
+{
+ return df::Touch{.m_location = m2::PointF(static_cast(x), static_cast(y)), .m_id = 0};
+}
+
+df::Touch GetSymmetricalTouch(Framework & framework, df::Touch const & touch)
+{
+ m2::PointD const pixelCenter = framework.GetVisiblePixelCenter();
+ m2::PointD const symmetricalLocation = pixelCenter + pixelCenter - m2::PointD(touch.m_location);
+
+ df::Touch result;
+ result.m_id = touch.m_id + 1;
+ result.m_location = symmetricalLocation;
+
+ return result;
+}
+
+df::TouchEvent GetTouchEvent(Framework & framework, double x, double y, int mods, df::TouchEvent::ETouchType type)
+{
+ df::TouchEvent event;
+ event.SetTouchType(type);
+ event.SetFirstTouch(GetTouch(x, y));
+ if (mods & GLFW_MOD_SUPER)
+ event.SetSecondTouch(GetSymmetricalTouch(framework, event.GetFirstTouch()));
+ return event;
+}
+
+void FormatMapSize(uint64_t sizeInBytes, std::string & units, size_t & sizeToDownload)
+{
+ int const mbInBytes = 1024 * 1024;
+ int const kbInBytes = 1024;
+ if (sizeInBytes > mbInBytes)
+ {
+ sizeToDownload = (sizeInBytes + mbInBytes - 1) / mbInBytes;
+ units = "MB";
+ }
+ else if (sizeInBytes > kbInBytes)
+ {
+ sizeToDownload = (sizeInBytes + kbInBytes - 1) / kbInBytes;
+ units = "KB";
+ }
+ else
+ {
+ sizeToDownload = sizeInBytes;
+ units = "B";
+ }
+}
+
+std::string_view GetMyPoisitionText(location::EMyPositionMode mode)
+{
+ switch(mode)
+ {
+ case location::EMyPositionMode::PendingPosition: return "Pending";
+ case location::EMyPositionMode::NotFollowNoPosition: return "No position";
+ case location::EMyPositionMode::NotFollow: return "Not follow";
+ case location::EMyPositionMode::Follow: return "Follow";
+ case location::EMyPositionMode::FollowAndRotate: return "Follow and Rotate";
+ }
+ return "";
+}
+
+dp::ApiVersion GetApiVersion(char const * apiLabel)
+{
+ std::string_view v(apiLabel);
+ if (v == "Metal") return dp::ApiVersion::Metal;
+ if (v == "Vulkan") return dp::ApiVersion::Vulkan;
+ if (v == "OpenGL") return dp::ApiVersion::OpenGLES3;
+ return dp::ApiVersion::Invalid;
+}
+
+#if defined(OMIM_OS_LINUX)
+class LinuxGuiThread : public base::TaskLoop
+{
+public:
+ PushResult Push(Task && task) override
+ {
+ std::lock_guard lock(m_mutex);
+ m_tasks.emplace_back(std::move(task));
+ return {true, base::TaskLoop::kNoId};
+ }
+
+ PushResult Push(Task const & task) override
+ {
+ std::lock_guard lock(m_mutex);
+ m_tasks.emplace_back(task);
+ return {true, base::TaskLoop::kNoId};
+ }
+
+ void ExecuteTasks()
+ {
+ std::lock_guard lock(m_mutex);
+ for (auto & task : m_tasks)
+ task();
+ m_tasks.clear();
+ }
+
+private:
+ std::vector m_tasks;
+ std::mutex m_mutex;
+};
+#endif
+} // namespace
+
+int main(int argc, char * argv[])
+{
+ // Our double parsing code (base/string_utils.hpp) needs dots as a floating point delimiters, not commas.
+ // TODO: Refactor our doubles parsing code to use locale-independent delimiters.
+ // For example, https://github.com/google/double-conversion can be used.
+ // See http://dbaron.org/log/20121222-locale for more details.
+ (void)::setenv("LC_NUMERIC", "C", 1);
+
+ Platform & platform = GetPlatform();
+
+ LOG(LINFO, ("Organic Maps: Developer Sandbox", platform.Version(), "detected CPU cores:", platform.CpuCores()));
+
+ gflags::SetUsageMessage("Developer Sandbox.");
+ gflags::SetVersionString(platform.Version());
+ gflags::ParseCommandLineFlags(&argc, &argv, true);
+
+ if (!FLAGS_resources_path.empty())
+ platform.SetResourceDir(FLAGS_resources_path);
+ if (!FLAGS_data_path.empty())
+ platform.SetWritableDirForTests(FLAGS_data_path);
+
+ if (auto const logLevel = base::FromString(FLAGS_log_abort_level); logLevel)
+ base::g_LogAbortLevel = *logLevel;
+ else
+ LOG(LCRITICAL, ("Invalid log level:", FLAGS_log_abort_level));
+
+#if defined(OMIM_OS_LINUX)
+ auto guiThread = std::make_unique();
+ auto guiThreadPtr = guiThread.get();
+ platform.SetGuiThread(std::move(guiThread));
+#endif
+
+ // Init GLFW.
+ glfwSetErrorCallback(errorCallback);
+ if (!glfwInit())
+ {
+ return -1;
+ }
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+#if defined(OMIM_OS_WINDOWS)
+ glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
+#endif
+ auto monitor = glfwGetPrimaryMonitor();
+ auto mode = glfwGetVideoMode(monitor);
+ GLFWwindow * window =
+ glfwCreateWindow(mode->width, mode->height, "Organic Maps: Developer Sandbox", nullptr, nullptr);
+ int fbWidth = 0, fbHeight = 0;
+ glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
+ float xs = 1.0f, ys = 1.0f;
+ glfwGetWindowContentScale(window, &xs, &ys);
+ float visualScale = std::max(xs, ys);
+
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
+ ImGui::StyleColorsClassic();
+ glfwMaximizeWindow(window);
+
+ platform.SetupMeasurementSystem();
+
+ bool outvalue;
+ if (!settings::Get(settings::kDeveloperMode, outvalue))
+ settings::Set(settings::kDeveloperMode, true);
+
+ if (!FLAGS_lang.empty())
+ (void)::setenv("LANGUAGE", FLAGS_lang.c_str(), 1);
+
+ FrameworkParams frameworkParams;
+ Framework framework(frameworkParams);
+
+ ImguiRenderer imguiRenderer;
+ Framework::DrapeCreationParams drapeParams{
+#if defined(OMIM_OS_MAC)
+ .m_apiVersion = dp::ApiVersion::Metal,
+#else
+ .m_apiVersion = dp::ApiVersion::Vulkan,
+#endif
+ .m_visualScale = visualScale,
+ .m_surfaceWidth = fbWidth,
+ .m_surfaceHeight = fbHeight,
+ .m_renderInjectionHandler = [&](ref_ptr context,
+ ref_ptr textureManager,
+ ref_ptr programManager,
+ bool shutdown)
+ {
+ if (shutdown)
+ imguiRenderer.Reset();
+ else
+ imguiRenderer.Render(context, textureManager, programManager);
+ }};
+ gui::Skin guiSkin(gui::ResolveGuiSkinFile("default"), visualScale);
+ guiSkin.Resize(fbWidth, fbHeight);
+ guiSkin.ForEach([&](gui::EWidget widget, gui::Position const & pos) { drapeParams.m_widgetsInitInfo[widget] = pos; });
+ drapeParams.m_widgetsInitInfo[gui::WIDGET_SCALE_FPS_LABEL] = gui::Position(dp::LeftTop);
+
+ drape_ptr contextFactory;
+ auto CreateDrapeEngine = [&](dp::ApiVersion version)
+ {
+ drapeParams.m_apiVersion = version;
+ drapeParams.m_visualScale = visualScale;
+ drapeParams.m_surfaceWidth = fbWidth;
+ drapeParams.m_surfaceHeight = fbHeight;
+ contextFactory = CreateContextFactory(window, drapeParams.m_apiVersion,
+ m2::PointU(static_cast(drapeParams.m_surfaceWidth),
+ static_cast(drapeParams.m_surfaceHeight)));
+ auto params = drapeParams;
+ framework.CreateDrapeEngine(make_ref(contextFactory), std::move(params));
+ OnCreateDrapeEngine(window, version, make_ref(contextFactory));
+ framework.SetRenderingEnabled(nullptr);
+ };
+ CreateDrapeEngine(drapeParams.m_apiVersion);
+
+ auto DestroyDrapeEngine = [&]()
+ {
+ framework.SetRenderingDisabled(true);
+ framework.DestroyDrapeEngine();
+ PrepareDestroyContextFactory(make_ref(contextFactory));
+ contextFactory.reset();
+ };
+
+ // Process resizing.
+ onResize = [&](int w, int h)
+ {
+ fbWidth = w;
+ fbHeight = h;
+ if (fbWidth > 0 && fbHeight > 0)
+ {
+ UpdateSize(make_ref(contextFactory), fbWidth, fbHeight);
+ framework.OnSize(fbWidth, fbHeight);
+
+ guiSkin.Resize(w, h);
+ gui::TWidgetsLayoutInfo layout;
+ guiSkin.ForEach([&layout](gui::EWidget w, gui::Position const & pos) { layout[w] = pos.m_pixelPivot; });
+ framework.SetWidgetLayout(std::move(layout));
+ framework.MakeFrameActive();
+ }
+ };
+ glfwSetFramebufferSizeCallback(window, [](GLFWwindow * wnd, int w, int h) { onResize(w, h); });
+
+ // Process change content scale.
+ onContentScale = [&](float xscale, float yscale)
+ {
+ visualScale = std::max(xscale, yscale);
+ framework.UpdateVisualScale(visualScale);
+
+ int w = 0, h = 0;
+ glfwGetWindowSize(window, &w, &h);
+#if defined(OMIM_OS_MAC)
+ w *= xscale;
+ h *= yscale;
+#endif
+
+ if (w != fbWidth || h != fbHeight)
+ {
+#if defined(OMIM_OS_MAC)
+ UpdateContentScale(window, xscale);
+#endif
+ fbWidth = w;
+ fbHeight = h;
+ UpdateSize(make_ref(contextFactory), fbWidth, fbHeight);
+ framework.OnSize(fbWidth, fbHeight);
+ }
+ };
+ glfwSetWindowContentScaleCallback(window,
+ [](GLFWwindow *, float xscale, float yscale) { onContentScale(xscale, yscale); });
+
+ // Location handler
+ std::optional lastLatLon;
+ bool bearingEnabled = false;
+ float bearing = 0.0f;
+ auto setUserLocation = [&]()
+ {
+ if (lastLatLon)
+ {
+ framework.OnLocationUpdate(
+ location::GpsInfo{.m_source = location::EUser,
+ .m_timestamp = static_cast(std::chrono::duration_cast(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count()) /
+ 1000,
+ .m_latitude = lastLatLon->m_lat,
+ .m_longitude = lastLatLon->m_lon,
+ .m_horizontalAccuracy = 10,
+ .m_bearing = bearingEnabled ? bearing : -1.0f});
+ if (bearingEnabled)
+ {
+ framework.OnCompassUpdate(location::CompassInfo{.m_bearing = base::DegToRad(bearing)});
+ }
+ }
+ };
+
+ // Download maps handler
+ std::string downloadButtonLabel;
+ std::string retryButtonLabel;
+ std::string downloadStatusLabel;
+ storage::CountryId lastCountry;
+ auto const onCountryChanged = [&](storage::CountryId const & countryId)
+ {
+ downloadButtonLabel.clear();
+ retryButtonLabel.clear();
+ downloadStatusLabel.clear();
+ lastCountry = countryId;
+ // Called by Framework in World zoom level.
+ if (countryId.empty())
+ return;
+
+ auto const & storage = framework.GetStorage();
+ auto status = storage.CountryStatusEx(countryId);
+ auto const & countryName = countryId;
+
+ if (status == storage::Status::NotDownloaded)
+ {
+ std::string units;
+ size_t sizeToDownload = 0;
+ FormatMapSize(storage.CountrySizeInBytes(countryId).second, units, sizeToDownload);
+ std::stringstream str;
+ str << "Download (" << countryName << ") " << sizeToDownload << units;
+ downloadButtonLabel = str.str();
+ }
+ else if (status == storage::Status::InQueue)
+ {
+ std::stringstream str;
+ str << countryName << " is waiting for downloading";
+ downloadStatusLabel = str.str();
+ }
+ else if (status != storage::Status::Downloading && status != storage::Status::OnDisk &&
+ status != storage::Status::OnDiskOutOfDate)
+ {
+ std::stringstream str;
+ str << "Retry to download " << countryName;
+ retryButtonLabel = str.str();
+ }
+ };
+ framework.SetCurrentCountryChangedListener(onCountryChanged);
+
+ framework.GetStorage().Subscribe(
+ [&](storage::CountryId const & countryId)
+ {
+ // Storage also calls notifications for parents, but we are interested in leafs only.
+ if (framework.GetStorage().IsLeaf(countryId))
+ onCountryChanged(countryId);
+ },
+ [&](storage::CountryId const & countryId, downloader::Progress const & progress)
+ {
+ std::stringstream str;
+ str << "Downloading (" << countryId << ") " << (progress.m_bytesDownloaded * 100 / progress.m_bytesTotal)
+ << "%";
+ downloadStatusLabel = str.str();
+ framework.MakeFrameActive();
+ });
+
+ // Handle mouse buttons.
+ bool touchActive = false;
+ int touchMods = 0;
+ bool setUpLocationByLeftClick = false;
+ onMouseButton = [&](double x, double y, int button, int action, int mods)
+ {
+#if defined(OMIM_OS_LINUX)
+ ImGui::GetIO().MousePos = ImVec2(x / visualScale, y / visualScale);
+#endif
+ if (ImGui::GetIO().WantCaptureMouse)
+ {
+ framework.MakeFrameActive();
+ return;
+ }
+
+#if defined(OMIM_OS_MAC)
+ x *= visualScale;
+ y *= visualScale;
+#endif
+ lastLatLon = mercator::ToLatLon(framework.PtoG(m2::PointD(x, y)));
+
+ if (setUpLocationByLeftClick)
+ {
+ setUserLocation();
+ return;
+ }
+
+ if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
+ {
+ framework.TouchEvent(GetTouchEvent(framework, x, y, mods, df::TouchEvent::TOUCH_DOWN));
+ touchActive = true;
+ touchMods = mods;
+ }
+
+ if (touchActive && action == GLFW_RELEASE)
+ {
+ framework.TouchEvent(GetTouchEvent(framework, x, y, 0, df::TouchEvent::TOUCH_UP));
+ touchActive = false;
+ touchMods = 0;
+ }
+ };
+ glfwSetMouseButtonCallback(window,
+ [](GLFWwindow * wnd, int button, int action, int mods)
+ {
+ double x, y;
+ glfwGetCursorPos(wnd, &x, &y);
+ onMouseButton(x, y, button, action, mods);
+ });
+
+ // Handle mouse moving.
+ onMouseMove = [&](double x, double y)
+ {
+#if defined(OMIM_OS_LINUX)
+ ImGui::GetIO().MousePos = ImVec2(x / visualScale, y / visualScale);
+#endif
+ if (ImGui::GetIO().WantCaptureMouse)
+ framework.MakeFrameActive();
+
+ if (touchActive)
+ {
+#if defined(OMIM_OS_MAC)
+ x *= visualScale;
+ y *= visualScale;
+#endif
+ framework.TouchEvent(
+ GetTouchEvent(framework, x, y, touchMods, df::TouchEvent::TOUCH_MOVE));
+ }
+ };
+ glfwSetCursorPosCallback(window, [](GLFWwindow *, double x, double y) { onMouseMove(x, y); });
+
+ // Handle scroll.
+ onScroll = [&](double x, double y, double xOffset, double yOffset)
+ {
+#if defined(OMIM_OS_LINUX)
+ ImGui::GetIO().MousePos = ImVec2(x / visualScale, y / visualScale);
+#endif
+ if (ImGui::GetIO().WantCaptureMouse)
+ {
+ framework.MakeFrameActive();
+ return;
+ }
+
+#if defined(OMIM_OS_MAC)
+ x *= visualScale;
+ y *= visualScale;
+#endif
+ constexpr double kSensitivity = 0.01;
+ double const factor = yOffset * kSensitivity;
+ framework.Scale(exp(factor), m2::PointD(x, y), false);
+ };
+ glfwSetScrollCallback(window,
+ [](GLFWwindow * wnd, double xoffset, double yoffset)
+ {
+ double x, y;
+ glfwGetCursorPos(wnd, &x, &y);
+ onScroll(x, y, xoffset, yoffset);
+ });
+
+ // Keys.
+ onKeyboardButton = [&](int key, int scancode, int action, int mods) {};
+ glfwSetKeyCallback(window, [](GLFWwindow *, int key, int scancode, int action, int mods)
+ { onKeyboardButton(key, scancode, action, mods); });
+
+ // imGui UI
+ bool enableDebugRectRendering = false;
+ bool enableAA = false;
+ auto imGuiUI = [&]()
+ {
+ ImGui::SetNextWindowPos(ImVec2(5, 20), ImGuiCond_Appearing);
+ ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
+
+ // Drape controls
+ char const * apiLabels[] = {
+#if defined(OMIM_OS_MAC)
+ "Metal",
+ "Vulkan",
+ "OpenGL"
+#elif defined(OMIM_OS_LINUX)
+ "Vulkan",
+ "OpenGL"
+#endif
+ };
+ static int currentAPI = 0;
+ if (ImGui::Combo("API", ¤tAPI, apiLabels, IM_ARRAYSIZE(apiLabels)))
+ {
+ auto const apiVersion = GetApiVersion(apiLabels[currentAPI]);
+ if (framework.GetDrapeEngine()->GetApiVersion() != apiVersion)
+ {
+ DestroyDrapeEngine();
+ CreateDrapeEngine(apiVersion);
+ }
+ }
+ if (ImGui::Checkbox("Debug rect rendering", &enableDebugRectRendering))
+ framework.EnableDebugRectRendering(enableDebugRectRendering);
+ if (ImGui::Checkbox("Antialiasing", &enableAA))
+ framework.GetDrapeEngine()->SetPosteffectEnabled(df::PostprocessRenderer::Antialiasing, enableAA);
+ ImGui::NewLine();
+ ImGui::Separator();
+ ImGui::NewLine();
+
+ // Map controls
+ if (ImGui::Button("Scale +"))
+ framework.Scale(Framework::SCALE_MAG, true);
+ ImGui::SameLine();
+ if (ImGui::Button("Scale -"))
+ framework.Scale(Framework::SCALE_MIN, true);
+ ImGui::Checkbox("Set up location by left click", &setUpLocationByLeftClick);
+ if (setUpLocationByLeftClick)
+ {
+ if (ImGui::Checkbox("Bearing", &bearingEnabled))
+ setUserLocation();
+ ImGui::SameLine();
+ if (ImGui::SliderFloat(" ", &bearing, 0.0f, 360.0f, "%.1f"))
+ setUserLocation();
+ }
+ ImGui::Text("My positon mode: %s", GetMyPoisitionText(framework.GetMyPositionMode()).data());
+ if (ImGui::Button("Next Position Mode"))
+ framework.SwitchMyPositionNextMode();
+ ImGui::NewLine();
+ ImGui::Separator();
+ ImGui::NewLine();
+
+ // No downloading on Linux at the moment, need to implement http_thread without Qt.
+#if !defined(OMIM_OS_LINUX)
+ // Download controls
+ if (!downloadButtonLabel.empty())
+ {
+ if (ImGui::Button(downloadButtonLabel.c_str()))
+ framework.GetStorage().DownloadNode(lastCountry);
+ }
+ if (!retryButtonLabel.empty())
+ {
+ if (ImGui::Button(retryButtonLabel.c_str()))
+ framework.GetStorage().RetryDownloadNode(lastCountry);
+ }
+ if (!downloadStatusLabel.empty())
+ ImGui::Text("%s", downloadStatusLabel.c_str());
+ if (!downloadButtonLabel.empty() || !retryButtonLabel.empty() || !downloadStatusLabel.empty())
+ {
+ ImGui::NewLine();
+ ImGui::Separator();
+ ImGui::NewLine();
+ }
+#endif
+
+ ImGui::End();
+ };
+
+ ImGui_ImplGlfw_InitForOther(window, true);
+
+ // Main loop.
+ while (!glfwWindowShouldClose(window))
+ {
+ glfwPollEvents();
+
+#if defined(OMIM_OS_LINUX)
+ guiThreadPtr->ExecuteTasks();
+#endif
+
+ // Render imGui UI
+ ImGui_ImplGlfw_NewFrame();
+ ImGuiIO& io = ImGui::GetIO();
+#if defined(OMIM_OS_LINUX)
+ // Apply correct visual scale on Linux
+ // In glfw for Linux, window size and framebuffer size are the same,
+ // even if visual scale is not 1.0. It's different from behaviour on Mac.
+ io.DisplaySize = ImVec2(fbWidth / visualScale, fbHeight / visualScale);
+ io.DisplayFramebufferScale = ImVec2(visualScale, visualScale);
+ double mouseX, mouseY;
+ glfwGetCursorPos(window, &mouseX, &mouseY);
+ io.AddMousePosEvent((float)mouseX / visualScale, (float)mouseY / visualScale);
+#endif
+ io.IniFilename = nullptr;
+ imguiRenderer.Update(imGuiUI);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 30));
+ }
+
+ framework.EnterBackground();
+ DestroyDrapeEngine();
+
+ ImGui_ImplGlfw_Shutdown();
+ ImGui::DestroyContext();
+
+ glfwDestroyWindow(window);
+ glfwTerminate();
+ return 0;
+}
diff --git a/dev_sandbox/main.mm b/dev_sandbox/main.mm
new file mode 100644
index 0000000000..8ad4d03c7e
--- /dev/null
+++ b/dev_sandbox/main.mm
@@ -0,0 +1,370 @@
+#include "iphone/Maps/Classes/MetalContextFactory.h"
+
+#include "drape/gl_functions.hpp"
+#include "drape/oglcontext.hpp"
+#include "drape/metal/metal_base_context.hpp"
+#include "drape/vulkan/vulkan_context_factory.hpp"
+
+#define GLFW_INCLUDE_NONE
+#include
+
+#if __APPLE__
+#define GLFW_EXPOSE_NATIVE_COCOA
+#else
+#error Unsupported OS
+#endif
+#include
+
+#import
+#import
+#import
+#import
+
+#include
+
+#include
+#include
+
+class MacOSVulkanContextFactory : public dp::vulkan::VulkanContextFactory
+{
+public:
+ MacOSVulkanContextFactory()
+ : dp::vulkan::VulkanContextFactory(1, 33, false) {}
+
+ void SetSurface(CAMetalLayer *layer)
+ {
+ VkMacOSSurfaceCreateInfoMVK createInfo = {
+ .sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK,
+ .flags = 0,
+ .pView = static_cast(CFBridgingRetain(layer)),
+ };
+
+ VkResult statusCode;
+ CHECK(vkCreateMacOSSurfaceMVK, ());
+ statusCode = vkCreateMacOSSurfaceMVK(m_vulkanInstance, &createInfo, nullptr,
+ &m_surface);
+ if (statusCode != VK_SUCCESS)
+ {
+ LOG_ERROR_VK_CALL(vkCreateMacOSSurfaceMVK, statusCode);
+ return;
+ }
+
+ uint32_t const renderingQueueIndex = m_drawContext->GetRenderingQueueFamilyIndex();
+ VkBool32 supportsPresent;
+ statusCode = vkGetPhysicalDeviceSurfaceSupportKHR(m_gpu, renderingQueueIndex, m_surface, &supportsPresent);
+ if (statusCode != VK_SUCCESS)
+ {
+ LOG_ERROR_VK_CALL(vkGetPhysicalDeviceSurfaceSupportKHR, statusCode);
+ return;
+ }
+ CHECK_EQUAL(supportsPresent, VK_TRUE, ());
+
+ CHECK(QuerySurfaceSize(), ());
+
+ if (m_drawContext)
+ m_drawContext->SetSurface(m_surface, m_surfaceFormat, m_surfaceCapabilities);
+ }
+
+ void ResetSurface()
+ {
+ if (m_drawContext)
+ m_drawContext->ResetSurface(false);
+
+ vkDestroySurfaceKHR(m_vulkanInstance, m_surface, nullptr);
+ }
+};
+
+class MacGLContext : public dp::OGLContext
+{
+public:
+ MacGLContext(MacGLContext * contextToShareWith)
+ : m_viewSet(false)
+ {
+ NSOpenGLPixelFormatAttribute attributes[] = {
+ NSOpenGLPFAAccelerated,
+ NSOpenGLPFAOpenGLProfile,
+ NSOpenGLProfileVersion4_1Core,
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFAColorSize,
+ 24,
+ NSOpenGLPFAAlphaSize,
+ 8,
+ NSOpenGLPFADepthSize,
+ 24,
+ NSOpenGLPFAStencilSize,
+ 8,
+ 0
+ };
+ m_pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
+ CHECK(m_pixelFormat, ("Pixel format is not found"));
+ m_context = [[NSOpenGLContext alloc] initWithFormat:m_pixelFormat
+ shareContext:(contextToShareWith ? contextToShareWith->m_context : nil)];
+ int interval = 1;
+ [m_context getValues:&interval forParameter:NSOpenGLContextParameterSwapInterval];
+ }
+
+ ~MacGLContext()
+ {
+ @autoreleasepool {
+ [m_context clearDrawable];
+ m_pixelFormat = nil;
+ m_context = nil;
+ }
+ }
+
+ bool BeginRendering() override { return m_viewSet; }
+
+ void Present() override
+ {
+ if (m_viewSet)
+ {
+ std::lock_guard lock(m_updateSizeMutex);
+ [m_context flushBuffer];
+ }
+ }
+
+ void MakeCurrent() override
+ {
+ [m_context makeCurrentContext];
+ }
+
+ void DoneCurrent() override
+ {
+ [NSOpenGLContext clearCurrentContext];
+ }
+
+ void SetFramebuffer(ref_ptr framebuffer) override
+ {
+ if (framebuffer)
+ framebuffer->Bind();
+ else
+ GLFunctions::glBindFramebuffer(0);
+ }
+
+ void SetView(NSView* view)
+ {
+ [m_context setView: view];
+ [m_context update];
+ m_viewSet = true;
+ }
+
+ void UpdateSize(int w, int h)
+ {
+ std::lock_guard lock(m_updateSizeMutex);
+ [m_context update];
+ }
+
+private:
+ NSOpenGLPixelFormat * m_pixelFormat = nil;
+ NSOpenGLContext* m_context = nil;
+ std::atomic m_viewSet;
+
+ std::mutex m_updateSizeMutex;
+};
+
+class MacGLContextFactory: public dp::GraphicsContextFactory
+{
+public:
+ dp::GraphicsContext * GetDrawContext() override
+ {
+ bool needNotify = false;
+ {
+ std::lock_guard lock(m_contextAccess);
+ if (m_drawContext == nullptr)
+ {
+ m_drawContext = std::make_unique(m_uploadContext.get());
+ needNotify = true;
+ }
+ }
+ if (needNotify)
+ NotifyView();
+
+ std::lock_guard lock(m_contextAccess);
+ return m_drawContext.get();
+ }
+
+ dp::GraphicsContext * GetResourcesUploadContext() override
+ {
+ std::lock_guard lock(m_contextAccess);
+ if (m_uploadContext == nullptr)
+ m_uploadContext = std::make_unique(m_drawContext.get());
+ return m_uploadContext.get();
+ }
+
+ void WaitForInitialization(dp::GraphicsContext *) override
+ {
+ std::unique_lock lock(m_initializationMutex);
+ if (m_isInitialized)
+ return;
+
+ m_initializationCounter++;
+ if (m_initializationCounter >= kGLThreadsCount)
+ {
+ m_isInitialized = true;
+ m_initializationCondition.notify_all();
+ }
+ else
+ {
+ m_initializationCondition.wait(lock, [this] { return m_isInitialized; });
+ }
+ }
+
+ bool IsDrawContextCreated() const override
+ {
+ std::lock_guard lock(m_contextAccess);
+ return m_drawContext != nullptr;
+ }
+
+ bool IsUploadContextCreated() const override
+ {
+ std::lock_guard lock(m_contextAccess);
+ return m_uploadContext != nullptr;
+ }
+
+ void SetView(NSView* view)
+ {
+ bool needWait;
+ {
+ std::lock_guard lock(m_contextAccess);
+ needWait = (m_drawContext == nullptr);
+ }
+ if (needWait)
+ {
+ std::unique_lock lock(m_viewSetMutex);
+ m_viewSetCondition.wait(lock, [this] { return m_viewSet; });
+ }
+
+ std::lock_guard lock(m_contextAccess);
+ CHECK(m_drawContext, ());
+ m_drawContext->SetView(view);
+ }
+
+ void UpdateSize(int w, int h)
+ {
+ std::lock_guard lock(m_contextAccess);
+ if (m_drawContext)
+ m_drawContext->UpdateSize(w, h);
+ }
+
+private:
+ void NotifyView()
+ {
+ std::lock_guard lock(m_viewSetMutex);
+ m_viewSet = true;
+ m_viewSetCondition.notify_all();
+ }
+
+ static size_t constexpr kGLThreadsCount = 2;
+
+ std::unique_ptr m_drawContext;
+ std::unique_ptr m_uploadContext;
+
+ mutable std::mutex m_contextAccess;
+
+ bool m_isInitialized = false;
+ size_t m_initializationCounter = 0;
+ std::condition_variable m_initializationCondition;
+ std::mutex m_initializationMutex;
+
+ bool m_viewSet = false;
+ std::condition_variable m_viewSetCondition;
+ std::mutex m_viewSetMutex;
+};
+
+drape_ptr CreateContextFactory(GLFWwindow *window, dp::ApiVersion api, m2::PointU size)
+{
+ if (api == dp::ApiVersion::Metal)
+ {
+ CAMetalLayer *layer = [CAMetalLayer layer];
+ layer.device = MTLCreateSystemDefaultDevice();
+ layer.opaque = YES;
+ layer.displaySyncEnabled = YES;
+
+ NSWindow *nswindow = glfwGetCocoaWindow(window);
+ NSScreen *screen = [NSScreen mainScreen];
+ CGFloat factor = [screen backingScaleFactor];
+ layer.contentsScale = factor;
+ nswindow.contentView.layer = layer;
+ nswindow.contentView.wantsLayer = YES;
+
+ return make_unique_dp(layer, size);
+ }
+
+ if (api == dp::ApiVersion::Vulkan)
+ {
+ CAMetalLayer *layer = [CAMetalLayer layer];
+ layer.device = MTLCreateSystemDefaultDevice();
+ layer.opaque = YES;
+ layer.displaySyncEnabled = YES;
+
+ NSWindow *nswindow = glfwGetCocoaWindow(window);
+ NSScreen *screen = [NSScreen mainScreen];
+ CGFloat factor = [screen backingScaleFactor];
+ layer.contentsScale = factor;
+ nswindow.contentView.layer = layer;
+ nswindow.contentView.wantsLayer = YES;
+
+ auto contextFactory = make_unique_dp();
+ contextFactory->SetSurface(layer);
+ return contextFactory;
+ }
+
+ if (api == dp::ApiVersion::OpenGLES3)
+ {
+ NSWindow *nswindow = glfwGetCocoaWindow(window);
+ [nswindow.contentView setWantsBestResolutionOpenGLSurface:YES];
+ return make_unique_dp();
+ }
+
+ ASSERT(false, ("API is not available yet"));
+ return nullptr;
+}
+
+void OnCreateDrapeEngine(GLFWwindow *window, dp::ApiVersion api,
+ ref_ptr contextFactory)
+{
+ if (api == dp::ApiVersion::OpenGLES3)
+ {
+ NSWindow *nswindow = glfwGetCocoaWindow(window);
+ ref_ptr macosContextFactory = contextFactory;
+ macosContextFactory->SetView(nswindow.contentView);
+ }
+}
+
+void PrepareDestroyContextFactory(ref_ptr contextFactory)
+{
+ auto const api = contextFactory->GetDrawContext()->GetApiVersion();
+ if (api == dp::ApiVersion::Metal || api == dp::ApiVersion::OpenGLES3)
+ {
+ // Do nothing
+ }
+ else if (api == dp::ApiVersion::Vulkan)
+ {
+ ref_ptr macosContextFactory = contextFactory;
+ macosContextFactory->ResetSurface();
+ }
+ else
+ {
+ ASSERT(false, ("API is not available yet"));
+ }
+}
+
+void UpdateContentScale(GLFWwindow *window, float scale)
+{
+ NSWindow *nswindow = glfwGetCocoaWindow(window);
+ if (nswindow.contentView.layer)
+ nswindow.contentView.layer.contentsScale = scale;
+}
+
+void UpdateSize(ref_ptr contextFactory, int w, int h)
+{
+ if (!contextFactory || !contextFactory->GetDrawContext())
+ return;
+
+ auto const api = contextFactory->GetDrawContext()->GetApiVersion();
+ if (api == dp::ApiVersion::OpenGLES3)
+ {
+ ref_ptr macosContextFactory = contextFactory;
+ macosContextFactory->UpdateSize(w, h);
+ }
+}
diff --git a/dev_sandbox/main_linux.cpp b/dev_sandbox/main_linux.cpp
new file mode 100644
index 0000000000..43113d6346
--- /dev/null
+++ b/dev_sandbox/main_linux.cpp
@@ -0,0 +1,411 @@
+#include "std/target_os.hpp"
+#if !defined(OMIM_OS_LINUX)
+#error Unsupported OS
+#endif
+
+#define GLFW_INCLUDE_NONE
+#include
+#define GLFW_EXPOSE_NATIVE_X11
+#include
+
+#include
+#include
+
+#include
+#include
+// Workaround for TestFunction::Always compilation issue:
+// /usr/include/X11/X.h:441:33: note: expanded from macro 'Always'
+#undef Always
+// Workaround for storage::Status compilation issue:
+// /usr/include/X11/Xlib.h:83:16: note: expanded from macro 'Status'
+#undef Status
+
+#include "drape/vulkan/vulkan_context_factory.hpp"
+
+#include "drape/gl_functions.hpp"
+#include "drape/gl_includes.hpp"
+#include "drape/oglcontext.hpp"
+
+#include
+#include
+#include
+
+class LinuxVulkanContextFactory : public dp::vulkan::VulkanContextFactory
+{
+public:
+ LinuxVulkanContextFactory() : dp::vulkan::VulkanContextFactory(1, 33, false) {}
+
+ void SetSurface(Display * display, Window window)
+ {
+ VkXlibSurfaceCreateInfoKHR const createInfo = {
+ .sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
+ .pNext = nullptr,
+ .flags = 0,
+ .dpy = display,
+ .window = window,
+ };
+
+ VkResult statusCode;
+ CHECK(vkCreateXlibSurfaceKHR, ());
+ statusCode = vkCreateXlibSurfaceKHR(m_vulkanInstance, &createInfo, nullptr, &m_surface);
+ if (statusCode != VK_SUCCESS)
+ {
+ LOG_ERROR_VK_CALL(vkCreateXlibSurfaceKHR, statusCode);
+ return;
+ }
+
+ uint32_t const renderingQueueIndex = m_drawContext->GetRenderingQueueFamilyIndex();
+ VkBool32 supportsPresent;
+ statusCode = vkGetPhysicalDeviceSurfaceSupportKHR(m_gpu, renderingQueueIndex, m_surface, &supportsPresent);
+ if (statusCode != VK_SUCCESS)
+ {
+ LOG_ERROR_VK_CALL(vkGetPhysicalDeviceSurfaceSupportKHR, statusCode);
+ return;
+ }
+ CHECK_EQUAL(supportsPresent, VK_TRUE, ());
+
+ CHECK(QuerySurfaceSize(), ());
+
+ if (m_drawContext)
+ m_drawContext->SetSurface(m_surface, m_surfaceFormat, m_surfaceCapabilities);
+ }
+
+ void ResetSurface()
+ {
+ if (m_drawContext)
+ m_drawContext->ResetSurface(false);
+
+ vkDestroySurfaceKHR(m_vulkanInstance, m_surface, nullptr);
+ }
+};
+
+// Based on: https://github.com/glfw/glfw/blob/master/src/glx_context.c
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define GLX_PBUFFER_HEIGHT 0x8040
+#define GLX_PBUFFER_WIDTH 0x8041
+#define GLX_DOUBLEBUFFER 5
+#define GLX_DRAWABLE_TYPE 0x8010
+#define GLX_RENDER_TYPE 0x8011
+#define GLX_WINDOW_BIT 0x00000001
+#define GLX_PBUFFER_BIT 0x00000004
+#define GLX_RGBA_BIT 0x00000001
+#define GLX_RED_SIZE 8
+#define GLX_GREEN_SIZE 9
+#define GLX_BLUE_SIZE 10
+#define GLX_ALPHA_SIZE 11
+#define GLX_DEPTH_SIZE 12
+#define GLX_STENCIL_SIZE 13
+
+typedef XID GLXDrawable;
+typedef struct __GLXcontext * GLXContext;
+typedef XID GLXPbuffer;
+typedef struct __GLXFBConfig * GLXFBConfig;
+typedef void (*__GLXextproc)(void);
+
+typedef __GLXextproc (*PFNGLXGETPROCADDRESSPROC)(const GLubyte * procName);
+
+typedef int (*PFNXFREE)(void *);
+typedef GLXFBConfig * (*PFNGLXCHOOSEFBCONFIGPROC)(Display *, int, const int *, int *);
+typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARB)(Display *, GLXFBConfig, GLXContext, Bool, const int *);
+typedef void (*PFNGLXDESTROYCONTEXT)(Display *, GLXContext);
+typedef GLXPbuffer (*PFNGLXCREATEPBUFFERPROC)(Display *, GLXFBConfig, const int *);
+typedef void (*PFNGLXDESTROYPBUFFER)(Display *, GLXPbuffer);
+typedef Bool (*PFNGLXMAKECURRENTPROC)(Display *, GLXDrawable, GLXContext);
+typedef void (*PFNGLXSWAPBUFFERSPROC)(Display *, GLXDrawable);
+
+struct GLXFunctions
+{
+ GLXFunctions()
+ {
+ std::array libs = {
+ "libGLX.so.0",
+ "libGL.so.1",
+ "libGL.so",
+ };
+
+ for (char const * lib : libs)
+ {
+ m_module = dlopen(lib, RTLD_LAZY | RTLD_LOCAL);
+ if (m_module)
+ {
+ break;
+ }
+ }
+
+ CHECK(m_module != nullptr, ("Failed to initialize GLX"));
+
+ XFree = loadFunction("XFree");
+
+ glXGetProcAddress = loadFunction("glXGetProcAddress");
+ glXGetProcAddressARB = loadFunction("glXGetProcAddressARB");
+
+ glXChooseFBConfig = loadGlxFunction("glXChooseFBConfig");
+ glXCreateContextAttribsARB = loadGlxFunction("glXCreateContextAttribsARB");
+
+ glXDestroyContext = loadGlxFunction("glXDestroyContext");
+ glXCreatePbuffer = loadGlxFunction("glXCreatePbuffer");
+ glXDestroyPbuffer = loadGlxFunction("glXDestroyPbuffer");
+ glXMakeCurrent = loadGlxFunction("glXMakeCurrent");
+ glXSwapBuffers = loadGlxFunction("glXSwapBuffers");
+ }
+
+ ~GLXFunctions()
+ {
+ if (m_module)
+ {
+ dlclose(m_module);
+ }
+ }
+
+ PFNXFREE XFree = nullptr;
+
+ PFNGLXGETPROCADDRESSPROC glXGetProcAddress = nullptr;
+ PFNGLXGETPROCADDRESSPROC glXGetProcAddressARB = nullptr;
+
+ PFNGLXCHOOSEFBCONFIGPROC glXChooseFBConfig = nullptr;
+ PFNGLXCREATECONTEXTATTRIBSARB glXCreateContextAttribsARB = nullptr;
+ PFNGLXDESTROYCONTEXT glXDestroyContext = nullptr;
+ PFNGLXCREATEPBUFFERPROC glXCreatePbuffer = nullptr;
+ PFNGLXDESTROYPBUFFER glXDestroyPbuffer = nullptr;
+ PFNGLXMAKECURRENTPROC glXMakeCurrent = nullptr;
+ PFNGLXSWAPBUFFERSPROC glXSwapBuffers = nullptr;
+
+private:
+ template
+ T loadFunction(char const * func)
+ {
+ auto f = reinterpret_cast(dlsym(m_module, func));
+ ASSERT(f, ("Failed to initialize GLX:", func, "is not found"));
+ return f;
+ }
+
+ template
+ T loadGlxFunction(char const * func)
+ {
+ if (auto f = reinterpret_cast(glXGetProcAddress(reinterpret_cast(func))))
+ return f;
+
+ if (auto f = reinterpret_cast(glXGetProcAddressARB(reinterpret_cast(func))))
+ return f;
+
+ return loadFunction(func);
+ }
+
+ void * m_module = nullptr;
+};
+
+class LinuxGLContext : public dp::OGLContext
+{
+public:
+ LinuxGLContext(GLXFunctions const & glx, Display * display, Window window, LinuxGLContext * contextToShareWith,
+ bool usePixelBuffer)
+ : m_glx(glx), m_display(display), m_window(window)
+ {
+ static int visualAttribs[] = {
+ GLX_DOUBLEBUFFER, True,
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_DRAWABLE_TYPE, (usePixelBuffer ? GLX_PBUFFER_BIT : GLX_WINDOW_BIT),
+ GLX_RED_SIZE, 8,
+ GLX_GREEN_SIZE, 8,
+ GLX_BLUE_SIZE, 8,
+ GLX_ALPHA_SIZE, 8,
+ GLX_DEPTH_SIZE, 24,
+ GLX_STENCIL_SIZE, 8,
+ None
+ };
+ int contextAttribs[] = {
+ GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+ GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
+ GLX_CONTEXT_MINOR_VERSION_ARB, 1,
+ None};
+ int fbcount = 0;
+ if (GLXFBConfig * config = m_glx.glXChooseFBConfig(display, DefaultScreen(display), visualAttribs, &fbcount))
+ {
+ m_context =
+ m_glx.glXCreateContextAttribsARB(display, config[0], contextToShareWith ? contextToShareWith->m_context : 0, True, contextAttribs);
+ CHECK(m_context != nullptr, ("Failed to create GLX context"));
+
+ if (usePixelBuffer)
+ {
+ int pbufferAttribs[] = {GLX_PBUFFER_WIDTH, 1, GLX_PBUFFER_HEIGHT, 1, None};
+
+ m_pixelBufferHandle = m_glx.glXCreatePbuffer(display, config[0], pbufferAttribs);
+ CHECK(m_pixelBufferHandle != 0, ("Failed to create GLX pbuffer"));
+ }
+
+ m_glx.XFree(config);
+ }
+ }
+
+ ~LinuxGLContext() override
+ {
+ if (m_pixelBufferHandle)
+ {
+ m_glx.glXDestroyPbuffer(m_display, m_pixelBufferHandle);
+ m_pixelBufferHandle = 0;
+ }
+ if (m_context)
+ {
+ m_glx.glXDestroyContext(m_display, m_context);
+ m_context = nullptr;
+ }
+ }
+
+ void Present() override
+ {
+ if (!m_pixelBufferHandle)
+ m_glx.glXSwapBuffers(m_display, m_window);
+ }
+
+ void MakeCurrent() override
+ {
+ if (!m_glx.glXMakeCurrent(m_display, m_pixelBufferHandle ? m_pixelBufferHandle : m_window, m_context))
+ LOG(LERROR, ("MakeCurrent(): glXMakeCurrent failed"));
+ }
+
+ void DoneCurrent() override
+ {
+ if (!m_glx.glXMakeCurrent(m_display, None, nullptr))
+ LOG(LERROR, ("DoneCurrent(): glXMakeCurrent failed"));
+ }
+
+ void SetFramebuffer(ref_ptr framebuffer) override
+ {
+ if (framebuffer)
+ framebuffer->Bind();
+ else
+ GLFunctions::glBindFramebuffer(0);
+ }
+
+private:
+ GLXFunctions const & m_glx;
+
+ Display * m_display = nullptr;
+ Window m_window = 0;
+ GLXDrawable m_pixelBufferHandle = 0;
+ GLXContext m_context = nullptr;
+};
+
+class LinuxContextFactory : public dp::GraphicsContextFactory
+{
+public:
+ LinuxContextFactory(Display * display, Window window) : m_display(display), m_window(window) {}
+
+ dp::GraphicsContext * GetDrawContext() override
+ {
+ std::lock_guard lock(m_contextAccess);
+ if (m_drawContext == nullptr)
+ m_drawContext = std::make_unique(m_glx, m_display, m_window, m_uploadContext.get(), false);
+ return m_drawContext.get();
+ }
+
+ dp::GraphicsContext * GetResourcesUploadContext() override
+ {
+ std::lock_guard lock(m_contextAccess);
+ if (m_uploadContext == nullptr)
+ m_uploadContext = std::make_unique(m_glx, m_display, 0, m_drawContext.get(), true);
+ return m_uploadContext.get();
+ }
+
+ void WaitForInitialization(dp::GraphicsContext *) override
+ {
+ std::unique_lock lock(m_initializationMutex);
+ if (m_isInitialized)
+ return;
+
+ m_initializationCounter++;
+ if (m_initializationCounter >= kGLThreadsCount)
+ {
+ m_isInitialized = true;
+ m_initializationCondition.notify_all();
+ }
+ else
+ {
+ m_initializationCondition.wait(lock, [this] { return m_isInitialized; });
+ }
+ }
+
+ bool IsDrawContextCreated() const override
+ {
+ std::lock_guard lock(m_contextAccess);
+ return m_drawContext != nullptr;
+ }
+
+ bool IsUploadContextCreated() const override
+ {
+ std::lock_guard lock(m_contextAccess);
+ return m_uploadContext != nullptr;
+ }
+
+private:
+ static size_t constexpr kGLThreadsCount = 2;
+
+ GLXFunctions m_glx;
+
+ Display * m_display = nullptr;
+ Window m_window = 0;
+
+ std::unique_ptr m_drawContext;
+ std::unique_ptr m_uploadContext;
+
+ mutable std::mutex m_contextAccess;
+
+ bool m_isInitialized = false;
+ size_t m_initializationCounter = 0;
+ std::condition_variable m_initializationCondition;
+ std::mutex m_initializationMutex;
+};
+
+drape_ptr CreateContextFactory(GLFWwindow * window, dp::ApiVersion api, m2::PointU size)
+{
+ if (api == dp::ApiVersion::Vulkan)
+ {
+ auto contextFactory = make_unique_dp();
+ contextFactory->SetSurface(glfwGetX11Display(), glfwGetX11Window(window));
+ return contextFactory;
+ }
+
+ if (api == dp::ApiVersion::OpenGLES3)
+ {
+ return make_unique_dp(glfwGetX11Display(), glfwGetX11Window(window));
+ }
+
+ ASSERT(false, ("API is not available yet"));
+ return nullptr;
+}
+
+void OnCreateDrapeEngine(GLFWwindow * window, dp::ApiVersion api, ref_ptr contextFactory)
+{
+ // Do nothing
+}
+
+void PrepareDestroyContextFactory(ref_ptr contextFactory)
+{
+ auto const api = contextFactory->GetDrawContext()->GetApiVersion();
+ if (api == dp::ApiVersion::OpenGLES3)
+ {
+ // Do nothing
+ }
+ else if (api == dp::ApiVersion::Vulkan)
+ {
+ ref_ptr linuxContextFactory = contextFactory;
+ linuxContextFactory->ResetSurface();
+ }
+ else
+ {
+ ASSERT(false, ("API is not available yet"));
+ }
+}
+
+void UpdateContentScale(GLFWwindow * window, float scale)
+{
+ // Do nothing
+}
+
+void UpdateSize(ref_ptr contextFactory, int w, int h)
+{
+ // Do nothing
+}
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index e4095ce611..77660b127e 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -115,6 +115,10 @@ sudo apt update && sudo apt install -y \
libqt6positioning6-plugins \
libqt6positioning6 \
libsqlite3-dev \
+ libxrandr-dev \
+ libxinerama-dev \
+ libxcursor-dev \
+ libxi-dev \
zlib1g-dev
```
diff --git a/drape/data_buffer.cpp b/drape/data_buffer.cpp
index 8040056ccf..878757782a 100644
--- a/drape/data_buffer.cpp
+++ b/drape/data_buffer.cpp
@@ -21,7 +21,7 @@ void DataBuffer::MoveToGPU(ref_ptr context, GPUBuffer::Target t
uint32_t const currentSize = m_impl->GetCurrentSize();
auto const apiVersion = context->GetApiVersion();
- if (apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3)
+ if (apiVersion == dp::ApiVersion::OpenGLES3)
{
if (currentSize != 0)
{
diff --git a/drape/drape_global.hpp b/drape/drape_global.hpp
index d0f449483b..3939ad9420 100644
--- a/drape/drape_global.hpp
+++ b/drape/drape_global.hpp
@@ -26,7 +26,6 @@ namespace dp
enum class ApiVersion
{
Invalid = -1,
- OpenGLES2 = 0,
OpenGLES3,
Metal,
Vulkan
@@ -101,7 +100,6 @@ inline std::string DebugPrint(dp::ApiVersion apiVersion)
switch (apiVersion)
{
case dp::ApiVersion::Invalid: return "Invalid";
- case dp::ApiVersion::OpenGLES2: return "OpenGLES2";
case dp::ApiVersion::OpenGLES3: return "OpenGLES3";
case dp::ApiVersion::Metal: return "Metal";
case dp::ApiVersion::Vulkan: return "Vulkan";
@@ -121,9 +119,6 @@ inline dp::ApiVersion ApiVersionFromString(std::string const & str)
return dp::ApiVersion::Vulkan;
#endif
- if (str == "OpenGLES2")
- return dp::ApiVersion::OpenGLES2;
-
if (str == "OpenGLES3")
return dp::ApiVersion::OpenGLES3;
diff --git a/drape/drape_tests/font_texture_tests.cpp b/drape/drape_tests/font_texture_tests.cpp
index a835e16697..3e58d99102 100644
--- a/drape/drape_tests/font_texture_tests.cpp
+++ b/drape/drape_tests/font_texture_tests.cpp
@@ -105,7 +105,7 @@ UNIT_TEST(UploadingGlyphs)
TestingGraphicsContext context;
Texture::Params p;
p.m_allocator = GetDefaultAllocator(make_ref(&context));
- p.m_format = dp::TextureFormat::Alpha;
+ p.m_format = dp::TextureFormat::Red;
p.m_width = p.m_height = kTextureSize;
DummyTexture tex;
diff --git a/drape/drape_tests/testing_graphics_context.hpp b/drape/drape_tests/testing_graphics_context.hpp
index 95b9580c3c..e7f3d1da70 100644
--- a/drape/drape_tests/testing_graphics_context.hpp
+++ b/drape/drape_tests/testing_graphics_context.hpp
@@ -2,7 +2,7 @@
#include "drape/graphics_context.hpp"
-// Testing context simulates OpenGLES2 API version.
+// Testing context simulates OpenGLES3 API version.
class TestingGraphicsContext : public dp::GraphicsContext
{
public:
@@ -38,5 +38,5 @@ public:
void SetCullingEnabled(bool enabled) override {}
private:
- dp::ApiVersion m_apiVersion = dp::ApiVersion::OpenGLES2;
+ dp::ApiVersion m_apiVersion = dp::ApiVersion::OpenGLES3;
};
diff --git a/drape/font_texture.hpp b/drape/font_texture.hpp
index ac25ad0948..b658ba0dc2 100644
--- a/drape/font_texture.hpp
+++ b/drape/font_texture.hpp
@@ -81,7 +81,7 @@ public:
FontTexture(m2::PointU const & size, ref_ptr glyphMng, ref_ptr allocator)
: m_index(size, glyphMng)
{
- DynamicTextureParams const params{size, TextureFormat::Alpha, TextureFilter::Linear, true /* m_usePixelBuffer */};
+ DynamicTextureParams const params{size, TextureFormat::Red, TextureFilter::Linear, true /* m_usePixelBuffer */};
Init(allocator, make_ref(&m_index), params);
}
diff --git a/drape/framebuffer.cpp b/drape/framebuffer.cpp
index 72b6d098b3..c2b5f4f99a 100644
--- a/drape/framebuffer.cpp
+++ b/drape/framebuffer.cpp
@@ -134,7 +134,7 @@ void Framebuffer::SetSize(ref_ptr context, uint32_t width,
m_depthStencilRef->SetSize(context, m_width, m_height);
auto const apiVersion = context->GetApiVersion();
- if (apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3)
+ if (apiVersion == dp::ApiVersion::OpenGLES3)
{
glConst depthAttachmentId = 0;
glConst stencilAttachmentId = 0;
diff --git a/drape/gl_extensions_list.cpp b/drape/gl_extensions_list.cpp
index bd80605cfe..a616d232d2 100644
--- a/drape/gl_extensions_list.cpp
+++ b/drape/gl_extensions_list.cpp
@@ -7,67 +7,14 @@
namespace dp
{
-void GLExtensionsList::Init(dp::ApiVersion apiVersion)
+void GLExtensionsList::Init()
{
-#if defined(OMIM_OS_MOBILE)
- if (apiVersion == dp::ApiVersion::OpenGLES2)
- {
#ifdef OMIM_OS_ANDROID
- SetExtension(VertexArrayObject, false);
- // On some Android devices glMapBufferRange/glMapBuffer works very slow.
- // We have to substitute these functions to glBufferData/glBufferSubData.
- SetExtension(MapBuffer, false);
- SetExtension(MapBufferRange, false);
-#else
- CheckExtension(VertexArrayObject, "GL_OES_vertex_array_object");
- CheckExtension(MapBuffer, "GL_OES_mapbuffer");
- CheckExtension(MapBufferRange, "GL_EXT_map_buffer_range");
-#endif
- CheckExtension(UintIndices, "GL_OES_element_index_uint");
- }
- else
- {
-#ifdef OMIM_OS_ANDROID
- SetExtension(MapBuffer, false);
- SetExtension(MapBufferRange, false);
-#else
- SetExtension(MapBuffer, true);
- SetExtension(MapBufferRange, true);
-#endif
- SetExtension(VertexArrayObject, true);
- SetExtension(UintIndices, true);
- }
-#elif defined(OMIM_OS_LINUX)
- SetExtension(MapBuffer, true);
- SetExtension(UintIndices, true);
- SetExtension(VertexArrayObject, true);
- SetExtension(MapBufferRange, true);
-#elif defined(OMIM_OS_WINDOWS)
- SetExtension(MapBuffer, true);
- SetExtension(UintIndices, true);
- if (apiVersion == dp::ApiVersion::OpenGLES2)
- {
- SetExtension(VertexArrayObject, false);
- SetExtension(MapBufferRange, false);
- }
- else
- {
- SetExtension(VertexArrayObject, true);
- SetExtension(MapBufferRange, true);
- }
+ // NOTE: MapBuffer/MapBufferRange are disabled by performance reasons according to
+ // https://github.com/organicmaps/organicmaps/commit/d72ab7c8cd8be0eb5a622d9d33ae943b391d5707
+ SetExtension(MapBuffer, false);
#else
SetExtension(MapBuffer, true);
- SetExtension(UintIndices, true);
- if (apiVersion == dp::ApiVersion::OpenGLES2)
- {
- CheckExtension(VertexArrayObject, "GL_APPLE_vertex_array_object");
- SetExtension(MapBufferRange, false);
- }
- else
- {
- SetExtension(VertexArrayObject, true);
- SetExtension(MapBufferRange, true);
- }
#endif
}
diff --git a/drape/gl_extensions_list.hpp b/drape/gl_extensions_list.hpp
index c5fb4dfc1b..c962c0714c 100644
--- a/drape/gl_extensions_list.hpp
+++ b/drape/gl_extensions_list.hpp
@@ -14,14 +14,11 @@ class GLExtensionsList
public:
enum ExtensionName
{
- VertexArrayObject,
MapBuffer,
- UintIndices,
- MapBufferRange
};
GLExtensionsList() = default;
- void Init(dp::ApiVersion apiVersion);
+ void Init();
bool IsSupported(ExtensionName extName) const;
private:
diff --git a/drape/gl_functions.cpp b/drape/gl_functions.cpp
index 14c6ecf3eb..7efebf1acf 100644
--- a/drape/gl_functions.cpp
+++ b/drape/gl_functions.cpp
@@ -239,81 +239,26 @@ void GLFunctions::Init(dp::ApiVersion apiVersion)
return;
CurrentApiVersion = apiVersion;
- ExtensionsList.Init(apiVersion);
+ ExtensionsList.Init();
s_inited = true;
-/// VAO
#if !defined(OMIM_OS_WINDOWS)
- if (CurrentApiVersion == dp::ApiVersion::OpenGLES2)
- {
-#if defined(OMIM_OS_MAC)
-
- glGenVertexArraysFn = &glGenVertexArraysAPPLE;
- glBindVertexArrayFn = &glBindVertexArrayAPPLE;
- glDeleteVertexArrayFn = &glDeleteVertexArraysAPPLE;
- glMapBufferFn = &::glMapBuffer;
- glUnmapBufferFn = &::glUnmapBuffer;
-
-#elif defined(OMIM_OS_LINUX)
- void *libhandle = dlopen("libGL.so.1", RTLD_LAZY);
- if (!libhandle)
- LOG(LCRITICAL, ("Failed to open libGL.so.1:", dlerror()));
- glGenVertexArraysFn = (TglGenVertexArraysFn)dlsym(libhandle,"glGenVertexArraysOES");
- glBindVertexArrayFn = (TglBindVertexArrayFn)dlsym(libhandle, "glBindVertexArrayOES");
- glDeleteVertexArrayFn = (TglDeleteVertexArrayFn)dlsym(libhandle,"glDeleteVertexArraysOES");
- glMapBufferFn = (TglMapBufferFn)dlsym(libhandle, "glMapBufferOES");
- glUnmapBufferFn = (TglUnmapBufferFn)dlsym(libhandle, "glUnmapBufferOES");
- glMapBufferRangeFn = (TglMapBufferRangeFn)dlsym(libhandle, "glMapBufferRangeEXT");
- glFlushMappedBufferRangeFn =
- (TglFlushMappedBufferRangeFn)dlsym(libhandle, "glFlushMappedBufferRangeEXT");
-
-#elif defined(OMIM_OS_ANDROID)
-
- glGenVertexArraysFn = (TglGenVertexArraysFn)eglGetProcAddress("glGenVertexArraysOES");
- glBindVertexArrayFn = (TglBindVertexArrayFn)eglGetProcAddress("glBindVertexArrayOES");
- glDeleteVertexArrayFn = (TglDeleteVertexArrayFn)eglGetProcAddress("glDeleteVertexArraysOES");
- glMapBufferFn = &::glMapBufferOES;
- glUnmapBufferFn = &::glUnmapBufferOES;
- glMapBufferRangeFn = (TglMapBufferRangeFn)eglGetProcAddress("glMapBufferRangeEXT");
- glFlushMappedBufferRangeFn =
- (TglFlushMappedBufferRangeFn)eglGetProcAddress("glFlushMappedBufferRangeEXT");
-
-#elif defined(OMIM_OS_MOBILE)
-
- glGenVertexArraysFn = &glGenVertexArraysOES;
- glBindVertexArrayFn = &glBindVertexArrayOES;
- glDeleteVertexArrayFn = &glDeleteVertexArraysOES;
- glMapBufferFn = &::glMapBufferOES;
- glUnmapBufferFn = &::glUnmapBufferOES;
- glMapBufferRangeFn = &::glMapBufferRangeEXT;
- glFlushMappedBufferRangeFn = &::glFlushMappedBufferRangeEXT;
-#endif // #if defined(OMIM_OS_MAC)
- }
- else if (CurrentApiVersion == dp::ApiVersion::OpenGLES3)
- {
- // OpenGL ES3 api is the same for all systems, except WINDOWS.
- glGenVertexArraysFn = ::glGenVertexArrays;
- glBindVertexArrayFn = ::glBindVertexArray;
- glDeleteVertexArrayFn = ::glDeleteVertexArrays;
- glUnmapBufferFn = ::glUnmapBuffer;
- glMapBufferRangeFn = ::glMapBufferRange;
- glFlushMappedBufferRangeFn = ::glFlushMappedBufferRange;
- glGetStringiFn = ::glGetStringi;
- }
- else
- {
- CHECK(false, ("Unknown Graphics API"));
- }
-
+ // OpenGL ES3 api is the same for all systems, except WINDOWS.
+ glGenVertexArraysFn = ::glGenVertexArrays;
+ glBindVertexArrayFn = ::glBindVertexArray;
+ glDeleteVertexArrayFn = ::glDeleteVertexArrays;
+ glUnmapBufferFn = ::glUnmapBuffer;
+ glMapBufferRangeFn = ::glMapBufferRange;
+ glFlushMappedBufferRangeFn = ::glFlushMappedBufferRange;
+ glGetStringiFn = ::glGetStringi;
#else // OMIM_OS_WINDOWS
- if (ExtensionsList.IsSupported(dp::GLExtensionsList::VertexArrayObject))
- {
- glGenVertexArraysFn = LOAD_GL_FUNC(TglGenVertexArraysFn, glGenVertexArrays);
- glBindVertexArrayFn = LOAD_GL_FUNC(TglBindVertexArrayFn, glBindVertexArray);
- glDeleteVertexArrayFn = LOAD_GL_FUNC(TglDeleteVertexArrayFn, glDeleteVertexArrays);
- }
- glMapBufferFn = LOAD_GL_FUNC(TglMapBufferFn, glMapBuffer);
+ glGenVertexArraysFn = LOAD_GL_FUNC(TglGenVertexArraysFn, glGenVertexArrays);
+ glBindVertexArrayFn = LOAD_GL_FUNC(TglBindVertexArrayFn, glBindVertexArray);
+ glDeleteVertexArrayFn = LOAD_GL_FUNC(TglDeleteVertexArrayFn, glDeleteVertexArrays);
glUnmapBufferFn = LOAD_GL_FUNC(TglUnmapBufferFn, glUnmapBuffer);
+ glMapBufferFn = LOAD_GL_FUNC(TglMapBufferFn, glMapBuffer);
+ glFlushMappedBufferRangeFn = LOAD_GL_FUNC(TglFlushMappedBufferRangeFn, glFlushMappedBufferRange);
+ glGetStringiFn = LOAD_GL_FUNC(TglGetStringiFn, glGetStringi);
#endif
glClearColorFn = LOAD_GL_FUNC(TglClearColorFn, glClearColor);
@@ -393,115 +338,94 @@ void GLFunctions::Init(dp::ApiVersion apiVersion)
bool GLFunctions::glHasExtension(std::string const & name)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
- if (CurrentApiVersion == dp::ApiVersion::OpenGLES2)
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
+ ASSERT(glGetStringiFn != nullptr, ());
+ GLint n = 0;
+ glGetIntegerv(GL_NUM_EXTENSIONS, &n);
+ for (GLint i = 0; i < n; i++)
{
- char const * extensions = reinterpret_cast(::glGetString(GL_EXTENSIONS));
- GLCHECKCALL();
- if (extensions == nullptr)
- return false;
-
- char const * extName = name.c_str();
- char const * ptr = nullptr;
- while ((ptr = strstr(extensions, extName)) != nullptr)
- {
- char const * end = ptr + strlen(extName);
- if (isspace(*end) || *end == '\0')
- return true;
-
- extensions = end;
- }
- }
- else if (CurrentApiVersion == dp::ApiVersion::OpenGLES3)
- {
- ASSERT(glGetStringiFn != nullptr, ());
- GLint n = 0;
- glGetIntegerv(GL_NUM_EXTENSIONS, &n);
- for (GLint i = 0; i < n; i++)
- {
- std::string const extension =
- std::string(reinterpret_cast(glGetStringiFn(GL_EXTENSIONS, i)));
- if (extension == name)
- return true;
- }
+ std::string const extension =
+ std::string(reinterpret_cast(glGetStringiFn(GL_EXTENSIONS, i)));
+ if (extension == name)
+ return true;
}
return false;
}
void GLFunctions::glClearColor(float r, float g, float b, float a)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glClearColorFn != nullptr, ());
GLCHECK(glClearColorFn(r, g, b, a));
}
void GLFunctions::glClear(uint32_t clearBits)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glClearFn != nullptr, ());
GLCHECK(glClearFn(clearBits));
}
void GLFunctions::glViewport(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glViewportFn != nullptr, ());
GLCHECK(glViewportFn(x, y, w, h));
}
void GLFunctions::glScissor(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glScissorFn != nullptr, ());
GLCHECK(glScissorFn(x, y, w, h));
}
void GLFunctions::glFlush()
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glFlushFn != nullptr, ());
GLCHECK(glFlushFn());
}
void GLFunctions::glFinish()
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glFinish());
}
void GLFunctions::glFrontFace(glConst mode)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glFrontFace(mode));
}
void GLFunctions::glCullFace(glConst face)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glCullFace(face));
}
void GLFunctions::glStencilOpSeparate(glConst face, glConst sfail, glConst dpfail, glConst dppass)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glStencilOpSeparate(face, sfail, dpfail, dppass));
}
void GLFunctions::glStencilFuncSeparate(glConst face, glConst func, int ref, uint32_t mask)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glStencilFuncSeparate(face, func, ref, mask));
}
void GLFunctions::glPixelStore(glConst name, uint32_t value)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glPixelStorei(name, value));
}
int32_t GLFunctions::glGetInteger(glConst pname)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLint value;
GLCHECK(::glGetIntegerv(pname, &value));
return (int32_t)value;
@@ -509,7 +433,7 @@ int32_t GLFunctions::glGetInteger(glConst pname)
std::string GLFunctions::glGetString(glConst pname)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
char const * str = reinterpret_cast(::glGetString(pname));
GLCHECKCALL();
if (str == nullptr)
@@ -520,7 +444,7 @@ std::string GLFunctions::glGetString(glConst pname)
int32_t GLFunctions::glGetMaxLineWidth()
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLint range[2];
GLCHECK(::glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, range));
return std::max(range[0], range[1]);
@@ -528,7 +452,7 @@ int32_t GLFunctions::glGetMaxLineWidth()
int32_t GLFunctions::glGetBufferParameter(glConst target, glConst name)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLint result;
ASSERT(glGetBufferParameterFn != nullptr, ());
GLCHECK(glGetBufferParameterFn(target, name, &result));
@@ -537,19 +461,19 @@ int32_t GLFunctions::glGetBufferParameter(glConst target, glConst name)
void GLFunctions::glEnable(glConst mode)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glEnable(mode));
}
void GLFunctions::glDisable(glConst mode)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glDisable(mode));
}
void GLFunctions::glClearDepthValue(double depth)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
#if defined(OMIM_OS_IPHONE) || defined(OMIM_OS_ANDROID) || defined(OMIM_OS_LINUX)
GLCHECK(::glClearDepthf(static_cast(depth)));
#else
@@ -559,32 +483,32 @@ void GLFunctions::glClearDepthValue(double depth)
void GLFunctions::glDepthMask(bool needWriteToDepthBuffer)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glDepthMask(convert(needWriteToDepthBuffer)));
}
void GLFunctions::glDepthFunc(glConst depthFunc)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glDepthFunc(depthFunc));
}
void GLFunctions::glBlendEquation(glConst function)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glBlendEquationFn != nullptr, ());
GLCHECK(glBlendEquationFn(function));
}
void GLFunctions::glBlendFunc(glConst srcFactor, glConst dstFactor)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glBlendFunc(srcFactor, dstFactor));
}
bool GLFunctions::CanEnableDebugMessages()
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
if (glDebugMessageCallbackFn == nullptr)
return false;
if (glDebugMessageControlFn == nullptr)
@@ -596,7 +520,7 @@ bool GLFunctions::CanEnableDebugMessages()
void GLFunctions::glDebugMessageCallback(TglDebugProc messageCallback, void * userParam)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glDebugMessageCallbackFn != nullptr, ());
GLCHECK(glDebugMessageCallbackFn(reinterpret_cast(messageCallback), userParam));
}
@@ -604,14 +528,14 @@ void GLFunctions::glDebugMessageCallback(TglDebugProc messageCallback, void * us
void GLFunctions::glDebugMessageControl(glConst source, glConst type, glConst severity,
int32_t count, uint32_t const * ids, uint8_t enabled)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glDebugMessageControlFn != nullptr, ());
GLCHECK(glDebugMessageControlFn(source, type, severity, count, ids, enabled));
}
uint32_t GLFunctions::glGenVertexArray()
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glGenVertexArraysFn != nullptr, ());
GLuint result = std::numeric_limits::max();
GLCHECK(glGenVertexArraysFn(1, &result));
@@ -620,21 +544,21 @@ uint32_t GLFunctions::glGenVertexArray()
void GLFunctions::glBindVertexArray(uint32_t vao)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glBindVertexArrayFn != nullptr, ());
GLCHECK(glBindVertexArrayFn(vao));
}
void GLFunctions::glDeleteVertexArray(uint32_t vao)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glDeleteVertexArrayFn != nullptr, ());
GLCHECK(glDeleteVertexArrayFn(1, &vao));
}
uint32_t GLFunctions::glGenBuffer()
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glGenBuffersFn != nullptr, ());
GLuint result = std::numeric_limits::max();
GLCHECK(glGenBuffersFn(1, &result));
@@ -643,7 +567,7 @@ uint32_t GLFunctions::glGenBuffer()
void GLFunctions::glBindBuffer(uint32_t vbo, uint32_t target)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glBindBufferFn != nullptr, ());
#ifdef DEBUG
std::lock_guard guard(g_boundBuffersMutex);
@@ -654,7 +578,7 @@ void GLFunctions::glBindBuffer(uint32_t vbo, uint32_t target)
void GLFunctions::glDeleteBuffer(uint32_t vbo)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glDeleteBuffersFn != nullptr, ());
#ifdef DEBUG
std::lock_guard guard(g_boundBuffersMutex);
@@ -666,21 +590,21 @@ void GLFunctions::glDeleteBuffer(uint32_t vbo)
void GLFunctions::glBufferData(glConst target, uint32_t size, void const * data, glConst usage)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glBufferDataFn != nullptr, ());
GLCHECK(glBufferDataFn(target, size, data, usage));
}
void GLFunctions::glBufferSubData(glConst target, uint32_t size, void const * data, uint32_t offset)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glBufferSubDataFn != nullptr, ());
GLCHECK(glBufferSubDataFn(target, offset, size, data));
}
void * GLFunctions::glMapBuffer(glConst target, glConst access)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glMapBufferFn != nullptr, ());
void * result = glMapBufferFn(target, access);
GLCHECKCALL();
@@ -689,7 +613,7 @@ void * GLFunctions::glMapBuffer(glConst target, glConst access)
void GLFunctions::glUnmapBuffer(glConst target)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glUnmapBufferFn != nullptr, ());
VERIFY(glUnmapBufferFn(target) == GL_TRUE, ());
GLCHECKCALL();
@@ -698,7 +622,7 @@ void GLFunctions::glUnmapBuffer(glConst target)
void * GLFunctions::glMapBufferRange(glConst target, uint32_t offset, uint32_t length,
glConst access)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glMapBufferRangeFn != nullptr, ());
void * result = glMapBufferRangeFn(target, offset, length, access);
GLCHECKCALL();
@@ -707,14 +631,14 @@ void * GLFunctions::glMapBufferRange(glConst target, uint32_t offset, uint32_t l
void GLFunctions::glFlushMappedBufferRange(glConst target, uint32_t offset, uint32_t length)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glFlushMappedBufferRangeFn != nullptr, ());
GLCHECK(glFlushMappedBufferRangeFn(target, offset, length));
}
uint32_t GLFunctions::glCreateShader(glConst type)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glCreateShaderFn != nullptr, ());
GLuint result = glCreateShaderFn(type);
GLCHECKCALL();
@@ -723,7 +647,7 @@ uint32_t GLFunctions::glCreateShader(glConst type)
void GLFunctions::glShaderSource(uint32_t shaderID, std::string const & src, std::string const & defines)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glShaderSourceFn != nullptr, ());
std::string fullSrc;
@@ -746,7 +670,7 @@ void GLFunctions::glShaderSource(uint32_t shaderID, std::string const & src, std
bool GLFunctions::glCompileShader(uint32_t shaderID, std::string & errorLog)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glCompileShaderFn != nullptr, ());
ASSERT(glGetShaderivFn != nullptr, ());
ASSERT(glGetShaderInfoLogFn != nullptr, ());
@@ -766,14 +690,14 @@ bool GLFunctions::glCompileShader(uint32_t shaderID, std::string & errorLog)
void GLFunctions::glDeleteShader(uint32_t shaderID)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glDeleteShaderFn != nullptr, ());
GLCHECK(glDeleteBuffersFn(1, &shaderID));
}
uint32_t GLFunctions::glCreateProgram()
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glCreateProgramFn != nullptr, ());
GLuint result = glCreateProgramFn();
GLCHECKCALL();
@@ -782,21 +706,21 @@ uint32_t GLFunctions::glCreateProgram()
void GLFunctions::glAttachShader(uint32_t programID, uint32_t shaderID)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glAttachShaderFn != nullptr, ());
GLCHECK(glAttachShaderFn(programID, shaderID));
}
void GLFunctions::glDetachShader(uint32_t programID, uint32_t shaderID)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glDetachShaderFn != nullptr, ());
GLCHECK(glDetachShaderFn(programID, shaderID));
}
bool GLFunctions::glLinkProgram(uint32_t programID, std::string & errorLog)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glLinkProgramFn != nullptr, ());
ASSERT(glGetProgramivFn != nullptr, ());
ASSERT(glGetProgramInfoLogFn != nullptr, ());
@@ -817,21 +741,21 @@ bool GLFunctions::glLinkProgram(uint32_t programID, std::string & errorLog)
void GLFunctions::glDeleteProgram(uint32_t programID)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glDeleteProgramFn != nullptr, ());
GLCHECK(glDeleteProgramFn(programID));
}
void GLFunctions::glUseProgram(uint32_t programID)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glUseProgramFn != nullptr, ());
GLCHECK(glUseProgramFn(programID));
}
int8_t GLFunctions::glGetAttribLocation(uint32_t programID, std::string const & name)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glGetAttribLocationFn != nullptr, ());
int result = glGetAttribLocationFn(programID, name.c_str());
GLCHECKCALL();
@@ -841,14 +765,14 @@ int8_t GLFunctions::glGetAttribLocation(uint32_t programID, std::string const &
void GLFunctions::glBindAttribLocation(uint32_t programID, uint8_t index, std::string const & name)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glBindAttribLocationFn != nullptr, ());
GLCHECK(glBindAttribLocationFn(programID, index, name.c_str()));
}
void GLFunctions::glEnableVertexAttribute(int attributeLocation)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glEnableVertexAttributeFn != nullptr, ());
GLCHECK(glEnableVertexAttributeFn(attributeLocation));
}
@@ -856,7 +780,7 @@ void GLFunctions::glEnableVertexAttribute(int attributeLocation)
void GLFunctions::glVertexAttributePointer(int attrLocation, uint32_t count, glConst type,
bool needNormalize, uint32_t stride, uint32_t offset)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glVertexAttributePointerFn != nullptr, ());
GLCHECK(glVertexAttributePointerFn(attrLocation, count, type, convert(needNormalize), stride,
reinterpret_cast(offset)));
@@ -865,7 +789,7 @@ void GLFunctions::glVertexAttributePointer(int attrLocation, uint32_t count, glC
void GLFunctions::glGetActiveUniform(uint32_t programID, uint32_t uniformIndex,
int32_t * uniformSize, glConst * type, std::string & name)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glGetActiveUniformFn != nullptr, ());
GLchar buff[256];
GLCHECK(glGetActiveUniformFn(programID, uniformIndex, ARRAY_SIZE(buff), nullptr, uniformSize,
@@ -875,17 +799,17 @@ void GLFunctions::glGetActiveUniform(uint32_t programID, uint32_t uniformIndex,
int8_t GLFunctions::glGetUniformLocation(uint32_t programID, std::string const & name)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glGetUniformLocationFn != nullptr, ());
int result = glGetUniformLocationFn(programID, name.c_str());
GLCHECKCALL();
- ASSERT(result != -1, ());
+ ASSERT(result != -1, (name));
return static_cast(result);
}
void GLFunctions::glUniformValuei(int8_t location, int32_t v)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glUniform1iFn != nullptr, ());
ASSERT(location != -1, ());
GLCHECK(glUniform1iFn(location, v));
@@ -893,7 +817,7 @@ void GLFunctions::glUniformValuei(int8_t location, int32_t v)
void GLFunctions::glUniformValuei(int8_t location, int32_t v1, int32_t v2)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glUniform2iFn != nullptr, ());
ASSERT(location != -1, ());
GLCHECK(glUniform2iFn(location, v1, v2));
@@ -901,7 +825,7 @@ void GLFunctions::glUniformValuei(int8_t location, int32_t v1, int32_t v2)
void GLFunctions::glUniformValuei(int8_t location, int32_t v1, int32_t v2, int32_t v3)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glUniform3iFn != nullptr, ());
ASSERT(location != -1, ());
GLCHECK(glUniform3iFn(location, v1, v2, v3));
@@ -909,7 +833,7 @@ void GLFunctions::glUniformValuei(int8_t location, int32_t v1, int32_t v2, int32
void GLFunctions::glUniformValuei(int8_t location, int32_t v1, int32_t v2, int32_t v3, int32_t v4)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glUniform4iFn != nullptr, ());
ASSERT(location != -1, ());
GLCHECK(glUniform4iFn(location, v1, v2, v3, v4));
@@ -917,7 +841,7 @@ void GLFunctions::glUniformValuei(int8_t location, int32_t v1, int32_t v2, int32
void GLFunctions::glUniformValueiv(int8_t location, int32_t * v, uint32_t size)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glUniform1ivFn != nullptr, ());
ASSERT(location != -1, ());
GLCHECK(glUniform1ivFn(location, size, v));
@@ -925,7 +849,7 @@ void GLFunctions::glUniformValueiv(int8_t location, int32_t * v, uint32_t size)
void GLFunctions::glUniformValuef(int8_t location, float v)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glUniform1fFn != nullptr, ());
ASSERT(location != -1, ());
GLCHECK(glUniform1fFn(location, v));
@@ -933,7 +857,7 @@ void GLFunctions::glUniformValuef(int8_t location, float v)
void GLFunctions::glUniformValuef(int8_t location, float v1, float v2)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glUniform2fFn != nullptr, ());
ASSERT(location != -1, ());
GLCHECK(glUniform2fFn(location, v1, v2));
@@ -941,7 +865,7 @@ void GLFunctions::glUniformValuef(int8_t location, float v1, float v2)
void GLFunctions::glUniformValuef(int8_t location, float v1, float v2, float v3)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glUniform3fFn != nullptr, ());
ASSERT(location != -1, ());
GLCHECK(glUniform3fFn(location, v1, v2, v3));
@@ -949,7 +873,7 @@ void GLFunctions::glUniformValuef(int8_t location, float v1, float v2, float v3)
void GLFunctions::glUniformValuef(int8_t location, float v1, float v2, float v3, float v4)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glUniform4fFn != nullptr, ());
ASSERT(location != -1, ());
GLCHECK(glUniform4fFn(location, v1, v2, v3, v4));
@@ -957,7 +881,7 @@ void GLFunctions::glUniformValuef(int8_t location, float v1, float v2, float v3,
void GLFunctions::glUniformValuefv(int8_t location, float * v, uint32_t size)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glUniform1fvFn != nullptr, ());
ASSERT(location != -1, ());
GLCHECK(glUniform1fvFn(location, size, v));
@@ -965,7 +889,7 @@ void GLFunctions::glUniformValuefv(int8_t location, float * v, uint32_t size)
void GLFunctions::glUniformMatrix4x4Value(int8_t location, float const * values)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glUniformMatrix4fvFn != nullptr, ());
ASSERT(location != -1, ());
GLCHECK(glUniformMatrix4fvFn(location, 1, GL_FALSE, values));
@@ -973,7 +897,7 @@ void GLFunctions::glUniformMatrix4x4Value(int8_t location, float const * values)
uint32_t GLFunctions::glGetCurrentProgram()
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLint programIndex = 0;
GLCHECK(glGetIntegerv(GL_CURRENT_PROGRAM, &programIndex));
ASSERT_GREATER_OR_EQUAL(programIndex, 0, ());
@@ -982,7 +906,7 @@ uint32_t GLFunctions::glGetCurrentProgram()
int32_t GLFunctions::glGetProgramiv(uint32_t program, glConst paramName)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glGetProgramivFn != nullptr, ());
GLint paramValue = 0;
GLCHECK(glGetProgramivFn(program, paramName, ¶mValue));
@@ -991,14 +915,14 @@ int32_t GLFunctions::glGetProgramiv(uint32_t program, glConst paramName)
void GLFunctions::glActiveTexture(glConst texBlock)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glActiveTextureFn != nullptr, ());
GLCHECK(glActiveTextureFn(texBlock));
}
uint32_t GLFunctions::glGenTexture()
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLuint result = std::numeric_limits::max();
GLCHECK(::glGenTextures(1, &result));
return result;
@@ -1006,20 +930,20 @@ uint32_t GLFunctions::glGenTexture()
void GLFunctions::glDeleteTexture(uint32_t id)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glDeleteTextures(1, &id));
}
void GLFunctions::glBindTexture(uint32_t textureID)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glBindTexture(GL_TEXTURE_2D, textureID));
}
void GLFunctions::glTexImage2D(int width, int height, glConst layout, glConst pixelType,
void const * data)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
// 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;
@@ -1058,20 +982,20 @@ void GLFunctions::glTexImage2D(int width, int height, glConst layout, glConst pi
void GLFunctions::glTexSubImage2D(int x, int y, int width, int height, glConst layout,
glConst pixelType, void const * data)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, layout, pixelType, data));
}
void GLFunctions::glTexParameter(glConst param, glConst value)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glTexParameteri(GL_TEXTURE_2D, param, value));
}
void GLFunctions::glDrawElements(glConst primitive, uint32_t sizeOfIndex, uint32_t indexCount,
uint32_t startIndex)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glDrawElements(primitive, indexCount,
sizeOfIndex == sizeof(uint32_t) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT,
reinterpret_cast(startIndex * sizeOfIndex)));
@@ -1079,41 +1003,41 @@ void GLFunctions::glDrawElements(glConst primitive, uint32_t sizeOfIndex, uint32
void GLFunctions::glDrawArrays(glConst mode, int32_t first, uint32_t count)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glDrawArrays(mode, first, count));
}
void GLFunctions::glGenFramebuffer(uint32_t * fbo)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glGenFramebuffersFn != nullptr, ());
GLCHECK(glGenFramebuffersFn(1, fbo));
}
void GLFunctions::glDeleteFramebuffer(uint32_t * fbo)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glDeleteFramebuffersFn != nullptr, ());
GLCHECK(glDeleteFramebuffersFn(1, fbo));
}
void GLFunctions::glFramebufferTexture2D(glConst attachment, glConst texture)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glFramebufferTexture2DFn != nullptr, ());
GLCHECK(glFramebufferTexture2DFn(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture, 0));
}
void GLFunctions::glBindFramebuffer(uint32_t fbo)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glBindFramebufferFn != nullptr, ());
GLCHECK(glBindFramebufferFn(GL_FRAMEBUFFER, fbo));
}
uint32_t GLFunctions::glCheckFramebufferStatus()
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
ASSERT(glCheckFramebufferStatusFn != nullptr, ());
uint32_t const result = glCheckFramebufferStatusFn(GL_FRAMEBUFFER);
GLCHECKCALL();
@@ -1122,7 +1046,7 @@ uint32_t GLFunctions::glCheckFramebufferStatus()
void GLFunctions::glLineWidth(uint32_t value)
{
- ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLCHECK(::glLineWidth(static_cast(value)));
}
@@ -1143,7 +1067,7 @@ std::string GetGLError(GLenum error)
void CheckGLError(base::SrcPoint const & srcPoint)
{
- ASSERT_NOT_EQUAL(GLFunctions::CurrentApiVersion, dp::ApiVersion::Invalid, ());
+ ASSERT_EQUAL(GLFunctions::CurrentApiVersion, dp::ApiVersion::OpenGLES3, ());
GLenum result = glGetError();
while (result != GL_NO_ERROR)
{
diff --git a/drape/gl_gpu_program.cpp b/drape/gl_gpu_program.cpp
index 3a3bfedbcf..2778a38ec7 100644
--- a/drape/gl_gpu_program.cpp
+++ b/drape/gl_gpu_program.cpp
@@ -23,26 +23,14 @@ GLGpuProgram::GLGpuProgram(std::string const & programName,
if (!GLFunctions::glLinkProgram(m_programID, errorLog))
LOG(LERROR, ("Program ", programName, " link error = ", errorLog));
- // On Tegra3 glGetActiveUniform isn't work if you detach shaders after linking.
LoadUniformLocations();
- // On Tegra2 we cannot detach shaders at all.
- // https://devtalk.nvidia.com/default/topic/528941/alpha-blending-not-working-on-t20-and-t30-under-ice-cream-sandwich/
- if (!SupportManager::Instance().IsTegraDevice())
- {
- GLFunctions::glDetachShader(m_programID, m_vertexShader->GetID());
- GLFunctions::glDetachShader(m_programID, m_fragmentShader->GetID());
- }
+ GLFunctions::glDetachShader(m_programID, m_vertexShader->GetID());
+ GLFunctions::glDetachShader(m_programID, m_fragmentShader->GetID());
}
GLGpuProgram::~GLGpuProgram()
{
- if (SupportManager::Instance().IsTegraDevice())
- {
- GLFunctions::glDetachShader(m_programID, m_vertexShader->GetID());
- GLFunctions::glDetachShader(m_programID, m_fragmentShader->GetID());
- }
-
GLFunctions::glDeleteProgram(m_programID);
}
@@ -107,7 +95,7 @@ void GLGpuProgram::LoadUniformLocations()
std::string name;
GLFunctions::glGetActiveUniform(m_programID, static_cast(i), &size, &info.m_type, name);
CHECK(kSupportedTypes.find(info.m_type) != kSupportedTypes.cend(),
- ("Used uniform has unsupported type. Program =", m_programName, "Type =", info.m_type));
+ ("Used uniform has unsupported type. Program =", m_programName, "; Type =", info.m_type, "; Name =", name));
info.m_location = GLFunctions::glGetUniformLocation(m_programID, name);
m_uniforms[name] = std::move(info);
diff --git a/drape/gpu_buffer.cpp b/drape/gpu_buffer.cpp
index af84906909..a280aeddd3 100644
--- a/drape/gpu_buffer.cpp
+++ b/drape/gpu_buffer.cpp
@@ -87,26 +87,17 @@ void * GPUBuffer::Map(uint32_t elementOffset, uint32_t elementCount)
m_isMapped = true;
#endif
- if (GLFunctions::CurrentApiVersion == dp::ApiVersion::OpenGLES2)
+ if (!IsMapBufferSupported())
{
m_mappingOffset = elementOffset;
- return IsMapBufferSupported() ? GLFunctions::glMapBuffer(glTarget(m_t)) : nullptr;
+ return nullptr;
}
- else if (GLFunctions::CurrentApiVersion == dp::ApiVersion::OpenGLES3)
- {
- if (!IsMapBufferSupported())
- {
- m_mappingOffset = elementOffset;
- return nullptr;
- }
- m_mappingOffset = 0;
- uint32_t const elementSize = GetElementSize();
- uint32_t const byteOffset = elementOffset * elementSize;
- uint32_t const byteCount = elementCount * elementSize;
- return GLFunctions::glMapBufferRange(glTarget(m_t), byteOffset, byteCount,
- gl_const::GLWriteBufferBit);
- }
- return nullptr;
+ m_mappingOffset = 0;
+ uint32_t const elementSize = GetElementSize();
+ uint32_t const byteOffset = elementOffset * elementSize;
+ uint32_t const byteCount = elementCount * elementSize;
+ return GLFunctions::glMapBufferRange(glTarget(m_t), byteOffset, byteCount,
+ gl_const::GLWriteBufferBit);
}
void GPUBuffer::UpdateData(void * gpuPtr, void const * data, uint32_t elementOffset,
diff --git a/drape/hw_texture.cpp b/drape/hw_texture.cpp
index 560e8978f3..1d99e20284 100644
--- a/drape/hw_texture.cpp
+++ b/drape/hw_texture.cpp
@@ -36,7 +36,7 @@ void UnpackFormat(ref_ptr context, TextureFormat format,
glConst & layout, glConst & pixelType)
{
auto const apiVersion = context->GetApiVersion();
- CHECK(apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3, ());
+ CHECK(apiVersion == dp::ApiVersion::OpenGLES3, ());
switch (format)
{
@@ -45,21 +45,17 @@ void UnpackFormat(ref_ptr context, TextureFormat format,
pixelType = gl_const::GL8BitOnChannel;
return;
- case TextureFormat::Alpha:
- // On OpenGL ES3 GLAlpha is not supported, we use GLRed instead.
- layout = apiVersion == dp::ApiVersion::OpenGLES2 ? gl_const::GLAlpha : gl_const::GLRed;
+ case TextureFormat::Red:
+ layout = gl_const::GLRed;
pixelType = gl_const::GL8BitOnChannel;
return;
case TextureFormat::RedGreen:
- // On OpenGL ES2 2-channel textures are not supported.
- layout = (apiVersion == dp::ApiVersion::OpenGLES2) ? gl_const::GLRGBA : gl_const::GLRedGreen;
+ layout = gl_const::GLRedGreen;
pixelType = gl_const::GL8BitOnChannel;
return;
case TextureFormat::DepthStencil:
- // OpenGLES2 does not support texture-based depth-stencil.
- CHECK(apiVersion != dp::ApiVersion::OpenGLES2, ());
layout = gl_const::GLDepthStencil;
pixelType = gl_const::GLUnsignedInt24_8Type;
return;
diff --git a/drape/hw_texture_ios.mm b/drape/hw_texture_ios.mm
index f83725f411..658ce02e03 100644
--- a/drape/hw_texture_ios.mm
+++ b/drape/hw_texture_ios.mm
@@ -61,7 +61,7 @@ CVPixelBufferRef HWTextureAllocatorApple::CVCreatePixelBuffer(uint32_t width, ui
cvRetval = CVPixelBufferCreate(kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA,
attrsRef, &result);
break;
- case dp::TextureFormat::Alpha:
+ case dp::TextureFormat::Red:
cvRetval = CVPixelBufferCreate(kCFAllocatorDefault, width, height, kCVPixelFormatType_OneComponent8,
attrsRef, &result);
break;
diff --git a/drape/index_storage.cpp b/drape/index_storage.cpp
index 5f6bb8fc91..3432e8be9f 100644
--- a/drape/index_storage.cpp
+++ b/drape/index_storage.cpp
@@ -56,7 +56,7 @@ void const * IndexStorage::GetRawConst() const
bool IndexStorage::IsSupported32bit()
{
// We do not use 32-bit indices now to reduce size of index buffers.
- static bool const supports32Bit = false;//GLFunctions::ExtensionsList.IsSupported(GLExtensionsList::UintIndices);
+ static bool const supports32Bit = false;
return supports32Bit;
}
diff --git a/drape/mesh_object.cpp b/drape/mesh_object.cpp
index 525c31b0cb..4fbaa899e0 100644
--- a/drape/mesh_object.cpp
+++ b/drape/mesh_object.cpp
@@ -36,13 +36,8 @@ public:
{
UNUSED_VALUE(context);
- bool const isVAOSupported =
- GLFunctions::ExtensionsList.IsSupported(dp::GLExtensionsList::VertexArrayObject);
- if (isVAOSupported)
- {
- m_VAO = GLFunctions::glGenVertexArray();
- GLFunctions::glBindVertexArray(m_VAO);
- }
+ m_VAO = GLFunctions::glGenVertexArray();
+ GLFunctions::glBindVertexArray(m_VAO);
for (auto & buffer : m_mesh->m_buffers)
{
@@ -64,23 +59,19 @@ public:
m_mesh->m_indices.data(), gl_const::GLStaticDraw);
}
- if (isVAOSupported)
+ ref_ptr p = program;
+ for (auto const & attribute : buffer->m_attributes)
{
- ref_ptr p = program;
- for (auto const & attribute : buffer->m_attributes)
- {
- int8_t const attributePosition = p->GetAttributeLocation(attribute.m_attributeName);
- ASSERT_NOT_EQUAL(attributePosition, -1, ());
- GLFunctions::glEnableVertexAttribute(attributePosition);
- GLFunctions::glVertexAttributePointer(attributePosition, attribute.m_componentsCount,
- attribute.m_type, false, buffer->GetStrideInBytes(),
- attribute.m_offset);
- }
+ int8_t const attributePosition = p->GetAttributeLocation(attribute.m_attributeName);
+ ASSERT_NOT_EQUAL(attributePosition, -1, ());
+ GLFunctions::glEnableVertexAttribute(attributePosition);
+ GLFunctions::glVertexAttributePointer(attributePosition, attribute.m_componentsCount,
+ attribute.m_type, false, buffer->GetStrideInBytes(),
+ attribute.m_offset);
}
}
- if (isVAOSupported)
- GLFunctions::glBindVertexArray(0);
+ GLFunctions::glBindVertexArray(0);
GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer);
if (!m_mesh->m_indices.empty())
GLFunctions::glBindBuffer(0, gl_const::GLElementArrayBuffer);
@@ -134,34 +125,12 @@ public:
void Bind(ref_ptr program) override
{
- if (GLFunctions::ExtensionsList.IsSupported(dp::GLExtensionsList::VertexArrayObject))
- {
- GLFunctions::glBindVertexArray(m_VAO);
- return;
- }
-
- ref_ptr p = program;
- for (auto const & buffer : m_mesh->m_buffers)
- {
- GLFunctions::glBindBuffer(buffer->m_bufferId, gl_const::GLArrayBuffer);
- if (m_indexBuffer != 0)
- GLFunctions::glBindBuffer(m_indexBuffer, gl_const::GLElementArrayBuffer);
- for (auto const & attribute : buffer->m_attributes)
- {
- int8_t const attributePosition = p->GetAttributeLocation(attribute.m_attributeName);
- ASSERT_NOT_EQUAL(attributePosition, -1, ());
- GLFunctions::glEnableVertexAttribute(attributePosition);
- GLFunctions::glVertexAttributePointer(attributePosition, attribute.m_componentsCount,
- attribute.m_type, false, buffer->GetStrideInBytes(),
- attribute.m_offset);
- }
- }
+ GLFunctions::glBindVertexArray(m_VAO);
}
void Unbind() override
{
- if (GLFunctions::ExtensionsList.IsSupported(dp::GLExtensionsList::VertexArrayObject))
- GLFunctions::glBindVertexArray(0);
+ GLFunctions::glBindVertexArray(0);
GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer);
if (m_indexBuffer != 0)
GLFunctions::glBindBuffer(0, gl_const::GLElementArrayBuffer);
@@ -197,7 +166,7 @@ MeshObject::MeshObject(ref_ptr context, DrawPrimitive drawP
, m_debugName(debugName)
{
auto const apiVersion = context->GetApiVersion();
- if (apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3)
+ if (apiVersion == dp::ApiVersion::OpenGLES3)
{
InitForOpenGL();
}
diff --git a/drape/metal/metal_texture.mm b/drape/metal/metal_texture.mm
index cd0a946171..89d674ef00 100644
--- a/drape/metal/metal_texture.mm
+++ b/drape/metal/metal_texture.mm
@@ -25,7 +25,7 @@ MTLPixelFormat UnpackFormat(TextureFormat format)
switch (format)
{
case TextureFormat::RGBA8: return MTLPixelFormatRGBA8Unorm;
- case TextureFormat::Alpha: return MTLPixelFormatA8Unorm;
+ case TextureFormat::Red: return MTLPixelFormatA8Unorm; // TODO: change to R8, fix shaders
case TextureFormat::RedGreen: return MTLPixelFormatRG8Unorm;
case TextureFormat::DepthStencil: return MTLPixelFormatDepth32Float_Stencil8;
case TextureFormat::Depth: return MTLPixelFormatDepth32Float;
diff --git a/drape/render_state.cpp b/drape/render_state.cpp
index 5c09fd8078..55611a2030 100644
--- a/drape/render_state.cpp
+++ b/drape/render_state.cpp
@@ -30,7 +30,7 @@ void AlphaBlendingState::Apply(ref_ptr context)
{
// For Metal Rendering these settings must be set in the pipeline state.
auto const apiVersion = context->GetApiVersion();
- if (apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3)
+ if (apiVersion == dp::ApiVersion::OpenGLES3)
{
GLFunctions::glBlendEquation(gl_const::GLAddBlend);
GLFunctions::glBlendFunc(gl_const::GLSrcAlpha, gl_const::GLOneMinusSrcAlpha);
@@ -45,7 +45,7 @@ void Blending::Apply(ref_ptr context, ref_ptr progr
{
// For Metal Rendering these settings must be set in the pipeline state.
auto const apiVersion = context->GetApiVersion();
- if (apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3)
+ if (apiVersion == dp::ApiVersion::OpenGLES3)
{
if (m_isEnabled)
GLFunctions::glEnable(gl_const::GLBlending);
@@ -216,7 +216,7 @@ void TextureState::ApplyTextures(ref_ptr context, RenderState c
{
m_usedSlots = 0;
auto const apiVersion = context->GetApiVersion();
- if (apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3)
+ if (apiVersion == dp::ApiVersion::OpenGLES3)
{
ref_ptr p = program;
for (auto const & texture : state.GetTextures())
@@ -324,7 +324,7 @@ void ApplyState(ref_ptr context, ref_ptr program, R
if (state.GetDrawAsLine())
{
- if (apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3)
+ if (apiVersion == dp::ApiVersion::OpenGLES3)
{
ASSERT_GREATER_OR_EQUAL(state.GetLineWidth(), 0, ());
GLFunctions::glLineWidth(static_cast(state.GetLineWidth()));
diff --git a/drape/stipple_pen_resource.cpp b/drape/stipple_pen_resource.cpp
index cb642f0aee..6158d1ed03 100644
--- a/drape/stipple_pen_resource.cpp
+++ b/drape/stipple_pen_resource.cpp
@@ -175,7 +175,7 @@ ref_ptr StipplePenIndex::MapResource(StipplePenKey const
void StipplePenIndex::UploadResources(ref_ptr context, ref_ptr texture)
{
- ASSERT(texture->GetFormat() == dp::TextureFormat::Alpha, ());
+ ASSERT(texture->GetFormat() == dp::TextureFormat::Red, ());
TPendingNodes pendingNodes;
{
std::lock_guard g(m_lock);
diff --git a/drape/stipple_pen_resource.hpp b/drape/stipple_pen_resource.hpp
index b8788ad731..7629c38ade 100644
--- a/drape/stipple_pen_resource.hpp
+++ b/drape/stipple_pen_resource.hpp
@@ -138,7 +138,7 @@ public:
StipplePenTexture(m2::PointU const & size, ref_ptr allocator)
: m_index(size)
{
- TBase::DynamicTextureParams params{size, TextureFormat::Alpha, TextureFilter::Nearest,
+ TBase::DynamicTextureParams params{size, TextureFormat::Red, TextureFilter::Nearest,
false /* m_usePixelBuffer */};
TBase::Init(allocator, make_ref(&m_index), params);
}
diff --git a/drape/support_manager.cpp b/drape/support_manager.cpp
index ca956a7187..3b213636ea 100644
--- a/drape/support_manager.cpp
+++ b/drape/support_manager.cpp
@@ -32,31 +32,8 @@ void SupportManager::Init(ref_ptr context)
m_rendererVersion = context->GetRendererVersion();
LOG(LINFO, ("Renderer =", m_rendererName, "| Api =", context->GetApiVersion(), "| Version =", m_rendererVersion));
- m_isSamsungGoogleNexus = (m_rendererName == "PowerVR SGX 540" &&
- m_rendererVersion.find("GOOGLENEXUS.ED945322") != std::string::npos);
- if (m_isSamsungGoogleNexus)
- LOG(LINFO, ("Samsung Google Nexus detected."));
-
- if (m_rendererName.find("Adreno") != std::string::npos)
- {
- std::array constexpr models = { "200", "203", "205", "220", "225" };
- for (auto const & model : models)
- {
- if (m_rendererName.find(model) != std::string::npos)
- {
- LOG(LINFO, ("Adreno 200 device detected."));
- m_isAdreno200 = true;
- break;
- }
- }
- }
-
- m_isTegra = (m_rendererName.find("Tegra") != std::string::npos);
- if (m_isTegra)
- LOG(LINFO, ("NVidia Tegra device detected."));
-
auto const apiVersion = context->GetApiVersion();
- if (apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3)
+ if (apiVersion == dp::ApiVersion::OpenGLES3)
{
m_maxLineWidth = static_cast(std::max(1, GLFunctions::glGetMaxLineWidth()));
m_maxTextureSize = static_cast(GLFunctions::glGetInteger(gl_const::GLMaxTextureSize));
diff --git a/drape/support_manager.hpp b/drape/support_manager.hpp
index fe2c54f4b9..f84c085b1c 100644
--- a/drape/support_manager.hpp
+++ b/drape/support_manager.hpp
@@ -26,9 +26,6 @@ public:
// reinitialization.
void Init(ref_ptr context);
- bool IsSamsungGoogleNexus() const { return m_isSamsungGoogleNexus; }
- bool IsAdreno200Device() const { return m_isAdreno200; }
- bool IsTegraDevice() const { return m_isTegra; }
bool IsAntialiasingEnabledByDefault() const { return m_isAntialiasingEnabledByDefault; }
float GetMaxLineWidth() const { return m_maxLineWidth; }
@@ -50,9 +47,6 @@ private:
std::string m_rendererName;
std::string m_rendererVersion;
- bool m_isSamsungGoogleNexus = false;
- bool m_isAdreno200 = false;
- bool m_isTegra = false;
bool m_isAntialiasingEnabledByDefault = false;
float m_maxLineWidth = 1;
diff --git a/drape/texture_manager.cpp b/drape/texture_manager.cpp
index 00db093e56..d688e27294 100644
--- a/drape/texture_manager.cpp
+++ b/drape/texture_manager.cpp
@@ -183,7 +183,7 @@ bool TextureManager::UpdateDynamicTextures(ref_ptr context)
if (m_nothingToUpload.test_and_set())
{
auto const apiVersion = context->GetApiVersion();
- if (apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3)
+ if (apiVersion == dp::ApiVersion::OpenGLES3)
{
// For some reasons OpenGL can not update textures immediately.
// Here we use some timeout to prevent rendering frozening.
@@ -302,7 +302,7 @@ void TextureManager::Init(ref_ptr context, Params const & p
m_maxTextureSize = std::min(kMaxTextureSize, dp::SupportManager::Instance().GetMaxTextureSize());
auto const apiVersion = context->GetApiVersion();
- if (apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3)
+ if (apiVersion == dp::ApiVersion::OpenGLES3)
GLFunctions::glPixelStore(gl_const::GLUnpackAlignment, 1);
// Initialize symbols.
@@ -323,16 +323,13 @@ void TextureManager::Init(ref_ptr context, Params const & p
CreateArrowTexture(context, make_ref(m_textureAllocator), params.m_arrowTexturePath,
params.m_arrowTextureUseDefaultResourceFolder);
- // SMAA is not supported on OpenGL ES2.
- if (apiVersion != dp::ApiVersion::OpenGLES2)
- {
- m_smaaAreaTexture =
- make_unique_dp(context, "smaa-area.png", StaticTexture::kDefaultResource,
- dp::TextureFormat::RedGreen, make_ref(m_textureAllocator));
- m_smaaSearchTexture =
- make_unique_dp(context, "smaa-search.png", StaticTexture::kDefaultResource,
- dp::TextureFormat::Alpha, make_ref(m_textureAllocator));
- }
+ // SMAA.
+ m_smaaAreaTexture =
+ make_unique_dp(context, "smaa-area.png", StaticTexture::kDefaultResource,
+ dp::TextureFormat::RedGreen, make_ref(m_textureAllocator));
+ m_smaaSearchTexture =
+ make_unique_dp(context, "smaa-search.png", StaticTexture::kDefaultResource,
+ dp::TextureFormat::Red, make_ref(m_textureAllocator));
// Initialize patterns (reserved ./data/patterns.txt lines count).
std::set patterns;
diff --git a/drape/texture_types.hpp b/drape/texture_types.hpp
index 5aa79221d5..ff95c59d3a 100644
--- a/drape/texture_types.hpp
+++ b/drape/texture_types.hpp
@@ -9,7 +9,7 @@ namespace dp
enum class TextureFormat : uint8_t
{
RGBA8,
- Alpha,
+ Red,
RedGreen,
DepthStencil,
Depth,
@@ -21,7 +21,7 @@ inline std::string DebugPrint(TextureFormat tf)
switch (tf)
{
case TextureFormat::RGBA8: return "RGBA8";
- case TextureFormat::Alpha: return "Alpha";
+ case TextureFormat::Red: return "Red";
case TextureFormat::RedGreen: return "RedGreen";
case TextureFormat::DepthStencil: return "DepthStencil";
case TextureFormat::Depth: return "Depth";
@@ -50,7 +50,7 @@ inline uint8_t GetBytesPerPixel(TextureFormat format)
switch (format)
{
case TextureFormat::RGBA8: result = 4; break;
- case TextureFormat::Alpha: result = 1; break;
+ case TextureFormat::Red: result = 1; break;
case TextureFormat::RedGreen: result = 2; break;
case TextureFormat::DepthStencil: result = 4; break;
case TextureFormat::Depth: result = 4; break;
diff --git a/drape/vertex_array_buffer.cpp b/drape/vertex_array_buffer.cpp
index 6190fa0298..8c417bfcde 100644
--- a/drape/vertex_array_buffer.cpp
+++ b/drape/vertex_array_buffer.cpp
@@ -56,9 +56,6 @@ public:
return false;
m_program = program;
- // If OES_vertex_array_object not supported, than buffers will be bound on each render call.
- if (!GLFunctions::ExtensionsList.IsSupported(GLExtensionsList::VertexArrayObject))
- return false;
if (m_VAO != 0)
GLFunctions::glDeleteVertexArray(m_VAO);
@@ -68,19 +65,14 @@ public:
bool Bind() override
{
- if (GLFunctions::ExtensionsList.IsSupported(GLExtensionsList::VertexArrayObject))
- {
- ASSERT(m_VAO != 0, ("You need to call Build method before bind it and render."));
- GLFunctions::glBindVertexArray(m_VAO);
- return true;
- }
- return false;
+ ASSERT(m_VAO != 0, ("You need to call Build method before bind it and render."));
+ GLFunctions::glBindVertexArray(m_VAO);
+ return true;
}
void Unbind() override
{
- if (GLFunctions::ExtensionsList.IsSupported(GLExtensionsList::VertexArrayObject))
- GLFunctions::glBindVertexArray(0);
+ GLFunctions::glBindVertexArray(0);
}
void BindBuffers(BuffersMap const & buffers) const override
@@ -126,10 +118,6 @@ VertexArrayBuffer::VertexArrayBuffer(uint32_t indexBufferSize, uint32_t dataBuff
, m_batcherHash(batcherHash)
{
m_indexBuffer = make_unique_dp(indexBufferSize);
-
- // Adreno 200 GPUs aren't able to share OpenGL resources between 2 OGL-contexts correctly,
- // so we have to create and destroy VBO on one context.
- m_moveToGpuOnBuild = SupportManager::Instance().IsAdreno200Device();
}
VertexArrayBuffer::~VertexArrayBuffer()
@@ -142,8 +130,7 @@ VertexArrayBuffer::~VertexArrayBuffer()
void VertexArrayBuffer::Preflush(ref_ptr context)
{
- if (!m_moveToGpuOnBuild)
- PreflushImpl(context);
+ PreflushImpl(context);
}
void VertexArrayBuffer::PreflushImpl(ref_ptr context)
@@ -163,7 +150,7 @@ void VertexArrayBuffer::PreflushImpl(ref_ptr context)
// Preflush can be called on BR, where impl is not initialized.
// For Metal rendering this code has no meaning.
auto const apiVersion = context->GetApiVersion();
- if (apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3)
+ if (apiVersion == dp::ApiVersion::OpenGLES3)
{
GLFunctions::glBindBuffer(0, gl_const::GLElementArrayBuffer);
GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer);
@@ -199,7 +186,7 @@ void VertexArrayBuffer::RenderRange(ref_ptr context,
void VertexArrayBuffer::Build(ref_ptr context, ref_ptr program)
{
- if (m_moveToGpuOnBuild && !m_isPreflushed)
+ if (!m_isPreflushed)
PreflushImpl(context);
if (!HasBuffers())
@@ -208,7 +195,7 @@ void VertexArrayBuffer::Build(ref_ptr context, ref_ptrGetApiVersion();
- if (apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3)
+ if (apiVersion == dp::ApiVersion::OpenGLES3)
{
m_impl = make_unique_dp();
}
diff --git a/drape/vertex_array_buffer.hpp b/drape/vertex_array_buffer.hpp
index 34a7277049..bc4f69fccc 100644
--- a/drape/vertex_array_buffer.hpp
+++ b/drape/vertex_array_buffer.hpp
@@ -124,7 +124,6 @@ private:
drape_ptr m_indexBuffer;
bool m_isPreflushed = false;
- bool m_moveToGpuOnBuild = false;
bool m_isChanged = false;
BindingInfoArray m_bindingInfo;
uint8_t m_bindingInfoCount = 0;
diff --git a/drape/vulkan/vulkan_utils.cpp b/drape/vulkan/vulkan_utils.cpp
index f32af92f3d..1472358e8d 100644
--- a/drape/vulkan/vulkan_utils.cpp
+++ b/drape/vulkan/vulkan_utils.cpp
@@ -158,7 +158,7 @@ VkFormat VulkanFormatUnpacker::Unpack(TextureFormat format)
switch (format)
{
case TextureFormat::RGBA8: return VK_FORMAT_R8G8B8A8_UNORM;
- case TextureFormat::Alpha: return VK_FORMAT_R8_UNORM;
+ case TextureFormat::Red: return VK_FORMAT_R8_UNORM;
case TextureFormat::RedGreen: return VK_FORMAT_R8G8_UNORM;
#if defined(OMIM_OS_MAC)
case TextureFormat::DepthStencil: return VK_FORMAT_D32_SFLOAT_S8_UINT;
diff --git a/drape_frontend/arrow3d.cpp b/drape_frontend/arrow3d.cpp
index 48bf8f6e60..d763407571 100644
--- a/drape_frontend/arrow3d.cpp
+++ b/drape_frontend/arrow3d.cpp
@@ -308,7 +308,7 @@ Arrow3d::Arrow3d(ref_ptr context, ref_ptrGetApiVersion();
- if (apiVersion == dp::ApiVersion::OpenGLES2 || apiVersion == dp::ApiVersion::OpenGLES3)
+ if (apiVersion == dp::ApiVersion::OpenGLES3)
m_state.SetColorTexture(texMng->GetSymbolsTexture());
m_isValid = preloadedData.m_meshData.has_value();
diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp
index 8f0861e488..2904ef8eb2 100755
--- a/drape_frontend/frontend_renderer.cpp
+++ b/drape_frontend/frontend_renderer.cpp
@@ -1426,7 +1426,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView, bool activeFram
RefreshBgColor();
uint32_t clearBits = dp::ClearBits::ColorBit | dp::ClearBits::DepthBit;
- if (m_apiVersion == dp::ApiVersion::OpenGLES2 || m_apiVersion == dp::ApiVersion::OpenGLES3)
+ if (m_apiVersion == dp::ApiVersion::OpenGLES3)
clearBits |= dp::ClearBits::StencilBit;
uint32_t storeBits = dp::ClearBits::ColorBit;
@@ -1524,7 +1524,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView, bool activeFram
if (IsValidCurrentZoom())
{
uint32_t clearBits = dp::ClearBits::DepthBit;
- if (m_apiVersion == dp::ApiVersion::OpenGLES2 || m_apiVersion == dp::ApiVersion::OpenGLES3)
+ if (m_apiVersion == dp::ApiVersion::OpenGLES3)
clearBits |= dp::ClearBits::StencilBit;
m_context->Clear(clearBits, dp::kClearBitsStoreAll);
diff --git a/drape_frontend/gui/layer_render.cpp b/drape_frontend/gui/layer_render.cpp
index bace4c1a54..5ab3239c9a 100644
--- a/drape_frontend/gui/layer_render.cpp
+++ b/drape_frontend/gui/layer_render.cpp
@@ -369,7 +369,6 @@ void LayerCacher::CacheScaleFpsLabel(ref_ptr context, Posit
std::string apiLabel;
switch (apiVersion)
{
- case dp::ApiVersion::OpenGLES2: apiLabel = "GL2"; break;
case dp::ApiVersion::OpenGLES3: apiLabel = "GL3"; break;
case dp::ApiVersion::Metal: apiLabel = "M"; break;
case dp::ApiVersion::Vulkan: apiLabel = "V"; break;
diff --git a/drape_frontend/postprocess_renderer.cpp b/drape_frontend/postprocess_renderer.cpp
index 0118f5dd1e..083eeabe28 100644
--- a/drape_frontend/postprocess_renderer.cpp
+++ b/drape_frontend/postprocess_renderer.cpp
@@ -203,10 +203,6 @@ bool PostprocessRenderer::IsEnabled() const
void PostprocessRenderer::SetEffectEnabled(ref_ptr context,
Effect effect, bool enabled)
{
- // Do not support AA for OpenGLES 2.0.
- if (m_apiVersion == dp::ApiVersion::OpenGLES2 && effect == Effect::Antialiasing)
- return;
-
auto const oldValue = m_effects;
auto const effectMask = static_cast(effect);
m_effects = (m_effects & ~effectMask) | (enabled ? effectMask : 0);
@@ -238,7 +234,7 @@ bool PostprocessRenderer::CanRenderAntialiasing() const
return false;
}
- if (m_apiVersion == dp::ApiVersion::OpenGLES2 || m_apiVersion == dp::ApiVersion::OpenGLES3)
+ if (m_apiVersion == dp::ApiVersion::OpenGLES3)
{
return m_staticTextures->m_smaaAreaTexture->GetID() != 0 &&
m_staticTextures->m_smaaSearchTexture->GetID() != 0;
@@ -289,7 +285,7 @@ bool PostprocessRenderer::EndFrame(ref_ptr context,
ASSERT(m_staticTextures->m_smaaAreaTexture != nullptr, ());
ASSERT(m_staticTextures->m_smaaSearchTexture != nullptr, ());
- if (m_apiVersion == dp::ApiVersion::OpenGLES2 || m_apiVersion == dp::ApiVersion::OpenGLES3)
+ if (m_apiVersion == dp::ApiVersion::OpenGLES3)
{
ASSERT_GREATER(m_staticTextures->m_smaaAreaTexture->GetID(), 0, ());
ASSERT_GREATER(m_staticTextures->m_smaaSearchTexture->GetID(), 0, ());
@@ -418,15 +414,12 @@ void PostprocessRenderer::UpdateFramebuffers(ref_ptr contex
ASSERT_NOT_EQUAL(height, 0, ());
CHECK_EQUAL(m_apiVersion, context->GetApiVersion(), ());
- InitFramebuffer(context, m_mainFramebuffer, width, height, true /* depthEnabled */,
- m_apiVersion != dp::ApiVersion::OpenGLES2 /* stencilEnabled */);
+ InitFramebuffer(context, m_mainFramebuffer, width, height, true /* depthEnabled */, true /* stencilEnabled */);
m_isMainFramebufferRendered = false;
m_isSmaaFramebufferRendered = false;
if (!m_isRouteFollowingActive && IsEffectEnabled(Effect::Antialiasing))
{
- CHECK_NOT_EQUAL(m_apiVersion, dp::ApiVersion::OpenGLES2, ());
-
InitFramebuffer(context, m_edgesFramebuffer, dp::TextureFormat::RedGreen,
m_mainFramebuffer->GetDepthStencilRef(),
width, height);
diff --git a/iphone/Maps/Classes/EAGLView.mm b/iphone/Maps/Classes/EAGLView.mm
index 1a730321c2..9c14c163ff 100644
--- a/iphone/Maps/Classes/EAGLView.mm
+++ b/iphone/Maps/Classes/EAGLView.mm
@@ -81,7 +81,7 @@ double getExactDPI(double contentScaleFactor)
if (tempContext != nil)
apiVersion = dp::ApiVersion::OpenGLES3;
else
- apiVersion = dp::ApiVersion::OpenGLES2;
+ CHECK(false, ("OpenGL ES3 is not supported"));
}
return apiVersion;
diff --git a/iphone/Maps/Classes/iosOGLContext.mm b/iphone/Maps/Classes/iosOGLContext.mm
index ec18d14c81..04b86cb0d1 100644
--- a/iphone/Maps/Classes/iosOGLContext.mm
+++ b/iphone/Maps/Classes/iosOGLContext.mm
@@ -17,20 +17,14 @@ iosOGLContext::iosOGLContext(CAEAGLLayer * layer, dp::ApiVersion apiVersion,
, m_frameBufferId(0)
, m_presentAvailable(true)
{
- EAGLRenderingAPI api;
- if (m_apiVersion == dp::ApiVersion::OpenGLES3)
- api = kEAGLRenderingAPIOpenGLES3;
- else
- api = kEAGLRenderingAPIOpenGLES2;
-
if (contextToShareWith != NULL)
{
- m_nativeContext = [[EAGLContext alloc] initWithAPI:api
+ m_nativeContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3
sharegroup: contextToShareWith->m_nativeContext.sharegroup];
}
else
{
- m_nativeContext = [[EAGLContext alloc] initWithAPI:api];
+ m_nativeContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
}
}
diff --git a/map/framework.hpp b/map/framework.hpp
index c46de8942d..1eda2269f3 100644
--- a/map/framework.hpp
+++ b/map/framework.hpp
@@ -395,7 +395,7 @@ private:
public:
struct DrapeCreationParams
{
- dp::ApiVersion m_apiVersion = dp::ApiVersion::OpenGLES2;
+ dp::ApiVersion m_apiVersion = dp::ApiVersion::OpenGLES3;
float m_visualScale = 1.0f;
int m_surfaceWidth = 0;
int m_surfaceHeight = 0;
diff --git a/qt/qt_common/map_widget.cpp b/qt/qt_common/map_widget.cpp
index 07da1e31f3..dc3f2455a9 100644
--- a/qt/qt_common/map_widget.cpp
+++ b/qt/qt_common/map_widget.cpp
@@ -107,7 +107,7 @@ void MapWidget::CreateEngine()
{
Framework::DrapeCreationParams p;
- p.m_apiVersion = m_apiOpenGLES3 ? dp::ApiVersion::OpenGLES3 : dp::ApiVersion::OpenGLES2;
+ p.m_apiVersion = dp::ApiVersion::OpenGLES3;
p.m_surfaceWidth = m_screenshotMode ? width() : static_cast(m_ratio * width());
p.m_surfaceHeight = m_screenshotMode ? height() : static_cast(m_ratio * height());
@@ -232,8 +232,6 @@ void MapWidget::Build()
{
std::string_view vertexSrc;
std::string_view fragmentSrc;
- if (m_apiOpenGLES3)
- {
#if defined(OMIM_OS_LINUX)
vertexSrc = ":common/shaders/gles_300.vsh.glsl";
fragmentSrc = ":common/shaders/gles_300.fsh.glsl";
@@ -241,12 +239,6 @@ void MapWidget::Build()
vertexSrc = ":common/shaders/gl_150.vsh.glsl";
fragmentSrc = ":common/shaders/gl_150.fsh.glsl";
#endif
- }
- else
- {
- vertexSrc = ":common/shaders/gles_200.vsh.glsl";
- fragmentSrc = ":common/shaders/gles_200.fsh.glsl";
- }
m_program = std::make_unique(this);
m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, vertexSrc.data());
@@ -348,8 +340,6 @@ void MapWidget::initializeGL()
if (!m_screenshotMode)
m_ratio = devicePixelRatio();
- m_apiOpenGLES3 = true;
-
#if defined(OMIM_OS_LINUX)
{
QOpenGLFunctions * funcs = context()->functions();
@@ -367,29 +357,14 @@ void MapWidget::initializeGL()
auto fmt = context()->format();
if (context()->format().version() < qMakePair(3, 0))
{
- LOG(LINFO, ("OpenGL ES version is below 3.0, taking the OpenGL ES 2.0 path"));
- m_apiOpenGLES3 = false;
-
- constexpr const char* requiredExtensions[3] =
- { "GL_EXT_map_buffer_range", "GL_OES_mapbuffer", "GL_OES_vertex_array_object" };
- for (auto & requiredExtension : requiredExtensions)
- {
- if (context()->hasExtension(QByteArray::fromStdString(requiredExtension)))
- LOG(LDEBUG, ("Found OpenGL ES 2.0 extension: ", requiredExtension));
- else
- LOG(LCRITICAL, ("A required OpenGL ES 2.0 extension is missing:", requiredExtension));
- }
- fmt.setProfile(QSurfaceFormat::CompatibilityProfile);
- fmt.setVersion(2, 0);
+ CHECK(false, ("OpenGL ES2 is not supported"));
}
else
{
LOG(LINFO, ("OpenGL version is at least 3.0, enabling GLSL '#version 300 es'"));
- m_apiOpenGLES3 = true;
fmt.setVersion(3, 0);
}
-
QSurfaceFormat::setDefaultFormat(fmt);
}
#endif
diff --git a/qt/qt_common/map_widget.hpp b/qt/qt_common/map_widget.hpp
index 304a51aea0..aacb292370 100644
--- a/qt/qt_common/map_widget.hpp
+++ b/qt/qt_common/map_widget.hpp
@@ -97,7 +97,6 @@ protected:
void wheelEvent(QWheelEvent * e) override;
Framework & m_framework;
- bool m_apiOpenGLES3;
bool m_screenshotMode;
ScaleSlider * m_slider;
SliderState m_sliderState;
diff --git a/qt/qt_common/res/resources_common.qrc b/qt/qt_common/res/resources_common.qrc
index 8aa243bd91..0bc03d9f7e 100644
--- a/qt/qt_common/res/resources_common.qrc
+++ b/qt/qt_common/res/resources_common.qrc
@@ -16,8 +16,6 @@
spinner12.png
shaders/gl_150.fsh.glsl
shaders/gl_150.vsh.glsl
- shaders/gles_200.fsh.glsl
- shaders/gles_200.vsh.glsl
shaders/gles_300.fsh.glsl
shaders/gles_300.vsh.glsl
diff --git a/qt/qt_common/res/shaders/gles_200.fsh.glsl b/qt/qt_common/res/shaders/gles_200.fsh.glsl
deleted file mode 100644
index baa46225b3..0000000000
--- a/qt/qt_common/res/shaders/gles_200.fsh.glsl
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifdef GL_ES
-#ifdef GL_FRAGMENT_PRECISION_HIGH
-precision highp float;
-#else
-precision mediump float;
-#endif
-#endif
-
-uniform sampler2D u_sampler;
-varying vec2 v_texCoord;
-
-void main()
-{
- gl_FragColor = vec4(texture2D(u_sampler, v_texCoord).rgb, 1.0);
-}
diff --git a/qt/qt_common/res/shaders/gles_200.vsh.glsl b/qt/qt_common/res/shaders/gles_200.vsh.glsl
deleted file mode 100644
index 7d1208f962..0000000000
--- a/qt/qt_common/res/shaders/gles_200.vsh.glsl
+++ /dev/null
@@ -1,9 +0,0 @@
-attribute vec4 a_position;
-uniform vec2 u_samplerSize;
-varying vec2 v_texCoord;
-
-void main()
-{
- v_texCoord = vec2(a_position.z * u_samplerSize.x, a_position.w * u_samplerSize.y);
- gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0);
-}
diff --git a/qt_tstfrm/test_main_loop.cpp b/qt_tstfrm/test_main_loop.cpp
index 1f773c3073..ecd0518864 100644
--- a/qt_tstfrm/test_main_loop.cpp
+++ b/qt_tstfrm/test_main_loop.cpp
@@ -51,8 +51,7 @@ void RunTestLoop(char const * testName, testing::RenderFunction && fn, bool auto
app.exec();
}
-void RunTestInOpenGLOffscreenEnvironment(char const * testName, bool apiOpenGLES3,
- testing::TestFunction const & fn)
+void RunTestInOpenGLOffscreenEnvironment(char const * testName, testing::TestFunction const & fn)
{
std::vector buf(strlen(testName) + 1);
strcpy(buf.data(), testName);
@@ -71,16 +70,8 @@ void RunTestInOpenGLOffscreenEnvironment(char const * testName, bool apiOpenGLES
fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
fmt.setSwapInterval(1);
fmt.setDepthBufferSize(16);
- if (apiOpenGLES3)
- {
- fmt.setProfile(QSurfaceFormat::CoreProfile);
- fmt.setVersion(3, 2);
- }
- else
- {
- fmt.setProfile(QSurfaceFormat::CompatibilityProfile);
- fmt.setVersion(2, 1);
- }
+ fmt.setProfile(QSurfaceFormat::CoreProfile);
+ fmt.setVersion(3, 2);
auto surface = std::make_unique