diff --git a/drape/gl_extensions_list.cpp b/drape/gl_extensions_list.cpp index f6313379bc..5f182c247e 100644 --- a/drape/gl_extensions_list.cpp +++ b/drape/gl_extensions_list.cpp @@ -37,6 +37,20 @@ void GLExtensionsList::Init(dp::ApiVersion apiVersion) SetExtension(VertexArrayObject, true); SetExtension(UintIndices, true); } +#elif defined(OMIM_OS_LINUX) + SetExtension(MapBuffer, true); + SetExtension(UintIndices, true); + if (apiVersion == dp::ApiVersion::OpenGLES2) + { + SetExtension(VertexArrayObject, true); + SetExtension(MapBuffer, true); + SetExtension(MapBufferRange, true); + } + else // OpenGLES3 branch + { + SetExtension(VertexArrayObject, true); + SetExtension(MapBufferRange, true); + } #elif defined(OMIM_OS_WINDOWS) SetExtension(MapBuffer, true); SetExtension(UintIndices, true); diff --git a/drape/gl_functions.cpp b/drape/gl_functions.cpp index 75ef2b9d8c..5ffc0264de 100644 --- a/drape/gl_functions.cpp +++ b/drape/gl_functions.cpp @@ -255,8 +255,16 @@ void GLFunctions::Init(dp::ApiVersion apiVersion) glUnmapBufferFn = &::glUnmapBuffer; #elif defined(OMIM_OS_LINUX) - - CHECK(false, ("OpenGLES2 is not yet supported")); + void *libhandle = dlopen("libGL.so.1", RTLD_NOW); + ASSERT(libhandle, ("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) diff --git a/drape/gl_includes.hpp b/drape/gl_includes.hpp index 4ecf09463d..b4a3e1f66f 100644 --- a/drape/gl_includes.hpp +++ b/drape/gl_includes.hpp @@ -21,6 +21,11 @@ #include #include "android/jni/app/organicmaps/opengl/gl3stub.h" #include +#elif defined(OMIM_OS_LINUX) + #define GL_GLEXT_PROTOTYPES + #include + #include + #include #else #define GL_GLEXT_PROTOTYPES #include diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp index 7529d6941a..fc31d7d4ce 100644 --- a/qt/draw_widget.cpp +++ b/qt/draw_widget.cpp @@ -703,7 +703,7 @@ void DrawWidget::SetDefaultSurfaceFormat(bool apiOpenGLES3) else { fmt.setProfile(QSurfaceFormat::CompatibilityProfile); - fmt.setVersion(2, 1); + fmt.setVersion(2, 0); } //fmt.setOption(QSurfaceFormat::DebugContext); QSurfaceFormat::setDefaultFormat(fmt); diff --git a/qt/main.cpp b/qt/main.cpp index 23075d75e1..37a48a8e68 100644 --- a/qt/main.cpp +++ b/qt/main.cpp @@ -22,6 +22,9 @@ #include #include +#include +#include +#include #include #include #include @@ -46,6 +49,7 @@ DEFINE_int32(height, 0, "Screenshot height."); DEFINE_double(dpi_scale, 0.0, "Screenshot dpi scale (mdpi = 1.0, hdpi = 1.5, " "xhdpiScale = 2.0, 6plus = 2.4, xxhdpi = 3.0, xxxhdpi = 3.5)."); + using namespace std; namespace @@ -175,11 +179,55 @@ int main(int argc, char * argv[]) #if defined(OMIM_OS_MAC) apiOpenGLES3 = app.arguments().contains("es3", Qt::CaseInsensitive); #elif defined(OMIM_OS_LINUX) - // TODO: Implement proper runtime version detection in a separate commit - // Currently on Linux in a maximum ES2 scenario, - // the GL function pointers wouldn't be properly resolved anyway, - // so here at least a possibly successful path is chosen. - apiOpenGLES3 = true; + { // Start of temporary scope for temporary surface + QOffscreenSurface temporarySurface; + temporarySurface.create(); + + QOpenGLContext ctx; + ctx.create(); + ctx.makeCurrent(&temporarySurface); + + const std::string vendor = QString::fromLatin1( + (const char*)ctx.functions()->glGetString(GL_VENDOR)).toStdString(); + const std::string renderer = QString::fromLatin1( + (const char*)ctx.functions()->glGetString(GL_RENDERER)).toStdString(); + const std::string version = QString::fromLatin1( + (const char*)ctx.functions()->glGetString(GL_VERSION)).toStdString(); + const std::string glslVersion = QString::fromLatin1( + (const char*)ctx.functions()->glGetString(GL_SHADING_LANGUAGE_VERSION)).toStdString(); + const std::string extensions = QString::fromLatin1( + (const char*)ctx.functions()->glGetString(GL_EXTENSIONS)).toStdString(); + + LOG(LINFO, ("Vendor:", vendor, "\nRenderer:", renderer, + "\nVersion:", version, "\nShading language version:\n", glslVersion, + "\nExtensions:", extensions)); + + if (ctx.isOpenGLES()) + { + LOG(LINFO, ("Context is LibGLES")); + // TODO: Fix the ES3 code path with ES3 compatible shader code. + 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(ctx.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)); + } + } + } + else + { + LOG(LINFO, ("Contex is LibGL")); + // TODO: Separate apiOpenGL3 from apiOpenGLES3, and use that for the currend shader code. + apiOpenGLES3 = true; + } + } #endif if (!FLAGS_lang.empty()) diff --git a/qt/qt_common/map_widget.cpp b/qt/qt_common/map_widget.cpp index 5afe534870..2951d82ed5 100644 --- a/qt/qt_common/map_widget.cpp +++ b/qt/qt_common/map_widget.cpp @@ -245,6 +245,13 @@ void MapWidget::Build() fragmentSrc = "\ + #ifdef GL_ES\n\ + #ifdef GL_FRAGMENT_PRECISION_HIGH\n\ + precision highp float;\n\ + #else\n\ + precision mediump float;\n\ + #endif\n\ + #endif\n\ uniform sampler2D u_sampler; \ varying vec2 v_texCoord; \ \