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");      }  |