Merge "In Vk DeferredLayerUpdater make sure we releause buffers to foreign queue." into sc-dev
diff --git a/libs/hwui/AutoBackendTextureRelease.cpp b/libs/hwui/AutoBackendTextureRelease.cpp
index 33264d5..ef5eacb 100644
--- a/libs/hwui/AutoBackendTextureRelease.cpp
+++ b/libs/hwui/AutoBackendTextureRelease.cpp
@@ -89,5 +89,27 @@
     }
 }
 
+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 06f51fc..c9bb767 100644
--- a/libs/hwui/AutoBackendTextureRelease.h
+++ b/libs/hwui/AutoBackendTextureRelease.h
@@ -49,6 +49,8 @@
 
     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 6589dbd..8d112d1 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -76,6 +76,9 @@
 
     mLayer = nullptr;
 
+    for (auto& [index, slot] : mImageSlots) {
+        slot.clear(mRenderState.getRenderThread().getGrContext());
+    }
     mImageSlots.clear();
 }
 
@@ -89,31 +92,39 @@
     }
 }
 
-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 @@
             // 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 @@
     if (!mTextureRelease || !mTextureRelease->getImage().get() || dataspace != mDataspace ||
         forceCreate || mBuffer != buffer) {
         if (buffer != mBuffer) {
-            clear();
+            clear(context);
         }
 
         if (!buffer) {
@@ -213,8 +225,11 @@
     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 @@
     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 6731e9c..8f79c4e 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 @@
      */
     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 @@
         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 @@
     SkMatrix* mTransform;
     bool mGLContextAttached;
     bool mUpdateTexImage;
+    int mCurrentSlot = -1;
 
     Layer* mLayer;
 };