Decouple SurfaceTexture from HWUI

Remove all Skia and HWUI types from SurfaceTexture
implementation.
Move SurfaceTexture to libgui (ag/9578265).
Define private C++ API for SurfaceTexture, which is consumed
by DeferredLayerUpdater.
Move AutoBackendTextureRelease/Skia code from SurfaceTexture
to HWUI.

Test: pass CtsUiRenderingTestCases and CtsViewTestCases
Bug: 136263580
Change-Id: I3f971bb490f64a3ac0b2a66a89ba935bf7f08213
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index f300703..d6b516f 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -18,8 +18,15 @@
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
+#include "AutoBackendTextureRelease.h"
+#include "Matrix.h"
+#include "Properties.h"
 #include "renderstate/RenderState.h"
-#include "utils/PaintUtils.h"
+#include "renderthread/EglManager.h"
+#include "renderthread/RenderThread.h"
+#include "renderthread/VulkanManager.h"
+
+using namespace android::uirenderer::renderthread;
 
 namespace android {
 namespace uirenderer {
@@ -27,7 +34,6 @@
 DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState)
         : mRenderState(renderState)
         , mBlend(false)
-        , mSurfaceTexture(nullptr)
         , mTransform(nullptr)
         , mGLContextAttached(false)
         , mUpdateTexImage(false)
@@ -41,14 +47,12 @@
     destroyLayer();
 }
 
-void DeferredLayerUpdater::setSurfaceTexture(const sp<SurfaceTexture>& consumer) {
-    if (consumer.get() != mSurfaceTexture.get()) {
-        mSurfaceTexture = consumer;
+void DeferredLayerUpdater::setSurfaceTexture(AutoTextureRelease&& consumer) {
+    mSurfaceTexture = std::move(consumer);
 
-        GLenum target = consumer->getCurrentTextureTarget();
-        LOG_ALWAYS_FATAL_IF(target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES,
-                            "set unsupported SurfaceTexture with target %x", target);
-    }
+    GLenum target = ASurfaceTexture_getCurrentTextureTarget(mSurfaceTexture.get());
+    LOG_ALWAYS_FATAL_IF(target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES,
+                        "set unsupported SurfaceTexture with target %x", target);
 }
 
 void DeferredLayerUpdater::onContextDestroyed() {
@@ -61,13 +65,15 @@
     }
 
     if (mSurfaceTexture.get() && mGLContextAttached) {
-        mSurfaceTexture->detachFromView();
+        ASurfaceTexture_releaseConsumerOwnership(mSurfaceTexture.get());
         mGLContextAttached = false;
     }
 
     mLayer->postDecStrong();
 
     mLayer = nullptr;
+
+    mImageSlots.clear();
 }
 
 void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
@@ -80,6 +86,35 @@
     }
 }
 
