In Vk DeferredLayerUpdater make sure we releause buffers to foreign queue.

For Vulkan we need to make sure that when we draw AHBs we must
transition them to and from the foreign queue so that the producer is
able to write new data to them and we are able to see the new writes.

Test: Manual running of Lens app
Bug: 178773035
Change-Id: I807709d2b671bf5a01a82237f3b5838734f0d978
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;
 };