Support render-ahead in vulkan

Bug: 127822449
Test: verified render_ahead working with skiavk
Change-Id: Iae1b227a763f6def035057f38cca4b0ab65c7e82
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index 8b02c11..a31081c 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -21,17 +21,16 @@
 #include "RenderThread.h"
 #include "pipeline/skia/ShaderCache.h"
 #include "pipeline/skia/SkiaMemoryTracer.h"
-#include "Properties.h"
 #include "renderstate/RenderState.h"
 #include "thread/CommonPool.h"
 
 #include <GrContextOptions.h>
 #include <SkExecutor.h>
 #include <SkGraphics.h>
+#include <SkMathPriv.h>
 #include <gui/Surface.h>
 #include <math.h>
 #include <set>
-#include <SkMathPriv.h>
 
 namespace android {
 namespace uirenderer {
@@ -79,14 +78,13 @@
 
 class CommonPoolExecutor : public SkExecutor {
 public:
-    virtual void add(std::function<void(void)> func) override {
-        CommonPool::post(std::move(func));
-    }
+    virtual void add(std::function<void(void)> func) override { CommonPool::post(std::move(func)); }
 };
 
 static CommonPoolExecutor sDefaultExecutor;
 
-void CacheManager::configureContext(GrContextOptions* contextOptions, const void* identity, ssize_t size) {
+void CacheManager::configureContext(GrContextOptions* contextOptions, const void* identity,
+                                    ssize_t size) {
     contextOptions->fAllowPathMaskCaching = true;
 
     // This sets the maximum size for a single texture atlas in the GPU font cache.  If necessary,
@@ -180,7 +178,8 @@
         }
 
         const char* layerType = Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL
-                ? "GlLayer" : "VkLayer";
+                                        ? "GlLayer"
+                                        : "VkLayer";
         size_t layerMemoryTotal = 0;
         for (std::set<Layer*>::iterator it = renderState->mActiveLayers.begin();
              it != renderState->mActiveLayers.end(); it++) {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 4808d68..1b3bd30 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -17,6 +17,7 @@
 #include "CanvasContext.h"
 #include <GpuMemoryTracker.h>
 
+#include "../Properties.h"
 #include "AnimationContext.h"
 #include "EglManager.h"
 #include "Frame.h"
@@ -31,7 +32,6 @@
 #include "utils/GLUtils.h"
 #include "utils/TimeUtils.h"
 #include "utils/TraceUtils.h"
-#include "../Properties.h"
 
 #include <cutils/properties.h>
 #include <private/hwui/DrawGlInfo.h>
@@ -153,7 +153,8 @@
     }
 
     ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::SRGB;
-    bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode);
+    bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode,
+                                                  mRenderAheadDepth);
 
     mFrameNumber = -1;
 
@@ -298,7 +299,7 @@
 
     mAnimationContext->startFrame(info.mode);
     mRenderPipeline->onPrepareTree();
-    for (const sp<RenderNode> &node : mRenderNodes) {
+    for (const sp<RenderNode>& node : mRenderNodes) {
         // Only the primary target node will be drawn full - all other nodes would get drawn in
         // real time mode. In case of a window, the primary node is the window content and the other
         // node(s) are non client / filler nodes.
@@ -322,7 +323,7 @@
 
     if (CC_LIKELY(mSwapHistory.size() && !Properties::forceDrawFrame)) {
         nsecs_t latestVsync = mRenderThread.timeLord().latestVsync();
-        SwapHistory &lastSwap = mSwapHistory.back();
+        SwapHistory& lastSwap = mSwapHistory.back();
         nsecs_t vsyncDelta = std::abs(lastSwap.vsyncTime - latestVsync);
         // The slight fudge-factor is to deal with cases where
         // the vsync was estimated due to being slow handling the signal.
@@ -405,8 +406,7 @@
     SkRect dirty;
     mDamageAccumulator.finish(&dirty);
 
-    if (dirty.isEmpty() && Properties::skipEmptyFrames
-            && !surfaceRequiresRedraw()) {
+    if (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw()) {
         mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
         return;
     }
@@ -416,21 +416,21 @@
     Frame frame = mRenderPipeline->getFrame();
 
     SkRect windowDirty = computeDirtyRect(frame, &dirty);
+    if (mRenderAheadDepth) {
+        auto presentTime =
+                mCurrentFrameInfo->get(FrameInfoIndex::Vsync) +
+                (mRenderThread.timeLord().frameIntervalNanos() * (mRenderAheadDepth + 1));
+        native_window_set_buffers_timestamp(mNativeSurface.get(), presentTime);
+    }
 
     bool drew = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue,
-                                      mContentDrawBounds, mOpaque, mLightInfo,
-                                      mRenderNodes, &(profiler()));
+                                      mContentDrawBounds, mOpaque, mLightInfo, mRenderNodes,
+                                      &(profiler()));
 
     int64_t frameCompleteNr = mFrameCompleteCallbacks.size() ? getFrameNumber() : -1;
 
     waitOnFences();
 
-    if (mRenderAheadDepth) {
-        auto presentTime = mCurrentFrameInfo->get(FrameInfoIndex::Vsync) +
-                (mRenderThread.timeLord().frameIntervalNanos() * (mRenderAheadDepth + 1));
-        native_window_set_buffers_timestamp(mNativeSurface.get(), presentTime);
-    }
-
     bool requireSwap = false;
     bool didSwap =
             mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo, &requireSwap);
@@ -645,21 +645,13 @@
 }
 
 void CanvasContext::applyRenderAheadSettings() {
-    if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
-        // TODO: Fix SkiaVulkan's assumptions on buffer counts. And SIGBUS crashes.
-        mRenderAheadDepth = 0;
-        return;
-    }
-    if (mNativeSurface) {
-        native_window_set_buffer_count(mNativeSurface.get(), 3 + mRenderAheadDepth);
-        if (!mRenderAheadDepth) {
-            native_window_set_buffers_timestamp(mNativeSurface.get(), NATIVE_WINDOW_TIMESTAMP_AUTO);
-        }
+    if (mNativeSurface && !mRenderAheadDepth) {
+        native_window_set_buffers_timestamp(mNativeSurface.get(), NATIVE_WINDOW_TIMESTAMP_AUTO);
     }
 }
 
-void CanvasContext::setRenderAheadDepth(int renderAhead) {
-    if (renderAhead < 0 || renderAhead > 2 || renderAhead == mRenderAheadDepth) {
+void CanvasContext::setRenderAheadDepth(uint32_t renderAhead) {
+    if (renderAhead > 2 || renderAhead == mRenderAheadDepth || mNativeSurface) {
         return;
     }
     mRenderAheadDepth = renderAhead;
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 4a3119a..0bd080d 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -17,15 +17,15 @@
 #pragma once
 
 #include "DamageAccumulator.h"
-#include "Lighting.h"
 #include "FrameInfo.h"
 #include "FrameInfoVisualizer.h"
 #include "FrameMetricsReporter.h"
 #include "IContextFactory.h"
 #include "IRenderPipeline.h"
 #include "LayerUpdateQueue.h"
-#include "RenderNode.h"
+#include "Lighting.h"
 #include "ReliableSurface.h"
+#include "RenderNode.h"
 #include "renderthread/RenderTask.h"
 #include "renderthread/RenderThread.h"
 
@@ -37,10 +37,10 @@
 #include <utils/Functor.h>
 
 #include <functional>
+#include <future>
 #include <set>
 #include <string>
 #include <vector>
-#include <future>
 
 namespace android {
 namespace uirenderer {
@@ -187,9 +187,7 @@
         mRenderPipeline->setPictureCapturedCallback(callback);
     }
 
-    void setForceDark(bool enable) {
-        mUseForceDark = enable;
-    }
+    void setForceDark(bool enable) { mUseForceDark = enable; }
 
     bool useForceDark() {
         // The force-dark override has the highest priority, followed by the disable setting
@@ -204,7 +202,8 @@
         return mUseForceDark;
     }
 
-    void setRenderAheadDepth(int renderAhead);
+    // Must be called before setSurface
+    void setRenderAheadDepth(uint32_t renderAhead);
 
 private:
     CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
@@ -238,7 +237,7 @@
     // painted onto its surface.
     bool mIsDirty = false;
     SwapBehavior mSwapBehavior = SwapBehavior::kSwap_default;
-    int mRenderAheadDepth = 0;
+    uint32_t mRenderAheadDepth = 0;
     struct SwapHistory {
         SkRect damage;
         nsecs_t vsyncTime;
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 51eeab7..91dc3bc 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -109,9 +109,8 @@
 
     // Even if we aren't drawing this vsync pulse the next frame number will still be accurate
     if (CC_UNLIKELY(callback)) {
-        context->enqueueFrameWork([callback, frameNr = context->getFrameNumber()]() {
-            callback(frameNr);
-        });
+        context->enqueueFrameWork(
+                [callback, frameNr = context->getFrameNumber()]() { callback(frameNr); });
     }
 
     if (CC_LIKELY(canDrawThisFrame)) {
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 2cc3f36..1d55334 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -29,10 +29,10 @@
 #include <EGL/eglext.h>
 #include <GLES/gl.h>
 
+#include <gui/Surface.h>
+#include <system/window.h>
 #include <string>
 #include <vector>
-#include <system/window.h>
-#include <gui/Surface.h>
 
 #define GLES_VERSION 2
 
@@ -171,8 +171,7 @@
                         EGL_NONE};
     EGLConfig config = EGL_NO_CONFIG_KHR;
     EGLint numConfigs = 1;
-    if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) ||
-        numConfigs != 1) {
+    if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) || numConfigs != 1) {
         return EGL_NO_CONFIG_KHR;
     }
     return config;
@@ -203,8 +202,7 @@
                         EGL_NONE};
     EGLConfig config = EGL_NO_CONFIG_KHR;
     EGLint numConfigs = 1;
-    if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) ||
-        numConfigs != 1) {
+    if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) || numConfigs != 1) {
         return EGL_NO_CONFIG_KHR;
     }
     return config;
