From 5c3d243fcca6d0678bcbb0461bbbe0b63f35212c Mon Sep 17 00:00:00 2001 From: Eric Penner Date: Fri, 11 Jul 2014 19:08:04 -0700 Subject: GLProducer: Reference count images rather than buffers. In most cases, EGLImages can be created one-to-one with graphic buffers in slots, but that was difficult due to some special cases: - ReleaseTexImage binds a custom 'unslotted' debug image. - When all slots are freed, we still need to hang on to one. These cases were handled by keeping an additional reference to the 'current' buffer (mCurrentTextureBuf), but we would create new images since we can't reference count them in the same way. This patch uses the same semantics, except that it reference counts the image (an EglImage wrapper class) rather than just buffer. The wrapper class also detects the cases when we need a new EGLImage, and only creates them in those rare cases. Change-Id: I2915761dbe49d2a9bda1f59e60f857543634636b --- include/gui/GLConsumer.h | 83 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h index 1aacee9..37530db 100644 --- a/include/gui/GLConsumer.h +++ b/include/gui/GLConsumer.h @@ -231,7 +231,7 @@ public: protected: // abandonLocked overrides the ConsumerBase method to clear - // mCurrentTextureBuf in addition to the ConsumerBase behavior. + // mCurrentTextureImage in addition to the ConsumerBase behavior. virtual void abandonLocked(); // dumpLocked overrides the ConsumerBase method to dump GLConsumer- @@ -262,7 +262,7 @@ protected: status_t updateAndReleaseLocked(const BufferQueue::BufferItem& item); // Binds mTexName and the current buffer to mTexTarget. Uses - // mCurrentTexture if it's set, mCurrentTextureBuf if not. If the + // mCurrentTexture if it's set, mCurrentTextureImage if not. If the // bind succeeds, this calls doGLFenceWait. status_t bindTextureImageLocked(); @@ -275,11 +275,57 @@ protected: status_t checkAndUpdateEglStateLocked(bool contextCheck = false); private: - // createImage creates a new EGLImage from a GraphicBuffer. - EGLImageKHR createImage(EGLDisplay dpy, - const sp& graphicBuffer, const Rect& crop); + // EglImage is a utility class for tracking and creating EGLImageKHRs. There + // is primarily just one image per slot, but there is also special cases: + // - For releaseTexImage, we use a debug image (mReleasedTexImage) + // - After freeBuffer, we must still keep the current image/buffer + // Reference counting EGLImages lets us handle all these cases easily while + // also only creating new EGLImages from buffers when required. + class EglImage : public LightRefBase { + public: + EglImage(sp graphicBuffer); + + // createIfNeeded creates an EGLImage if required (we haven't created + // one yet, or the EGLDisplay or crop-rect has changed). + status_t createIfNeeded(EGLDisplay display, const Rect& cropRect); + + // This calls glEGLImageTargetTexture2DOES to bind the image to the + // texture in the specified texture target. + void bindToTextureTarget(uint32_t texTarget); + + const sp& graphicBuffer() { return mGraphicBuffer; } + const native_handle* graphicBufferHandle() { + return mGraphicBuffer == NULL ? NULL : mGraphicBuffer->handle; + } + + private: + // Only allow instantiation using ref counting. + friend class LightRefBase; + virtual ~EglImage(); + + // createImage creates a new EGLImage from a GraphicBuffer. + EGLImageKHR createImage(EGLDisplay dpy, + const sp& graphicBuffer, const Rect& crop); + + // Disallow copying + EglImage(const EglImage& rhs); + void operator = (const EglImage& rhs); + + // mGraphicBuffer is the buffer that was used to create this image. + sp mGraphicBuffer; + + // mEglImage is the EGLImage created from mGraphicBuffer. + EGLImageKHR mEglImage; + + // mEGLDisplay is the EGLDisplay that was used to create mEglImage. + EGLDisplay mEglDisplay; - // freeBufferLocked frees up the given buffer slot. If the slot has been + // mCropRect is the crop rectangle passed to EGL when mEglImage + // was created. + Rect mCropRect; + }; + + // freeBufferLocked frees up the given buffer slot. If the slot has been // initialized this will release the reference to the GraphicBuffer in that // slot and destroy the EGLImage in that slot. Otherwise it has no effect. // @@ -289,7 +335,7 @@ private: // computeCurrentTransformMatrixLocked computes the transform matrix for the // current texture. It uses mCurrentTransform and the current GraphicBuffer // to compute this matrix and stores it in mCurrentTransformMatrix. - // mCurrentTextureBuf must not be NULL. + // mCurrentTextureImage must not be NULL. void computeCurrentTransformMatrixLocked(); // doGLFenceWaitLocked inserts a wait command into the OpenGL ES command @@ -303,13 +349,6 @@ private: // before the outstanding accesses have completed. status_t syncForReleaseLocked(EGLDisplay dpy); - // Normally, when we bind a buffer to a texture target, we bind a buffer - // that is referenced by an entry in mEglSlots. In some situations we - // have a buffer in mCurrentTextureBuf, but no corresponding entry for - // it in our slot array. bindUnslottedBuffer handles that situation by - // binding the buffer without touching the EglSlots. - status_t bindUnslottedBufferLocked(EGLDisplay dpy); - // returns a graphic buffer used when the texture image has been released static sp getDebugTexImageBuffer(); @@ -319,10 +358,10 @@ private: // consume buffers as hardware textures. static const uint32_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE; - // mCurrentTextureBuf is the graphic buffer of the current texture. It's + // mCurrentTextureImage is the EglImage/buffer of the current texture. It's // possible that this buffer is not associated with any buffer slot, so we // must track it separately in order to support the getCurrentBuffer method. - sp mCurrentTextureBuf; + sp mCurrentTextureImage; // mCurrentCrop is the crop rectangle that applies to the current texture. // It gets set each time updateTexImage is called. @@ -382,17 +421,10 @@ private: // EGLSlot contains the information and object references that // GLConsumer maintains about a BufferQueue buffer slot. struct EglSlot { - EglSlot() - : mEglImage(EGL_NO_IMAGE_KHR), - mEglFence(EGL_NO_SYNC_KHR) { - } + EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {} // mEglImage is the EGLImage created from mGraphicBuffer. - EGLImageKHR mEglImage; - - // mCropRect is the crop rectangle passed to EGL when mEglImage was - // created. - Rect mCropRect; + sp mEglImage; // mFence is the EGL sync object that must signal before the buffer // associated with this buffer slot may be dequeued. It is initialized @@ -444,6 +476,7 @@ private: // mReleasedTexImageBuffer is a dummy buffer used when in single buffer // mode and releaseTexImage() has been called static sp sReleasedTexImageBuffer; + sp mReleasedTexImage; }; // ---------------------------------------------------------------------------- -- cgit v1.1