Add support for dummy draws for Vulkan webview and texture views.

Test: manual testing
Change-Id: Iaec8c3a34367673c281665ff6c6e97d1ce532265
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index f24c1fb..8f7787b 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -116,6 +116,7 @@
     Texture.cpp \
     TextureCache.cpp \
     VectorDrawable.cpp \
+    VkLayer.cpp \
     protos/hwui.proto
 
 hwui_test_common_src_files := \
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 21aa6e1..3e8e8a1 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -16,6 +16,7 @@
 #include "DeferredLayerUpdater.h"
 
 #include "GlLayer.h"
+#include "VkLayer.h"
 #include "renderthread/EglManager.h"
 #include "renderthread/RenderTask.h"
 #include "utils/PaintUtils.h"
@@ -56,16 +57,23 @@
     mLayer->setAlpha(mAlpha, mMode);
 
     if (mSurfaceTexture.get()) {
-        LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
-                            "apply surfaceTexture with non GL backend %x, GL %x, VK %x",
-                            mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
-        if (mNeedsGLContextAttach) {
-            mNeedsGLContextAttach = false;
-            mSurfaceTexture->attachToContext(static_cast<GlLayer*>(mLayer)->getTextureId());
-        }
-        if (mUpdateTexImage) {
-            mUpdateTexImage = false;
-            doUpdateTexImage();
+        if (mLayer->getApi() == Layer::Api::Vulkan) {
+            if (mUpdateTexImage) {
+                mUpdateTexImage = false;
+                doUpdateVkTexImage();
+            }
+        } else {
+            LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
+                                "apply surfaceTexture with non GL backend %x, GL %x, VK %x",
+                                mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
+            if (mNeedsGLContextAttach) {
+                mNeedsGLContextAttach = false;
+                mSurfaceTexture->attachToContext(static_cast<GlLayer*>(mLayer)->getTextureId());
+            }
+            if (mUpdateTexImage) {
+                mUpdateTexImage = false;
+                doUpdateTexImage();
+            }
         }
         if (mTransform) {
             mLayer->getTransform().load(*mTransform);
@@ -117,16 +125,25 @@
     }
 }
 
+void DeferredLayerUpdater::doUpdateVkTexImage() {
+    LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::Vulkan,
+                        "updateLayer non Vulkan backend %x, GL %x, VK %x",
+                        mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
+
+    static const mat4 identityMatrix;
+    updateLayer(false, identityMatrix.data);
+
+    VkLayer* vkLayer = static_cast<VkLayer*>(mLayer);
+    vkLayer->updateTexture();
+}
+
 void DeferredLayerUpdater::updateLayer(bool forceFilter, GLenum renderTarget,
         const float* textureTransform) {
     LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
                         "updateLayer non GL backend %x, GL %x, VK %x",
                         mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
 
-    mLayer->setBlend(mBlend);
-    mLayer->setForceFilter(forceFilter);
-    mLayer->setSize(mWidth, mHeight);
-    mLayer->getTexTransform().load(textureTransform);
+    updateLayer(forceFilter, textureTransform);
 
     GlLayer* glLayer = static_cast<GlLayer*>(mLayer);
     if (renderTarget != glLayer->getRenderTarget()) {
@@ -137,18 +154,24 @@
     }
 }
 
+void DeferredLayerUpdater::updateLayer(bool forceFilter, const float* textureTransform) {
+    mLayer->setBlend(mBlend);
+    mLayer->setForceFilter(forceFilter);
+    mLayer->setSize(mWidth, mHeight);
+    mLayer->getTexTransform().load(textureTransform);
+}
+
 void DeferredLayerUpdater::detachSurfaceTexture() {
     if (mSurfaceTexture.get()) {
-        LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
-                            "detachSurfaceTexture with non GL backend %x, GL %x, VK %x",
-                            mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
-        status_t err = mSurfaceTexture->detachFromContext();
-        if (err != 0) {
-            // TODO: Elevate to fatal exception
-            ALOGE("Failed to detach SurfaceTexture from context %d", err);
+        if (mLayer->getApi() == Layer::Api::OpenGL) {
+            status_t err = mSurfaceTexture->detachFromContext();
+            if (err != 0) {
+                // TODO: Elevate to fatal exception
+                ALOGE("Failed to detach SurfaceTexture from context %d", err);
+            }
+            static_cast<GlLayer*>(mLayer)->clearTexture();
         }
         mSurfaceTexture = nullptr;
-        static_cast<GlLayer*>(mLayer)->clearTexture();
     }
 }
 
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 9be415f4..ead8314 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -63,8 +63,8 @@
 
     ANDROID_API void setSurfaceTexture(const sp<GLConsumer>& texture, bool needsAttach) {
         if (texture.get() != mSurfaceTexture.get()) {
-            mSurfaceTexture = texture;
             mNeedsGLContextAttach = needsAttach;
+            mSurfaceTexture = texture;
 
             GLenum target = texture->getCurrentTextureTarget();
             LOG_ALWAYS_FATAL_IF(target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES,
@@ -113,6 +113,8 @@
     Layer* mLayer;
 
     void doUpdateTexImage();
+    void doUpdateVkTexImage();
+    void updateLayer(bool forceFilter, const float* textureTransform);
 };
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/GpuMemoryTracker.cpp b/libs/hwui/GpuMemoryTracker.cpp
index 4fb5701..a52ec87 100644
--- a/libs/hwui/GpuMemoryTracker.cpp
+++ b/libs/hwui/GpuMemoryTracker.cpp
@@ -67,13 +67,13 @@
     gObjectStats[static_cast<int>(mType)].count--;
 }
 
-void GpuMemoryTracker::onGLContextCreated() {
-    LOG_ALWAYS_FATAL_IF(gGpuThread != 0, "We already have a GL thread? "
-            "current = %lu, gl thread = %lu", pthread_self(), gGpuThread);
+void GpuMemoryTracker::onGpuContextCreated() {
+    LOG_ALWAYS_FATAL_IF(gGpuThread != 0, "We already have a gpu thread? "
+            "current = %lu, gpu thread = %lu", pthread_self(), gGpuThread);
     gGpuThread = pthread_self();
 }
 
-void GpuMemoryTracker::onGLContextDestroyed() {
+void GpuMemoryTracker::onGpuContextDestroyed() {
     gGpuThread = 0;
     if (CC_UNLIKELY(gObjectSet.size() > 0)) {
         std::stringstream os;
diff --git a/libs/hwui/GpuMemoryTracker.h b/libs/hwui/GpuMemoryTracker.h
index bfb1bf1..f94fe28 100644
--- a/libs/hwui/GpuMemoryTracker.h
+++ b/libs/hwui/GpuMemoryTracker.h
@@ -43,8 +43,8 @@
     GpuObjectType objectType() { return mType; }
     int objectSize() { return mSize; }
 
-    static void onGLContextCreated();
-    static void onGLContextDestroyed();
+    static void onGpuContextCreated();
+    static void onGpuContextDestroyed();
     static void dump();
     static void dump(std::ostream& stream);
     static int getInstanceCount(GpuObjectType type);
diff --git a/libs/hwui/VkLayer.cpp b/libs/hwui/VkLayer.cpp
new file mode 100644
index 0000000..391acf1
--- /dev/null
+++ b/libs/hwui/VkLayer.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VkLayer.h"
+
+#include "renderstate/RenderState.h"
+
+#include <SkCanvas.h>
+#include <SkSurface.h>
+
+namespace android {
+namespace uirenderer {
+
+void VkLayer::updateTexture() {
+    sk_sp<SkSurface> surface;
+    SkImageInfo info = SkImageInfo::MakeS32(mWidth, mHeight, kPremul_SkAlphaType);
+    surface = SkSurface::MakeRenderTarget(mRenderState.getGrContext(), SkBudgeted::kNo, info);
+    surface->getCanvas()->clear(SK_ColorBLUE);
+    mImage = surface->makeImageSnapshot(SkBudgeted::kNo, SkSurface::kNo_ForceUnique);
+}
+
+void VkLayer::onVkContextDestroyed() {
+    mImage = nullptr;
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/VkLayer.h b/libs/hwui/VkLayer.h
index 353939f..39522b3 100644
--- a/libs/hwui/VkLayer.h
+++ b/libs/hwui/VkLayer.h
@@ -18,7 +18,7 @@
 
 #include "Layer.h"
 
-#include <SkSurface.h>
+#include <SkImage.h>
 
 namespace android {
 namespace uirenderer {
@@ -53,16 +53,22 @@
         return mBlend;
     }
 
-    sk_sp<SkSurface> getSurface() {
-        return mSurface;
+    sk_sp<SkImage> getImage() {
+        return mImage;
     }
 
+    void updateTexture();
+
+    // If we've destroyed the vulkan context (VkInstance, VkDevice, etc.), we must make sure to
+    // destroy any VkImages that were made with that context.
+    void onVkContextDestroyed();
+
 private:
     int mWidth;
     int mHeight;
     bool mBlend;
 
-   sk_sp<SkSurface> mSurface;
+   sk_sp<SkImage> mImage;
 
 }; // struct VkLayer
 
diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
index fb2134c..419c8a9 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
@@ -52,6 +52,11 @@
 
     canvas->flush();
 
+    if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
+        canvas->clear(SK_ColorRED);
+        return;
+    }
+
     SkImageInfo canvasInfo = canvas->imageInfo();
     SkMatrix44 mat4(canvas->getTotalMatrix());
 
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index 05d28e4..2ebfbcc 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -16,7 +16,10 @@
 
 #include "GlLayer.h"
 #include "LayerDrawable.h"
+#include "VkLayer.h"
+
 #include "SkColorFilter.h"
+#include "SkSurface.h"
 #include "gl/GrGLTypes.h"
 
 namespace android {
@@ -37,17 +40,26 @@
         canvas->concat(transform);
     }
 
-    GlLayer* glLayer = static_cast<GlLayer*>(layer);
-    GrGLTextureInfo externalTexture;
-    externalTexture.fTarget = glLayer->getRenderTarget();
-    externalTexture.fID = glLayer->getTextureId();
-    GrBackendTextureDesc textureDescription;
-    textureDescription.fWidth = glLayer->getWidth();
-    textureDescription.fHeight = glLayer->getHeight();
-    textureDescription.fConfig = kRGBA_8888_GrPixelConfig;
-    textureDescription.fOrigin = kTopLeft_GrSurfaceOrigin;
-    textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture);
-    sk_sp<SkImage> layerImage = SkImage::MakeFromTexture(context, textureDescription);
+    sk_sp<SkImage> layerImage;
+    if (layer->getApi() == Layer::Api::OpenGL) {
+        GlLayer* glLayer = static_cast<GlLayer*>(layer);
+        GrGLTextureInfo externalTexture;
+        externalTexture.fTarget = glLayer->getRenderTarget();
+        externalTexture.fID = glLayer->getTextureId();
+        GrBackendTextureDesc textureDescription;
+        textureDescription.fWidth = glLayer->getWidth();
+        textureDescription.fHeight = glLayer->getHeight();
+        textureDescription.fConfig = kRGBA_8888_GrPixelConfig;
+        textureDescription.fOrigin = kTopLeft_GrSurfaceOrigin;
+        textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture);
+        layerImage = SkImage::MakeFromTexture(context, textureDescription);
+    } else {
+        SkASSERT(layer->getApi() == Layer::Api::Vulkan);
+        VkLayer* vkLayer = static_cast<VkLayer*>(layer);
+        canvas->clear(SK_ColorGREEN);
+        layerImage = vkLayer->getImage();
+    }
+
     if (layerImage) {
         SkPaint paint;
         paint.setAlpha(layer->getAlpha());
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index a23e676..17ee390 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 #include "GlLayer.h"
+#include "VkLayer.h"
 #include <GpuMemoryTracker.h>
 #include "renderstate/RenderState.h"
 
@@ -41,7 +42,7 @@
 void RenderState::onGLContextCreated() {
     LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil,
             "State object lifecycle not managed correctly");
-    GpuMemoryTracker::onGLContextCreated();
+    GpuMemoryTracker::onGpuContextCreated();
 
     mBlend = new Blend();
     mMeshState = new MeshState();
@@ -78,7 +79,29 @@
     delete mStencil;
     mStencil = nullptr;
 
-    GpuMemoryTracker::onGLContextDestroyed();
+    GpuMemoryTracker::onGpuContextDestroyed();
+}
+
+void RenderState::onVkContextCreated() {
+    LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil,
+            "State object lifecycle not managed correctly");
+    GpuMemoryTracker::onGpuContextCreated();
+}
+
+static void layerDestroyedVkContext(Layer* layer) {
+    LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::Vulkan,
+                        "layerLostVkContext on non Vulkan layer");
+    static_cast<VkLayer*>(layer)->onVkContextDestroyed();
+}
+
+void RenderState::onVkContextDestroyed() {
+    mLayerPool.clear();
+    std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerDestroyedVkContext);
+    GpuMemoryTracker::onGpuContextDestroyed();
+}
+
+GrContext* RenderState::getGrContext() const {
+    return mRenderThread.getGrContext();
 }
 
 void RenderState::flush(Caches::FlushMode mode) {
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index 3d119dc..d183a15 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -35,6 +35,8 @@
 #include <utils/RefBase.h>
 #include <private/hwui/DrawGlInfo.h>
 
+class GrContext;
+
 namespace android {
 namespace uirenderer {
 
@@ -56,6 +58,9 @@
     void onGLContextCreated();
     void onGLContextDestroyed();
 
+    void onVkContextCreated();
+    void onVkContextDestroyed();
+
     void flush(Caches::FlushMode flushMode);
 
     void setViewport(GLsizei width, GLsizei height);
@@ -98,6 +103,8 @@
 
     OffscreenBufferPool& layerPool() { return mLayerPool; }
 
+    GrContext* getGrContext() const;
+
     void dump();
 
 private:
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 68c04af..2b90744 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -19,6 +19,7 @@
 #include "DeviceInfo.h"
 #include "Properties.h"
 #include "RenderThread.h"
+#include "renderstate/RenderState.h"
 
 #include <GrContext.h>
 #include <GrTypes.h>
@@ -37,10 +38,14 @@
 void VulkanManager::destroy() {
     if (!hasVkContext()) return;
 
+    mRenderThread.renderState().onVkContextDestroyed();
+    mRenderThread.setGrContext(nullptr);
+
     if (VK_NULL_HANDLE != mCommandPool) {
         mDestroyCommandPool(mBackendContext->fDevice, mCommandPool, nullptr);
         mCommandPool = VK_NULL_HANDLE;
     }
+    mBackendContext.reset();
 }
 
 void VulkanManager::initialize() {
@@ -105,6 +110,8 @@
     if (Properties::enablePartialUpdates && Properties::useBufferAge) {
         mSwapBehavior = SwapBehavior::BufferAge;
     }
+
+    mRenderThread.renderState().onVkContextCreated();
 }
 
 // Returns the next BackbufferInfo to use for the next draw. The function will make sure all
@@ -156,6 +163,9 @@
         if (!createSwapchain(surface)) {
             return nullptr;
         }
+        backbuffer = getAvailableBackbuffer(surface);
+        res = mResetFences(mBackendContext->fDevice, 2, backbuffer->mUsageFences);
+        SkASSERT(VK_SUCCESS == res);
 
         // acquire the image
         res = mAcquireNextImageKHR(mBackendContext->fDevice, surface->mSwapchain, UINT64_MAX,
diff --git a/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp b/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp
index aa1dcb2..8cbd24e 100644
--- a/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp
+++ b/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp
@@ -51,7 +51,7 @@
 TEST(GpuMemoryTracker, sizeCheck) {
     destroyEglContext();
 
-    GpuMemoryTracker::onGLContextCreated();
+    GpuMemoryTracker::onGpuContextCreated();
     ASSERT_EQ(0, GpuMemoryTracker::getTotalSize(GpuObjectType::Texture));
     ASSERT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::Texture));
     {
@@ -66,5 +66,5 @@
     }
     ASSERT_EQ(0, GpuMemoryTracker::getTotalSize(GpuObjectType::Texture));
     ASSERT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::Texture));
-    GpuMemoryTracker::onGLContextDestroyed();
+    GpuMemoryTracker::onGpuContextDestroyed();
 }