@@ -262,7 +260,7 @@
         mEglConfigWideGamut = loadFP16Config(mEglDisplay, mSwapBehavior);
         if (mEglConfigWideGamut == EGL_NO_CONFIG_KHR) {
             ALOGE("Device claims wide gamut support, cannot find matching config, error = %s",
-                    eglErrorString());
+                  eglErrorString());
             EglExtensions.pixelFormatFloat = false;
         }
     } else if (wideColorType == SkColorType::kN32_SkColorType) {
@@ -350,7 +348,7 @@
     EGLSurface surface = eglCreateWindowSurface(
             mEglDisplay, wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs);
     if (surface == EGL_NO_SURFACE) {
-        return Error<EGLint> { eglGetError() };
+        return Error<EGLint>{eglGetError()};
     }
 
     if (mSwapBehavior != SwapBehavior::Preserved) {
@@ -525,12 +523,8 @@
             ALOGE("EglManager::fenceWait: error dup'ing fence fd: %d", errno);
             return -errno;
         }
-        EGLint attribs[] = {
-            EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
-            EGL_NONE
-        };
-        EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay,
-                EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+        EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
+        EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
         if (sync == EGL_NO_SYNC_KHR) {
             close(fenceFd);
             ALOGE("EglManager::fenceWait: error creating EGL fence: %#x", eglGetError());
@@ -559,18 +553,16 @@
 }
 
 status_t EglManager::createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence,
-        sp<Fence>& nativeFence) {
+                                        sp<Fence>& nativeFence) {
     if (!hasEglContext()) {
         ALOGE("EglManager::createReleaseFence: EGLDisplay not initialized");
         return INVALID_OPERATION;
     }
 
     if (SyncFeatures::getInstance().useNativeFenceSync()) {
-        EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay,
-                EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
+        EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
         if (sync == EGL_NO_SYNC_KHR) {
-            ALOGE("EglManager::createReleaseFence: error creating EGL fence: %#x",
-                    eglGetError());
+            ALOGE("EglManager::createReleaseFence: error creating EGL fence: %#x", eglGetError());
             return UNKNOWN_ERROR;
         }
         glFlush();
@@ -578,7 +570,8 @@
         eglDestroySyncKHR(mEglDisplay, sync);
         if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
             ALOGE("EglManager::createReleaseFence: error dup'ing native fence "
-                    "fd: %#x", eglGetError());
+                  "fd: %#x",
+                  eglGetError());
             return UNKNOWN_ERROR;
         }
         nativeFence = new Fence(fenceFd);
