EmuGL: Deliver every frame to a callback
To enable multi-touch on a tethered device, allow a callback to be registered with the OpenGL renderer. On every frame, the framebuffer is read into system memory and provided to the callback, so it can be mirrored to the device. This change is co-dependent on Idae3b026d52ed8dd666cbcdc3f3af80175c90ad3 in external/qemu. Change-Id: I03c49bc55ed9e66ffb59462333181f77e7e46035
This commit is contained in:
@@ -101,7 +101,7 @@ void FrameBuffer::finalize(){
|
||||
}
|
||||
}
|
||||
|
||||
bool FrameBuffer::initialize(int width, int height)
|
||||
bool FrameBuffer::initialize(int width, int height, OnPostFn onPost, void* onPostContext)
|
||||
{
|
||||
if (s_theFrameBuffer != NULL) {
|
||||
return true;
|
||||
@@ -110,7 +110,7 @@ bool FrameBuffer::initialize(int width, int height)
|
||||
//
|
||||
// allocate space for the FrameBuffer object
|
||||
//
|
||||
FrameBuffer *fb = new FrameBuffer(width, height);
|
||||
FrameBuffer *fb = new FrameBuffer(width, height, onPost, onPostContext);
|
||||
if (!fb) {
|
||||
ERR("Failed to create fb\n");
|
||||
return false;
|
||||
@@ -334,6 +334,17 @@ bool FrameBuffer::initialize(int width, int height)
|
||||
//
|
||||
fb->initGLState();
|
||||
|
||||
//
|
||||
// Allocate space for the onPost framebuffer image
|
||||
//
|
||||
if (onPost) {
|
||||
fb->m_fbImage = (unsigned char*)malloc(4 * width * height);
|
||||
if (!fb->m_fbImage) {
|
||||
delete fb;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// release the FB context
|
||||
fb->unbind_locked();
|
||||
|
||||
@@ -344,7 +355,8 @@ bool FrameBuffer::initialize(int width, int height)
|
||||
return true;
|
||||
}
|
||||
|
||||
FrameBuffer::FrameBuffer(int p_width, int p_height) :
|
||||
FrameBuffer::FrameBuffer(int p_width, int p_height,
|
||||
OnPostFn onPost, void* onPostContext) :
|
||||
m_width(p_width),
|
||||
m_height(p_height),
|
||||
m_eglDisplay(EGL_NO_DISPLAY),
|
||||
@@ -360,13 +372,17 @@ FrameBuffer::FrameBuffer(int p_width, int p_height) :
|
||||
m_zRot(0.0f),
|
||||
m_eglContextInitialized(false),
|
||||
m_statsNumFrames(0),
|
||||
m_statsStartTime(0LL)
|
||||
m_statsStartTime(0LL),
|
||||
m_onPost(onPost),
|
||||
m_onPostContext(onPostContext),
|
||||
m_fbImage(NULL)
|
||||
{
|
||||
m_fpsStats = getenv("SHOW_FPS_STATS") != NULL;
|
||||
}
|
||||
|
||||
FrameBuffer::~FrameBuffer()
|
||||
{
|
||||
free(m_fbImage);
|
||||
}
|
||||
|
||||
bool FrameBuffer::setupSubWindow(FBNativeWindowType p_window,
|
||||
@@ -780,6 +796,15 @@ bool FrameBuffer::post(HandleType p_colorbuffer, bool needLock)
|
||||
s_gl.glPopMatrix();
|
||||
|
||||
if (ret) {
|
||||
//
|
||||
// Send framebuffer (without FPS overlay) to callback
|
||||
//
|
||||
if (m_onPost) {
|
||||
s_gl.glReadPixels(0, 0, m_width, m_height,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, m_fbImage);
|
||||
m_onPost(m_onPostContext, m_width, m_height, -1,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, m_fbImage);
|
||||
}
|
||||
|
||||
//
|
||||
// output FPS statistics
|
||||
|
||||
@@ -42,7 +42,7 @@ struct FrameBufferCaps
|
||||
class FrameBuffer
|
||||
{
|
||||
public:
|
||||
static bool initialize(int width, int height);
|
||||
static bool initialize(int width, int height, OnPostFn onPost, void* onPostContext);
|
||||
static bool setupSubWindow(FBNativeWindowType p_window,
|
||||
int x, int y,
|
||||
int width, int height, float zRot);
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
FrameBuffer(int p_width, int p_height);
|
||||
FrameBuffer(int p_width, int p_height, OnPostFn onPost, void* onPostContext);
|
||||
~FrameBuffer();
|
||||
HandleType genHandle();
|
||||
bool bindSubwin_locked();
|
||||
@@ -124,5 +124,9 @@ private:
|
||||
int m_statsNumFrames;
|
||||
long long m_statsStartTime;
|
||||
bool m_fpsStats;
|
||||
|
||||
OnPostFn m_onPost;
|
||||
void* m_onPostContext;
|
||||
unsigned char* m_fbImage;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -76,7 +76,8 @@ bool initLibrary(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool initOpenGLRenderer(int width, int height, int portNum)
|
||||
bool initOpenGLRenderer(int width, int height, int portNum,
|
||||
OnPostFn onPost, void* onPostContext)
|
||||
{
|
||||
|
||||
//
|
||||
@@ -93,7 +94,7 @@ bool initOpenGLRenderer(int width, int height, int portNum)
|
||||
// initialize the renderer and listen to connections
|
||||
// on a thread in the current process.
|
||||
//
|
||||
bool inited = FrameBuffer::initialize(width, height);
|
||||
bool inited = FrameBuffer::initialize(width, height, onPost, onPostContext);
|
||||
if (!inited) {
|
||||
return false;
|
||||
}
|
||||
@@ -106,6 +107,17 @@ bool initOpenGLRenderer(int width, int height, int portNum)
|
||||
s_renderThread->start();
|
||||
|
||||
#else
|
||||
if (onPost) {
|
||||
// onPost callback not supported with separate renderer process.
|
||||
//
|
||||
// If we ever revive separate process support, we could make the choice
|
||||
// between thread and process at runtime instead of compile time, and
|
||||
// choose the thread path if an onPost callback is requested. Or, the
|
||||
// callback could be supported with a separate process using shmem or
|
||||
// other IPC mechanism.
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Launch emulator_renderer
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user