diff options
-rw-r--r-- | libs/hwui/AutoBackendTextureRelease.cpp | 22 | ||||
-rw-r--r-- | libs/hwui/AutoBackendTextureRelease.h | 2 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.cpp | 50 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.h | 17 |
4 files changed, 74 insertions, 17 deletions
diff --git a/libs/hwui/AutoBackendTextureRelease.cpp b/libs/hwui/AutoBackendTextureRelease.cpp index 33264d5d5c86..ef5eacbdb4ad 100644 --- a/libs/hwui/AutoBackendTextureRelease.cpp +++ b/libs/hwui/AutoBackendTextureRelease.cpp @@ -89,5 +89,27 @@ void AutoBackendTextureRelease::newBufferContent(GrDirectContext* context) { } } +void AutoBackendTextureRelease::releaseQueueOwnership(GrDirectContext* context) { + if (!context) { + return; + } + + LOG_ALWAYS_FATAL_IF(Properties::getRenderPipelineType() != RenderPipelineType::SkiaVulkan); + if (mBackendTexture.isValid()) { + // Passing in VK_IMAGE_LAYOUT_UNDEFINED means we keep the old layout. + GrBackendSurfaceMutableState newState(VK_IMAGE_LAYOUT_UNDEFINED, + VK_QUEUE_FAMILY_FOREIGN_EXT); + + // The unref for this ref happens in the releaseProc passed into setBackendTextureState. The + // releaseProc callback will be made when the work to set the new state has finished on the + // gpu. + ref(); + // Note that we don't have an explicit call to set the backend texture back onto the + // graphics queue when we use the VkImage again. Internally, Skia will notice that the image + // is not on the graphics queue and will do the transition automatically. + context->setBackendTextureState(mBackendTexture, newState, nullptr, releaseProc, this); + } +} + } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/AutoBackendTextureRelease.h b/libs/hwui/AutoBackendTextureRelease.h index 06f51fcd1105..c9bb767a3185 100644 --- a/libs/hwui/AutoBackendTextureRelease.h +++ b/libs/hwui/AutoBackendTextureRelease.h @@ -49,6 +49,8 @@ public: void newBufferContent(GrDirectContext* context); + void releaseQueueOwnership(GrDirectContext* context); + private: // The only way to invoke dtor is with unref, when mUsageCount is 0. ~AutoBackendTextureRelease() {} diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index 6589dbd50cf7..8d112d1c64bf 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -76,6 +76,9 @@ void DeferredLayerUpdater::destroyLayer() { mLayer = nullptr; + for (auto& [index, slot] : mImageSlots) { + slot.clear(mRenderState.getRenderThread().getGrContext()); + } mImageSlots.clear(); } @@ -89,31 +92,39 @@ void DeferredLayerUpdater::setPaint(const SkPaint* paint) { } } -static status_t createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence, EGLDisplay* display, - int* releaseFence, void* handle) { +status_t DeferredLayerUpdater::createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence, + EGLDisplay* display, int* releaseFence, + void* handle) { *display = EGL_NO_DISPLAY; - RenderState* renderState = (RenderState*)handle; + DeferredLayerUpdater* dlu = (DeferredLayerUpdater*)handle; + RenderState& renderState = dlu->mRenderState; status_t err; if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) { - EglManager& eglManager = renderState->getRenderThread().eglManager(); + EglManager& eglManager = renderState.getRenderThread().eglManager(); *display = eglManager.eglDisplay(); err = eglManager.createReleaseFence(useFenceSync, eglFence, releaseFence); } else { - err = renderState->getRenderThread().vulkanManager().createReleaseFence( - releaseFence, renderState->getRenderThread().getGrContext()); + int previousSlot = dlu->mCurrentSlot; + if (previousSlot != -1) { + dlu->mImageSlots[previousSlot].releaseQueueOwnership( + renderState.getRenderThread().getGrContext()); + } + err = renderState.getRenderThread().vulkanManager().createReleaseFence( + releaseFence, renderState.getRenderThread().getGrContext()); } return err; } -static status_t fenceWait(int fence, void* handle) { +status_t DeferredLayerUpdater::fenceWait(int fence, void* handle) { // Wait on the producer fence for the buffer to be ready. status_t err; - RenderState* renderState = (RenderState*)handle; + DeferredLayerUpdater* dlu = (DeferredLayerUpdater*)handle; + RenderState& renderState = dlu->mRenderState; if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) { - err = renderState->getRenderThread().eglManager().fenceWait(fence); + err = renderState.getRenderThread().eglManager().fenceWait(fence); } else { - err = renderState->getRenderThread().vulkanManager().fenceWait( - fence, renderState->getRenderThread().getGrContext()); + err = renderState.getRenderThread().vulkanManager().fenceWait( + fence, renderState.getRenderThread().getGrContext()); } return err; } @@ -143,9 +154,10 @@ void DeferredLayerUpdater::apply() { // cannot tell which mode it is in. AHardwareBuffer* hardwareBuffer = ASurfaceTexture_dequeueBuffer( mSurfaceTexture.get(), &slot, &dataspace, transformMatrix, &newContent, - createReleaseFence, fenceWait, &mRenderState); + createReleaseFence, fenceWait, this); if (hardwareBuffer) { + mCurrentSlot = slot; sk_sp<SkImage> layerImage = mImageSlots[slot].createIfNeeded( hardwareBuffer, dataspace, newContent, mRenderState.getRenderThread().getGrContext()); @@ -193,7 +205,7 @@ sk_sp<SkImage> DeferredLayerUpdater::ImageSlot::createIfNeeded(AHardwareBuffer* if (!mTextureRelease || !mTextureRelease->getImage().get() || dataspace != mDataspace || forceCreate || mBuffer != buffer) { if (buffer != mBuffer) { - clear(); + clear(context); } if (!buffer) { @@ -213,8 +225,11 @@ sk_sp<SkImage> DeferredLayerUpdater::ImageSlot::createIfNeeded(AHardwareBuffer* return mTextureRelease ? mTextureRelease->getImage() : nullptr; } -void DeferredLayerUpdater::ImageSlot::clear() { +void DeferredLayerUpdater::ImageSlot::clear(GrDirectContext* context) { if (mTextureRelease) { + if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { + this->releaseQueueOwnership(context); + } // The following unref counteracts the initial mUsageCount of 1, set by default initializer. mTextureRelease->unref(true); mTextureRelease = nullptr; @@ -223,5 +238,12 @@ void DeferredLayerUpdater::ImageSlot::clear() { mBuffer = nullptr; } +void DeferredLayerUpdater::ImageSlot::releaseQueueOwnership(GrDirectContext* context) { + LOG_ALWAYS_FATAL_IF(Properties::getRenderPipelineType() != RenderPipelineType::SkiaVulkan); + if (mTextureRelease) { + mTextureRelease->releaseQueueOwnership(context); + } +} + } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h index 6731e9c428d6..8f79c4ec97b8 100644 --- a/libs/hwui/DeferredLayerUpdater.h +++ b/libs/hwui/DeferredLayerUpdater.h @@ -20,9 +20,12 @@ #include <SkImage.h> #include <SkMatrix.h> #include <android/hardware_buffer.h> -#include <cutils/compiler.h> #include <android/surface_texture.h> +#include <cutils/compiler.h> +#include <utils/Errors.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> #include <map> #include <memory> @@ -103,13 +106,16 @@ private: */ class ImageSlot { public: - ~ImageSlot() { clear(); } + ~ImageSlot() {} sk_sp<SkImage> createIfNeeded(AHardwareBuffer* buffer, android_dataspace dataspace, bool forceCreate, GrDirectContext* context); + void releaseQueueOwnership(GrDirectContext* context); + + void clear(GrDirectContext* context); + private: - void clear(); // the dataspace associated with the current image android_dataspace mDataspace = HAL_DATASPACE_UNKNOWN; @@ -123,6 +129,10 @@ private: AutoBackendTextureRelease* mTextureRelease = nullptr; }; + static status_t createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence, EGLDisplay* display, + int* releaseFence, void* handle); + static status_t fenceWait(int fence, void* handle); + /** * DeferredLayerUpdater stores the SkImages that have been allocated by the BufferQueue * for each buffer slot. @@ -142,6 +152,7 @@ private: SkMatrix* mTransform; bool mGLContextAttached; bool mUpdateTexImage; + int mCurrentSlot = -1; Layer* mLayer; }; |