@@ -592,7 +585,7 @@
             EGLint result = eglClientWaitSyncKHR(mEglDisplay, *eglFence, 0, 1000000000);
             if (result == EGL_FALSE) {
                 ALOGE("EglManager::createReleaseFence: error waiting for previous fence: %#x",
-                        eglGetError());
+                      eglGetError());
                 return UNKNOWN_ERROR;
             } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
                 ALOGE("EglManager::createReleaseFence: timeout waiting for previous fence");
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 0502eb8..3b81014 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -66,8 +66,8 @@
     virtual bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
                              FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
     virtual DeferredLayerUpdater* createTextureLayer() = 0;
-    virtual bool setSurface(ANativeWindow* window, SwapBehavior swapBehavior,
-                            ColorMode colorMode) = 0;
+    virtual bool setSurface(ANativeWindow* window, SwapBehavior swapBehavior, ColorMode colorMode,
+                            uint32_t extraBuffers) = 0;
     virtual void onStop() = 0;
     virtual bool isSurfaceReady() = 0;
     virtual bool isContextReady() = 0;
diff --git a/libs/hwui/renderthread/ReliableSurface.cpp b/libs/hwui/renderthread/ReliableSurface.cpp
index 6f2b9df..b9410c2 100644
--- a/libs/hwui/renderthread/ReliableSurface.cpp
+++ b/libs/hwui/renderthread/ReliableSurface.cpp
@@ -34,13 +34,13 @@
     // Make warnings happy
     SurfaceExposer() = delete;
 
-    using Surface::setBufferCount;
-    using Surface::setSwapInterval;
-    using Surface::dequeueBuffer;
-    using Surface::queueBuffer;
     using Surface::cancelBuffer;
+    using Surface::dequeueBuffer;
     using Surface::lockBuffer_DEPRECATED;
     using Surface::perform;
