diff options
author | Jesse Hall <jessehall@google.com> | 2012-05-09 15:45:23 -0700 |
---|---|---|
committer | Jesse Hall <jessehall@google.com> | 2012-05-10 10:06:56 -0700 |
commit | ab800d7b0188e840407a61fa931f678d2ef46de6 (patch) | |
tree | 7fd509cfa7f2e005f9b162f9200677c14fbd0fff | |
parent | 347fec44f5ebd8e037a47f66256eb739ade9aa6c (diff) | |
download | sdk-ab800d7b0188e840407a61fa931f678d2ef46de6.zip sdk-ab800d7b0188e840407a61fa931f678d2ef46de6.tar.gz sdk-ab800d7b0188e840407a61fa931f678d2ef46de6.tar.bz2 |
Allow frame callback to be enabled/disabled
Since per-frame readback is slow and clients don't need it on all the
time, this change allows the callback to be registered after
initialization, and allows it to be disabled later.
Change-Id: Ic73d4515d302a0981ee0c80b9e6f9ba5c84b82ae
5 files changed, 84 insertions, 57 deletions
diff --git a/emulator/opengl/host/include/libOpenglRender/render_api.h b/emulator/opengl/host/include/libOpenglRender/render_api.h index ebb02eb..4fe54f4 100644 --- a/emulator/opengl/host/include/libOpenglRender/render_api.h +++ b/emulator/opengl/host/include/libOpenglRender/render_api.h @@ -41,38 +41,6 @@ extern "C" { ret name args #endif -/* If a function with this signature is passed to initOpenGLRenderer(), - * it will be called by the renderer just before each new frame is displayed, - * providing a copy of the framebuffer contents. - * - * The callback will be called from one of the renderer's threads, so will - * probably need synchronization on any data structures it modifies. The - * pixels buffer may be overwritten as soon as the callback returns; if it needs - * the pixels afterwards it must copy them. - * - * The pixels buffer is intentionally not const: the callback may modify the - * data without copying to another buffer if it wants, e.g. in-place RGBA to RGB - * conversion, or in-place y-inversion. - * - * Parameters are: - * context The pointer optionally provided when the callback was - * registered. The client can use this to pass whatever - * information it wants to the callback. - * width, height Dimensions of the image, in pixels. Rows are tightly packed; - * there is no inter-row padding. - * ydir Indicates row order: 1 means top-to-bottom order, -1 means - * bottom-to-top order. - * format, type Format and type GL enums, as used in glTexImage2D() or - * glReadPixels(), describing the pixel format. - * pixels The framebuffer image. - * - * In the first implementation, ydir is always -1 (bottom to top), format and - * type are always GL_RGBA and GL_UNSIGNED_BYTE, and the width and height will - * always be the same as the ones passed to initOpenGLRenderer(). - */ -typedef void (*OnPostFn)(void* context, int width, int height, int ydir, - int format, int type, unsigned char* pixels); - /* initLibrary - initialize the library and tries to load the corresponding * GLES translator libraries. This function must be called before anything * else to ensure that everything works. If it returns an error, then @@ -98,8 +66,7 @@ DECL(int, setStreamMode, (int mode)); * This function is *NOT* thread safe and should be called first * to initialize the renderer after initLibrary(). */ -DECL(int, initOpenGLRenderer, (int width, int height, int portNum, - OnPostFn onPost, void* onPostContext)); +DECL(int, initOpenGLRenderer, (int width, int height, int portNum)); /* getHardwareStrings - describe the GPU hardware and driver. * The underlying GL's vendor/renderer/version strings are returned to the @@ -108,6 +75,40 @@ DECL(int, initOpenGLRenderer, (int width, int height, int portNum, DECL(void, getHardwareStrings, (const char** vendor, const char** renderer, const char** version)); +/* A per-frame callback can be registered with setPostCallback(); to remove it + * pass NULL for both parameters. While a callback is registered, the renderer + * will call it just before each new frame is displayed, providing a copy of + * the framebuffer contents. + * + * The callback will be called from one of the renderer's threads, so will + * probably need synchronization on any data structures it modifies. The + * pixels buffer may be overwritten as soon as the callback returns; if it + * needs the pixels afterwards it must copy them. + * + * The pixels buffer is intentionally not const: the callback may modify the + * data without copying to another buffer if it wants, e.g. in-place RGBA to + * RGB conversion, or in-place y-inversion. + * + * Parameters are: + * context The pointer optionally provided when the callback was + * registered. The client can use this to pass whatever + * information it wants to the callback. + * width, height Dimensions of the image, in pixels. Rows are tightly + * packed; there is no inter-row padding. + * ydir Indicates row order: 1 means top-to-bottom order, -1 means + * bottom-to-top order. + * format, type Format and type GL enums, as used in glTexImage2D() or + * glReadPixels(), describing the pixel format. + * pixels The framebuffer image. + * + * In the first implementation, ydir is always -1 (bottom to top), format and + * type are always GL_RGBA and GL_UNSIGNED_BYTE, and the width and height will + * always be the same as the ones passed to initOpenGLRenderer(). + */ +typedef void (*OnPostFn)(void* context, int width, int height, int ydir, + int format, int type, unsigned char* pixels); +DECL(void, setPostCallback, (OnPostFn onPost, void* onPostContext)); + /* createOpenGLSubwindow - * Create a native subwindow which is a child of 'window' * to be used for framebuffer display. diff --git a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp index fde82a1..2f7cd61 100644 --- a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp @@ -101,7 +101,7 @@ void FrameBuffer::finalize(){ } } -bool FrameBuffer::initialize(int width, int height, OnPostFn onPost, void* onPostContext) +bool FrameBuffer::initialize(int width, int height) { if (s_theFrameBuffer != NULL) { return true; @@ -110,7 +110,7 @@ bool FrameBuffer::initialize(int width, int height, OnPostFn onPost, void* onPos // // allocate space for the FrameBuffer object // - FrameBuffer *fb = new FrameBuffer(width, height, onPost, onPostContext); + FrameBuffer *fb = new FrameBuffer(width, height); if (!fb) { ERR("Failed to create fb\n"); return false; @@ -335,17 +335,6 @@ bool FrameBuffer::initialize(int width, int height, OnPostFn onPost, void* onPos 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; - } - } - - // // Cache the GL strings so we don't have to think about threading or // current-context when asked for them. // @@ -363,8 +352,7 @@ bool FrameBuffer::initialize(int width, int height, OnPostFn onPost, void* onPos return true; } -FrameBuffer::FrameBuffer(int p_width, int p_height, - OnPostFn onPost, void* onPostContext) : +FrameBuffer::FrameBuffer(int p_width, int p_height) : m_width(p_width), m_height(p_height), m_eglDisplay(EGL_NO_DISPLAY), @@ -381,8 +369,8 @@ FrameBuffer::FrameBuffer(int p_width, int p_height, m_eglContextInitialized(false), m_statsNumFrames(0), m_statsStartTime(0LL), - m_onPost(onPost), - m_onPostContext(onPostContext), + m_onPost(NULL), + m_onPostContext(NULL), m_fbImage(NULL), m_glVendor(NULL), m_glRenderer(NULL), @@ -396,6 +384,22 @@ FrameBuffer::~FrameBuffer() free(m_fbImage); } +void FrameBuffer::setPostCallback(OnPostFn onPost, void* onPostContext) +{ + android::Mutex::Autolock mutex(m_lock); + m_onPost = onPost; + m_onPostContext = onPostContext; + if (m_onPost && !m_fbImage) { + m_fbImage = (unsigned char*)malloc(4 * m_width * m_height); + if (!m_fbImage) { + ERR("out of memory, cancelling OnPost callback"); + m_onPost = NULL; + m_onPostContext = NULL; + return; + } + } +} + bool FrameBuffer::setupSubWindow(FBNativeWindowType p_window, int p_x, int p_y, int p_width, int p_height, float zRot) diff --git a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h index 89a708b..de0b71c 100644 --- a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h +++ b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h @@ -46,7 +46,7 @@ struct FrameBufferCaps class FrameBuffer { public: - static bool initialize(int width, int height, OnPostFn onPost, void* onPostContext); + static bool initialize(int width, int height); static bool setupSubWindow(FBNativeWindowType p_window, int x, int y, int width, int height, float zRot); @@ -59,6 +59,8 @@ public: int getWidth() const { return m_width; } int getHeight() const { return m_height; } + void setPostCallback(OnPostFn onPost, void* onPostContext); + void getGLStrings(const char** vendor, const char** renderer, const char** version) const { *vendor = m_glVendor; *renderer = m_glRenderer; @@ -96,7 +98,7 @@ public: } private: - FrameBuffer(int p_width, int p_height, OnPostFn onPost, void* onPostContext); + FrameBuffer(int p_width, int p_height); ~FrameBuffer(); HandleType genHandle(); bool bindSubwin_locked(); diff --git a/emulator/opengl/host/libs/libOpenglRender/render_api.cpp b/emulator/opengl/host/libs/libOpenglRender/render_api.cpp index 7d7a981..72cd9ba 100644 --- a/emulator/opengl/host/libs/libOpenglRender/render_api.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/render_api.cpp @@ -76,8 +76,7 @@ int initLibrary(void) return true; } -int initOpenGLRenderer(int width, int height, int portNum, - OnPostFn onPost, void* onPostContext) +int initOpenGLRenderer(int width, int height, int portNum) { // @@ -94,7 +93,7 @@ int 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, onPost, onPostContext); + bool inited = FrameBuffer::initialize(width, height); if (!inited) { return false; } @@ -191,6 +190,27 @@ int initOpenGLRenderer(int width, int height, int portNum, return true; } +void setPostCallback(OnPostFn onPost, void* onPostContext) +{ +#ifdef RENDER_API_USE_THREAD // should be defined for mac + FrameBuffer* fb = FrameBuffer::getFB(); + if (fb) { + fb->setPostCallback(onPost, onPostContext); + } +#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; + } +#endif +} + void getHardwareStrings(const char** vendor, const char** renderer, const char** version) { FrameBuffer* fb = FrameBuffer::getFB(); diff --git a/emulator/opengl/host/renderer/main.cpp b/emulator/opengl/host/renderer/main.cpp index ae7ace3..4549c56 100644 --- a/emulator/opengl/host/renderer/main.cpp +++ b/emulator/opengl/host/renderer/main.cpp @@ -120,7 +120,7 @@ int main(int argc, char *argv[]) // // initialize Framebuffer // - bool inited = FrameBuffer::initialize(winWidth, winHeight, NULL, NULL); + bool inited = FrameBuffer::initialize(winWidth, winHeight); if (!inited) { fprintf(stderr,"Failed to initialize Framebuffer\n"); return -1; |