diff options
| -rw-r--r-- | libs/hwui/surfacetexture/ImageConsumer.cpp | 70 | ||||
| -rw-r--r-- | libs/hwui/surfacetexture/ImageConsumer.h | 27 | ||||
| -rw-r--r-- | libs/hwui/surfacetexture/SurfaceTexture.cpp | 7 |
3 files changed, 84 insertions, 20 deletions
diff --git a/libs/hwui/surfacetexture/ImageConsumer.cpp b/libs/hwui/surfacetexture/ImageConsumer.cpp index 624c29058014..077a8f73b0da 100644 --- a/libs/hwui/surfacetexture/ImageConsumer.cpp +++ b/libs/hwui/surfacetexture/ImageConsumer.cpp @@ -23,6 +23,7 @@ #include "renderthread/RenderThread.h" #include "renderthread/VulkanManager.h" #include "utils/Color.h" +#include <GrAHardwareBufferUtils.h> // Macro for including the SurfaceTexture name in log messages #define IMG_LOGE(x, ...) ALOGE("[%s] " x, st.mName.string(), ##__VA_ARGS__) @@ -30,31 +31,67 @@ namespace android { void ImageConsumer::onFreeBufferLocked(int slotIndex) { - mImageSlots[slotIndex].mImage.reset(); + mImageSlots[slotIndex].clear(); } void ImageConsumer::onAcquireBufferLocked(BufferItem* item) { // If item->mGraphicBuffer is not null, this buffer has not been acquired // before, so any prior SkImage is created with a stale buffer. This resets the stale SkImage. if (item->mGraphicBuffer != nullptr) { - mImageSlots[item->mSlot].mImage.reset(); + mImageSlots[item->mSlot].clear(); } } void ImageConsumer::onReleaseBufferLocked(int buf) { - mImageSlots[buf].mEglFence = EGL_NO_SYNC_KHR; + mImageSlots[buf].eglFence() = EGL_NO_SYNC_KHR; } void ImageConsumer::ImageSlot::createIfNeeded(sp<GraphicBuffer> graphicBuffer, - android_dataspace dataspace, bool forceCreate) { + android_dataspace dataspace, bool forceCreate, + GrContext* context) { if (!mImage.get() || dataspace != mDataspace || forceCreate) { - mImage = graphicBuffer.get() - ? SkImage::MakeFromAHardwareBuffer( - reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()), - kPremul_SkAlphaType, - uirenderer::DataSpaceToColorSpace(dataspace)) - : nullptr; + if (!graphicBuffer.get()) { + clear(); + return; + } + + if (!mBackendTexture.isValid()) { + clear(); + bool createProtectedImage = + 0 != (graphicBuffer->getUsage() & GraphicBuffer::USAGE_PROTECTED); + GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat( + context, + reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()), + graphicBuffer->getPixelFormat(), + false); + mBackendTexture = GrAHardwareBufferUtils::MakeBackendTexture( + context, + reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()), + graphicBuffer->getWidth(), + graphicBuffer->getHeight(), + &mDeleteProc, + &mDeleteCtx, + createProtectedImage, + backendFormat, + false); + } mDataspace = dataspace; + SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat( + graphicBuffer->getPixelFormat()); + mImage = SkImage::MakeFromTexture(context, + mBackendTexture, + kTopLeft_GrSurfaceOrigin, + colorType, + kPremul_SkAlphaType, + uirenderer::DataSpaceToColorSpace(dataspace)); + } +} + +void ImageConsumer::ImageSlot::clear() { + mImage.reset(); + if (mBackendTexture.isValid()) { + mDeleteProc(mDeleteCtx); + mBackendTexture = {}; } } @@ -71,8 +108,8 @@ sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st, if (slot != BufferItem::INVALID_BUFFER_SLOT) { *queueEmpty = true; mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, - st.mCurrentDataSpace, false); - return mImageSlots[slot].mImage; + st.mCurrentDataSpace, false, renderState.getRenderThread().getGrContext()); + return mImageSlots[slot].getImage(); } } return nullptr; @@ -104,7 +141,7 @@ sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st, uirenderer::RenderPipelineType::SkiaGL) { auto& eglManager = renderState.getRenderThread().eglManager(); display = eglManager.eglDisplay(); - err = eglManager.createReleaseFence(st.mUseFenceSync, &mImageSlots[slot].mEglFence, + err = eglManager.createReleaseFence(st.mUseFenceSync, &mImageSlots[slot].eglFence(), releaseFence); } else { err = renderState.getRenderThread().vulkanManager().createReleaseFence(releaseFence); @@ -129,7 +166,7 @@ sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st, // Finally release the old buffer. status_t status = st.releaseBufferLocked( st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, display, - mImageSlots[st.mCurrentTexture].mEglFence); + mImageSlots[st.mCurrentTexture].eglFence()); if (status < NO_ERROR) { IMG_LOGE("dequeueImage: failed to release buffer: %s (%d)", strerror(-status), status); err = status; @@ -150,8 +187,9 @@ sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st, st.computeCurrentTransformMatrixLocked(); *queueEmpty = false; - mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, item.mDataSpace, true); - return mImageSlots[slot].mImage; + mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, item.mDataSpace, true, + renderState.getRenderThread().getGrContext()); + return mImageSlots[slot].getImage(); } } /* namespace android */ diff --git a/libs/hwui/surfacetexture/ImageConsumer.h b/libs/hwui/surfacetexture/ImageConsumer.h index 5c4190397bc4..eee0a0ac3512 100644 --- a/libs/hwui/surfacetexture/ImageConsumer.h +++ b/libs/hwui/surfacetexture/ImageConsumer.h @@ -25,6 +25,12 @@ #include <cutils/compiler.h> #include <gui/BufferItem.h> #include <system/graphics.h> +#include <GrBackendSurface.h> + +namespace GrAHardwareBufferUtils { +typedef void* DeleteImageCtx; +typedef void (*DeleteImageProc)(DeleteImageCtx); +} namespace android { @@ -67,9 +73,21 @@ private: * ImageSlot contains the information and object references that * ImageConsumer maintains about a BufferQueue buffer slot. */ - struct ImageSlot { + class ImageSlot { + public: ImageSlot() : mDataspace(HAL_DATASPACE_UNKNOWN), mEglFence(EGL_NO_SYNC_KHR) {} + ~ImageSlot() { clear(); } + + void createIfNeeded(sp<GraphicBuffer> graphicBuffer, android_dataspace dataspace, + bool forceCreate, GrContext* context); + void clear(); + + inline EGLSyncKHR& eglFence() { return mEglFence; } + + inline sk_sp<SkImage> getImage() { return mImage; } + + private: // mImage is the SkImage created from mGraphicBuffer. sk_sp<SkImage> mImage; @@ -82,8 +100,11 @@ private: */ EGLSyncKHR mEglFence; - void createIfNeeded(sp<GraphicBuffer> graphicBuffer, android_dataspace dataspace, - bool forceCreate); + GrBackendTexture mBackendTexture; + + GrAHardwareBufferUtils::DeleteImageProc mDeleteProc; + + GrAHardwareBufferUtils::DeleteImageCtx mDeleteCtx; }; /** diff --git a/libs/hwui/surfacetexture/SurfaceTexture.cpp b/libs/hwui/surfacetexture/SurfaceTexture.cpp index da094442684d..a27db6591d6a 100644 --- a/libs/hwui/surfacetexture/SurfaceTexture.cpp +++ b/libs/hwui/surfacetexture/SurfaceTexture.cpp @@ -23,6 +23,7 @@ #include "Matrix.h" #include "SurfaceTexture.h" +#include "ImageConsumer.h" namespace android { @@ -150,7 +151,7 @@ status_t SurfaceTexture::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicB // buffer has reallocated the original buffer slot after this buffer // was acquired. status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer, display, eglFence); - // We could be releasing an EGL buffer, even if not currently attached to a GL context. + // We could be releasing an EGL/Vulkan buffer, even if not currently attached to a GL context. mImageConsumer.onReleaseBufferLocked(buf); mEGLConsumer.onReleaseBufferLocked(buf); return err; @@ -235,6 +236,10 @@ void SurfaceTexture::detachFromView() { if (mOpMode == OpMode::attachedToView) { mOpMode = OpMode::detached; + // Free all EglImage and VkImage before the context is destroyed. + for (int i=0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) { + mImageConsumer.onFreeBufferLocked(i); + } } else { SFT_LOGE("detachFromView: not attached to View"); } |