+    using Surface::queueBuffer;
+    using Surface::setBufferCount;
+    using Surface::setSwapInterval;
 };
 
 #define callProtected(surface, func, ...) ((*surface).*&SurfaceExposer::func)(__VA_ARGS__)
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index b58bab1..1a1b9da 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -84,7 +84,7 @@
 
 void RenderProxy::setSurface(const sp<Surface>& surface) {
     mRenderThread.queue().post(
-            [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
+            [this, surf = surface]() mutable { mContext->setSurface(std::move(surf)); });
 }
 
 void RenderProxy::allocateBuffers() {
@@ -251,7 +251,7 @@
 
 void RenderProxy::setProcessStatsBuffer(int fd) {
     auto& rt = RenderThread::getInstance();
-    rt.queue().post([&rt, fd = dup(fd) ]() {
+    rt.queue().post([&rt, fd = dup(fd)]() {
         rt.globalProfileData().switchStorageToAshmem(fd);
         close(fd);
     });
@@ -285,7 +285,7 @@
 void RenderProxy::setPictureCapturedCallback(
         const std::function<void(sk_sp<SkPicture>&&)>& callback) {
     mRenderThread.queue().post(
-            [ this, cb = callback ]() { mContext->setPictureCapturedCallback(cb); });
+            [this, cb = callback]() { mContext->setPictureCapturedCallback(cb); });
 }
 
 void RenderProxy::setFrameCallback(std::function<void(int64_t)>&& callback) {
@@ -297,13 +297,13 @@
 }
 
 void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observerPtr) {
-    mRenderThread.queue().post([ this, observer = sp{observerPtr} ]() {
+    mRenderThread.queue().post([this, observer = sp{observerPtr}]() {
         mContext->addFrameMetricsObserver(observer.get());
     });
 }
 
 void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observerPtr) {
-    mRenderThread.queue().post([ this, observer = sp{observerPtr} ]() {
+    mRenderThread.queue().post([this, observer = sp{observerPtr}]() {
         mContext->removeFrameMetricsObserver(observer.get());
     });
 }
@@ -313,9 +313,8 @@
 }
 
 void RenderProxy::setRenderAheadDepth(int renderAhead) {
-    mRenderThread.queue().post([ context = mContext, renderAhead ] {
-        context->setRenderAheadDepth(renderAhead);
-    });
+    mRenderThread.queue().post(
+            [context = mContext, renderAhead] { context->setRenderAheadDepth(renderAhead); });
 }
 
 int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom,
@@ -393,9 +392,7 @@
 void RenderProxy::preload() {
     // Create RenderThread object and start the thread. Then preload Vulkan/EGL driver.
     auto& thread = RenderThread::getInstance();
-    thread.queue().post([&thread]() {
-        thread.preload();
-    });
+    thread.queue().post([&thread]() { thread.preload(); });
 }
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index b76e49c..eca7d88 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -16,6 +16,7 @@
 
 #include "RenderThread.h"
 
+#include "../HardwareBitmapUploader.h"
 #include "CanvasContext.h"
 #include "DeviceInfo.h"
 #include "EglManager.h"
@@ -29,7 +30,6 @@
 #include "utils/FatVector.h"
 #include "utils/TimeUtils.h"
 #include "utils/TraceUtils.h"
-#include "../HardwareBitmapUploader.h"
 
 #ifdef HWUI_GLES_WRAP_ENABLED
 #include "debug/GlesDriver.h"
@@ -410,9 +410,7 @@
 void RenderThread::preload() {
     // EGL driver is always preloaded only if HWUI renders with GL.
     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
-        std::thread eglInitThread([]() {
-            eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        });
+        std::thread eglInitThread([]() { eglGetDisplay(EGL_DEFAULT_DISPLAY); });
         eglInitThread.detach();
     } else {
         requireVkContext();
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 5f43b48..6bb26fd 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -22,8 +22,8 @@
 #include "../JankTracker.h"
 #include "CacheManager.h"
 #include "TimeLord.h"
-#include "thread/ThreadBase.h"
 #include "WebViewFunctorManager.h"
+#include "thread/ThreadBase.h"
 #include "utils/TimeUtils.h"
 
 #include <GrContext.h>
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 4011329..5edf330 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -29,7 +29,6 @@
 #include <GrBackendSurface.h>
 #include <GrContext.h>
 #include <GrTypes.h>
-#include <GrTypes.h>
 #include <vk/GrVkExtensions.h>
 #include <vk/GrVkTypes.h>
 
@@ -43,7 +42,7 @@
     // so we can get access to the pNext for the next struct.
     struct CommonVulkanHeader {
         VkStructureType sType;
-        void*           pNext;
+        void* pNext;
     };
 
     void* pNext = features.pNext;
@@ -94,13 +93,13 @@
     VkResult err;
 
     constexpr VkApplicationInfo app_info = {
-        VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
-        nullptr,                            // pNext
-        "android framework",                // pApplicationName
-        0,                                  // applicationVersion
-        "android framework",                // pEngineName
-        0,                                  // engineVerison
-        mAPIVersion,                        // apiVersion
+            VK_STRUCTURE_TYPE_APPLICATION_INFO,  // sType
+            nullptr,                             // pNext
+            "android framework",                 // pApplicationName
+            0,                                   // applicationVersion
+            "android framework",                 // pEngineName
+            0,                                   // engineVerison
+            mAPIVersion,                         // apiVersion
     };
 
     {
@@ -128,14 +127,14 @@
     }
 
     const VkInstanceCreateInfo instance_create = {
-        VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,    // sType
-        nullptr,                                   // pNext
-        0,                                         // flags
-        &app_info,                                 // pApplicationInfo
-        0,                                         // enabledLayerNameCount
-        nullptr,                                   // ppEnabledLayerNames
-        (uint32_t) mInstanceExtensions.size(),     // enabledExtensionNameCount
-        mInstanceExtensions.data(),                // ppEnabledExtensionNames
+            VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,  // sType
+            nullptr,                                 // pNext
+            0,                                       // flags
+            &app_info,                               // pApplicationInfo
+            0,                                       // enabledLayerNameCount
+            nullptr,                                 // ppEnabledLayerNames
+            (uint32_t)mInstanceExtensions.size(),    // enabledExtensionNameCount
+            mInstanceExtensions.data(),              // ppEnabledExtensionNames
     };
 
     GET_PROC(CreateInstance);
@@ -200,11 +199,11 @@
     {
         uint32_t extensionCount = 0;
         err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
-                nullptr);
+                                                  nullptr);
         LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
         mDeviceExtensionsOwner.resize(extensionCount);
         err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
-                mDeviceExtensionsOwner.data());
+                                                  mDeviceExtensionsOwner.data());
         LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
         bool hasKHRSwapchainExtension = false;
         for (const VkExtensionProperties& extension : mDeviceExtensionsOwner) {
@@ -216,7 +215,7 @@
         LOG_ALWAYS_FATAL_IF(!hasKHRSwapchainExtension);
     }
 
-    auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) {
+    auto getProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
         if (device != VK_NULL_HANDLE) {
             return vkGetDeviceProcAddr(device, proc_name);
         }
@@ -224,7 +223,8 @@
     };
 
     grExtensions.init(getProc, mInstance, mPhysicalDevice, mInstanceExtensions.size(),
-            mInstanceExtensions.data(), mDeviceExtensions.size(), mDeviceExtensions.data());
+                      mInstanceExtensions.data(), mDeviceExtensions.size(),
+                      mDeviceExtensions.data());
 
     LOG_ALWAYS_FATAL_IF(!grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1));
 
