From 4629d2412b7049d2daae2a6d3f6a7f22a1e336bf Mon Sep 17 00:00:00 2001 From: Guy Zadickario Date: Thu, 18 Aug 2011 12:32:24 +0300 Subject: [PATCH] opengles emulator: fixes flashing effect on Mac There is a flashing effect we see on Mac when switching between drawables (pbuffer and a window) on the same context. This change make the FrameBuffer object in the renderer to use two different OpenGL contexts, one which is used while the pbuffer drawable is bound and another which is used when the subwindow is bounded during swap. The two contexts share textures so both contexts have access to all allocated color buffers. While this fixes the flashing effect on Mac, it should be more effective on other platforms as well. Change-Id: I63b49f0cdae8e2785765503750bbf5fbd4d963a1 --- .../host/libs/libOpenglRender/ColorBuffer.cpp | 7 ++- .../host/libs/libOpenglRender/FrameBuffer.cpp | 48 ++++++++++++++++--- .../host/libs/libOpenglRender/FrameBuffer.h | 4 +- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp index c39dac31c..9facb6ceb 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp +++ b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp @@ -93,13 +93,13 @@ ColorBuffer *ColorBuffer::create(int p_width, int p_height, if (fb->getCaps().has_eglimage_texture_2d) { cb->m_eglImage = s_egl.eglCreateImageKHR(fb->getDisplay(), - fb->getContext(), + s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)cb->m_tex, NULL); cb->m_blitEGLImage = s_egl.eglCreateImageKHR(fb->getDisplay(), - fb->getContext(), + s_egl.eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)cb->m_blitTex, NULL); @@ -254,6 +254,8 @@ bool ColorBuffer::blitFromCurrentReadBuffer() // render m_blitTex s_gl.glBindTexture(GL_TEXTURE_2D, m_blitTex); + s_gl.glEnable(GL_TEXTURE_2D); + s_gl.glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); drawTexQuad(); // this will render the texture flipped // unbind the fbo @@ -353,6 +355,7 @@ bool ColorBuffer::post() { s_gl.glBindTexture(GL_TEXTURE_2D, m_tex); s_gl.glEnable(GL_TEXTURE_2D); + s_gl.glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); drawTexQuad(); return true; diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp index 3609a7768..acc472a03 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp +++ b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp @@ -93,7 +93,9 @@ void FrameBuffer::finalize(){ s_theFrameBuffer->m_colorbuffers.clear(); s_theFrameBuffer->m_windows.clear(); s_theFrameBuffer->m_contexts.clear(); + s_egl.eglMakeCurrent(s_theFrameBuffer->m_eglDisplay, NULL, NULL, NULL); s_egl.eglDestroyContext(s_theFrameBuffer->m_eglDisplay,s_theFrameBuffer->m_eglContext); + s_egl.eglDestroyContext(s_theFrameBuffer->m_eglDisplay,s_theFrameBuffer->m_pbufContext); s_egl.eglDestroySurface(s_theFrameBuffer->m_eglDisplay,s_theFrameBuffer->m_pbufSurface); s_theFrameBuffer = NULL; } @@ -221,6 +223,23 @@ bool FrameBuffer::initialize(int width, int height) return false; } + // + // Create another context which shares with the eglContext to be used + // when we bind the pbuffer. That prevent switching drawable binding + // back and forth on framebuffer context. + // The main purpose of it is to solve a "blanking" behaviour we see on + // on Mac platform when switching binded drawable for a context however + // it is more efficient on other platforms as well. + // + fb->m_pbufContext = s_egl.eglCreateContext(fb->m_eglDisplay, fb->m_eglConfig, + fb->m_eglContext, + glContextAttribs); + if (fb->m_pbufContext == EGL_NO_CONTEXT) { + printf("Failed to create Pbuffer Context 0x%x\n", s_egl.eglGetError()); + delete fb; + return false; + } + // // create a 1x1 pbuffer surface which will be used for binding // the FB context. @@ -329,13 +348,9 @@ bool FrameBuffer::initialize(int width, int height) } // - // Initialize some GL state + // Initialize some GL state in the pbuffer context // - s_gl.glMatrixMode(GL_PROJECTION); - s_gl.glLoadIdentity(); - s_gl.glOrthof(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); - s_gl.glMatrixMode(GL_MODELVIEW); - s_gl.glLoadIdentity(); + fb->initGLState(); // release the FB context fb->unbind_locked(); @@ -353,6 +368,7 @@ FrameBuffer::FrameBuffer(int p_width, int p_height) : m_eglDisplay(EGL_NO_DISPLAY), m_eglSurface(EGL_NO_SURFACE), m_eglContext(EGL_NO_CONTEXT), + m_pbufContext(EGL_NO_CONTEXT), m_prevContext(EGL_NO_CONTEXT), m_prevReadSurf(EGL_NO_SURFACE), m_prevDrawSurf(EGL_NO_SURFACE), @@ -360,6 +376,7 @@ FrameBuffer::FrameBuffer(int p_width, int p_height) : m_subWinDisplay(NULL), m_lastPostedColorBuffer(0), m_zRot(0.0f), + m_eglContextInitialized(false), m_statsNumFrames(0), m_statsStartTime(0LL) { @@ -695,7 +712,7 @@ bool FrameBuffer::bind_locked() EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW); if (!s_egl.eglMakeCurrent(m_eglDisplay, m_pbufSurface, - m_pbufSurface, m_eglContext)) { + m_pbufSurface, m_pbufContext)) { ERR("eglMakeCurrent failed\n"); return false; } @@ -718,6 +735,14 @@ bool FrameBuffer::bindSubwin_locked() return false; } + // + // initialize GL state in eglContext if not yet initilaized + // + if (!m_eglContextInitialized) { + initGLState(); + m_eglContextInitialized = true; + } + m_prevContext = prevContext; m_prevReadSurf = prevReadSurf; m_prevDrawSurf = prevDrawSurf; @@ -806,3 +831,12 @@ bool FrameBuffer::repost() } return false; } + +void FrameBuffer::initGLState() +{ + s_gl.glMatrixMode(GL_PROJECTION); + s_gl.glLoadIdentity(); + s_gl.glOrthof(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); + s_gl.glMatrixMode(GL_MODELVIEW); + s_gl.glLoadIdentity(); +} diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h index b415efe73..472531704 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h +++ b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h @@ -75,7 +75,6 @@ public: bool repost(); EGLDisplay getDisplay() const { return m_eglDisplay; } - EGLContext getContext() const { return m_eglContext; } EGLNativeWindowType getSubWindow() const { return m_subWin; } bool bind_locked(); bool unbind_locked(); @@ -90,6 +89,7 @@ private: ~FrameBuffer(); HandleType genHandle(); bool bindSubwin_locked(); + void initGLState(); private: static FrameBuffer *s_theFrameBuffer; @@ -109,6 +109,7 @@ private: EGLSurface m_eglSurface; EGLContext m_eglContext; EGLSurface m_pbufSurface; + EGLContext m_pbufContext; EGLContext m_prevContext; EGLSurface m_prevReadSurf; @@ -118,6 +119,7 @@ private: EGLConfig m_eglConfig; HandleType m_lastPostedColorBuffer; float m_zRot; + bool m_eglContextInitialized; int m_statsNumFrames; long long m_statsStartTime;