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
This commit is contained in:
Guy Zadickario
2011-08-18 12:32:24 +03:00
committed by Guy Zadickario
parent bdf4c1f436
commit 4629d2412b
3 changed files with 49 additions and 10 deletions

View File

@@ -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();
}