@@ -237,7 +237,7 @@
 
     if (grExtensions.hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2)) {
         VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT* blend;
-        blend = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*) malloc(
+        blend = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*)malloc(
                 sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT));
         LOG_ALWAYS_FATAL_IF(!blend);
         blend->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT;
@@ -247,7 +247,7 @@
     }
 
     VkPhysicalDeviceSamplerYcbcrConversionFeatures* ycbcrFeature;
-    ycbcrFeature = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*) malloc(
+    ycbcrFeature = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*)malloc(
             sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeatures));
     LOG_ALWAYS_FATAL_IF(!ycbcrFeature);
     ycbcrFeature->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
@@ -261,17 +261,17 @@
     // and we can't depend on it on all platforms
     features.features.robustBufferAccess = VK_FALSE;
 
-    float queuePriorities[1] = { 0.0 };
+    float queuePriorities[1] = {0.0};
 
     void* queueNextPtr = nullptr;
 
     VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo;
 
-    if (Properties::contextPriority != 0
-            && grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
+    if (Properties::contextPriority != 0 &&
+        grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
         memset(&queuePriorityCreateInfo, 0, sizeof(VkDeviceQueueGlobalPriorityCreateInfoEXT));
         queuePriorityCreateInfo.sType =
-            VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT;
+                VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT;
         queuePriorityCreateInfo.pNext = nullptr;
         switch (Properties::contextPriority) {
             case EGL_CONTEXT_PRIORITY_LOW_IMG:
@@ -285,41 +285,40 @@
                 break;
             default:
                 LOG_ALWAYS_FATAL("Unsupported context priority");
-         }
-         queueNextPtr = &queuePriorityCreateInfo;
+        }
+        queueNextPtr = &queuePriorityCreateInfo;
     }
 
     const VkDeviceQueueCreateInfo queueInfo[2] = {
-        {
-            VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
-            queueNextPtr,                               // pNext
-            0,                                          // VkDeviceQueueCreateFlags
-            mGraphicsQueueIndex,                        // queueFamilyIndex
-            1,                                          // queueCount
-            queuePriorities,                            // pQueuePriorities
-        },
-        {
-            VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
-            queueNextPtr,                               // pNext
-            0,                                          // VkDeviceQueueCreateFlags
-            mPresentQueueIndex,                         // queueFamilyIndex
-            1,                                          // queueCount
-            queuePriorities,                            // pQueuePriorities
-        }
-    };
+            {
+                    VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,  // sType
+                    queueNextPtr,                                // pNext
+                    0,                                           // VkDeviceQueueCreateFlags
+                    mGraphicsQueueIndex,                         // queueFamilyIndex
+                    1,                                           // queueCount
+                    queuePriorities,                             // pQueuePriorities
+            },
+            {
+                    VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,  // sType
+                    queueNextPtr,                                // pNext
+                    0,                                           // VkDeviceQueueCreateFlags
+                    mPresentQueueIndex,                          // queueFamilyIndex
+                    1,                                           // queueCount
+                    queuePriorities,                             // pQueuePriorities
+            }};
     uint32_t queueInfoCount = (mPresentQueueIndex != mGraphicsQueueIndex) ? 2 : 1;
 
     const VkDeviceCreateInfo deviceInfo = {
-        VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,    // sType
-        &features,                               // pNext
-        0,                                       // VkDeviceCreateFlags
-        queueInfoCount,                          // queueCreateInfoCount
-        queueInfo,                               // pQueueCreateInfos
-        0,                                       // layerCount
-        nullptr,                                 // ppEnabledLayerNames
-        (uint32_t) mDeviceExtensions.size(),     // extensionCount
-        mDeviceExtensions.data(),                // ppEnabledExtensionNames
-        nullptr,                                 // ppEnabledFeatures
+            VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,  // sType
+            &features,                             // pNext
+            0,                                     // VkDeviceCreateFlags
+            queueInfoCount,                        // queueCreateInfoCount
+            queueInfo,                             // pQueueCreateInfos
+            0,                                     // layerCount
+            nullptr,                               // ppEnabledLayerNames
+            (uint32_t)mDeviceExtensions.size(),    // extensionCount
+            mDeviceExtensions.data(),              // ppEnabledExtensionNames
+            nullptr,                               // ppEnabledFeatures
     };
 
     LOG_ALWAYS_FATAL_IF(mCreateDevice(mPhysicalDevice, &deviceInfo, nullptr, &mDevice));
