diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp index ef38bec6c..ae3a0fd40 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp +++ b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp @@ -458,7 +458,8 @@ HandleType FrameBuffer::createColorBuffer(int p_width, int p_height, ColorBufferPtr cb( ColorBuffer::create(p_width, p_height, p_internalFormat) ); if (cb.Ptr() != NULL) { ret = genHandle(); - m_colorbuffers[ret] = cb; + m_colorbuffers[ret].cb = cb; + m_colorbuffers[ret].refcount = 1; } return ret; } @@ -512,10 +513,28 @@ void FrameBuffer::DestroyWindowSurface(HandleType p_surface) m_windows.erase(p_surface); } -void FrameBuffer::DestroyColorBuffer(HandleType p_colorbuffer) +void FrameBuffer::openColorBuffer(HandleType p_colorbuffer) { android::Mutex::Autolock mutex(m_lock); - m_colorbuffers.erase(p_colorbuffer); + ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); + if (c == m_colorbuffers.end()) { + // bad colorbuffer handle + return; + } + (*c).second.refcount++; +} + +void FrameBuffer::closeColorBuffer(HandleType p_colorbuffer) +{ + android::Mutex::Autolock mutex(m_lock); + ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); + if (c == m_colorbuffers.end()) { + // bad colorbuffer handle + return; + } + if (--(*c).second.refcount == 0) { + m_colorbuffers.erase(c); + } } bool FrameBuffer::flushWindowSurfaceColorBuffer(HandleType p_surface) @@ -550,7 +569,7 @@ bool FrameBuffer::setWindowSurfaceColorBuffer(HandleType p_surface, return false; } - (*w).second->setColorBuffer( (*c).second ); + (*w).second->setColorBuffer( (*c).second.cb ); return true; } @@ -567,7 +586,7 @@ bool FrameBuffer::updateColorBuffer(HandleType p_colorbuffer, return false; } - (*c).second->subUpdate(x, y, width, height, format, type, pixels); + (*c).second.cb->subUpdate(x, y, width, height, format, type, pixels); return true; } @@ -582,7 +601,7 @@ bool FrameBuffer::bindColorBufferToTexture(HandleType p_colorbuffer) return false; } - return (*c).second->bindToTexture(); + return (*c).second.cb->bindToTexture(); } bool FrameBuffer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) @@ -595,7 +614,7 @@ bool FrameBuffer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) return false; } - return (*c).second->bindToRenderbuffer(); + return (*c).second.cb->bindToRenderbuffer(); } bool FrameBuffer::bindContext(HandleType p_context, @@ -776,7 +795,7 @@ bool FrameBuffer::post(HandleType p_colorbuffer, bool needLock) if (m_zRot != 0.0f) { s_gl.glClear(GL_COLOR_BUFFER_BIT); } - ret = (*c).second->post(); + ret = (*c).second.cb->post(); s_gl.glPopMatrix(); if (ret) { diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h index 472531704..b5293ffe3 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h +++ b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h @@ -26,9 +26,13 @@ #include typedef uint32_t HandleType; +struct ColorBufferRef { + ColorBufferPtr cb; + uint32_t refcount; // number of client-side references +}; typedef std::map RenderContextMap; typedef std::map WindowSurfaceMap; -typedef std::map ColorBufferMap; +typedef std::map ColorBufferMap; struct FrameBufferCaps { @@ -60,7 +64,8 @@ public: HandleType createColorBuffer(int p_width, int p_height, GLenum p_internalFormat); void DestroyRenderContext(HandleType p_context); void DestroyWindowSurface(HandleType p_surface); - void DestroyColorBuffer(HandleType p_colorbuffer); + void openColorBuffer(HandleType p_colorbuffer); + void closeColorBuffer(HandleType p_colorbuffer); bool bindContext(HandleType p_context, HandleType p_drawSurface, HandleType p_readSurface); bool setWindowSurfaceColorBuffer(HandleType p_surface, HandleType p_colorbuffer); diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp index 14c342375..6b8f8fd8d 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp +++ b/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp @@ -215,13 +215,22 @@ static uint32_t rcCreateColorBuffer(uint32_t width, return fb->createColorBuffer(width, height, internalFormat); } -static void rcDestroyColorBuffer(uint32_t colorbuffer) +static void rcOpenColorBuffer(uint32_t colorbuffer) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return; } - fb->DestroyColorBuffer( colorbuffer ); + fb->openColorBuffer( colorbuffer ); +} + +static void rcCloseColorBuffer(uint32_t colorbuffer) +{ + FrameBuffer *fb = FrameBuffer::getFB(); + if (!fb) { + return; + } + fb->closeColorBuffer( colorbuffer ); } static int rcFlushWindowColorBuffer(uint32_t windowSurface) @@ -336,7 +345,8 @@ void initRenderControlContext(renderControl_decoder_context_t *dec) dec->set_rcCreateWindowSurface(rcCreateWindowSurface); dec->set_rcDestroyWindowSurface(rcDestroyWindowSurface); dec->set_rcCreateColorBuffer(rcCreateColorBuffer); - dec->set_rcDestroyColorBuffer(rcDestroyColorBuffer); + dec->set_rcOpenColorBuffer(rcOpenColorBuffer); + dec->set_rcCloseColorBuffer(rcCloseColorBuffer); dec->set_rcSetWindowColorBuffer(rcSetWindowColorBuffer); dec->set_rcFlushWindowColorBuffer(rcFlushWindowColorBuffer); dec->set_rcMakeCurrent(rcMakeCurrent); diff --git a/tools/emulator/opengl/system/egl/egl.cpp b/tools/emulator/opengl/system/egl/egl.cpp index 93f868140..2ca3e3ba6 100644 --- a/tools/emulator/opengl/system/egl/egl.cpp +++ b/tools/emulator/opengl/system/egl/egl.cpp @@ -417,7 +417,7 @@ EGLBoolean egl_pbuffer_surface_t::rcDestroy() DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE); rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface); - rcEnc->rcDestroyColorBuffer(rcEnc, rcColorBuffer); + rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer); rcSurface = 0; return EGL_TRUE; diff --git a/tools/emulator/opengl/system/gralloc/gralloc.cpp b/tools/emulator/opengl/system/gralloc/gralloc.cpp index b27eaa3d2..bf098eba6 100644 --- a/tools/emulator/opengl/system/gralloc/gralloc.cpp +++ b/tools/emulator/opengl/system/gralloc/gralloc.cpp @@ -279,8 +279,8 @@ static int gralloc_free(alloc_device_t* dev, if (cb->hostHandle != 0) { DEFINE_AND_VALIDATE_HOST_CONNECTION; - D("Destroying host ColorBuffer 0x%x\n", cb->hostHandle); - rcEnc->rcDestroyColorBuffer(rcEnc, cb->hostHandle); + D("Closing host ColorBuffer 0x%x\n", cb->hostHandle); + rcEnc->rcCloseColorBuffer(rcEnc, cb->hostHandle); } // @@ -440,6 +440,12 @@ static int gralloc_register_buffer(gralloc_module_t const* module, return -EINVAL; } + if (cb->hostHandle != 0) { + DEFINE_AND_VALIDATE_HOST_CONNECTION; + D("Opening host ColorBuffer 0x%x\n", cb->hostHandle); + rcEnc->rcOpenColorBuffer(rcEnc, cb->hostHandle); + } + // // if the color buffer has ashmem region and it is not mapped in this // process map it now. @@ -471,6 +477,12 @@ static int gralloc_unregister_buffer(gralloc_module_t const* module, return -EINVAL; } + if (cb->hostHandle != 0) { + DEFINE_AND_VALIDATE_HOST_CONNECTION; + D("Closing host ColorBuffer 0x%x\n", cb->hostHandle); + rcEnc->rcCloseColorBuffer(rcEnc, cb->hostHandle); + } + // // unmap ashmem region if it was previously mapped in this process // (through register_buffer) diff --git a/tools/emulator/opengl/system/renderControl_enc/README b/tools/emulator/opengl/system/renderControl_enc/README index df870f6b2..2ee1a5701 100644 --- a/tools/emulator/opengl/system/renderControl_enc/README +++ b/tools/emulator/opengl/system/renderControl_enc/README @@ -76,13 +76,19 @@ uint32_t rcCreateColorBuffer(uint32_t width, uint32_t height, GLenum internalFor be specified as a render target for a window surface through rcSetWindowColorBuffer or to be displayed on the framebuffer window through rcFBPost. - The function returns a handle to the colorBuffer object. + The function returns a handle to the colorBuffer object, with an initial + reference count of 1. -void rcDestroyColorBuffer(uint32_t colorbuffer); - destroyes a colorBuffer object. +void rcOpenColorBuffer(uint32_t colorbuffer); + Adds an additional reference to the colorbuffer, typically from a + different Android process than the one which created it. + +void rcCloseColorBuffer(uint32_t colorbuffer); + Removes a reference to the colorbuffer. When the reference count drops + to zero the colorbuffer is automatically destroyed. void rcFlushWindowColorBuffer(uint32_t windowSurface, uint32_t colorBuffer); - This flushes the current window color buffer + This flushes the current window color buffer void rcSetWindowColorBuffer(uint32_t windowSurface, uint32_t colorBuffer); This set the target color buffer for a windowSurface, when set the diff --git a/tools/emulator/opengl/system/renderControl_enc/renderControl.in b/tools/emulator/opengl/system/renderControl_enc/renderControl.in index 18ce8a418..8281fd945 100644 --- a/tools/emulator/opengl/system/renderControl_enc/renderControl.in +++ b/tools/emulator/opengl/system/renderControl_enc/renderControl.in @@ -11,7 +11,8 @@ GL_ENTRY(void, rcDestroyContext, uint32_t context) GL_ENTRY(uint32_t, rcCreateWindowSurface, uint32_t config, uint32_t width, uint32_t height) GL_ENTRY(void, rcDestroyWindowSurface, uint32_t windowSurface) GL_ENTRY(uint32_t, rcCreateColorBuffer, uint32_t width, uint32_t height, GLenum internalFormat) -GL_ENTRY(void, rcDestroyColorBuffer, uint32_t colorbuffer) +GL_ENTRY(void, rcOpenColorBuffer, uint32_t colorbuffer) +GL_ENTRY(void, rcCloseColorBuffer, uint32_t colorbuffer) GL_ENTRY(void, rcSetWindowColorBuffer, uint32_t windowSurface, uint32_t colorBuffer) GL_ENTRY(int, rcFlushWindowColorBuffer, uint32_t windowSurface) GL_ENTRY(EGLint, rcMakeCurrent, uint32_t context, uint32_t drawSurf, uint32_t readSurf)