Merge "opengles emulator: fixed renderer termination flow"

This commit is contained in:
David Turner
2011-08-10 01:03:50 -07:00
committed by Android Code Review
9 changed files with 136 additions and 27 deletions

View File

@@ -88,4 +88,13 @@ private:
size_t m_free; size_t m_free;
}; };
//
// When a client opens a connection to the renderer, it should
// send unsigned int value indicating the "clientFlags".
// The following are the bitmask of the clientFlags.
// currently only one bit is used which flags the server
// it should exit.
//
#define IOSTREAM_CLIENT_EXIT_SERVER 1
#endif #endif

View File

@@ -85,6 +85,9 @@ static const char *getGLES2ExtensionString(EGLDisplay p_dpy,
void FrameBuffer::finalize(){ void FrameBuffer::finalize(){
if(s_theFrameBuffer){ if(s_theFrameBuffer){
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.eglMakeCurrent(s_theFrameBuffer->m_eglDisplay, NULL, NULL, NULL);
s_egl.eglDestroySurface(s_theFrameBuffer->m_eglDisplay,s_theFrameBuffer->m_eglSurface); s_egl.eglDestroySurface(s_theFrameBuffer->m_eglDisplay,s_theFrameBuffer->m_eglSurface);
s_egl.eglDestroyContext(s_theFrameBuffer->m_eglDisplay,s_theFrameBuffer->m_eglContext); s_egl.eglDestroyContext(s_theFrameBuffer->m_eglDisplay,s_theFrameBuffer->m_eglContext);

View File

@@ -16,10 +16,14 @@
#include "RenderServer.h" #include "RenderServer.h"
#include "TcpStream.h" #include "TcpStream.h"
#include "RenderThread.h" #include "RenderThread.h"
#include "FrameBuffer.h"
#include <set>
typedef std::set<RenderThread *> RenderThreadsSet;
RenderServer::RenderServer() : RenderServer::RenderServer() :
m_listenSock(NULL), m_listenSock(NULL),
m_exit(false) m_exiting(false)
{ {
} }
@@ -42,16 +46,26 @@ RenderServer *RenderServer::create(int port)
int RenderServer::Main() int RenderServer::Main()
{ {
while(!m_exit) { RenderThreadsSet threads;
while(1) {
TcpStream *stream = m_listenSock->accept(); TcpStream *stream = m_listenSock->accept();
if (!stream) { if (!stream) {
fprintf(stderr,"Error accepting connection, aborting\n"); fprintf(stderr,"Error accepting connection, aborting\n");
break; break;
} }
unsigned int clientFlags;
if (!stream->readFully(&clientFlags, sizeof(unsigned int))) {
fprintf(stderr,"Error reading clientFlags\n");
delete stream;
continue;
}
DBG("\n\n\n\n Got new stream!!!! \n\n\n\n\n"); DBG("\n\n\n\n Got new stream!!!! \n\n\n\n\n");
// check if we have been requested to exit while waiting on accept // check if we have been requested to exit while waiting on accept
if (m_exit) { if ((clientFlags & IOSTREAM_CLIENT_EXIT_SERVER) != 0) {
m_exiting = true;
break; break;
} }
@@ -64,10 +78,49 @@ int RenderServer::Main()
if (!rt->start()) { if (!rt->start()) {
fprintf(stderr,"Failed to start RenderThread\n"); fprintf(stderr,"Failed to start RenderThread\n");
delete stream; delete stream;
delete rt;
} }
//
// remove from the threads list threads which are
// no longer running
//
for (RenderThreadsSet::iterator n,t = threads.begin();
t != threads.end();
t = n) {
// first find next iterator
n = t;
n++;
// delete and erase the current iterator
// if thread is no longer running
if ((*t)->isFinished()) {
delete (*t);
threads.erase(t);
}
}
// insert the added thread to the list
threads.insert(rt);
printf("Started new RenderThread\n"); printf("Started new RenderThread\n");
} }
//
// Wait for all threads to finish
//
for (RenderThreadsSet::iterator t = threads.begin();
t != threads.end();
t++) {
int exitStatus;
(*t)->wait(&exitStatus);
delete (*t);
}
threads.clear();
//
// de-initialize the FrameBuffer object
//
FrameBuffer::finalize();
return 0; return 0;
} }

View File

@@ -25,14 +25,14 @@ public:
static RenderServer *create(int port); static RenderServer *create(int port);
virtual int Main(); virtual int Main();
void flagNeedExit() { m_exit = true; } bool isExiting() const { return m_exiting; }
private: private:
RenderServer(); RenderServer();
private: private:
TcpStream *m_listenSock; TcpStream *m_listenSock;
bool m_exit; bool m_exiting;
}; };
#endif #endif

View File

@@ -20,12 +20,14 @@
#include "TimeUtils.h" #include "TimeUtils.h"
#include "GLDispatch.h" #include "GLDispatch.h"
#include "GL2Dispatch.h" #include "GL2Dispatch.h"
#include "EGLDispatch.h"
#define STREAM_BUFFER_SIZE 4*1024*1024 #define STREAM_BUFFER_SIZE 4*1024*1024
RenderThread::RenderThread() : RenderThread::RenderThread() :
osUtils::Thread(), osUtils::Thread(),
m_stream(NULL) m_stream(NULL),
m_finished(false)
{ {
} }
@@ -141,5 +143,21 @@ int RenderThread::Main()
fclose(dumpFP); fclose(dumpFP);
} }
//
// release the thread from any EGL context
// if bound to context.
//
EGLDisplay eglDpy = s_egl.eglGetCurrentDisplay();
if (eglDpy != EGL_NO_DISPLAY) {
s_egl.eglMakeCurrent(eglDpy,
EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT);
}
//
// flag that this thread has finished execution
m_finished = true;
return 0; return 0;
} }