@@ -371,8 +370,8 @@
         // this needs to be on the render queue
         commandPoolInfo.queueFamilyIndex = mGraphicsQueueIndex;
         commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
-        SkDEBUGCODE(VkResult res =) mCreateCommandPool(mDevice, &commandPoolInfo, nullptr,
-                &mCommandPool);
+        SkDEBUGCODE(VkResult res =)
+                mCreateCommandPool(mDevice, &commandPoolInfo, nullptr, &mCommandPool);
         SkASSERT(VK_SUCCESS == res);
     }
     LOG_ALWAYS_FATAL_IF(mCommandPool == VK_NULL_HANDLE);
@@ -391,7 +390,7 @@
 }
 
 sk_sp<GrContext> VulkanManager::createContext(const GrContextOptions& options) {
-    auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) {
+    auto getProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
         if (device != VK_NULL_HANDLE) {
             return vkGetDeviceProcAddr(device, proc_name);
         }
@@ -431,7 +430,6 @@
 }
 
 Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) {
-
     VulkanSurface::NativeBufferInfo* bufferInfo = surface->dequeueNativeBuffer();
 
     if (bufferInfo == nullptr) {
@@ -480,7 +478,7 @@
                 bufferInfo->skSurface->wait(1, &backendSemaphore);
                 // The following flush blocks the GPU immediately instead of waiting for other
                 // drawing ops. It seems dequeue_fence is not respected otherwise.
-                //TODO: remove the flush after finding why backendSemaphore is not working.
+                // TODO: remove the flush after finding why backendSemaphore is not working.
                 bufferInfo->skSurface->flush();
             }
         }
@@ -557,15 +555,15 @@
 
 VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode,
                                             sk_sp<SkColorSpace> surfaceColorSpace,
-                                            SkColorType surfaceColorType,
-                                            GrContext* grContext) {
+                                            SkColorType surfaceColorType, GrContext* grContext,
+                                            uint32_t extraBuffers) {
     LOG_ALWAYS_FATAL_IF(!hasVkContext(), "Not initialized");
     if (!window) {
         return nullptr;
     }
 
     return VulkanSurface::Create(window, colorMode, surfaceColorType, surfaceColorSpace, grContext,
-                                  *this);
+                                 *this, extraBuffers);
 }
 
 bool VulkanManager::setupDummyCommandBuffer() {
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index a7a43cc..1a3a0e4 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -18,16 +18,16 @@
 #define VULKANMANAGER_H
 
 #if !defined(VK_USE_PLATFORM_ANDROID_KHR)
-#  define VK_USE_PLATFORM_ANDROID_KHR
+#define VK_USE_PLATFORM_ANDROID_KHR
 #endif
 #include <vulkan/vulkan.h>
 
 #include <GrContextOptions.h>
-#include <vk/GrVkExtensions.h>
 #include <SkSurface.h>
 #include <ui/Fence.h>
 #include <utils/StrongPointer.h>
 #include <vk/GrVkBackendContext.h>
+#include <vk/GrVkExtensions.h>
 #include "Frame.h"
 #include "IRenderPipeline.h"
 #include "VulkanSurface.h"
@@ -59,8 +59,8 @@
     // Create and destroy functions for wrapping an ANativeWindow in a VulkanSurface
     VulkanSurface* createSurface(ANativeWindow* window, ColorMode colorMode,
                                  sk_sp<SkColorSpace> surfaceColorSpace,
-                                 SkColorType surfaceColorType,
-                                 GrContext* grContext);
+                                 SkColorType surfaceColorType, GrContext* grContext,
+                                 uint32_t extraBuffers);
     void destroySurface(VulkanSurface* surface);
 
     Frame dequeueNextBuffer(VulkanSurface* surface);
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 36f540c..447512e 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -16,12 +16,12 @@
 
 #include "VulkanSurface.h"
 
-#include <algorithm>
 #include <SkSurface.h>
+#include <algorithm>
 
 #include "VulkanManager.h"
-#include "utils/TraceUtils.h"
 #include "utils/Color.h"