+static status_t createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence, EGLDisplay* display,
+                                   int* releaseFence, void* handle) {
+    *display = EGL_NO_DISPLAY;
+    RenderState* renderState = (RenderState*)handle;
+    status_t err;
+    if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
+        EglManager& eglManager = renderState->getRenderThread().eglManager();
+        *display = eglManager.eglDisplay();
+        err = eglManager.createReleaseFence(useFenceSync, eglFence, releaseFence);
+    } else {
+        err = renderState->getRenderThread().vulkanManager().createReleaseFence(
+                releaseFence, renderState->getRenderThread().getGrContext());
+    }
+    return err;
+}
+
+static status_t fenceWait(int fence, void* handle) {
+    // Wait on the producer fence for the buffer to be ready.
+    status_t err;
+    RenderState* renderState = (RenderState*)handle;
+    if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
+        err = renderState->getRenderThread().eglManager().fenceWait(fence);
+    } else {
+        err = renderState->getRenderThread().vulkanManager().fenceWait(
+                fence, renderState->getRenderThread().getGrContext());
+    }
+    return err;
+}
+
 void DeferredLayerUpdater::apply() {
     if (!mLayer) {
         mLayer = new Layer(mRenderState, mColorFilter, mAlpha, mMode);
@@ -92,24 +127,33 @@
         if (!mGLContextAttached) {
             mGLContextAttached = true;
             mUpdateTexImage = true;
-            mSurfaceTexture->attachToView();
+            ASurfaceTexture_takeConsumerOwnership(mSurfaceTexture.get());
         }
         if (mUpdateTexImage) {
             mUpdateTexImage = false;
-            sk_sp<SkImage> layerImage;
-            SkMatrix textureTransform;
-            bool queueEmpty = true;
-            // If the SurfaceTexture queue is in synchronous mode, need to discard all
-            // but latest frame. Since we can't tell which mode it is in,
-            // do this unconditionally.
-            do {
-                layerImage = mSurfaceTexture->dequeueImage(textureTransform, &queueEmpty,
-                        mRenderState);
-            } while (layerImage.get() && (!queueEmpty));
-            if (layerImage.get()) {
-                // force filtration if buffer size != layer size
-                bool forceFilter = mWidth != layerImage->width() || mHeight != layerImage->height();
-                updateLayer(forceFilter, textureTransform, layerImage);
+            float transformMatrix[16];
+            android_dataspace dataspace;
+            int slot;
+            bool newContent = false;
+            // Note: ASurfaceTexture_dequeueBuffer discards all but the last frame. This
+            // is necessary if the SurfaceTexture queue is in synchronous mode, and we
+            // cannot tell which mode it is in.
+            AHardwareBuffer* hardwareBuffer = ASurfaceTexture_dequeueBuffer(
+                    mSurfaceTexture.get(), &slot, &dataspace, transformMatrix, &newContent,
+                    createReleaseFence, fenceWait, &mRenderState);
+
+            if (hardwareBuffer) {
+                sk_sp<SkImage> layerImage = mImageSlots[slot].createIfNeeded(
+                        hardwareBuffer, dataspace, newContent,
+                        mRenderState.getRenderThread().getGrContext());
+                if (layerImage.get()) {
+                    SkMatrix textureTransform;
+                    mat4(transformMatrix).copyTo(textureTransform);
+                    // force filtration if buffer size != layer size
+                    bool forceFilter =
+                            mWidth != layerImage->width() || mHeight != layerImage->height();
+                    updateLayer(forceFilter, textureTransform, layerImage);
+                }
             }
         }
 
@@ -121,7 +165,7 @@
 }
 
 void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform,
-        const sk_sp<SkImage>& layerImage) {
+                                       const sk_sp<SkImage>& layerImage) {
     mLayer->setBlend(mBlend);
     mLayer->setForceFilter(forceFilter);
     mLayer->setSize(mWidth, mHeight);
@@ -136,5 +180,42 @@
     }
 }
 
+sk_sp<SkImage> DeferredLayerUpdater::ImageSlot::createIfNeeded(AHardwareBuffer* buffer,
+                                                               android_dataspace dataspace,
+                                                               bool forceCreate,
+                                                               GrContext* context) {
+    if (!mTextureRelease || !mTextureRelease->getImage().get() || dataspace != mDataspace ||
+        forceCreate || mBuffer != buffer) {
+        if (buffer != mBuffer) {
+            clear();
+        }
+
+        if (!buffer) {
+            return nullptr;
+        }
+
+        if (!mTextureRelease) {
+            mTextureRelease = new AutoBackendTextureRelease(context, buffer);
+        } else {
+            mTextureRelease->newBufferContent(context);
+        }
+
+        mDataspace = dataspace;
+        mBuffer = buffer;
+        mTextureRelease->makeImage(buffer, dataspace, context);
+    }
+    return mTextureRelease ? mTextureRelease->getImage() : nullptr;
+}
+
+void DeferredLayerUpdater::ImageSlot::clear() {
+    if (mTextureRelease) {
+        // The following unref counteracts the initial mUsageCount of 1, set by default initializer.
+        mTextureRelease->unref(true);
+        mTextureRelease = nullptr;
+    }
+
+    mBuffer = nullptr;
+}
+
 } /* namespace uirenderer */
 } /* namespace android */