EmuGL: refcount ColorBuffers on the host
The gralloc API assumes system-wide reference counting of gralloc buffers. The host-GL accelerated gralloc maps buffers to host-side ColorBuffer objects, but was destroying them unconditionally in gralloc_free(), ignoring any additional references from gralloc_register_buffer(). This affected the SurfaceTexture gralloc buffers used by the Browser/WebView. For some reason these buffers are actually allocated by SurfaceFlinger and passed back to the WebView through Binder. But since SurfaceFlinger doesn't actually need the buffer for anything, sometime after the WebView has called gralloc_register_buffer() SurfaceFlinger calls gralloc_free() on it. This caused the host ColorBuffer to be destroyed long before the WebView is done using it. Change-Id: I33dbee887a48a6907041cf19e9f38a1f6c983eff
This commit is contained in:
@@ -458,7 +458,8 @@ HandleType FrameBuffer::createColorBuffer(int p_width, int p_height,
|
|||||||
ColorBufferPtr cb( ColorBuffer::create(p_width, p_height, p_internalFormat) );
|
ColorBufferPtr cb( ColorBuffer::create(p_width, p_height, p_internalFormat) );
|
||||||
if (cb.Ptr() != NULL) {
|
if (cb.Ptr() != NULL) {
|
||||||
ret = genHandle();
|
ret = genHandle();
|
||||||
m_colorbuffers[ret] = cb;
|
m_colorbuffers[ret].cb = cb;
|
||||||
|
m_colorbuffers[ret].refcount = 1;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -512,10 +513,28 @@ void FrameBuffer::DestroyWindowSurface(HandleType p_surface)
|
|||||||
m_windows.erase(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);
|
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)
|
bool FrameBuffer::flushWindowSurfaceColorBuffer(HandleType p_surface)
|
||||||
@@ -550,7 +569,7 @@ bool FrameBuffer::setWindowSurfaceColorBuffer(HandleType p_surface,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*w).second->setColorBuffer( (*c).second );
|
(*w).second->setColorBuffer( (*c).second.cb );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -567,7 +586,7 @@ bool FrameBuffer::updateColorBuffer(HandleType p_colorbuffer,
|
|||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -582,7 +601,7 @@ bool FrameBuffer::bindColorBufferToTexture(HandleType p_colorbuffer)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (*c).second->bindToTexture();
|
return (*c).second.cb->bindToTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FrameBuffer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer)
|
bool FrameBuffer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer)
|
||||||
@@ -595,7 +614,7 @@ bool FrameBuffer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (*c).second->bindToRenderbuffer();
|
return (*c).second.cb->bindToRenderbuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FrameBuffer::bindContext(HandleType p_context,
|
bool FrameBuffer::bindContext(HandleType p_context,
|
||||||
@@ -776,7 +795,7 @@ bool FrameBuffer::post(HandleType p_colorbuffer, bool needLock)
|
|||||||
if (m_zRot != 0.0f) {
|
if (m_zRot != 0.0f) {
|
||||||
s_gl.glClear(GL_COLOR_BUFFER_BIT);
|
s_gl.glClear(GL_COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
ret = (*c).second->post();
|
ret = (*c).second.cb->post();
|
||||||
s_gl.glPopMatrix();
|
s_gl.glPopMatrix();
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|||||||
@@ -26,9 +26,13 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef uint32_t HandleType;
|
typedef uint32_t HandleType;
|
||||||
|
struct ColorBufferRef {
|
||||||
|
ColorBufferPtr cb;
|
||||||
|
uint32_t refcount; // number of client-side references
|
||||||
|
};
|
||||||
typedef std::map<HandleType, RenderContextPtr> RenderContextMap;
|
typedef std::map<HandleType, RenderContextPtr> RenderContextMap;
|
||||||
typedef std::map<HandleType, WindowSurfacePtr> WindowSurfaceMap;
|
typedef std::map<HandleType, WindowSurfacePtr> WindowSurfaceMap;
|
||||||
typedef std::map<HandleType, ColorBufferPtr> ColorBufferMap;
|
typedef std::map<HandleType, ColorBufferRef> ColorBufferMap;
|
||||||
|
|
||||||
struct FrameBufferCaps
|
struct FrameBufferCaps
|
||||||
{
|
{
|
||||||
@@ -60,7 +64,8 @@ public:
|
|||||||
HandleType createColorBuffer(int p_width, int p_height, GLenum p_internalFormat);
|
HandleType createColorBuffer(int p_width, int p_height, GLenum p_internalFormat);
|
||||||
void DestroyRenderContext(HandleType p_context);
|
void DestroyRenderContext(HandleType p_context);
|
||||||
void DestroyWindowSurface(HandleType p_surface);
|
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 bindContext(HandleType p_context, HandleType p_drawSurface, HandleType p_readSurface);
|
||||||
bool setWindowSurfaceColorBuffer(HandleType p_surface, HandleType p_colorbuffer);
|
bool setWindowSurfaceColorBuffer(HandleType p_surface, HandleType p_colorbuffer);
|
||||||
|
|||||||
@@ -215,13 +215,22 @@ static uint32_t rcCreateColorBuffer(uint32_t width,
|
|||||||
return fb->createColorBuffer(width, height, internalFormat);
|
return fb->createColorBuffer(width, height, internalFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rcDestroyColorBuffer(uint32_t colorbuffer)
|
static void rcOpenColorBuffer(uint32_t colorbuffer)
|
||||||
{
|
{
|
||||||
FrameBuffer *fb = FrameBuffer::getFB();
|
FrameBuffer *fb = FrameBuffer::getFB();
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return;
|
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)
|
static int rcFlushWindowColorBuffer(uint32_t windowSurface)
|
||||||
@@ -336,7 +345,8 @@ void initRenderControlContext(renderControl_decoder_context_t *dec)
|
|||||||
dec->set_rcCreateWindowSurface(rcCreateWindowSurface);
|
dec->set_rcCreateWindowSurface(rcCreateWindowSurface);
|
||||||
dec->set_rcDestroyWindowSurface(rcDestroyWindowSurface);
|
dec->set_rcDestroyWindowSurface(rcDestroyWindowSurface);
|
||||||
dec->set_rcCreateColorBuffer(rcCreateColorBuffer);
|
dec->set_rcCreateColorBuffer(rcCreateColorBuffer);
|
||||||
dec->set_rcDestroyColorBuffer(rcDestroyColorBuffer);
|
dec->set_rcOpenColorBuffer(rcOpenColorBuffer);
|
||||||
|
dec->set_rcCloseColorBuffer(rcCloseColorBuffer);
|
||||||
dec->set_rcSetWindowColorBuffer(rcSetWindowColorBuffer);
|
dec->set_rcSetWindowColorBuffer(rcSetWindowColorBuffer);
|
||||||
dec->set_rcFlushWindowColorBuffer(rcFlushWindowColorBuffer);
|
dec->set_rcFlushWindowColorBuffer(rcFlushWindowColorBuffer);
|
||||||
dec->set_rcMakeCurrent(rcMakeCurrent);
|
dec->set_rcMakeCurrent(rcMakeCurrent);
|
||||||
|
|||||||
@@ -417,7 +417,7 @@ EGLBoolean egl_pbuffer_surface_t::rcDestroy()
|
|||||||
|
|
||||||
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
|
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
|
||||||
rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
|
rcEnc->rcDestroyWindowSurface(rcEnc, rcSurface);
|
||||||
rcEnc->rcDestroyColorBuffer(rcEnc, rcColorBuffer);
|
rcEnc->rcCloseColorBuffer(rcEnc, rcColorBuffer);
|
||||||
rcSurface = 0;
|
rcSurface = 0;
|
||||||
|
|
||||||
return EGL_TRUE;
|
return EGL_TRUE;
|
||||||
|
|||||||
@@ -279,8 +279,8 @@ static int gralloc_free(alloc_device_t* dev,
|
|||||||
|
|
||||||
if (cb->hostHandle != 0) {
|
if (cb->hostHandle != 0) {
|
||||||
DEFINE_AND_VALIDATE_HOST_CONNECTION;
|
DEFINE_AND_VALIDATE_HOST_CONNECTION;
|
||||||
D("Destroying host ColorBuffer 0x%x\n", cb->hostHandle);
|
D("Closing host ColorBuffer 0x%x\n", cb->hostHandle);
|
||||||
rcEnc->rcDestroyColorBuffer(rcEnc, cb->hostHandle);
|
rcEnc->rcCloseColorBuffer(rcEnc, cb->hostHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -440,6 +440,12 @@ static int gralloc_register_buffer(gralloc_module_t const* module,
|
|||||||
return -EINVAL;
|
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
|
// if the color buffer has ashmem region and it is not mapped in this
|
||||||
// process map it now.
|
// process map it now.
|
||||||
@@ -471,6 +477,12 @@ static int gralloc_unregister_buffer(gralloc_module_t const* module,
|
|||||||
return -EINVAL;
|
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
|
// unmap ashmem region if it was previously mapped in this process
|
||||||
// (through register_buffer)
|
// (through register_buffer)
|
||||||
|
|||||||
@@ -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
|
be specified as a render target for a window surface through
|
||||||
rcSetWindowColorBuffer or to be displayed on the framebuffer window
|
rcSetWindowColorBuffer or to be displayed on the framebuffer window
|
||||||
through rcFBPost.
|
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);
|
void rcOpenColorBuffer(uint32_t colorbuffer);
|
||||||
destroyes a colorBuffer object.
|
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);
|
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);
|
void rcSetWindowColorBuffer(uint32_t windowSurface, uint32_t colorBuffer);
|
||||||
This set the target color buffer for a windowSurface, when set the
|
This set the target color buffer for a windowSurface, when set the
|
||||||
|
|||||||
@@ -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(uint32_t, rcCreateWindowSurface, uint32_t config, uint32_t width, uint32_t height)
|
||||||
GL_ENTRY(void, rcDestroyWindowSurface, uint32_t windowSurface)
|
GL_ENTRY(void, rcDestroyWindowSurface, uint32_t windowSurface)
|
||||||
GL_ENTRY(uint32_t, rcCreateColorBuffer, uint32_t width, uint32_t height, GLenum internalFormat)
|
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(void, rcSetWindowColorBuffer, uint32_t windowSurface, uint32_t colorBuffer)
|
||||||
GL_ENTRY(int, rcFlushWindowColorBuffer, uint32_t windowSurface)
|
GL_ENTRY(int, rcFlushWindowColorBuffer, uint32_t windowSurface)
|
||||||
GL_ENTRY(EGLint, rcMakeCurrent, uint32_t context, uint32_t drawSurf, uint32_t readSurf)
|
GL_ENTRY(EGLint, rcMakeCurrent, uint32_t context, uint32_t drawSurf, uint32_t readSurf)
|
||||||
|
|||||||
Reference in New Issue
Block a user