+#include "utils/TraceUtils.h"
 
 namespace android {
 namespace uirenderer {
@@ -31,10 +31,9 @@
     // For now, only support pure rotations, not flip or flip-and-rotate, until we have
     // more time to test them and build sample code. As far as I know we never actually
     // use anything besides pure rotations anyway.
-    return transform == 0
-        || transform == NATIVE_WINDOW_TRANSFORM_ROT_90
-        || transform == NATIVE_WINDOW_TRANSFORM_ROT_180
-        || transform == NATIVE_WINDOW_TRANSFORM_ROT_270;
+    return transform == 0 || transform == NATIVE_WINDOW_TRANSFORM_ROT_90 ||
+           transform == NATIVE_WINDOW_TRANSFORM_ROT_180 ||
+           transform == NATIVE_WINDOW_TRANSFORM_ROT_270;
 }
 
 static int InvertTransform(int transform) {
@@ -85,16 +84,16 @@
 }
 
 void VulkanSurface::ComputeWindowSizeAndTransform(WindowInfo* windowInfo, const SkISize& minSize,
-                                                   const SkISize& maxSize) {
+                                                  const SkISize& maxSize) {
     SkISize& windowSize = windowInfo->size;
 
     // clamp width & height to handle currentExtent of -1 and  protect us from broken hints
-    if (windowSize.width() < minSize.width() || windowSize.width() > maxSize.width()
-        || windowSize.height() < minSize.height() || windowSize.height() > maxSize.height()) {
+    if (windowSize.width() < minSize.width() || windowSize.width() > maxSize.width() ||
+        windowSize.height() < minSize.height() || windowSize.height() > maxSize.height()) {
         int width = std::min(maxSize.width(), std::max(minSize.width(), windowSize.width()));
         int height = std::min(maxSize.height(), std::max(minSize.height(), windowSize.height()));
-        ALOGE("Invalid Window Dimensions [%d, %d]; clamping to [%d, %d]",
-              windowSize.width(), windowSize.height(), width, height);
+        ALOGE("Invalid Window Dimensions [%d, %d]; clamping to [%d, %d]", windowSize.width(),
+              windowSize.height(), width, height);
         windowSize.set(width, height);
     }
 
@@ -145,12 +144,8 @@
 public:
     VkSurfaceAutoDeleter(VkInstance instance, VkSurfaceKHR surface,
                          PFN_vkDestroySurfaceKHR destroySurfaceKHR)
-            : mInstance(instance)
-            , mSurface(surface)
-            , mDestroySurfaceKHR(destroySurfaceKHR) {}
-    ~VkSurfaceAutoDeleter() {
-        destroy();
-    }
+            : mInstance(instance), mSurface(surface), mDestroySurfaceKHR(destroySurfaceKHR) {}
+    ~VkSurfaceAutoDeleter() { destroy(); }
 
     void destroy() {
         if (mSurface != VK_NULL_HANDLE) {
@@ -166,9 +161,9 @@
 };
 
 VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode,
-                                       SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
-                                       GrContext* grContext, const VulkanManager& vkManager) {
-
+                                     SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
+                                     GrContext* grContext, const VulkanManager& vkManager,
+                                     uint32_t extraBuffers) {
     VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
     memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
     surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
@@ -188,10 +183,11 @@
                                           vkManager.mDestroySurfaceKHR);
 
     SkDEBUGCODE(VkBool32 supported; res = vkManager.mGetPhysicalDeviceSurfaceSupportKHR(
-            vkManager.mPhysicalDevice, vkManager.mPresentQueueIndex, vkSurface, &supported);
-    // All physical devices and queue families on Android must be capable of
-    // presentation with any native window.
-    SkASSERT(VK_SUCCESS == res && supported););
+                                            vkManager.mPhysicalDevice, vkManager.mPresentQueueIndex,
+                                            vkSurface, &supported);
+                // All physical devices and queue families on Android must be capable of
+                // presentation with any native window.
+                SkASSERT(VK_SUCCESS == res && supported););
 
     // check for capabilities
     VkSurfaceCapabilitiesKHR caps;
@@ -225,14 +221,13 @@
     int query_value;
     int err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
     if (err != 0 || query_value < 0) {
-        ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
-              query_value);
+        ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err, query_value);
         return nullptr;
     }
     auto min_undequeued_buffers = static_cast<uint32_t>(query_value);
 
-    windowInfo.bufferCount = min_undequeued_buffers
-            + std::max(VulkanSurface::sTargetBufferCount, caps.minImageCount);
+    windowInfo.bufferCount = min_undequeued_buffers +
+                             std::max(sTargetBufferCount + extraBuffers, caps.minImageCount);
     if (caps.maxImageCount > 0 && windowInfo.bufferCount > caps.maxImageCount) {
         // Application must settle for fewer images than desired:
         windowInfo.bufferCount = caps.maxImageCount;
@@ -241,8 +236,7 @@
     // Currently Skia requires the images to be color attachments and support all transfer
     // operations.
     VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
-                                   VK_IMAGE_USAGE_SAMPLED_BIT |
-                                   VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+                                   VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
                                    VK_IMAGE_USAGE_TRANSFER_DST_BIT;
     LOG_ALWAYS_FATAL_IF((caps.supportedUsageFlags & usageFlags) != usageFlags);
 
@@ -337,7 +331,8 @@
     err = native_window_set_buffers_data_space(window, windowInfo.dataspace);
     if (err != 0) {
         ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_data_space(%d) "
-              "failed: %s (%d)", windowInfo.dataspace, strerror(-err), err);
+              "failed: %s (%d)",
+              windowInfo.dataspace, strerror(-err), err);
         return false;
     }
 
@@ -345,7 +340,8 @@
     err = native_window_set_buffers_dimensions(window, size.width(), size.height());
     if (err != 0) {
         ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_dimensions(%d,%d) "
-              "failed: %s (%d)", size.width(), size.height(), strerror(-err), err);
+              "failed: %s (%d)",
+              size.width(), size.height(), strerror(-err), err);
         return false;
     }
 
@@ -358,7 +354,8 @@
     err = native_window_set_buffers_transform(window, InvertTransform(windowInfo.transform));
     if (err != 0) {
         ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_transform(%d) "
-              "failed: %s (%d)", windowInfo.transform, strerror(-err), err);
+              "failed: %s (%d)",
+              windowInfo.transform, strerror(-err), err);
         return false;
     }
 
