Revert "Revert "Created HardwareBufferRenderer to support rendering into...""

This reverts commit cca989f2b52725468464534f337ee55d01644fb3.

Test: atest CtsUiRenderingTestCases --iterations 10 --armeabi-v7a
Change-Id: Iee19edeb489ed54b421ac8de37ee5a70b8f9756a
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 19cd7bd..202a62c 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -55,7 +55,9 @@
 MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() {
     // In case the surface was destroyed (e.g. a previous trimMemory call) we
     // need to recreate it here.
-    if (!isSurfaceReady() && mNativeWindow) {
+    if (mHardwareBuffer) {
+        mRenderThread.requireGlContext();
+    } else if (!isSurfaceReady() && mNativeWindow) {
         setSurface(mNativeWindow.get(), mSwapBehavior);
     }
 
@@ -67,17 +69,24 @@
 }
 
 Frame SkiaOpenGLPipeline::getFrame() {
-    LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
-                        "drawRenderNode called on a context with no surface!");
-    return mEglManager.beginFrame(mEglSurface);
+    if (mHardwareBuffer) {
+        AHardwareBuffer_Desc description;
+        AHardwareBuffer_describe(mHardwareBuffer, &description);
+        return Frame(description.width, description.height, 0);
+    } else {
+        LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
+                            "drawRenderNode called on a context with no surface!");
+        return mEglManager.beginFrame(mEglSurface);
+    }
 }
 
 IRenderPipeline::DrawResult SkiaOpenGLPipeline::draw(
         const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
         const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
         const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
-        const std::vector<sp<RenderNode>>& renderNodes, FrameInfoVisualizer* profiler) {
-    if (!isCapturingSkp()) {
+        const std::vector<sp<RenderNode>>& renderNodes, FrameInfoVisualizer* profiler,
+        const HardwareBufferRenderParams& bufferParams) {
+    if (!isCapturingSkp() && !mHardwareBuffer) {
         mEglManager.damageFrame(frame, dirty);
     }
 
@@ -104,13 +113,25 @@
     SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
 
     SkASSERT(mRenderThread.getGrContext() != nullptr);
-    sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(
-            mRenderThread.getGrContext(), backendRT, this->getSurfaceOrigin(), colorType,
-            mSurfaceColorSpace, &props));
+    sk_sp<SkSurface> surface;
+    SkMatrix preTransform;
+    if (mHardwareBuffer) {
+        surface = getBufferSkSurface(bufferParams);
+        preTransform = bufferParams.getTransform();
+    } else {
+        surface = SkSurface::MakeFromBackendRenderTarget(mRenderThread.getGrContext(), backendRT,
+                                                         getSurfaceOrigin(), colorType,
+                                                         mSurfaceColorSpace, &props);
+        preTransform = SkMatrix::I();
+    }
 
-    LightingInfo::updateLighting(lightGeometry, lightInfo);
+    SkPoint lightCenter = preTransform.mapXY(lightGeometry.center.x, lightGeometry.center.y);
+    LightGeometry localGeometry = lightGeometry;
+    localGeometry.center.x = lightCenter.fX;
+    localGeometry.center.y = lightCenter.fY;
+    LightingInfo::updateLighting(localGeometry, lightInfo);
     renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
-                SkMatrix::I());
+                preTransform);
 
     // Draw visual debugging features
     if (CC_UNLIKELY(Properties::showDirtyRegions ||
@@ -142,6 +163,10 @@
     // metrics the frame was swapped at this point
     currentFrameInfo->markSwapBuffers();
 
+    if (mHardwareBuffer) {
+        return false;
+    }
+
     *requireSwap = drew || mEglManager.damageRequiresSwap();
 
     if (*requireSwap && (CC_UNLIKELY(!mEglManager.swapBuffers(frame, screenDirty)))) {
@@ -197,6 +222,26 @@
     return false;
 }
 
+[[nodiscard]] android::base::unique_fd SkiaOpenGLPipeline::flush() {
+    int fence = -1;
+    EGLSyncKHR sync = EGL_NO_SYNC_KHR;
+    mEglManager.createReleaseFence(true, &sync, &fence);
+    // If a sync object is returned here then the device does not support native
+    // fences, we block on the returned sync and return -1 as a file descriptor
+    if (sync != EGL_NO_SYNC_KHR) {
+        EGLDisplay display = mEglManager.eglDisplay();
+        EGLint result = eglClientWaitSyncKHR(display, sync, 0, 1000000000);
+        if (result == EGL_FALSE) {
+            ALOGE("EglManager::createReleaseFence: error waiting for previous fence: %#x",
+                  eglGetError());
+        } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+            ALOGE("EglManager::createReleaseFence: timeout waiting for previous fence");
+        }
+        eglDestroySyncKHR(display, sync);
+    }
+    return android::base::unique_fd(fence);
+}
+
 bool SkiaOpenGLPipeline::isSurfaceReady() {
     return CC_UNLIKELY(mEglSurface != EGL_NO_SURFACE);
 }
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index a80c613..940d6bf 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -21,6 +21,7 @@
 
 #include "SkiaPipeline.h"
 #include "renderstate/RenderState.h"
+#include "renderthread/HardwareBufferRenderParams.h"
 
 namespace android {
 
@@ -36,19 +37,18 @@
 
     renderthread::MakeCurrentResult makeCurrent() override;
     renderthread::Frame getFrame() override;
-    renderthread::IRenderPipeline::DrawResult draw(const renderthread::Frame& frame,
-                                                   const SkRect& screenDirty, const SkRect& dirty,
-                                                   const LightGeometry& lightGeometry,
-                                                   LayerUpdateQueue* layerUpdateQueue,
-                                                   const Rect& contentDrawBounds, bool opaque,
-                                                   const LightInfo& lightInfo,
-                                                   const std::vector<sp<RenderNode> >& renderNodes,
-                                                   FrameInfoVisualizer* profiler) override;
+    renderthread::IRenderPipeline::DrawResult draw(
+            const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+            const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
+            const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
+            const std::vector<sp<RenderNode> >& renderNodes, FrameInfoVisualizer* profiler,
+            const renderthread::HardwareBufferRenderParams& bufferParams) override;
     GrSurfaceOrigin getSurfaceOrigin() override { return kBottomLeft_GrSurfaceOrigin; }
     bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
                      FrameInfo* currentFrameInfo, bool* requireSwap) override;
     DeferredLayerUpdater* createTextureLayer() override;
     bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior) override;
