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;