@@ -367,7 +364,8 @@
     err = native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_FREEZE);
     if (err != 0) {
         ALOGE("VulkanSurface::UpdateWindow() native_window_set_scaling_mode(SCALE_TO_WINDOW) "
-              "failed: %s (%d)", strerror(-err), err);
+              "failed: %s (%d)",
+              strerror(-err), err);
         return false;
     }
 
@@ -389,12 +387,12 @@
 }
 
 VulkanSurface::VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo,
-                               SkISize minWindowSize, SkISize maxWindowSize, GrContext* grContext)
+                             SkISize minWindowSize, SkISize maxWindowSize, GrContext* grContext)
         : mNativeWindow(window)
         , mWindowInfo(windowInfo)
         , mGrContext(grContext)
         , mMinWindowSize(minWindowSize)
-        , mMaxWindowSize(maxWindowSize) { }
+        , mMaxWindowSize(maxWindowSize) {}
 
 VulkanSurface::~VulkanSurface() {
     releaseBuffers();
@@ -437,8 +435,7 @@
     // value at the end of the function if everything dequeued correctly.
     mCurrentBufferInfo = nullptr;
 
-
-    //check if the native window has been resized or rotated and update accordingly
+    // check if the native window has been resized or rotated and update accordingly
     SkISize newSize = SkISize::MakeEmpty();
     int transformHint = 0;
     mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &newSize.fWidth);
@@ -458,8 +455,8 @@
                                                        newWindowInfo.actualSize.height());
             if (err != 0) {
                 ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
-                      newWindowInfo.actualSize.width(),
-                      newWindowInfo.actualSize.height(), strerror(-err), err);
+                      newWindowInfo.actualSize.width(), newWindowInfo.actualSize.height(),
+                      strerror(-err), err);
                 return nullptr;
             }
             // reset the NativeBufferInfo (including SkSurface) associated with the old buffers. The
@@ -470,7 +467,7 @@
 
         if (newWindowInfo.transform != mWindowInfo.transform) {
             err = native_window_set_buffers_transform(mNativeWindow.get(),
-                    InvertTransform(newWindowInfo.transform));
+                                                      InvertTransform(newWindowInfo.transform));
             if (err != 0) {
                 ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
                       newWindowInfo.transform, strerror(-err), err);
@@ -513,11 +510,9 @@
     VulkanSurface::NativeBufferInfo* bufferInfo = &mNativeBuffers[idx];
 
     if (bufferInfo->skSurface.get() == nullptr) {
-        bufferInfo->skSurface =
-                SkSurface::MakeFromAHardwareBuffer(mGrContext,
-                        ANativeWindowBuffer_getHardwareBuffer(bufferInfo->buffer.get()),
-                        kTopLeft_GrSurfaceOrigin, DataSpaceToColorSpace(mWindowInfo.dataspace),
-                        nullptr);
+        bufferInfo->skSurface = SkSurface::MakeFromAHardwareBuffer(
+                mGrContext, ANativeWindowBuffer_getHardwareBuffer(bufferInfo->buffer.get()),
+                kTopLeft_GrSurfaceOrigin, DataSpaceToColorSpace(mWindowInfo.dataspace), nullptr);
         if (bufferInfo->skSurface.get() == nullptr) {
             ALOGE("SkSurface::MakeFromAHardwareBuffer failed");
             mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd);
diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h
index 305483f..b7af596 100644
--- a/libs/hwui/renderthread/VulkanSurface.h
+++ b/libs/hwui/renderthread/VulkanSurface.h
@@ -19,8 +19,8 @@
 #include <system/window.h>
 #include <vulkan/vulkan.h>
 
-#include <SkSize.h>
 #include <SkRefCnt.h>
+#include <SkSize.h>
 
 #include "IRenderPipeline.h"
 
@@ -34,12 +34,9 @@
 
 class VulkanSurface {
 public:
-    static VulkanSurface* Create(ANativeWindow* window,
-                                  ColorMode colorMode,
-                                  SkColorType colorType,
-                                  sk_sp<SkColorSpace> colorSpace,
-                                  GrContext* grContext,
-                                  const VulkanManager& vkManager);
+    static VulkanSurface* Create(ANativeWindow* window, ColorMode colorMode, SkColorType colorType,
+                                 sk_sp<SkColorSpace> colorSpace, GrContext* grContext,
+                                 const VulkanManager& vkManager, uint32_t extraBuffers);
     ~VulkanSurface();
 
     sk_sp<SkSurface> getCurrentSkSurface() {
@@ -104,15 +101,10 @@
         SkMatrix preTransform;
     };
 
-    VulkanSurface(ANativeWindow* window,
-                  const WindowInfo& windowInfo,
-                  SkISize minWindowSize,
-                  SkISize maxWindowSize,
-                  GrContext* grContext);
-    static bool UpdateWindow(ANativeWindow* window,
-                             const WindowInfo& windowInfo);
-    static void ComputeWindowSizeAndTransform(WindowInfo* windowInfo,
-                                              const SkISize& minSize,
+    VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo, SkISize minWindowSize,
+                  SkISize maxWindowSize, GrContext* grContext);
+    static bool UpdateWindow(ANativeWindow* window, const WindowInfo& windowInfo);
+    static void ComputeWindowSizeAndTransform(WindowInfo* windowInfo, const SkISize& minSize,
                                               const SkISize& maxSize);
     void releaseBuffers();