From b1740c4329f496b316cb8b414b660e27717dcea2 Mon Sep 17 00:00:00 2001 From: rachytski Date: Sat, 7 Apr 2012 15:21:43 +0400 Subject: [PATCH] [android][iphone][mac] added support for rendering with GLSL shaders and enabled it by default. --- android/AndroidManifest.xml | 2 +- android/jni/Android.mk | 2 +- .../jni/com/mapswithme/platform/Platform.cpp | 4 - .../nvidia/devtech/NvEventQueueActivity.java | 40 +- iphone/Maps/Classes/RenderContext.mm | 4 +- map/coverage_generator.cpp | 9 +- map/qgl_render_context.cpp | 1 + map/render_policy.cpp | 3 + yg/base_texture.cpp | 8 +- yg/blitter.cpp | 30 +- yg/clipper.cpp | 4 +- yg/geometry_renderer.cpp | 18 +- yg/internal/opengl.cpp | 18 +- yg/internal/opengl.hpp | 52 ++- yg/internal/opengl_es.cpp | 26 ++ yg/internal/opengl_ext.cpp | 31 ++ yg/internal/opengl_glsl_es2.cpp | 84 ++++ yg/internal/opengl_glsl_ext.cpp | 79 ++++ yg/internal/opengl_glsl_impl.cpp | 369 ++++++++++++++++++ yg/internal/opengl_glsl_impl.hpp | 25 ++ yg/render_state_updater.cpp | 4 +- yg/rendercontext.cpp | 6 + yg/rendercontext.hpp | 2 +- yg/utils.cpp | 19 +- yg/vertex.cpp | 11 +- yg/yg.pro | 25 +- 26 files changed, 798 insertions(+), 78 deletions(-) create mode 100644 yg/internal/opengl_glsl_es2.cpp create mode 100644 yg/internal/opengl_glsl_ext.cpp create mode 100644 yg/internal/opengl_glsl_impl.cpp create mode 100644 yg/internal/opengl_glsl_impl.hpp diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 6b59825a82..80d6c3d864 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -7,7 +7,7 @@ android:sharedUserId="com.mapswithme" android:sharedUserLabel="@string/app_name"> - + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 091259ec19..05c0a15cd9 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -45,7 +45,7 @@ LOCAL_SRC_FILES := \ nv_event/nv_event.cpp \ nv_time/nv_time.cpp -LOCAL_LDLIBS := -llog -lGLESv1_CM \ +LOCAL_LDLIBS := -llog -lGLESv2 \ -lmap -lversion -lsearch -lstorage -lindexer -lyg -lplatform \ -lgeometry -lcoding -lbase -lexpat -lfreetype -lfribidi -lzlib -lbzip2 \ -ljansson -ltomcrypt -lprotobuf ./obj/local/$(TARGET_ARCH_ABI)/libgnustl_static.a diff --git a/android/jni/com/mapswithme/platform/Platform.cpp b/android/jni/com/mapswithme/platform/Platform.cpp index 08c3c4cb78..8c978c6f64 100644 --- a/android/jni/com/mapswithme/platform/Platform.cpp +++ b/android/jni/com/mapswithme/platform/Platform.cpp @@ -28,12 +28,8 @@ public: m_tileSize = min(max(ceiledScreenSize / 2, (size_t)128), (size_t)512); - double k = (256.0 / m_tileSize) * (256.0 / m_tileSize); - LOG(LINFO, ("tileSize=", m_tileSize)); - /// calculating how much tiles we need for the screen of such size - m_preCachingDepth = 3; switch (densityDpi) diff --git a/android/src/com/nvidia/devtech/NvEventQueueActivity.java b/android/src/com/nvidia/devtech/NvEventQueueActivity.java index 6aa760ff63..d620797d62 100644 --- a/android/src/com/nvidia/devtech/NvEventQueueActivity.java +++ b/android/src/com/nvidia/devtech/NvEventQueueActivity.java @@ -24,6 +24,8 @@ import android.view.SurfaceHolder.Callback; public abstract class NvEventQueueActivity extends Activity { private static final String TAG = "NvEventQueueActivity"; + private static final int EGL_RENDERABLE_TYPE = 0x3040; + private static final int EGL_OPENGL_ES2_BIT = 0x0004; private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; private EGL10 m_egl = (EGL10) EGLContext.getEGL(); @@ -414,6 +416,7 @@ public abstract class NvEventQueueActivity extends Activity EGL11.EGL_ALPHA_SIZE, alphaSize, EGL11.EGL_STENCIL_SIZE, stencilSize, EGL11.EGL_DEPTH_SIZE, depthSize, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL11.EGL_NONE }; m_eglDisplay = m_egl.eglGetDisplay(EGL11.EGL_DEFAULT_DISPLAY); @@ -446,19 +449,30 @@ public abstract class NvEventQueueActivity extends Activity m_choosenConfigIndex = 0; - m_eglConfig = m_configs[m_choosenConfigIndex]; - - // Debug print - Log.d(TAG, "Matched egl configs:"); - for (int i = 0; i < m_actualConfigsNumber[0]; ++i) - Log.d(TAG, (i == m_choosenConfigIndex ? "*" : " ") + i + ": " + eglConfigToString(m_configs[i])); - - final int[] contextAttrs = new int[] { EGL_CONTEXT_CLIENT_VERSION, 1, EGL11.EGL_NONE }; - m_eglContext = m_egl.eglCreateContext(m_eglDisplay, m_eglConfig, EGL11.EGL_NO_CONTEXT, contextAttrs); - if (m_eglContext == EGL11.EGL_NO_CONTEXT) + while (true) { - Log.d(TAG, "eglCreateContext failed with error " + m_egl.eglGetError()); - return false; + m_eglConfig = m_configs[m_choosenConfigIndex]; + + // Debug print + Log.d(TAG, "Matched egl configs:"); + for (int i = 0; i < m_actualConfigsNumber[0]; ++i) + Log.d(TAG, (i == m_choosenConfigIndex ? "*" : " ") + i + ": " + eglConfigToString(m_configs[i])); + + final int[] contextAttrs = new int[] { EGL_CONTEXT_CLIENT_VERSION, 2, EGL11.EGL_NONE }; + m_eglContext = m_egl.eglCreateContext(m_eglDisplay, m_eglConfig, EGL11.EGL_NO_CONTEXT, contextAttrs); + if (m_eglContext == EGL11.EGL_NO_CONTEXT) + { + Log.d(TAG, "eglCreateContext failed with error " + m_egl.eglGetError()); + m_choosenConfigIndex++; + } + else + break; + + if (m_choosenConfigIndex == m_configs.length) + { + Log.d(TAG, "No more configs left to choose"); + return false; + } } m_eglInitialized = true; @@ -570,7 +584,7 @@ public abstract class NvEventQueueActivity extends Activity m_egl.eglDestroyContext(m_eglDisplay, m_eglContext); // recreating context with same eglConfig as eglWindowSurface has - final int[] contextAttrs = new int[] { EGL_CONTEXT_CLIENT_VERSION, 1, EGL11.EGL_NONE }; + final int[] contextAttrs = new int[] { EGL_CONTEXT_CLIENT_VERSION, 2, EGL11.EGL_NONE }; m_eglContext = m_egl.eglCreateContext(m_eglDisplay, m_configs[choosenSurfaceConfigIndex], EGL11.EGL_NO_CONTEXT, contextAttrs); if (m_eglContext == EGL11.EGL_NO_CONTEXT) { diff --git a/iphone/Maps/Classes/RenderContext.mm b/iphone/Maps/Classes/RenderContext.mm index b29a47e5e1..6677de0a41 100644 --- a/iphone/Maps/Classes/RenderContext.mm +++ b/iphone/Maps/Classes/RenderContext.mm @@ -13,12 +13,12 @@ namespace iphone { RenderContext::RenderContext() { - m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; + m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; } RenderContext::RenderContext(RenderContext * renderContext) { - m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:renderContext->m_context.sharegroup]; + m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:renderContext->m_context.sharegroup]; } RenderContext::~RenderContext() diff --git a/map/coverage_generator.cpp b/map/coverage_generator.cpp index 60a7a900d5..a11637231a 100644 --- a/map/coverage_generator.cpp +++ b/map/coverage_generator.cpp @@ -28,7 +28,8 @@ CoverageGenerator::CoverageGenerator( g_coverageGeneratorDestroyed = false; m_resourceManager = rm; - m_renderContext = primaryRC->createShared(); + if (!glQueue) + m_renderContext = primaryRC->createShared(); m_currentStylesCache.reset(new yg::ResourceStyleCache(rm, rm->cacheThreadGlyphCacheID(), @@ -46,12 +47,14 @@ CoverageGenerator::CoverageGenerator( void CoverageGenerator::InitializeThreadGL() { - m_renderContext->makeCurrent(); + if (m_renderContext) + m_renderContext->makeCurrent(); } void CoverageGenerator::FinalizeThreadGL() { - m_renderContext->endThreadDrawing(); + if (m_renderContext) + m_renderContext->endThreadDrawing(); } CoverageGenerator::~CoverageGenerator() diff --git a/map/qgl_render_context.cpp b/map/qgl_render_context.cpp index cca74bcff3..d465c0b53c 100644 --- a/map/qgl_render_context.cpp +++ b/map/qgl_render_context.cpp @@ -40,6 +40,7 @@ namespace qt void RenderContext::endThreadDrawing() { m_context.reset(); + yg::gl::RenderContext::endThreadDrawing(); } RenderContext::RenderContext(RenderContext * renderContext) diff --git a/map/render_policy.cpp b/map/render_policy.cpp index 44ca09b31a..2bec92ecc9 100644 --- a/map/render_policy.cpp +++ b/map/render_policy.cpp @@ -7,6 +7,7 @@ #include "window_handle.hpp" #include "test_render_policy.hpp" #include "basic_render_policy.hpp" +#include "simple_render_policy.hpp" #include "render_policy_st.hpp" #include "render_policy_mt.hpp" #include "tiling_render_policy_st.hpp" @@ -26,6 +27,7 @@ RenderPolicy::~RenderPolicy() { LOG(LDEBUG, ("clearing cached drawing rules")); drule::rules().ClearCaches(); + yg::gl::FinalizeThread(); } RenderPolicy::RenderPolicy(shared_ptr const & primaryRC, bool doSupportRotation, size_t idCacheSize) @@ -37,6 +39,7 @@ RenderPolicy::RenderPolicy(shared_ptr const & primaryRC, LOG(LDEBUG, ("each BaseRule will hold up to", idCacheSize, "cached values")); drule::rules().ResizeCaches(idCacheSize); yg::gl::InitExtensions(); + yg::gl::InitializeThread(); yg::gl::CheckExtensionSupport(); } diff --git a/yg/base_texture.cpp b/yg/base_texture.cpp index 63bcff9d7e..59e1f7c786 100644 --- a/yg/base_texture.cpp +++ b/yg/base_texture.cpp @@ -16,10 +16,10 @@ namespace yg OGLCHECK(glBindTexture(GL_TEXTURE_2D, m_id)); - OGLCHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)); - OGLCHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)); - OGLCHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - OGLCHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + OGLCHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)); + OGLCHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)); + OGLCHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + OGLCHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); } BaseTexture::BaseTexture(m2::PointU const & size) diff --git a/yg/blitter.cpp b/yg/blitter.cpp index 295bfc0921..8d63d04979 100644 --- a/yg/blitter.cpp +++ b/yg/blitter.cpp @@ -148,10 +148,13 @@ namespace yg storage.m_indices->unlock(); storage.m_indices->makeCurrent(); +#ifndef USING_GLSL OGLCHECK(glEnable(GL_TEXTURE_2D)); +#endif - OGLCHECK(glDisable(GL_BLEND)); - OGLCHECK(glDisable(GL_DEPTH_TEST)); + OGLCHECK(glDisableFn(GL_ALPHA_TEST_MWM)); + OGLCHECK(glDisableFn(GL_BLEND)); + OGLCHECK(glDisableFn(GL_DEPTH_TEST)); OGLCHECK(glDepthMask(GL_FALSE)); for (unsigned i = 0; i < s; ++i) @@ -159,11 +162,12 @@ namespace yg if (blitInfo[i].m_srcSurface) blitInfo[i].m_srcSurface->makeCurrent(); - OGLCHECK(glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, (unsigned short *)storage.m_indices->glPtr() + i * 4)); + OGLCHECK(glDrawElementsFn(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, (unsigned short *)storage.m_indices->glPtr() + i * 4)); } - OGLCHECK(glEnable(GL_DEPTH_TEST)); - OGLCHECK(glEnable(GL_BLEND)); + OGLCHECK(glEnableFn(GL_ALPHA_TEST_MWM)); + OGLCHECK(glEnableFn(GL_DEPTH_TEST)); + OGLCHECK(glEnableFn(GL_BLEND)); OGLCHECK(glDepthMask(GL_TRUE)); // /// This call is necessary to avoid parasite blitting in updateActualTarget() on IPhone. // OGLCHECK(glFinish()); @@ -345,7 +349,9 @@ namespace yg if (m_texture) { +#ifndef USING_GLSL OGLCHECK(glEnable(GL_TEXTURE_2D)); +#endif m_texture->makeCurrent(); } @@ -354,15 +360,15 @@ namespace yg blitStorage.m_indices->unlock(); blitStorage.m_indices->makeCurrent(); - OGLCHECK(glDisable(GL_ALPHA_TEST)); - OGLCHECK(glDisable(GL_BLEND)); - OGLCHECK(glDisable(GL_DEPTH_TEST)); + OGLCHECK(glDisableFn(GL_ALPHA_TEST_MWM)); + OGLCHECK(glDisableFn(GL_BLEND)); + OGLCHECK(glDisableFn(GL_DEPTH_TEST)); OGLCHECK(glDepthMask(GL_FALSE)); - OGLCHECK(glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, blitStorage.m_indices->glPtr())); + OGLCHECK(glDrawElementsFn(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, blitStorage.m_indices->glPtr())); OGLCHECK(glDepthMask(GL_TRUE)); - OGLCHECK(glEnable(GL_DEPTH_TEST)); - OGLCHECK(glEnable(GL_BLEND)); - OGLCHECK(glEnable(GL_ALPHA_TEST)); + OGLCHECK(glEnableFn(GL_DEPTH_TEST)); + OGLCHECK(glEnableFn(GL_BLEND)); + OGLCHECK(glEnableFn(GL_ALPHA_TEST_MWM)); blitStorage.m_vertices->discard(); blitStorage.m_indices->discard(); diff --git a/yg/clipper.cpp b/yg/clipper.cpp index 42f30a48c9..9fbac42638 100644 --- a/yg/clipper.cpp +++ b/yg/clipper.cpp @@ -40,14 +40,14 @@ namespace yg { if (isDebugging()) LOG(LINFO, ("enabling scissor test")); - OGLCHECK(glEnable(GL_SCISSOR_TEST)); + OGLCHECK(glEnableFn(GL_SCISSOR_TEST)); } else { if (isDebugging()) { LOG(LINFO, ("disabling scissor test")); - OGLCHECK(glDisable(GL_SCISSOR_TEST)); + OGLCHECK(glDisableFn(GL_SCISSOR_TEST)); } } } diff --git a/yg/geometry_renderer.cpp b/yg/geometry_renderer.cpp index de4e1da09f..efac87be8e 100644 --- a/yg/geometry_renderer.cpp +++ b/yg/geometry_renderer.cpp @@ -36,7 +36,7 @@ namespace yg // OGLCHECK(glPolygonMode( GL_FRONT_AND_BACK, GL_LINE )); - OGLCHECK(glDrawElements( + OGLCHECK(glDrawElementsFn( GL_TRIANGLES, m_indicesCount, GL_UNSIGNED_SHORT, @@ -64,18 +64,22 @@ namespace yg if (renderQueue()) return; - OGLCHECK(glEnable(GL_TEXTURE_2D)); + OGLCHECK(glActiveTexture(GL_TEXTURE0)); + +#ifndef USING_GLSL + OGLCHECK(glEnableFn(GL_TEXTURE_2D)); +#endif OGLCHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); OGLCHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - OGLCHECK(glEnable(GL_DEPTH_TEST)); + OGLCHECK(glEnableFn(GL_DEPTH_TEST)); OGLCHECK(glDepthFunc(GL_LEQUAL)); - OGLCHECK(glEnable(GL_ALPHA_TEST)); - OGLCHECK(glAlphaFunc(GL_GREATER, 0.0)); + OGLCHECK(glEnableFn(GL_ALPHA_TEST_MWM)); + OGLCHECK(glAlphaFuncFn(GL_NOTEQUAL, 0.0)); - OGLCHECK(glEnable(GL_BLEND)); + OGLCHECK(glEnableFn(GL_BLEND)); if (yg::gl::g_isSeparateBlendFuncSupported) OGLCHECK(glBlendFuncSeparateFn(GL_SRC_ALPHA, @@ -86,7 +90,9 @@ namespace yg OGLCHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); +#ifndef USING_GLSL OGLCHECK(glColor4f(1.0f, 1.0f, 1.0f, 1.0f)); +#endif } } } diff --git a/yg/internal/opengl.cpp b/yg/internal/opengl.cpp index a9fbf08079..134301b076 100644 --- a/yg/internal/opengl.cpp +++ b/yg/internal/opengl.cpp @@ -56,6 +56,20 @@ namespace yg LOG(LINFO, ("--------------------------------------------")); } + // basic opengl functions and constants + void (OPENGL_CALLING_CONVENTION * glEnableFn)(GLenum cap); + void (OPENGL_CALLING_CONVENTION * glDisableFn)(GLenum cap); + void (OPENGL_CALLING_CONVENTION * glAlphaFuncFn)(GLenum func, GLclampf ref); + + void (OPENGL_CALLING_CONVENTION * glEnableClientStateFn) (GLenum array); + void (OPENGL_CALLING_CONVENTION * glVertexPointerFn) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (OPENGL_CALLING_CONVENTION * glTexCoordPointerFn) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + + void (OPENGL_CALLING_CONVENTION * glMatrixModeFn) (GLenum mode); + void (OPENGL_CALLING_CONVENTION * glLoadIdentityFn)(); + void (OPENGL_CALLING_CONVENTION * glOrthoFn) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); + void (OPENGL_CALLING_CONVENTION * glDrawElementsFn) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); + bool g_isBufferObjectsSupported = true; bool g_isFramebufferSupported = true; bool g_isRenderbufferSupported = true; @@ -113,8 +127,8 @@ namespace yg case GL_INVALID_ENUM: return "GL_INVALID_ENUM"; case GL_INVALID_VALUE: return "GL_INVALID_VALUE"; case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION"; - case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW"; - case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW"; +// case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW"; //< not supported in OpenGL ES2.0 +// case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW"; //< not supported in OpenGL ES2.0 case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY"; #ifdef OMIM_OS_BADA /* Errors / GetError return values */ case EGL_SUCCESS : return 0; diff --git a/yg/internal/opengl.hpp b/yg/internal/opengl.hpp index 9fd3ad86b9..19d816ff6a 100644 --- a/yg/internal/opengl.hpp +++ b/yg/internal/opengl.hpp @@ -4,6 +4,9 @@ #include "../../base/logging.hpp" +// This define is set in yg.pro +// #define USING_GLSL + #if defined(OMIM_OS_WINDOWS) #include "../../std/windows.hpp" #include @@ -19,16 +22,28 @@ #include #ifdef OMIM_OS_IPHONE - #define USE_OPENGLES20_IF_AVAILABLE 0 - #include - #define OMIM_GL_ES + #ifdef USING_GLSL + #define USE_OPENGLES20_IF_AVAILABLE 1 + #include + #define OMIM_GL_ES + #else + #define USE_OPENGLES20_IF_AVAILABLE 0 + #include + #define OMIM_GL_ES + #endif #else #include #include #endif #elif defined(OMIM_OS_ANDROID) - #include + + #ifdef USING_GLSL + #include + #else + #include + #endif + #define OMIM_GL_ES #else @@ -53,6 +68,29 @@ namespace yg { namespace gl { + // basic opengl functions and constants + extern void (OPENGL_CALLING_CONVENTION * glEnableFn)(GLenum cap); + extern void (OPENGL_CALLING_CONVENTION * glDisableFn)(GLenum cap); + extern void (OPENGL_CALLING_CONVENTION * glAlphaFuncFn)(GLenum func, GLclampf ref); + extern void (OPENGL_CALLING_CONVENTION * glEnableClientStateFn) (GLenum array); + extern void (OPENGL_CALLING_CONVENTION * glVertexPointerFn) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + extern void (OPENGL_CALLING_CONVENTION * glTexCoordPointerFn) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + + extern const GLenum GL_VERTEX_ARRAY_MWM; + extern const GLenum GL_TEXTURE_COORD_ARRAY_MWM; + + extern void (OPENGL_CALLING_CONVENTION * glMatrixModeFn) (GLenum mode); + extern void (OPENGL_CALLING_CONVENTION * glLoadIdentityFn)(); + extern void (OPENGL_CALLING_CONVENTION * glOrthoFn) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); + extern void (OPENGL_CALLING_CONVENTION * glDrawElementsFn) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); + + extern const GLenum GL_MODELVIEW_MWM; + extern const GLenum GL_PROJECTION_MWM; + + extern const GLenum GL_ALPHA_TEST_MWM; + + /// information about supported extensions + extern bool g_isFramebufferSupported; extern bool g_isBufferObjectsSupported; extern bool g_isRenderbufferSupported; @@ -122,6 +160,12 @@ namespace yg /// to check extensions support and initialize function pointers. void InitExtensions(); + /// Initialize per-thread OpenGL + void InitializeThread(); + + /// Finalize per-thread OpenGL + void FinalizeThread(); + /// Does we have an extension with the specified name? bool HasExtension(char const * name); diff --git a/yg/internal/opengl_es.cpp b/yg/internal/opengl_es.cpp index 3ee987ace5..66ebb579e8 100644 --- a/yg/internal/opengl_es.cpp +++ b/yg/internal/opengl_es.cpp @@ -32,10 +32,36 @@ namespace yg const int GL_WRITE_ONLY_MWM = GL_WRITE_ONLY_OES; + const GLenum GL_MODELVIEW_MWM = GL_MODELVIEW; + const GLenum GL_PROJECTION_MWM = GL_PROJECTION; + const GLenum GL_ALPHA_TEST_MWM = GL_ALPHA_TEST; + + const GLenum GL_VERTEX_ARRAY_MWM = GL_VERTEX_ARRAY; + const GLenum GL_TEXTURE_COORD_ARRAY_MWM = GL_TEXTURE_COORD_ARRAY; + + void InitializeThread() + {} + + void FinalizeThread() + {} + void InitExtensions() { DumpGLInformation(); + glEnableFn = &glEnable; + glDisableFn = &glDisable; + glAlphaFuncFn = &glAlphaFunc; + + glVertexPointerFn = &glVertexPointer; + glTexCoordPointerFn = &glTexCoordPointer; + glEnableClientStateFn = &glEnableClientState; + + glMatrixModeFn = &glMatrixMode; + glLoadIdentityFn = &glLoadIdentity; + glOrthoFn = &glOrthof; + glDrawElementsFn = &glDrawElements; + g_isBufferObjectsSupported = HasExtension("GL_OES_mapbuffer"); glBindBufferFn = &glBindBuffer; diff --git a/yg/internal/opengl_ext.cpp b/yg/internal/opengl_ext.cpp index 80d7afc12a..0db8543f8b 100644 --- a/yg/internal/opengl_ext.cpp +++ b/yg/internal/opengl_ext.cpp @@ -23,10 +23,41 @@ namespace yg const int GL_WRITE_ONLY_MWM = GL_WRITE_ONLY; + const GLenum GL_MODELVIEW_MWM = GL_MODELVIEW; + const GLenum GL_PROJECTION_MWM = GL_PROJECTION; + const GLenum GL_ALPHA_TEST_MWM = GL_ALPHA_TEST; + + const GLenum GL_VERTEX_ARRAY_MWM = GL_VERTEX_ARRAY; + const GLenum GL_TEXTURE_COORD_ARRAY_MWM = GL_TEXTURE_COORD_ARRAY; + + void glOrthoImpl (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) + { + glOrtho(left, right, bottom, top, zNear, zFar); + } + + void InitializeThread() + {} + + void FinalizeThread() + {} + void InitExtensions() { DumpGLInformation(); + glEnableFn = &glEnable; + glDisableFn = &glDisable; + glAlphaFuncFn = &glAlphaFunc; + + glVertexPointerFn = &glVertexPointer; + glTexCoordPointerFn = &glTexCoordPointer; + glEnableClientStateFn = &glEnableClientState; + + glMatrixModeFn = &glMatrixMode; + glLoadIdentityFn = &glLoadIdentity; + glOrthoFn = &glOrthoImpl; + glDrawElementsFn = &glDrawElements; + g_isBufferObjectsSupported = HasExtension("GL_ARB_vertex_buffer_object") || HasExtension("GLX_ARB_vertex_buffer_object"); diff --git a/yg/internal/opengl_glsl_es2.cpp b/yg/internal/opengl_glsl_es2.cpp new file mode 100644 index 0000000000..0cc8947d19 --- /dev/null +++ b/yg/internal/opengl_glsl_es2.cpp @@ -0,0 +1,84 @@ +#include "opengl.hpp" +#include "opengl_glsl_impl.hpp" + +#ifdef OMIM_OS_ANDROID + #define GL_GLEXT_PROTOTYPES + #include +#endif + +#ifdef OMIM_OS_IPHONE + #include + #include +#endif + +namespace yg +{ + namespace gl + { + const int GL_FRAMEBUFFER_BINDING_MWM = GL_FRAMEBUFFER_BINDING; + const int GL_FRAMEBUFFER_MWM = GL_FRAMEBUFFER; + const int GL_FRAMEBUFFER_UNSUPPORTED_MWM = GL_FRAMEBUFFER_UNSUPPORTED; + const int GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_MWM = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + const int GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_MWM = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; + const int GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_MWM = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; + const int GL_FRAMEBUFFER_COMPLETE_MWM = GL_FRAMEBUFFER_COMPLETE; + + const int GL_DEPTH_ATTACHMENT_MWM = GL_DEPTH_ATTACHMENT; + const int GL_COLOR_ATTACHMENT0_MWM = GL_COLOR_ATTACHMENT0; + const int GL_RENDERBUFFER_MWM = GL_RENDERBUFFER; + const int GL_RENDERBUFFER_BINDING_MWM = GL_RENDERBUFFER_BINDING; + const int GL_DEPTH_COMPONENT16_MWM = GL_DEPTH_COMPONENT16; + const int GL_DEPTH_COMPONENT24_MWM = GL_DEPTH_COMPONENT24_OES; + const int GL_RGBA8_MWM = GL_RGBA8_OES; + + const int GL_WRITE_ONLY_MWM = GL_WRITE_ONLY_OES; + + void InitExtensions() + { + DumpGLInformation(); + + glEnableFn = &glsl::glEnable; + glDisableFn = &glsl::glDisable; + glAlphaFuncFn = &glsl::glAlphaFunc; + + glVertexPointerFn = &glsl::glVertexPointer; + glTexCoordPointerFn = &glsl::glTexCoordPointer; + glEnableClientStateFn = &glsl::glEnableClientState; + + glMatrixModeFn = &glsl::glMatrixMode; + glLoadIdentityFn = &glsl::glLoadIdentity; + glOrthoFn = &glsl::glOrtho; + glDrawElementsFn = &glsl::glDrawElements; + + g_isBufferObjectsSupported = HasExtension("GL_OES_mapbuffer"); + + glBindBufferFn = &glBindBuffer; + glGenBuffersFn = &glGenBuffers; + glBufferDataFn = &glBufferData; + glBufferSubDataFn = &glBufferSubData; + glDeleteBuffersFn = &glDeleteBuffers; + glMapBufferFn = &glMapBufferOES; + glUnmapBufferFn = &glUnmapBufferOES; + + g_isFramebufferSupported = true; + + glBindFramebufferFn = &glBindFramebuffer; + glFramebufferTexture2DFn = &glFramebufferTexture2D; + glFramebufferRenderbufferFn = &glFramebufferRenderbuffer; + glGenFramebuffersFn = &glGenFramebuffers; + glDeleteFramebuffersFn = &glDeleteFramebuffers; + glCheckFramebufferStatusFn = &glCheckFramebufferStatus; + + g_isRenderbufferSupported = g_isFramebufferSupported; + + glGenRenderbuffersFn = &glGenRenderbuffers; + glDeleteRenderbuffersFn = &glDeleteRenderbuffers; + glBindRenderbufferFn = &glBindRenderbuffer; + glRenderbufferStorageFn = &glRenderbufferStorage; + + g_isSeparateBlendFuncSupported = true; + glBlendFuncSeparateFn = &glBlendFuncSeparate; + } + } +} + diff --git a/yg/internal/opengl_glsl_ext.cpp b/yg/internal/opengl_glsl_ext.cpp new file mode 100644 index 0000000000..9192a884d2 --- /dev/null +++ b/yg/internal/opengl_glsl_ext.cpp @@ -0,0 +1,79 @@ +#include "opengl.hpp" + +#include "opengl_glsl_impl.hpp" + +#include "../../base/matrix.hpp" +#include "../../platform/platform.hpp" + +namespace yg +{ + namespace gl + { + const int GL_FRAMEBUFFER_BINDING_MWM = GL_FRAMEBUFFER_BINDING_EXT; + const int GL_FRAMEBUFFER_MWM = GL_FRAMEBUFFER_EXT; + const int GL_FRAMEBUFFER_UNSUPPORTED_MWM = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + const int GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_MWM = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; + const int GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_MWM = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT; + const int GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_MWM = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT; + const int GL_FRAMEBUFFER_COMPLETE_MWM = GL_FRAMEBUFFER_COMPLETE_EXT; + + const int GL_DEPTH_ATTACHMENT_MWM = GL_DEPTH_ATTACHMENT_EXT; + const int GL_COLOR_ATTACHMENT0_MWM = GL_COLOR_ATTACHMENT0_EXT; + const int GL_RENDERBUFFER_MWM = GL_RENDERBUFFER_EXT; + const int GL_RENDERBUFFER_BINDING_MWM = GL_RENDERBUFFER_BINDING_EXT; + const int GL_DEPTH_COMPONENT16_MWM = GL_DEPTH_COMPONENT16; + const int GL_DEPTH_COMPONENT24_MWM = GL_DEPTH_COMPONENT24; + const int GL_RGBA8_MWM = GL_RGBA8; + + const int GL_WRITE_ONLY_MWM = GL_WRITE_ONLY; + + void InitExtensions() + { + DumpGLInformation(); + + glEnableFn = &glsl::glEnable; + glDisableFn = &glsl::glDisable; + glAlphaFuncFn = &glsl::glAlphaFunc; + + glVertexPointerFn = &glsl::glVertexPointer; + glTexCoordPointerFn = &glsl::glTexCoordPointer; + glEnableClientStateFn = &glsl::glEnableClientState; + + glMatrixModeFn = &glsl::glMatrixMode; + glLoadIdentityFn = &glsl::glLoadIdentity; + glOrthoFn = &glsl::glOrtho; + glDrawElementsFn = &glsl::glDrawElements; + + g_isBufferObjectsSupported = HasExtension("GL_OES_mapbuffer"); + + glBindBufferFn = &glBindBuffer; + glGenBuffersFn = &glGenBuffers; + glBufferDataFn = &glBufferData; + glBufferSubDataFn = &glBufferSubData; + glDeleteBuffersFn = &glDeleteBuffers; + glMapBufferFn = &glMapBuffer; + glUnmapBufferFn = &glUnmapBuffer; + + g_isFramebufferSupported = HasExtension("GL_ARB_framebuffer_object"); + + glBindFramebufferFn = &glBindFramebufferEXT; + glFramebufferTexture2DFn = &glFramebufferTexture2DEXT; + glFramebufferRenderbufferFn = &glFramebufferRenderbufferEXT; + glGenFramebuffersFn = &glGenFramebuffersEXT; + glDeleteFramebuffersFn = &glDeleteFramebuffersEXT; + glCheckFramebufferStatusFn = &glCheckFramebufferStatusEXT; + + g_isRenderbufferSupported = g_isFramebufferSupported; + + glGenRenderbuffersFn = &glGenRenderbuffersEXT; + glDeleteRenderbuffersFn = &glDeleteRenderbuffersEXT; + glBindRenderbufferFn = &glBindRenderbufferEXT; + glRenderbufferStorageFn = &glRenderbufferStorageEXT; + + g_isSeparateBlendFuncSupported = HasExtension("GL_EXT_blend_func_separate"); + glBlendFuncSeparateFn = &glBlendFuncSeparateEXT; + } + } +} + + diff --git a/yg/internal/opengl_glsl_impl.cpp b/yg/internal/opengl_glsl_impl.cpp new file mode 100644 index 0000000000..943c83e8f7 --- /dev/null +++ b/yg/internal/opengl_glsl_impl.cpp @@ -0,0 +1,369 @@ +#include "opengl_glsl_impl.hpp" + +#include "opengl.hpp" + +#include "../../base/matrix.hpp" +#include "../../base/thread.hpp" + +namespace yg +{ + namespace gl + { + const GLenum GL_MODELVIEW_MWM = 0; + const GLenum GL_PROJECTION_MWM = 1; + + const GLenum GL_VERTEX_ARRAY_MWM = 0; + const GLenum GL_TEXTURE_COORD_ARRAY_MWM = 1; + + const GLenum GL_ALPHA_TEST_MWM = 0x0BC0; + +#if defined(OMIM_GL_ES) + #define PRECISION "lowp" +#else + #define PRECISION "" +#endif + + namespace glsl + { + /// Vertex Shader Source + + static const char g_vxSrc[] = + "attribute vec4 Position;\n" + "attribute vec2 TexCoordIn;\n" + "uniform mat4 ProjM;\n" + "uniform mat4 ModelViewM;\n" + "varying vec2 TexCoordOut;\n" + "void main(void) {\n" + " gl_Position = ProjM * Position;\n" + " TexCoordOut = TexCoordIn;\n" + "}\n"; + + /// Fragment Shader with alphaTest + + static const char g_alphaTestFrgSrc [] = + "uniform sampler2D Texture;\n" + "varying " PRECISION " vec2 TexCoordOut;\n" + "void main(void) {\n" + " gl_FragColor = texture2D(Texture, TexCoordOut);\n" + " if (gl_FragColor.a == 0.0)\n" + " discard;\n" + "}\n"; + + /// Fragment shader without alphaTest + + static const char g_noAlphaTestFrgSrc[] = + "uniform sampler2D Texture;\n" + "varying " PRECISION " vec2 TexCoordOut;\n" + "void main(void) {\n" + " gl_FragColor = texture2D(Texture, TexCoordOut);\n" + "}\n"; + + /// Structure that holds a single GLSL program + /// along with handles to attributes and uniforms + struct Program + { + GLuint m_program; + GLuint m_positionHandle; + GLuint m_texCoordHandle; + GLuint m_projectionUniform; + GLuint m_textureUniform; + + bool createProgram(GLuint vertexShader, GLuint fragmentShader) + { + m_program = ::glCreateProgram(); + OGLCHECKAFTER; + + if (!m_program) + return false; + + OGLCHECK(::glAttachShader(m_program, vertexShader)); + OGLCHECK(::glAttachShader(m_program, fragmentShader)); + OGLCHECK(::glLinkProgram(m_program)); + + int linkStatus = GL_FALSE; + OGLCHECK(::glGetProgramiv(m_program, GL_LINK_STATUS, &linkStatus)); + + if (linkStatus != GL_TRUE) + { + int bufLength = 0; + OGLCHECK(::glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &bufLength)); + if (bufLength) + { + char * buf = new char[bufLength]; + ::glGetProgramInfoLog(m_program, bufLength, NULL, buf); + LOG(LINFO, ("Could not link program:")); + LOG(LINFO, (buf)); + delete [] buf; + } + + return false; + } + + return true; + } + + void attachProjection(char const * name) + { + m_projectionUniform = ::glGetUniformLocation(m_program, name); + OGLCHECKAFTER; + } + + void attachTexture(char const * name) + { + m_textureUniform = ::glGetUniformLocation(m_program, name); + OGLCHECKAFTER; + } + + void attachPosition(char const * name) + { + m_positionHandle = ::glGetAttribLocation(m_program, name); + OGLCHECKAFTER; + } + + void attachTexCoord(char const * name) + { + m_texCoordHandle = ::glGetAttribLocation(m_program, "TexCoordIn"); + OGLCHECKAFTER; + } + + void apply() + { + OGLCHECK(::glUseProgram(m_program)); + } + }; + + struct ThreadData + { + GLenum m_matrixMode; + math::Matrix m_matrices[2]; + + Program m_noAlphaTestProgram; + Program m_alphaTestProgram; + + /// currently bound GLSL program + Program * m_currentProgram; + + GLuint m_vertexShader; + GLuint m_noAlphaTestFrgSh; + GLuint m_alphaTestFrgSh; + + void setCurrentProgram(Program * program) + { + if (m_currentProgram != program) + { + m_currentProgram = program; + m_currentProgram->apply(); + } + } + + GLuint loadShader(char const * shaderSource, GLenum shaderType) + { + GLuint res = ::glCreateShader(shaderType); + OGLCHECKAFTER; + + int len = strlen(shaderSource); + + OGLCHECK(::glShaderSource(res, 1, &shaderSource, &len)); + + OGLCHECK(::glCompileShader(res)); + + GLint compileRes; + OGLCHECK(::glGetShaderiv(res, GL_COMPILE_STATUS, &compileRes)); + + if (compileRes == GL_FALSE) + { + GLchar msg[256]; + OGLCHECK(::glGetShaderInfoLog(res, sizeof(msg), 0, msg)); + LOG(LINFO, ("Couldn't compile shader :")); + LOG(LERROR, (msg)); + return 0; + } + + return res; + } + + ThreadData() + : m_matrixMode(-1), + m_vertexShader(0), + m_noAlphaTestFrgSh(0), + m_alphaTestFrgSh(0) + {} + + void Initialize() + { + m_vertexShader = loadShader(g_vxSrc, GL_VERTEX_SHADER); + m_noAlphaTestFrgSh = loadShader(g_noAlphaTestFrgSrc, GL_FRAGMENT_SHADER); + m_alphaTestFrgSh = loadShader(g_alphaTestFrgSrc, GL_FRAGMENT_SHADER); + + /// creating program + m_alphaTestProgram.createProgram(m_vertexShader, m_alphaTestFrgSh); + m_noAlphaTestProgram.createProgram(m_vertexShader, m_noAlphaTestFrgSh); + + m_alphaTestProgram.attachProjection("ProjM"); + m_alphaTestProgram.attachTexture("Texture"); + m_alphaTestProgram.attachPosition("Position"); + m_alphaTestProgram.attachTexCoord("TexCoordIn"); + + m_noAlphaTestProgram.attachProjection("ProjM"); + m_noAlphaTestProgram.attachTexture("Texture"); + m_noAlphaTestProgram.attachPosition("Position"); + m_noAlphaTestProgram.attachTexCoord("TexCoordIn"); + + m_currentProgram = &m_noAlphaTestProgram; + m_currentProgram->apply(); + } + + void Finalize() + { + if (yg::gl::g_hasContext) + ::glDeleteProgram(m_alphaTestProgram.m_program); + if (yg::gl::g_hasContext) + ::glDeleteProgram(m_noAlphaTestProgram.m_program); + if (yg::gl::g_hasContext) + ::glDeleteShader(m_vertexShader); + if (yg::gl::g_hasContext) + ::glDeleteShader(m_noAlphaTestFrgSh); + if (yg::gl::g_hasContext) + ::glDeleteShader(m_alphaTestFrgSh); + } + }; + + typedef map ThreadDataMap; + ThreadDataMap g_threadData; + + void glEnable(GLenum cap) + { + if (cap == GL_ALPHA_TEST_MWM) + { + ThreadData & threadData = g_threadData[threads::GetCurrentThreadID()]; + threadData.setCurrentProgram(&threadData.m_alphaTestProgram); + } + else + ::glEnable(cap); + } + + void glDisable(GLenum cap) + { + if (cap == GL_ALPHA_TEST_MWM) + { + ThreadData & threadData = g_threadData[threads::GetCurrentThreadID()]; + threadData.setCurrentProgram(&threadData.m_noAlphaTestProgram); + } + else + ::glDisable(cap); + } + + void glAlphaFunc(GLenum func, GLclampf ref) + { + ASSERT((func == GL_NOTEQUAL) && (ref == 0.0), ("only GL_NOEQUAL with 0.0 reference value is supported for alphaTest")); + } + + void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) + { + ThreadData & threadData = g_threadData[threads::GetCurrentThreadID()]; + ::glVertexAttribPointer(threadData.m_alphaTestProgram.m_positionHandle, size, type, GL_FALSE, stride, pointer); + ::glVertexAttribPointer(threadData.m_noAlphaTestProgram.m_positionHandle, size, type, GL_FALSE, stride, pointer); + } + + void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) + { + ThreadData & threadData = g_threadData[threads::GetCurrentThreadID()]; + ::glVertexAttribPointer(threadData.m_alphaTestProgram.m_texCoordHandle, size, type, GL_FALSE, stride, pointer); + ::glVertexAttribPointer(threadData.m_noAlphaTestProgram.m_texCoordHandle, size, type, GL_FALSE, stride, pointer); + } + + void glEnableClientState(GLenum array) + { + ThreadData & threadData = g_threadData[threads::GetCurrentThreadID()]; + switch (array) + { + case GL_VERTEX_ARRAY_MWM: + ::glEnableVertexAttribArray(threadData.m_alphaTestProgram.m_positionHandle); + ::glEnableVertexAttribArray(threadData.m_noAlphaTestProgram.m_positionHandle); + break; + case GL_TEXTURE_COORD_ARRAY_MWM: + ::glEnableVertexAttribArray(threadData.m_alphaTestProgram.m_texCoordHandle); + ::glEnableVertexAttribArray(threadData.m_noAlphaTestProgram.m_texCoordHandle); + break; + default: + LOG(LERROR, ("Unknown option is passed to glEnableClientState")); + }; + } + + void glMatrixMode(GLenum mode) + { + ThreadData & threadData = g_threadData[threads::GetCurrentThreadID()]; + threadData.m_matrixMode = mode; + } + + void glLoadIdentity() + { + ThreadData & threadData = g_threadData[threads::GetCurrentThreadID()]; + threadData.m_matrices[threadData.m_matrixMode] = math::Identity(); + } + + void glOrtho(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) + { + ThreadData & threadData = g_threadData[threads::GetCurrentThreadID()]; + + math::Matrix m = math::Identity(); + + /// matrices are stored in column-major order + + m(0, 0) = 2 / (r - l); m(1, 0) = 0; m(2, 0) = 0; m(3, 0) = -(r + l) / (r - l); + m(0, 1) = 0; m(1, 1) = 2 / (t - b);m(2, 1) = 0; m(3, 1) = -(t + b) / (t - b); + m(0, 2) = 0; m(1, 2) = 0; m(2, 2) = -2 / (f - n); m(3, 2) = - (f + n) / (f - n); + m(0, 3) = 0; m(1, 3) = 0; m(2, 3) = 0; m(3, 3) = 1; + + threadData.m_matrices[threadData.m_matrixMode] = m * threadData.m_matrices[threadData.m_matrixMode]; + } + + void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) + { + ThreadData & threadData = g_threadData[threads::GetCurrentThreadID()]; + + math::Matrix const & projM = threadData.m_matrices[GL_PROJECTION_MWM]; + math::Matrix const & modelViewM = threadData.m_matrices[GL_MODELVIEW_MWM]; + + // applying shader parameters + OGLCHECK(::glUniformMatrix4fv(threadData.m_currentProgram->m_projectionUniform, 1, 0, &projM(0, 0))); + OGLCHECK(::glUniform1i(threadData.m_currentProgram->m_textureUniform, 0)); + + // drawing elements + OGLCHECK(::glDrawElements(mode, count, type, indices)); + } + } + + void InitializeThread() + { + threads::ThreadID id = threads::GetCurrentThreadID(); + glsl::ThreadDataMap::const_iterator it = glsl::g_threadData.find(id); + + if (it != glsl::g_threadData.end()) + { + LOG(LWARNING, ("GLSL structures for thread", threads::GetCurrentThreadID(), "is already initialized")); + return; + } + + LOG(LINFO, ("initializing GLSL structures for thread", threads::GetCurrentThreadID())); + glsl::g_threadData[id].Initialize(); + } + + void FinalizeThread() + { + threads::ThreadID id = threads::GetCurrentThreadID(); + glsl::ThreadDataMap::const_iterator it = glsl::g_threadData.find(id); + + if (it == glsl::g_threadData.end()) + { + LOG(LWARNING, ("GLSL structures for thread", threads::GetCurrentThreadID(), "is already finalized")); + return; + } + + LOG(LINFO, ("finalizing GLSL structures for thread", threads::GetCurrentThreadID())); + + glsl::g_threadData[id].Finalize(); + glsl::g_threadData.erase(id); + } + } +} diff --git a/yg/internal/opengl_glsl_impl.hpp b/yg/internal/opengl_glsl_impl.hpp new file mode 100644 index 0000000000..f2cb2b093d --- /dev/null +++ b/yg/internal/opengl_glsl_impl.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "opengl.hpp" + +namespace yg +{ + namespace gl + { + namespace glsl + { + void glEnable(GLenum cap); + void glDisable(GLenum cap); + void glAlphaFunc(GLenum func, GLclampf ref); + + void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void glEnableClientState(GLenum array); + + void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); + void glOrtho(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); + void glLoadIdentity(); + void glMatrixMode(GLenum mode); + } + } +} diff --git a/yg/render_state_updater.cpp b/yg/render_state_updater.cpp index 28ab926ca4..4a043a0032 100644 --- a/yg/render_state_updater.cpp +++ b/yg/render_state_updater.cpp @@ -67,7 +67,7 @@ namespace yg OGLCHECK(glFinish()); - OGLCHECK(glDisable(GL_SCISSOR_TEST)); + OGLCHECK(glDisableFn(GL_SCISSOR_TEST)); m_auxFrameBuffer->setRenderTarget(m_renderState->m_backBuffer); m_auxFrameBuffer->makeCurrent(); @@ -91,7 +91,7 @@ namespace yg m_frameBuffer->makeCurrent(); if (m_isClipRectEnabled) - OGLCHECK(glEnable(GL_SCISSOR_TEST)); + OGLCHECK(glEnableFn(GL_SCISSOR_TEST)); OGLCHECK(glScissor(m_clipRect.minX(), m_clipRect.minY(), m_clipRect.maxX(), m_clipRect.maxY())); diff --git a/yg/rendercontext.cpp b/yg/rendercontext.cpp index 2619d4b2d7..91f3a239c3 100644 --- a/yg/rendercontext.cpp +++ b/yg/rendercontext.cpp @@ -10,6 +10,12 @@ namespace yg { OGLCHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); OGLCHECK(glPixelStorei(GL_PACK_ALIGNMENT, 1)); + yg::gl::InitializeThread(); + } + + void RenderContext::endThreadDrawing() + { + yg::gl::FinalizeThread(); } } } diff --git a/yg/rendercontext.hpp b/yg/rendercontext.hpp index 7ff41a2af2..640caa3629 100644 --- a/yg/rendercontext.hpp +++ b/yg/rendercontext.hpp @@ -15,7 +15,7 @@ namespace yg /// Create a render context which is shared with this one. virtual shared_ptr createShared() = 0; /// called at the end of thread - virtual void endThreadDrawing() = 0; + virtual void endThreadDrawing(); /// !! IMPORTANT !! /// this function must be called from each opengl /// thread to setup texture related params diff --git a/yg/utils.cpp b/yg/utils.cpp index 3c96b3403c..84c8820ef4 100644 --- a/yg/utils.cpp +++ b/yg/utils.cpp @@ -15,23 +15,16 @@ namespace yg { OGLCHECK(glViewport(0, 0, width, height)); - OGLCHECK(glMatrixMode(GL_MODELVIEW)); - OGLCHECK(glLoadIdentity()); + OGLCHECK(glMatrixModeFn(GL_MODELVIEW_MWM)); + OGLCHECK(glLoadIdentityFn()); - OGLCHECK(glMatrixMode(GL_PROJECTION)); - OGLCHECK(glLoadIdentity()); + OGLCHECK(glMatrixModeFn(GL_PROJECTION_MWM)); + OGLCHECK(glLoadIdentityFn()); -#ifdef OMIM_GL_ES if (!doSwap) - OGLCHECK(glOrthof(0, width, 0, height, -yg::maxDepth, yg::maxDepth)); + OGLCHECK(glOrthoFn(0, width, 0, height, -yg::maxDepth, yg::maxDepth)); else - OGLCHECK(glOrthof(0, width, height, 0, -yg::maxDepth, yg::maxDepth)); -#else - if (!doSwap) - OGLCHECK(glOrtho(0, width, 0, height, -yg::maxDepth, yg::maxDepth)); - else - OGLCHECK(glOrtho(0, width, height, 0, -yg::maxDepth, yg::maxDepth)); -#endif + OGLCHECK(glOrthoFn(0, width, height, 0, -yg::maxDepth, yg::maxDepth)); } } } diff --git a/yg/vertex.cpp b/yg/vertex.cpp index 5cba704f24..6253fc31ed 100644 --- a/yg/vertex.cpp +++ b/yg/vertex.cpp @@ -30,12 +30,11 @@ namespace yg void Vertex::setupLayout(void * glPtr) { - OGLCHECK(glDisableClientState(GL_COLOR_ARRAY)); - OGLCHECK(glEnableClientState(GL_VERTEX_ARRAY)); - OGLCHECK(glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (void*)((char*)glPtr + Vertex::vertexOffset))); - OGLCHECK(glEnable(GL_TEXTURE_2D)); - OGLCHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); - OGLCHECK(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void*)((char*)glPtr + Vertex::texCoordOffset))); + OGLCHECK(glEnableClientStateFn(GL_VERTEX_ARRAY_MWM)); + OGLCHECK(glVertexPointerFn(3, GL_FLOAT, sizeof(Vertex), (void*)((char*)glPtr + Vertex::vertexOffset))); + + OGLCHECK(glEnableClientStateFn(GL_TEXTURE_COORD_ARRAY_MWM)); + OGLCHECK(glTexCoordPointerFn(2, GL_FLOAT, sizeof(Vertex), (void*)((char*)glPtr + Vertex::texCoordOffset))); } } } diff --git a/yg/yg.pro b/yg/yg.pro index 0ddd4faa00..2c473fbf4a 100644 --- a/yg/yg.pro +++ b/yg/yg.pro @@ -120,14 +120,35 @@ HEADERS += \ circle_element.hpp \ packets_queue.hpp \ +# uncomment to enable GLSL support +CONFIG += glsl + win32* { SOURCES += internal/opengl_win32.cpp } else: android*|iphone* { - SOURCES += internal/opengl_es.cpp + CONFIG(glsl) { + DEFINES += USING_GLSL + HEADERS += internal/opengl_glsl_impl.hpp + SOURCES += internal/opengl_glsl_es2.cpp \ + internal/opengl_glsl_impl.cpp + } else { + SOURCES += internal/opengl_es.cpp + } } else { - SOURCES += internal/opengl_ext.cpp + CONFIG(glsl) { + DEFINES += USING_GLSL + HEADERS += internal/opengl_glsl_impl.hpp + SOURCES += internal/opengl_glsl_ext.cpp \ + internal/opengl_glsl_impl.cpp + } else { + SOURCES += internal/opengl_ext.cpp + } } + + + +