aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Hall <jessehall@google.com>2013-06-18 11:34:53 -0700
committerJesse Hall <jessehall@google.com>2013-06-18 11:34:53 -0700
commita85d7d3c12fbb639277488a3810a6b5833fe1f33 (patch)
treed14651689e27f2f9db6c0fc1adccaae3222a8384
parentf5be21fc841bf03d8cfde657a231c22de46a0f54 (diff)
downloadsdk-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
-rw-r--r--emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp6
-rw-r--r--emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp33
-rw-r--r--emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp2
-rw-r--r--emulator/opengl/host/libs/libOpenglRender/RenderThread.cpp24
-rw-r--r--emulator/opengl/host/libs/libOpenglRender/ThreadInfo.cpp36
-rw-r--r--emulator/opengl/host/libs/libOpenglRender/ThreadInfo.h6
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