+    [[nodiscard]] android::base::unique_fd flush() override;
     void onStop() override;
     bool isSurfaceReady() override;
     bool isContextReady() override;
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 09c3120..2017eb6 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -605,6 +605,31 @@
     ALOGD("%s", log.c_str());
 }
 
+void SkiaPipeline::setHardwareBuffer(AHardwareBuffer* buffer) {
+    if (mHardwareBuffer) {
+        AHardwareBuffer_release(mHardwareBuffer);
+        mHardwareBuffer = nullptr;
+    }
+
+    if (buffer) {
+        AHardwareBuffer_acquire(buffer);
+        mHardwareBuffer = buffer;
+    }
+}
+
+sk_sp<SkSurface> SkiaPipeline::getBufferSkSurface(
+        const renderthread::HardwareBufferRenderParams& bufferParams) {
+    auto bufferColorSpace = bufferParams.getColorSpace();
+    if (mBufferSurface == nullptr || mBufferColorSpace == nullptr ||
+        !SkColorSpace::Equals(mBufferColorSpace.get(), bufferColorSpace.get())) {
+        mBufferSurface = SkSurface::MakeFromAHardwareBuffer(
+                mRenderThread.getGrContext(), mHardwareBuffer, kTopLeft_GrSurfaceOrigin,
+                bufferColorSpace, nullptr, true);
+        mBufferColorSpace = bufferColorSpace;
+    }
+    return mBufferSurface;
+}
+
 void SkiaPipeline::setSurfaceColorProperties(ColorMode colorMode) {
     mColorMode = colorMode;
     switch (colorMode) {
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index b7d799f..befee89 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -20,9 +20,11 @@
 #include <SkDocument.h>
 #include <SkMultiPictureDocument.h>
 #include <SkSurface.h>
+
 #include "Lighting.h"
 #include "hwui/AnimatedImageDrawable.h"
 #include "renderthread/CanvasContext.h"
+#include "renderthread/HardwareBufferRenderParams.h"
 #include "renderthread/IRenderPipeline.h"
 
 class SkFILEWStream;
@@ -73,14 +75,22 @@
         mCaptureMode = callback ? CaptureMode::CallbackAPI : CaptureMode::None;
     }
 
+    virtual void setHardwareBuffer(AHardwareBuffer* buffer) override;
+    bool hasHardwareBuffer() override { return mHardwareBuffer != nullptr; }
 
     void setTargetSdrHdrRatio(float ratio) override;
 
 protected:
+    sk_sp<SkSurface> getBufferSkSurface(
+            const renderthread::HardwareBufferRenderParams& bufferParams);
     void dumpResourceCacheUsage() const;
 
     renderthread::RenderThread& mRenderThread;
 
+    AHardwareBuffer* mHardwareBuffer = nullptr;
+    sk_sp<SkSurface> mBufferSurface = nullptr;
+    sk_sp<SkColorSpace> mBufferColorSpace = nullptr;
+
     ColorMode mColorMode = ColorMode::Default;
     SkColorType mSurfaceColorType;
     sk_sp<SkColorSpace> mSurfaceColorSpace;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index a8c752f..99298bc 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -57,37 +57,55 @@
 MakeCurrentResult SkiaVulkanPipeline::makeCurrent() {
     // In case the surface was destroyed (e.g. a previous trimMemory call) we
     // need to recreate it here.
-    if (!isSurfaceReady() && mNativeWindow) {
+    if (mHardwareBuffer) {
+        mRenderThread.requireVkContext();
+    } else if (!isSurfaceReady() && mNativeWindow) {
         setSurface(mNativeWindow.get(), SwapBehavior::kSwap_default);
     }
     return isContextReady() ? MakeCurrentResult::AlreadyCurrent : MakeCurrentResult::Failed;
 }
 
 Frame SkiaVulkanPipeline::getFrame() {
-    LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr, "getFrame() called on a context with no surface!");
-    return vulkanManager().dequeueNextBuffer(mVkSurface);
+    if (mHardwareBuffer) {
+        AHardwareBuffer_Desc description;
+        AHardwareBuffer_describe(mHardwareBuffer, &description);
+        return Frame(description.width, description.height, 0);
+    } else {
+        LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr,
+                            "getFrame() called on a context with no surface!");
+        return vulkanManager().dequeueNextBuffer(mVkSurface);
+    }
 }
 
 IRenderPipeline::DrawResult SkiaVulkanPipeline::draw(
         const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
         const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
         const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
-        const std::vector<sp<RenderNode>>& renderNodes, FrameInfoVisualizer* profiler) {
-    sk_sp<SkSurface> backBuffer = mVkSurface->getCurrentSkSurface();
+        const std::vector<sp<RenderNode>>& renderNodes, FrameInfoVisualizer* profiler,
+        const HardwareBufferRenderParams& bufferParams) {
+    sk_sp<SkSurface> backBuffer;
+    SkMatrix preTransform;
+    if (mHardwareBuffer) {
+        backBuffer = getBufferSkSurface(bufferParams);
+        preTransform = bufferParams.getTransform();
+    } else {
+        backBuffer = mVkSurface->getCurrentSkSurface();
+        preTransform = mVkSurface->getCurrentPreTransform();
+    }
+
     if (backBuffer.get() == nullptr) {
         return {false, -1};
     }
 
     // update the coordinates of the global light position based on surface rotation
-    SkPoint lightCenter = mVkSurface->getCurrentPreTransform().mapXY(lightGeometry.center.x,
-                                                                     lightGeometry.center.y);
+    SkPoint lightCenter = preTransform.mapXY(lightGeometry.center.x, lightGeometry.center.y);
     LightGeometry localGeometry = lightGeometry;
     localGeometry.center.x = lightCenter.fX;
     localGeometry.center.y = lightCenter.fY;
 
     LightingInfo::updateLighting(localGeometry, lightInfo);
     renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer,
-                mVkSurface->getCurrentPreTransform());
+                preTransform);
 
     // Draw visual debugging features
     if (CC_UNLIKELY(Properties::showDirtyRegions ||
@@ -116,12 +134,16 @@
 
 bool SkiaVulkanPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
                                      FrameInfo* currentFrameInfo, bool* requireSwap) {
-    *requireSwap = drew;
-
     // Even if we decided to cancel the frame, from the perspective of jank
     // metrics the frame was swapped at this point
     currentFrameInfo->markSwapBuffers();
 
+    if (mHardwareBuffer) {
+        return false;
+    }
+
+    *requireSwap = drew;
+
     if (*requireSwap) {
         vulkanManager().swapBuffers(mVkSurface, screenDirty);
     }
@@ -137,6 +159,12 @@
 
 void SkiaVulkanPipeline::onStop() {}
 
+[[nodiscard]] android::base::unique_fd SkiaVulkanPipeline::flush() {
+    int fence = -1;
+    vulkanManager().createReleaseFence(&fence, mRenderThread.getGrContext());
+    return android::base::unique_fd(fence);
+}
+
 // We can safely ignore the swap behavior because VkManager will always operate
 // in a mode equivalent to EGLManager::SwapBehavior::kBufferAge
 bool SkiaVulkanPipeline::setSurface(ANativeWindow* surface, SwapBehavior /*swapBehavior*/) {
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index e0884a8..d921ddb 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -16,14 +16,13 @@
 
 #pragma once
 
+#include "SkRefCnt.h"
 #include "SkiaPipeline.h"
+#include "renderstate/RenderState.h"
+#include "renderthread/HardwareBufferRenderParams.h"
 #include "renderthread/VulkanManager.h"
 #include "renderthread/VulkanSurface.h"
 
-#include "renderstate/RenderState.h"
-
-#include "SkRefCnt.h"
-
 class SkBitmap;
 struct SkRect;
 
@@ -38,18 +37,18 @@
 
     renderthread::MakeCurrentResult makeCurrent() override;
     renderthread::Frame getFrame() override;
-    renderthread::IRenderPipeline::DrawResult draw(const renderthread::Frame& frame,
-                                                   const SkRect& screenDirty, const SkRect& dirty,
-                                                   const LightGeometry& lightGeometry,
-                                                   LayerUpdateQueue* layerUpdateQueue,
-                                                   const Rect& contentDrawBounds, bool opaque,
-                                                   const LightInfo& lightInfo,
-                                                   const std::vector<sp<RenderNode> >& renderNodes,
-                                                   FrameInfoVisualizer* profiler) override;
+    renderthread::IRenderPipeline::DrawResult draw(
+            const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+            const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
+            const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
+            const std::vector<sp<RenderNode> >& renderNodes, FrameInfoVisualizer* profiler,
+            const renderthread::HardwareBufferRenderParams& bufferParams) override;
     GrSurfaceOrigin getSurfaceOrigin() override { return kTopLeft_GrSurfaceOrigin; }
     bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
                      FrameInfo* currentFrameInfo, bool* requireSwap) override;
     DeferredLayerUpdater* createTextureLayer() override;
+    [[nodiscard]] android::base::unique_fd flush() override;
+
     bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior) override;
     void onStop() override;
     bool isSurfaceReady() override;
@@ -66,7 +65,6 @@
 
 private:
     renderthread::VulkanManager& vulkanManager();
-
     renderthread::VulkanSurface* mVkSurface = nullptr;
     sp<ANativeWindow> mNativeWindow;
 };