diff options
author | Jesse Hall <jessehall@google.com> | 2013-06-18 11:34:53 -0700 |
---|---|---|
committer | Jesse Hall <jessehall@google.com> | 2013-06-18 11:34:53 -0700 |
commit | a85d7d3c12fbb639277488a3810a6b5833fe1f33 (patch) | |
tree | d14651689e27f2f9db6c0fc1adccaae3222a8384 | |
parent | f5be21fc841bf03d8cfde657a231c22de46a0f54 (diff) | |
download | sdk-a85d7d3c12fbb639277488a3810a6b5833fe1f33.zip sdk-a85d7d3c12fbb639277488a3810a6b5833fe1f33.tar.gz sdk-a85d7d3c12fbb639277488a3810a6b5833fe1f33.tar.bz2 |
Fix RenderThreadInfo lifetime and cleanup
Instead of using a TLS destructor, RenderThreadInfo is now an automatic
variable of RenderThread::Main(), so is automatically destroyed on thread exit.
RenderThread::Main() now explicitly unbinds the thread's context and surfaces
from the FrameBuffer, ensuring that the thread has released all references
before it exits.
This fixes a bug where RenderThreadInfo's destructor was releasing the
references in the TLS destructor, which caused ColorBuffer's destructor to call
FrameBuffer::bind_locked() when the FrameBuffer lock wasn't held. By clearing
the references in FrameBuffer::bindContext(), locking around destruction
happens correctly.
Change-Id: I617cea838d5f352a597ccc6d3dbd8f9c08cb91bd
6 files changed, 45 insertions, 62 deletions
diff --git a/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp b/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp index c970337..193bc3b 100644 --- a/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp @@ -170,7 +170,7 @@ void ColorBuffer::subUpdate(int x, int y, int width, int height, GLenum p_format bool ColorBuffer::blitFromCurrentReadBuffer() { - RenderThreadInfo *tInfo = getRenderThreadInfo(); + RenderThreadInfo *tInfo = RenderThreadInfo::get(); if (!tInfo->currContext.Ptr()) { // no Current context return false; @@ -257,7 +257,7 @@ bool ColorBuffer::blitFromCurrentReadBuffer() bool ColorBuffer::bindToTexture() { if (m_eglImage) { - RenderThreadInfo *tInfo = getRenderThreadInfo(); + RenderThreadInfo *tInfo = RenderThreadInfo::get(); if (tInfo->currContext.Ptr()) { #ifdef WITH_GLES2 if (tInfo->currContext->isGL2()) { @@ -278,7 +278,7 @@ bool ColorBuffer::bindToTexture() bool ColorBuffer::bindToRenderbuffer() { if (m_eglImage) { - RenderThreadInfo *tInfo = getRenderThreadInfo(); + RenderThreadInfo *tInfo = RenderThreadInfo::get(); if (tInfo->currContext.Ptr()) { #ifdef WITH_GLES2 if (tInfo->currContext->isGL2()) { diff --git a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp index d41b9a5..2c9e8c5 100644 --- a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp @@ -419,7 +419,7 @@ bool FrameBuffer::setupSubWindow(FBNativeWindowType p_window, fb->m_nativeWindow = p_window; // create EGLSurface from the generated subwindow - fb->m_eglSurface = s_egl.eglCreateWindowSurface(fb->m_eglDisplay, + fb->m_eglSurface = s_egl.eglCreateWindowSurface(fb->m_eglDisplay, fb->m_eglConfig, fb->m_subWin, NULL); @@ -692,28 +692,31 @@ bool FrameBuffer::bindContext(HandleType p_context, draw ? draw->getEGLSurface() : EGL_NO_SURFACE, read ? read->getEGLSurface() : EGL_NO_SURFACE, ctx ? ctx->getEGLContext() : EGL_NO_CONTEXT)) { - // MakeCurrent failed + ERR("eglMakeCurrent failed\n"); return false; } // // Bind the surface(s) to the context // - RenderThreadInfo *tinfo = getRenderThreadInfo(); + RenderThreadInfo *tinfo = RenderThreadInfo::get(); + WindowSurfacePtr bindDraw, bindRead; if (draw.Ptr() == NULL && read.Ptr() == NULL) { - // if this is an unbind operation - make sure the current bound - // surfaces get unbound from the context. - draw = tinfo->currDrawSurf; - read = tinfo->currReadSurf; - } - - if (draw.Ptr() != NULL && read.Ptr() != NULL) { - if (p_readSurface != p_drawSurface) { - draw->bind( ctx, SURFACE_BIND_DRAW ); - read->bind( ctx, SURFACE_BIND_READ ); + // Unbind the current read and draw surfaces from the context + bindDraw = tinfo->currDrawSurf; + bindRead = tinfo->currReadSurf; + } else { + bindDraw = draw; + bindRead = read; + } + + if (bindDraw.Ptr() != NULL && bindRead.Ptr() != NULL) { + if (bindDraw.Ptr() != bindRead.Ptr()) { + bindDraw->bind(ctx, SURFACE_BIND_DRAW); + bindRead->bind(ctx, SURFACE_BIND_READ); } else { - draw->bind( ctx, SURFACE_BIND_READDRAW ); + bindDraw->bind(ctx, SURFACE_BIND_READDRAW); } } @@ -846,7 +849,7 @@ bool FrameBuffer::post(HandleType p_colorbuffer, bool needLock) s_egl.eglSwapBuffers(m_eglDisplay, m_eglSurface); } - + // restore previous binding unbind_locked(); diff --git a/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp b/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp index 6b8f8fd..960dec7 100644 --- a/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp @@ -63,7 +63,7 @@ static EGLint rcQueryEGLString(EGLenum name, void* buffer, EGLint bufferSize) static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize) { - RenderThreadInfo *tInfo = getRenderThreadInfo(); + RenderThreadInfo *tInfo = RenderThreadInfo::get(); if (!tInfo || !tInfo->currContext.Ptr()) { return 0; } diff --git a/emulator/opengl/host/libs/libOpenglRender/RenderThread.cpp b/emulator/opengl/host/libs/libOpenglRender/RenderThread.cpp index 5ffea4b..1b2c0fe 100644 --- a/emulator/opengl/host/libs/libOpenglRender/RenderThread.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/RenderThread.cpp @@ -21,6 +21,7 @@ #include "GLDispatch.h" #include "GL2Dispatch.h" #include "EGLDispatch.h" +#include "FrameBuffer.h" #define STREAM_BUFFER_SIZE 4*1024*1024 @@ -50,12 +51,13 @@ RenderThread *RenderThread::create(IOStream *p_stream) int RenderThread::Main() { - RenderThreadInfo * tInfo = getRenderThreadInfo(); + RenderThreadInfo tInfo; + // // initialize decoders // - tInfo->m_glDec.initGL( gl_dispatch_get_proc_func, NULL ); - tInfo->m_gl2Dec.initGL( gl2_dispatch_get_proc_func, NULL ); + tInfo.m_glDec.initGL( gl_dispatch_get_proc_func, NULL ); + tInfo.m_gl2Dec.initGL( gl2_dispatch_get_proc_func, NULL ); initRenderControlContext( &m_rcDec ); ReadBuffer readBuf(m_stream, STREAM_BUFFER_SIZE); @@ -114,7 +116,7 @@ int RenderThread::Main() // // try to process some of the command buffer using the GLESv1 decoder // - size_t last = tInfo->m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream); + size_t last = tInfo.m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream); if (last > 0) { progress = true; readBuf.consume(last); @@ -123,7 +125,7 @@ int RenderThread::Main() // // try to process some of the command buffer using the GLESv2 decoder // - last = tInfo->m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream); + last = tInfo.m_gl2Dec.decode(readBuf.buf(), readBuf.validData(), m_stream); if (last > 0) { progress = true; readBuf.consume(last); @@ -148,15 +150,11 @@ int RenderThread::Main() } // - // release the thread from any EGL context - // if bound to context. + // Release references to the current thread's context/surfaces if any // - EGLDisplay eglDpy = s_egl.eglGetCurrentDisplay(); - if (eglDpy != EGL_NO_DISPLAY) { - s_egl.eglMakeCurrent(eglDpy, - EGL_NO_SURFACE, - EGL_NO_SURFACE, - EGL_NO_CONTEXT); + FrameBuffer::getFB()->bindContext(0, 0, 0); + if (tInfo.currContext || tInfo.currDrawSurf || tInfo.currReadSurf) { + fprintf(stderr, "ERROR: RenderThread exiting with current context/surfaces\n"); } // diff --git a/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.cpp b/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.cpp index 82be7b9..566ca40 100644 --- a/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.cpp @@ -13,39 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include <stdio.h> -#include "ThreadInfo.h" - -//#define TRACE_THREADINFO -#ifdef TRACE_THREADINFO -#define LOG_THREADINFO(x...) fprintf(stderr, x) -#else -#define LOG_THREADINFO(x...) -#endif +#include "ThreadInfo.h" #include <cutils/threads.h> + static thread_store_t s_tls = THREAD_STORE_INITIALIZER; -static int active_instance = 0; -static void tlsDestruct(void *ptr) -{ - active_instance--; - LOG_THREADINFO("tlsDestruct Render %lx %d\n", (long)ptr, active_instance); - if (ptr) { - RenderThreadInfo *ti = (RenderThreadInfo *)ptr; - delete ti; - } +RenderThreadInfo::RenderThreadInfo() { + thread_store_set(&s_tls, this, NULL); } -RenderThreadInfo *getRenderThreadInfo() -{ - RenderThreadInfo *ti = (RenderThreadInfo *)thread_store_get(&s_tls); - if (!ti) { - ti = new RenderThreadInfo(); - thread_store_set(&s_tls, ti, tlsDestruct); - active_instance++; - LOG_THREADINFO("getRenderThreadInfo %lx %d\n", (long)ti, active_instance); - } - return ti; +RenderThreadInfo::~RenderThreadInfo() { } +RenderThreadInfo* RenderThreadInfo::get() { + return (RenderThreadInfo*)thread_store_get(&s_tls); +} diff --git a/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.h b/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.h index b147290..2e67521 100644 --- a/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.h +++ b/emulator/opengl/host/libs/libOpenglRender/ThreadInfo.h @@ -23,6 +23,10 @@ struct RenderThreadInfo { + RenderThreadInfo(); + ~RenderThreadInfo(); + static RenderThreadInfo* get(); + RenderContextPtr currContext; WindowSurfacePtr currDrawSurf; WindowSurfacePtr currReadSurf; @@ -30,6 +34,4 @@ struct RenderThreadInfo GL2Decoder m_gl2Dec; }; -RenderThreadInfo *getRenderThreadInfo(); - #endif |