diff --git a/android/jni/opengl/android_gl_utils.h b/android/jni/opengl/android_gl_utils.h index 206bf13e04..2edccb1b8d 100644 --- a/android/jni/opengl/android_gl_utils.h +++ b/android/jni/opengl/android_gl_utils.h @@ -3,28 +3,6 @@ #include #include -static int gl_config_weight(EGLConfig const & config, EGLDisplay const & display) -{ - int val = -1; - eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &val); - - switch (val) { - case EGL_NONE: - return 0; - case EGL_SLOW_CONFIG: - return 1; - case EGL_NON_CONFORMANT_CONFIG: - return 2; - default: - return 0; - } -} - -int gl_compare_config(EGLConfig const & l, EGLConfig const & r, EGLDisplay const & display) -{ - return gl_config_weight(l, display) - gl_config_weight(r, display); -} - class ConfigComparator { public: @@ -34,7 +12,24 @@ public: int operator()(EGLConfig const & l, EGLConfig const & r) { - return gl_compare_config(l ,r, m_display); + return configWeight(l) - configWeight(r); + } + + int configWeight(EGLConfig const & config) + { + int val = -1; + eglGetConfigAttrib(m_display, config, EGL_CONFIG_CAVEAT, &val); + + switch (val) { + case EGL_NONE: + return 0; + case EGL_SLOW_CONFIG: + return 1; + case EGL_NON_CONFORMANT_CONFIG: + return 2; + default: + return 0; + } } private: diff --git a/android/jni/opengl/androidoglcontext.cpp b/android/jni/opengl/androidoglcontext.cpp index 60abe9b82d..1fb853f017 100644 --- a/android/jni/opengl/androidoglcontext.cpp +++ b/android/jni/opengl/androidoglcontext.cpp @@ -1,26 +1,10 @@ #include "androidoglcontext.hpp" -#include "android_gl_utils.h" #include "../../../base/assert.hpp" #include "../../../base/logging.hpp" -#include -EGLint * AndroidOGLContext::getConfigAttributesList() -{ - 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; -} -EGLint * AndroidOGLContext::getContextAttributesList() +static EGLint * getContextAttributesList() { static EGLint contextAttrList[] = { EGL_CONTEXT_CLIENT_VERSION, 2, @@ -29,95 +13,24 @@ EGLint * AndroidOGLContext::getContextAttributesList() return contextAttrList; } -AndroidOGLContext::AndroidOGLContext(EGLDisplay * display, ANativeWindow * nativeWindow) +AndroidOGLContext::AndroidOGLContext(EGLDisplay display, EGLSurface surface, EGLConfig config, AndroidOGLContext * contextToShareWith) : m_nativeContext(EGL_NO_CONTEXT) - , m_surface(EGL_NO_SURFACE) + , m_surface(surface) , m_display(display) - , m_nativeWindow(nativeWindow) - , m_config(NULL) - , m_needPixelBufferSurface(false) { + ASSERT(m_surface != EGL_NO_SURFACE, ()); ASSERT(m_display != EGL_NO_DISPLAY, ()); - ASSERT(m_nativeWindow != NULL, ()); - createNativeContextAndSurface(); -} + EGLContext sharedContext = (contextToShareWith == NULL) ? EGL_NO_CONTEXT : contextToShareWith->m_nativeContext; + m_nativeContext = eglCreateContext(m_display, config, sharedContext, getContextAttributesList()); -void AndroidOGLContext::createNativeContextAndSurface() -{ - EGLConfig configs[40]; - int num_configs = 0; - ASSERT(eglChooseConfig(m_display, getConfigAttributesList(), configs, 40, &num_configs) == EGL_TRUE, ()); - ASSERT(num_configs > 0, ("Didn't find any configs.")); - std::sort(&configs[0], &configs[num_configs], ConfigComparator(m_display)); - - for (int i = 0; i < num_configs; ++i) - { - EGLConfig currentConfig = configs[i]; - - m_surface = eglCreateWindowSurface(m_display, currentConfig, m_nativeWindow, 0); - if (m_surface == EGL_NO_SURFACE) - continue; - - m_nativeContext = eglCreateContext(m_display, currentConfig, EGL_NO_CONTEXT, getConfigAttributesList()); - if (m_nativeContext == EGL_NO_CONTEXT) - { - eglDestroySurface(m_display, m_surface); - continue; - } - - // Here we have valid config - m_config = currentConfig; - - EGLint configId = 0; - eglGetConfigAttrib(m_display, m_config, EGL_CONFIG_ID, &configId); - LOG(LINFO, ("Choosen config id:", configId)); - - break; - } - - ASSERT(m_surface != EGL_NO_SURFACE, ()); - ASSERT(m_nativeContext != EGL_NO_CONTEXT, ()); -} - -AndroidOGLContext::AndroidOGLContext(AndroidOGLContext * contextToShareWith) - : m_nativeContext(EGL_NO_CONTEXT) - , m_surface(EGL_NO_SURFACE) - , m_display(EGL_NO_DISPLAY) - , m_nativeWindow(NULL) - , m_config(NULL) - , m_needPixelBufferSurface(true) -{ - ASSERT(contextToShareWith != NULL, ("Must pass valid context to share with")); - m_config = contextToShareWith->m_config; - m_display = contextToShareWith->m_display; - m_nativeContext = eglCreateContext(m_display, m_config, contextToShareWith->m_nativeContext, getContextAttributesList()); - ASSERT(m_nativeContext != EGL_NO_CONTEXT, ()); - - createPixelbufferSurface(); -} - -void AndroidOGLContext::createPixelbufferSurface() -{ - ASSERT(m_needPixelBufferSurface, ()); - static GLuint size = 1; // yes, 1 is the correct size, we dont really draw on it - static EGLint surfaceConfig[] = { - EGL_WIDTH, size, EGL_HEIGHT, size, EGL_NONE - }; - m_surface = eglCreatePbufferSurface(m_display, m_config, surfaceConfig); - ASSERT(m_surface != EGL_NO_SURFACE, ()); + CHECK(m_nativeContext != EGL_NO_CONTEXT, ()); } AndroidOGLContext::~AndroidOGLContext() { - if (m_display != EGL_NO_DISPLAY) - { - if (m_nativeContext != EGL_NO_CONTEXT) - eglDestroyContext(m_display, m_nativeContext); - - if (m_surface != EGL_NO_SURFACE) - eglDestroySurface(m_display, m_surface); - } + // Native context must exist + eglDestroyContext(m_display, m_nativeContext); } void AndroidOGLContext::setDefaultFramebuffer() @@ -127,10 +40,12 @@ void AndroidOGLContext::setDefaultFramebuffer() void AndroidOGLContext::makeCurrent() { - ASSERT(eglMakeCurrent(m_display, m_surface, m_surface, m_nativeContext) == EGL_TRUE, ()); + if (eglMakeCurrent(m_display, m_surface, m_surface, m_nativeContext) != EGL_TRUE) + LOG(LINFO, ("Failed to set current context:", eglGetError())); } void AndroidOGLContext::present() { - ASSERT(eglSwapBuffers(m_display, m_surface) == EGL_TRUE, ()); + if(eglSwapBuffers(m_display, m_surface) != EGL_TRUE) + LOG(LINFO, ("Failed to swap buffers:", eglGetError())); } diff --git a/android/jni/opengl/androidoglcontext.hpp b/android/jni/opengl/androidoglcontext.hpp index 8620b3aba2..fec8ef99d0 100644 --- a/android/jni/opengl/androidoglcontext.hpp +++ b/android/jni/opengl/androidoglcontext.hpp @@ -10,8 +10,7 @@ class AndroidOGLContext : public OGLContext { public: - AndroidOGLContext(AndroidOGLContext * contextToShareWith); - AndroidOGLContext(EGLDisplay * display, ANativeWindow * nativeWindow); + AndroidOGLContext(EGLDisplay display, EGLSurface surface, EGLConfig config, AndroidOGLContext * contextToShareWith); ~AndroidOGLContext(); virtual void makeCurrent(); @@ -19,23 +18,13 @@ public: virtual void setDefaultFramebuffer(); private: - static EGLint * getConfigAttributesList(); - static EGLint * getContextAttributesList(); - void createNativeContextAndSurface(); - void createPixelbufferSurface(); - // {@ Owned by Context EGLContext m_nativeContext; - EGLSurface m_surface; // @} // {@ Owned by Factory + EGLSurface m_surface; EGLDisplay m_display; - ANativeWindow * m_nativeWindow; // @} - - EGLConfig m_config; - - bool m_needPixelBufferSurface; }; diff --git a/android/jni/opengl/androidoglcontextfactory.cpp b/android/jni/opengl/androidoglcontextfactory.cpp index f23566e8bc..01c3094178 100644 --- a/android/jni/opengl/androidoglcontextfactory.cpp +++ b/android/jni/opengl/androidoglcontextfactory.cpp @@ -1,14 +1,35 @@ #include "androidoglcontextfactory.h" +#include "android_gl_utils.h" #include "../../../base/assert.hpp" +#include + +static EGLint * getConfigAttributesList() +{ + 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; +} + AndroidOGLContextFactory::AndroidOGLContextFactory(JNIEnv * env, jobject jsurface) : m_drawContext(NULL) , m_uploadContext(NULL) + , m_windowSurface(EGL_NO_SURFACE) + , m_pixelbufferSurface(EGL_NO_SURFACE) + , m_config(NULL) , m_nativeWindow(NULL) , m_display(EGL_NO_DISPLAY) { - ASSERT(jsurface, ()); + CHECK(jsurface, ()); m_nativeWindow = ANativeWindow_fromSurface(env, jsurface); ASSERT(m_nativeWindow, ()); @@ -17,7 +38,10 @@ AndroidOGLContextFactory::AndroidOGLContextFactory(JNIEnv * env, jobject jsurfac ASSERT(m_display != EGL_NO_DISPLAY, ()); EGLint version[2] = {0}; - ASSERT(eglInitialize(m_display, &version[0], &version[1]), ()); + VERIFY(eglInitialize(m_display, &version[0], &version[1]), ()); + + createWindowSurface(); + createPixelbufferSurface(); } AndroidOGLContextFactory::~AndroidOGLContextFactory() @@ -25,22 +49,67 @@ AndroidOGLContextFactory::~AndroidOGLContextFactory() delete m_drawContext; delete m_uploadContext; + eglDestroySurface(m_display, m_windowSurface); + eglDestroySurface(m_display, m_pixelbufferSurface); eglTerminate(m_display); + ANativeWindow_release(m_nativeWindow); } OGLContext * AndroidOGLContextFactory::getDrawContext() { + CHECK(m_windowSurface != EGL_NO_SURFACE, ()); if (m_drawContext == NULL) - m_drawContext = new AndroidOGLContext(m_display, m_nativeWindow); + m_drawContext = new AndroidOGLContext(m_display, m_windowSurface, m_config, m_uploadContext); return m_drawContext; } OGLContext * AndroidOGLContextFactory::getResourcesUploadContext() { + CHECK(m_pixelbufferSurface != EGL_NO_SURFACE, ()); if (m_uploadContext == NULL) - m_uploadContext = new AndroidOGLContext(getDrawContext()); + m_uploadContext = new AndroidOGLContext(m_display, m_pixelbufferSurface, m_config, m_drawContext); return m_uploadContext; } +void AndroidOGLContextFactory::createWindowSurface() +{ + EGLConfig configs[40]; + int num_configs = 0; + VERIFY(eglChooseConfig(m_display, getConfigAttributesList(), configs, 40, &num_configs) == EGL_TRUE, ()); + ASSERT(num_configs > 0, ("Didn't find any configs.")); + + std::sort(&configs[0], &configs[num_configs], ConfigComparator(m_display)); + for (int i = 0; i < num_configs; ++i) + { + EGLConfig currentConfig = configs[i]; + + m_windowSurface = eglCreateWindowSurface(m_display, currentConfig, m_nativeWindow, EGL_BACK_BUFFER); + if (m_windowSurface == EGL_NO_SURFACE) + continue; + else + m_config = currentConfig; + + EGLint configId = 0; + eglGetConfigAttrib(m_display, m_config, EGL_CONFIG_ID, &configId); + LOG(LINFO, ("Choosen config id:", configId)); + + break; + } + + CHECK(m_windowSurface != EGL_NO_SURFACE, ()); +} + +void AndroidOGLContextFactory::createPixelbufferSurface() +{ + CHECK(m_config != NULL, ()); + + const GLuint size = 1; // yes, 1 is the correct size, we dont really draw on it + static EGLint surfaceConfig[] = { + EGL_WIDTH, size, EGL_HEIGHT, size, EGL_NONE + }; + m_pixelbufferSurface = eglCreatePbufferSurface(m_display, m_config, surfaceConfig); + ASSERT(m_pixelbufferSurface != EGL_NO_SURFACE, ()); +} + diff --git a/android/jni/opengl/androidoglcontextfactory.h b/android/jni/opengl/androidoglcontextfactory.h index fa124ae0e2..3b2f4c1b97 100644 --- a/android/jni/opengl/androidoglcontextfactory.h +++ b/android/jni/opengl/androidoglcontextfactory.h @@ -14,9 +14,17 @@ public: virtual OGLContext * getResourcesUploadContext(); private: + void createWindowSurface(); + void createPixelbufferSurface(); + + AndroidOGLContext * m_drawContext; AndroidOGLContext * m_uploadContext; + EGLSurface m_windowSurface; + EGLSurface m_pixelbufferSurface; + EGLConfig m_config; + ANativeWindow * m_nativeWindow; EGLDisplay m_display; };