View File

@@ -26,6 +26,8 @@ class RenderThread : public osUtils::Thread
public: public:
static RenderThread *create(IOStream *p_stream); static RenderThread *create(IOStream *p_stream);
bool isFinished() const { return m_finished; }
private: private:
RenderThread(); RenderThread();
virtual int Main(); virtual int Main();
@@ -33,6 +35,7 @@ private:
private: private:
IOStream *m_stream; IOStream *m_stream;
renderControl_decoder_context_t m_rcDec; renderControl_decoder_context_t m_rcDec;
bool m_finished;
}; };
#endif #endif

View File

@@ -24,7 +24,8 @@ static osUtils::childProcess *s_renderProc = NULL;
static RenderServer *s_renderThread = NULL; static RenderServer *s_renderThread = NULL;
static int s_renderPort = 0; static int s_renderPort = 0;
static IOStream *createRenderThread(int p_stream_buffer_size); static IOStream *createRenderThread(int p_stream_buffer_size,
unsigned int clientFlags);
#ifdef __APPLE__ #ifdef __APPLE__
#define RENDER_API_USE_THREAD #define RENDER_API_USE_THREAD
@@ -108,7 +109,7 @@ bool initOpenGLRenderer(FBNativeWindowType window,
} }
#endif #endif
dummy = createRenderThread(8); dummy = createRenderThread(8, 0);
if (!dummy) { if (!dummy) {
// stop if the process is no longer running // stop if the process is no longer running
@@ -139,31 +140,28 @@ bool stopOpenGLRenderer()
{ {
bool ret = false; bool ret = false;
// open a dummy connection to the renderer to make it
// realize the exit request.
// (send the exit request in clientFlags)
IOStream *dummy = createRenderThread(8, IOSTREAM_CLIENT_EXIT_SERVER);
if (!dummy) return false;
if (s_renderProc) { if (s_renderProc) {
// //
// kill the render process // wait for the process to exit
// //
ret = osUtils::KillProcess(s_renderProc->getPID(), true) != 0; int exitStatus;
if (ret) { ret = s_renderProc->wait(&exitStatus);
delete s_renderProc; delete s_renderProc;
s_renderProc = NULL; s_renderProc = NULL;
} }
}
else if (s_renderThread) { else if (s_renderThread) {
// flag the thread it should exit
s_renderThread->flagNeedExit();
// open a dummy connection to the renderer to make it
// realize the exit request
IOStream *dummy = createRenderThread(8);
if (dummy) {
// wait for the thread to exit // wait for the thread to exit
int status; int status;
ret = s_renderThread->wait(&status); ret = s_renderThread->wait(&status);
delete dummy;
}
delete s_renderThread; delete s_renderThread;
s_renderThread = NULL; s_renderThread = NULL;
} }
@@ -171,7 +169,7 @@ bool stopOpenGLRenderer()
return ret; return ret;
} }
IOStream *createRenderThread(int p_stream_buffer_size) IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags)
{ {
TcpStream *stream = new TcpStream(p_stream_buffer_size); TcpStream *stream = new TcpStream(p_stream_buffer_size);
if (!stream) { if (!stream) {
@@ -185,5 +183,13 @@ IOStream *createRenderThread(int p_stream_buffer_size)
return NULL; return NULL;
} }
//
// send clientFlags to the renderer
//
unsigned int *pClientFlags =
(unsigned int *)stream->allocBuffer(sizeof(unsigned int));
*pClientFlags = clientFlags;
stream->commitBuffer(sizeof(unsigned int));
return stream; return stream;
} }

View File

@@ -160,6 +160,16 @@ int main(int argc, char *argv[])
GetMessage(&msg, hWnd, 0, 0); GetMessage(&msg, hWnd, 0, 0);
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessage(&msg); DispatchMessage(&msg);
//
// if server thread has exiting
// wait for it to exit and done.
//
if (server->isExiting()) {
int exitStatus;
server->wait(&exitStatus);
done = true;
}
} }
#endif #endif

View File

@@ -106,6 +106,13 @@ HostConnection *HostConnection::get()
} }
con->m_stream = stream; con->m_stream = stream;
} }
// send zero 'clientFlags' to the host.
unsigned int *pClientFlags =
(unsigned int *)con->m_stream->allocBuffer(sizeof(unsigned int));
*pClientFlags = 0;
con->m_stream->commitBuffer(sizeof(unsigned int));
LOGD("HostConnection::get() New Host Connection established %p, tid %d\n", con, gettid()); LOGD("HostConnection::get() New Host Connection established %p, tid %d\n", con, gettid());
tinfo->hostConn = con; tinfo->hostConn = con;
} }