Break Layer class into Gl and Vulkan subclasses

Test: manual testing
Change-Id: Ibd2beed39de3ac6da7448e96496253cfe427dfbb
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 18e59e5..f24c1fb 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -75,6 +75,7 @@
     FrameInfo.cpp \
     FrameInfoVisualizer.cpp \
     GammaFontRenderer.cpp \
+    GlLayer.cpp \
     GlopBuilder.cpp \
     GpuMemoryTracker.cpp \
     GradientCache.cpp \
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index b463e45..a0366de 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -17,7 +17,7 @@
 #include "Caches.h"
 
 #include "GammaFontRenderer.h"
-#include "Layer.h"
+#include "GlLayer.h"
 #include "Properties.h"
 #include "renderstate/RenderState.h"
 #include "ShadowTessellator.h"
@@ -170,9 +170,11 @@
         for (std::set<Layer*>::iterator it = mRenderState->mActiveLayers.begin();
                 it != mRenderState->mActiveLayers.end(); it++) {
             const Layer* layer = *it;
-            log.appendFormat("    Layer size %dx%d; texid=%u refs=%d\n",
+            LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::OpenGL);
+            const GlLayer* glLayer = static_cast<const GlLayer*>(layer);
+            log.appendFormat("    GlLayer size %dx%d; texid=%u refs=%d\n",
                     layer->getWidth(), layer->getHeight(),
-                    layer->getTextureId(),
+                    glLayer->getTextureId(),
                     layer->getStrongCount());
             memused += layer->getWidth() * layer->getHeight() * 4;
         }
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index a7d5f60..21aa6e1 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -15,6 +15,7 @@
  */
 #include "DeferredLayerUpdater.h"
 
+#include "GlLayer.h"
 #include "renderthread/EglManager.h"
 #include "renderthread/RenderTask.h"
 #include "utils/PaintUtils.h"
@@ -55,9 +56,12 @@
     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(mLayer->getTextureId());
+            mSurfaceTexture->attachToContext(static_cast<GlLayer*>(mLayer)->getTextureId());
         }
         if (mUpdateTexImage) {
             mUpdateTexImage = false;
@@ -71,6 +75,9 @@
 }
 
 void DeferredLayerUpdater::doUpdateTexImage() {
+    LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
+                        "doUpdateTexImage non GL backend %x, GL %x, VK %x",
+                        mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
     if (mSurfaceTexture->updateTexImage() == NO_ERROR) {
         float transform[16];
 
@@ -112,28 +119,36 @@
 
 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);
 
-    if (renderTarget != mLayer->getRenderTarget()) {
-        mLayer->setRenderTarget(renderTarget);
-        mLayer->bindTexture();
-        mLayer->setFilter(GL_NEAREST, false, true);
-        mLayer->setWrap(GL_CLAMP_TO_EDGE, false, true);
+    GlLayer* glLayer = static_cast<GlLayer*>(mLayer);
+    if (renderTarget != glLayer->getRenderTarget()) {
+        glLayer->setRenderTarget(renderTarget);
+        glLayer->bindTexture();
+        glLayer->setFilter(GL_NEAREST, false, true);
+        glLayer->setWrap(GL_CLAMP_TO_EDGE, false, true);
     }
 }
 
 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);
         }
         mSurfaceTexture = nullptr;
-        mLayer->clearTexture();
+        static_cast<GlLayer*>(mLayer)->clearTexture();
     }
 }
 
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 7335008..9be415f 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -22,6 +22,9 @@
 #include <SkMatrix.h>
 #include <utils/StrongPointer.h>
 
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
 #include "Layer.h"
 #include "Rect.h"
 #include "renderthread/RenderThread.h"
@@ -60,8 +63,8 @@
 
     ANDROID_API void setSurfaceTexture(const sp<GLConsumer>& texture, bool needsAttach) {
         if (texture.get() != mSurfaceTexture.get()) {
-            mNeedsGLContextAttach = needsAttach;
             mSurfaceTexture = texture;
+            mNeedsGLContextAttach = needsAttach;
 
             GLenum target = texture->getCurrentTextureTarget();
             LOG_ALWAYS_FATAL_IF(target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES,
diff --git a/libs/hwui/GlLayer.cpp b/libs/hwui/GlLayer.cpp
new file mode 100644
index 0000000..c0ab895
--- /dev/null
+++ b/libs/hwui/GlLayer.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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 "GlLayer.h"
+
+#include "Caches.h"
+#include "RenderNode.h"
+#include "renderstate/RenderState.h"
+#include "utils/TraceUtils.h"
+
+#include <utils/Log.h>
+
+#define ATRACE_LAYER_WORK(label) \
+    ATRACE_FORMAT("%s HW Layer DisplayList %s %ux%u", \
+            label, \
+            (renderNode.get() != NULL) ? renderNode->getName() : "", \
+            getWidth(), getHeight())
+
+namespace android {
+namespace uirenderer {
+
+GlLayer::GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight)
+        : Layer(renderState, Api::OpenGL)
+        , caches(Caches::getInstance())
+        , texture(caches) {
+    texture.mWidth = layerWidth;
+    texture.mHeight = layerHeight;
+}
+
+GlLayer::~GlLayer() {
+    if (texture.mId) {
+        texture.deleteTexture();
+    }
+}
+
+void GlLayer::onGlContextLost() {
+    texture.deleteTexture();
+}
+
+void GlLayer::bindTexture() const {
+    if (texture.mId) {
+        caches.textureState().bindTexture(texture.target(), texture.mId);
+    }
+}
+
+void GlLayer::generateTexture() {
+    if (!texture.mId) {
+        glGenTextures(1, &texture.mId);
+    }
+}
+
+void GlLayer::clearTexture() {
+    // There's a rare possibility that Caches could have been destroyed already
+    // since this method is queued up as a task.
+    // Since this is a reset method, treat this as non-fatal.
+    if (caches.isInitialized()) {
+        caches.textureState().unbindTexture(texture.mId);
+    }
+    texture.mId = 0;
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/GlLayer.h b/libs/hwui/GlLayer.h
new file mode 100644
index 0000000..54bf5ad
--- /dev/null
+++ b/libs/hwui/GlLayer.h
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Layer.h"
+
+#include "Texture.h"
+
+namespace android {
+namespace uirenderer {
+
+// Forward declarations
+class Caches;
+
+/**
+ * A layer has dimensions and is backed by an OpenGL texture or FBO.
+ */
+class GlLayer : public Layer {
+public:
+    GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight);
+    virtual ~GlLayer();
+
+    uint32_t getWidth() const override {
+        return texture.mWidth;
+    }
+
+    uint32_t getHeight() const override {
+        return texture.mHeight;
+    }
+
+    void setSize(uint32_t width, uint32_t height) override {
+        texture.updateSize(width, height, texture.internalFormat(), texture.format(),
+                texture.target());
+    }
+
+    void setBlend(bool blend) override {
+        texture.blend = blend;
+    }
+
+    bool isBlend() const override {
+        return texture.blend;
+    }
+
+    inline GLuint getTextureId() const {
+        return texture.id();
+    }
+
+    inline Texture& getTexture() {
+        return texture;
+    }
+
+    inline GLenum getRenderTarget() const {
+        return texture.target();
+    }
+
+    inline void setRenderTarget(GLenum renderTarget) {
+        texture.mTarget = renderTarget;
+    }
+
+    inline bool isRenderable() const {
+        return texture.target() != GL_NONE;
+    }
+
+    void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
+        texture.setWrap(wrap, bindTexture, force);
+    }
+
+    void setFilter(GLenum filter, bool bindTexture = false, bool force = false) {
+        texture.setFilter(filter, bindTexture, force);
+    }
+
+    void bindTexture() const;
+    void generateTexture();
+
+    /**
+     * When the caller frees the texture itself, the caller
+     * must call this method to tell this layer that it lost
+     * the texture.
+     */
+    void clearTexture();
+
+    /**
+     * Lost the GL context but the layer is still around, mark it invalid internally
+     * so the dtor knows not to do any GL work
+     */
+    void onGlContextLost();
+
+private:
+    Caches& caches;
+
+    /**
+     * The texture backing this layer.
+     */
+    Texture texture;
+}; // struct GlLayer
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 34e6d39..8a6e038 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -16,6 +16,7 @@
 #include "GlopBuilder.h"
 
 #include "Caches.h"
+#include "GlLayer.h"
 #include "Glop.h"
 #include "Layer.h"
 #include "Matrix.h"
@@ -440,7 +441,7 @@
     return *this;
 }
 
-GlopBuilder& GlopBuilder::setFillTextureLayer(Layer& layer, float alpha) {
+GlopBuilder& GlopBuilder::setFillTextureLayer(GlLayer& layer, float alpha) {
     TRIGGER_STAGE(kFillStage);
     REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
 
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index 8a8b652..87b1568 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -28,6 +28,7 @@
 namespace uirenderer {
 
 class Caches;
+class GlLayer;
 class Matrix4;
 class Patch;
 class RenderState;
@@ -71,7 +72,7 @@
     GlopBuilder& setFillClear();
     GlopBuilder& setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
             float alpha, SkBlendMode mode, Blend::ModeOrderSwap modeUsage);
-    GlopBuilder& setFillTextureLayer(Layer& layer, float alpha);
+    GlopBuilder& setFillTextureLayer(GlLayer& layer, float alpha);
     // TODO: setFillLayer normally forces its own wrap & filter mode,
     // which isn't always correct.
     GlopBuilder& setFillExternalTexture(Texture& texture, Matrix4& textureTransform);
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 88817ef..331bb81 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -16,77 +16,36 @@
 
 #include "Layer.h"
 
-#include "Caches.h"
-#include "RenderNode.h"
 #include "renderstate/RenderState.h"
-#include "utils/TraceUtils.h"
 
-#include <utils/Log.h>
-
-#define ATRACE_LAYER_WORK(label) \
-    ATRACE_FORMAT("%s HW Layer DisplayList %s %ux%u", \
-            label, \
-            (renderNode.get() != NULL) ? renderNode->getName() : "", \
-            getWidth(), getHeight())
+#include <SkColorFilter.h>
 
 namespace android {
 namespace uirenderer {
 
-Layer::Layer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight)
+Layer::Layer(RenderState& renderState, Api api)
         : GpuMemoryTracker(GpuObjectType::Layer)
-        , state(State::Uncached)
-        , caches(Caches::getInstance())
-        , renderState(renderState)
-        , texture(caches) {
+        , mRenderState(renderState)
+        , mApi(api) {
     // TODO: This is a violation of Android's typical ref counting, but it
     // preserves the old inc/dec ref locations. This should be changed...
     incStrong(nullptr);
-    texture.mWidth = layerWidth;
-    texture.mHeight = layerHeight;
+
     renderState.registerLayer(this);
 }
 
 Layer::~Layer() {
-    renderState.unregisterLayer(this);
     SkSafeUnref(colorFilter);
 
-    if (texture.mId) {
-        texture.deleteTexture();
-    }
-}
-
-void Layer::onGlContextLost() {
-    texture.deleteTexture();
+    mRenderState.unregisterLayer(this);
 }
 
 void Layer::setColorFilter(SkColorFilter* filter) {
     SkRefCnt_SafeAssign(colorFilter, filter);
 }
 
-void Layer::bindTexture() const {
-    if (texture.mId) {
-        caches.textureState().bindTexture(texture.target(), texture.mId);
-    }
-}
-
-void Layer::generateTexture() {
-    if (!texture.mId) {
-        glGenTextures(1, &texture.mId);
-    }
-}
-
-void Layer::clearTexture() {
-    // There's a rare possibility that Caches could have been destroyed already
-    // since this method is queued up as a task.
-    // Since this is a reset method, treat this as non-fatal.
-    if (caches.isInitialized()) {
-        caches.textureState().unbindTexture(texture.mId);
-    }
-    texture.mId = 0;
-}
-
 void Layer::postDecStrong() {
-    renderState.postDecStrong(this);
+    mRenderState.postDecStrong(this);
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 8e71cd1..3b639ee 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -16,25 +16,13 @@
 
 #pragma once
 
-#include <cutils/compiler.h>
-#include <sys/types.h>
-#include <utils/StrongPointer.h>
 #include <utils/RefBase.h>
-#include <memory>
-
-#include <GLES2/gl2.h>
 #include <GpuMemoryTracker.h>
 
-#include <ui/Region.h>
-
 #include <SkPaint.h>
 #include <SkBlendMode.h>
 
 #include "Matrix.h"
-#include "Rect.h"
-#include "RenderBuffer.h"
-#include "Texture.h"
-#include "Vertex.h"
 
 namespace android {
 namespace uirenderer {
@@ -43,49 +31,33 @@
 // Layers
 ///////////////////////////////////////////////////////////////////////////////
 
-// Forward declarations
-class Caches;
 class RenderState;
 
 /**
- * A layer has dimensions and is backed by an OpenGL texture or FBO.
+ * A layer has dimensions and is backed by a backend specific texture or framebuffer.
  */
 class Layer : public VirtualLightRefBase, GpuMemoryTracker {
 public:
-    // layer lifecycle, controlled from outside
-    enum class State {
-        Uncached = 0,
-        InCache = 1,
-        FailedToCache = 2,
-        RemovedFromCache = 3,
-        DeletedFromCache = 4,
-        InGarbageList = 5,
+    enum class Api {
+        OpenGL = 0,
+        Vulkan = 1,
     };
-    State state; // public for logging/debugging purposes
 
-    Layer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight);
+    Api getApi() const {
+        return mApi;
+    }
+
     ~Layer();
 
-    inline uint32_t getWidth() const {
-        return texture.mWidth;
-    }
+    virtual uint32_t getWidth() const = 0;
 
-    inline uint32_t getHeight() const {
-        return texture.mHeight;
-    }
+    virtual uint32_t getHeight() const = 0;
 
-    void setSize(uint32_t width, uint32_t height) {
-        texture.updateSize(width, height, texture.internalFormat(), texture.format(),
-                texture.target());
-    }
+    virtual void setSize(uint32_t width, uint32_t height) = 0;
 
-    inline void setBlend(bool blend) {
-        texture.blend = blend;
-    }
+    virtual void setBlend(bool blend) = 0;
 
-    inline bool isBlend() const {
-        return texture.blend;
-    }
+    virtual bool isBlend() const = 0;
 
     inline void setForceFilter(bool forceFilter) {
         this->forceFilter = forceFilter;
@@ -112,50 +84,12 @@
         return mode;
     }
 
-    inline GLuint getTextureId() const {
-        return texture.id();
-    }
-
-    inline Texture& getTexture() {
-        return texture;
-    }
-
-    inline GLenum getRenderTarget() const {
-        return texture.target();
-    }
-
-    inline void setRenderTarget(GLenum renderTarget) {
-        texture.mTarget = renderTarget;
-    }
-
-    inline bool isRenderable() const {
-        return texture.target() != GL_NONE;
-    }
-
-    void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
-        texture.setWrap(wrap, bindTexture, force);
-    }
-
-    void setFilter(GLenum filter, bool bindTexture = false, bool force = false) {
-        texture.setFilter(filter, bindTexture, force);
-    }
-
     inline SkColorFilter* getColorFilter() const {
         return colorFilter;
     }
 
     void setColorFilter(SkColorFilter* filter);
 
-    void bindTexture() const;
-    void generateTexture();
-
-    /**
-     * When the caller frees the texture itself, the caller
-     * must call this method to tell this layer that it lost
-     * the texture.
-     */
-    void clearTexture();
-
     inline mat4& getTexTransform() {
         return texTransform;
     }
@@ -170,21 +104,13 @@
      */
     void postDecStrong();
 
-    /**
-     * Lost the GL context but the layer is still around, mark it invalid internally
-     * so the dtor knows not to do any GL work
-     */
-    void onGlContextLost();
+protected:
+    Layer(RenderState& renderState, Api api);
+
+    RenderState& mRenderState;
 
 private:
-    Caches& caches;
-
-    RenderState& renderState;
-
-    /**
-     * The texture backing this layer.
-     */
-    Texture texture;
+    Api mApi;
 
     /**
      * Color filter used to draw this layer. Optional.
diff --git a/libs/hwui/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp
index 938b6ef..c460c0d 100644
--- a/libs/hwui/OpenGLReadback.cpp
+++ b/libs/hwui/OpenGLReadback.cpp
@@ -19,7 +19,7 @@
 #include "Caches.h"
 #include "Image.h"
 #include "GlopBuilder.h"
-#include "Layer.h"
+#include "GlLayer.h"
 #include "renderstate/RenderState.h"
 #include "renderthread/EglManager.h"
 #include "utils/GLUtils.h"
@@ -262,7 +262,7 @@
 }
 
 bool OpenGLReadbackImpl::copyLayerInto(renderthread::RenderThread& renderThread,
-        Layer& layer, SkBitmap* bitmap) {
+        GlLayer& layer, SkBitmap* bitmap) {
     return CopyResult::Success == copyTextureInto(Caches::getInstance(),
             renderThread.renderState(), layer.getTexture(), layer.getTexTransform(),
             Rect(), bitmap);
diff --git a/libs/hwui/OpenGLReadback.h b/libs/hwui/OpenGLReadback.h
index f4ebabc..c9222cf 100644
--- a/libs/hwui/OpenGLReadback.h
+++ b/libs/hwui/OpenGLReadback.h
@@ -22,7 +22,7 @@
 namespace uirenderer {
 
 class Matrix4;
-class Layer;
+class GlLayer;
 
 class OpenGLReadback : public Readback {
 public:
@@ -49,7 +49,7 @@
     /**
      * Copies the layer's contents into the provided bitmap.
      */
-    static bool copyLayerInto(renderthread::RenderThread& renderThread, Layer& layer,
+    static bool copyLayerInto(renderthread::RenderThread& renderThread, GlLayer& layer,
             SkBitmap* bitmap);
 
 protected:
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index f9a7c36f2..dea2be6 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include "font/FontUtil.h"
+#include "GlLayer.h"
 #include "Matrix.h"
 #include "Rect.h"
 #include "RenderNode.h"
@@ -413,7 +414,7 @@
 };
 
 struct TextureLayerOp : RecordedOp {
-    TextureLayerOp(BASE_PARAMS_PAINTLESS, Layer* layer)
+    TextureLayerOp(BASE_PARAMS_PAINTLESS, GlLayer* layer)
             : SUPER_PAINTLESS(TextureLayerOp)
             , layer(layer) {}
 
@@ -424,7 +425,7 @@
             , layer(op.layer) {
 
     }
-    Layer* layer;
+    GlLayer* layer;
 };
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index ee6279d..b5e5d68 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -606,13 +606,14 @@
     // We ref the DeferredLayerUpdater due to its thread-safe ref-counting semantics.
     mDisplayList->ref(layerHandle);
 
+    LOG_ALWAYS_FATAL_IF(layerHandle->backingLayer()->getApi() != Layer::Api::OpenGL);
     // Note that the backing layer has *not* yet been updated, so don't trust
     // its width, height, transform, etc...!
     addOp(alloc().create_trivial<TextureLayerOp>(
             Rect(layerHandle->getWidth(), layerHandle->getHeight()),
             *(mState.currentSnapshot()->transform),
             getRecordedClip(),
-            layerHandle->backingLayer()));
+            static_cast<GlLayer*>(layerHandle->backingLayer())));
 }
 
 void RecordingCanvas::callDrawGLFunction(Functor* functor,
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index fadb960..9239986 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -18,7 +18,6 @@
 
 #include "Caches.h"
 #include "Extensions.h"
-#include "Layer.h"
 #include "Matrix.h"
 #include "Texture.h"
 #include "hwui/Bitmap.h"
@@ -317,42 +316,6 @@
     return true;
 }
 
-bool tryStoreLayer(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
-        GLuint* textureUnit, ProgramDescription* description,
-        SkiaShaderData::LayerShaderData* outData) {
-    Layer* layer;
-    if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) {
-        return false;
-    }
-
-    description->hasBitmap = true;
-    outData->layer = layer;
-    outData->bitmapSampler = (*textureUnit)++;
-
-    const float width = layer->getWidth();
-    const float height = layer->getHeight();
-
-    computeScreenSpaceMatrix(outData->textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
-            modelViewMatrix);
-
-    outData->textureDimension[0] = 1.0f / width;
-    outData->textureDimension[1] = 1.0f / height;
-    return true;
-}
-
-void applyLayer(Caches& caches, const SkiaShaderData::LayerShaderData& data) {
-    caches.textureState().activateTexture(data.bitmapSampler);
-
-    data.layer->bindTexture();
-    data.layer->setWrap(GL_CLAMP_TO_EDGE);
-    data.layer->setFilter(GL_LINEAR);
-
-    glUniform1i(caches.program().getUniform("bitmapSampler"), data.bitmapSampler);
-    glUniformMatrix4fv(caches.program().getUniform("textureTransform"), 1,
-            GL_FALSE, &data.textureTransform.data[0]);
-    glUniform2fv(caches.program().getUniform("textureDimension"), 1, &data.textureDimension[0]);
-}
-
 void SkiaShader::store(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
         GLuint* textureUnit, ProgramDescription* description,
         SkiaShaderData* outData) {
@@ -374,12 +337,6 @@
         return;
     }
 
-    if (tryStoreLayer(caches, shader, modelViewMatrix,
-            textureUnit, description, &outData->layerData)) {
-        outData->skiaShaderType = kLayer_SkiaShaderType;
-        return;
-    }
-
     // Unknown/unsupported type, so explicitly ignore shader
     outData->skiaShaderType = kNone_SkiaShaderType;
 }
@@ -394,10 +351,6 @@
     if (data.skiaShaderType & kBitmap_SkiaShaderType) {
         applyBitmap(caches, data.bitmapData);
     }
-
-    if (data.skiaShaderType == kLayer_SkiaShaderType) {
-        applyLayer(caches, data.layerData);
-    }
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index d2f37cd..ab578d5 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -29,7 +29,6 @@
 
 class Caches;
 class Extensions;
-class Layer;
 class Texture;
 struct ProgramDescription;
 
@@ -45,7 +44,6 @@
     kBitmap_SkiaShaderType = 1,
     kGradient_SkiaShaderType = 2,
     kCompose_SkiaShaderType = kBitmap_SkiaShaderType | kGradient_SkiaShaderType,
-    kLayer_SkiaShaderType = 4,
 };
 
 struct SkiaShaderData {
@@ -71,15 +69,6 @@
         GLuint gradientSampler;
         GLenum wrapST;
     } gradientData;
-    struct LayerShaderData {
-        Layer* layer;
-        GLuint bitmapSampler;
-        GLenum wrapS;
-        GLenum wrapT;
-
-        Matrix4 textureTransform;
-        float textureDimension[2];
-    } layerData;
 };
 
 class SkiaShader {
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index c75e88f..b8397cc 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -159,10 +159,10 @@
      */
     void* isInUse = nullptr;
 private:
-    // TODO: Temporarily grant private access to Layer, remove once
-    // Layer can be de-tangled from being a dual-purpose render target
+    // TODO: Temporarily grant private access to GlLayer, remove once
+    // GlLayer can be de-tangled from being a dual-purpose render target
     // and external texture wrapper
-    friend class Layer;
+    friend class GlLayer;
 
     // Returns true if the size changed, false if it was the same
     bool updateSize(uint32_t width, uint32_t height, GLint internalFormat,
diff --git a/libs/hwui/VkLayer.h b/libs/hwui/VkLayer.h
new file mode 100644
index 0000000..353939f
--- /dev/null
+++ b/libs/hwui/VkLayer.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Layer.h"
+
+#include <SkSurface.h>
+
+namespace android {
+namespace uirenderer {
+/**
+ * A layer has dimensions and is backed by a VkImage.
+ */
+class VkLayer : public Layer {
+public:
+    VkLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight)
+            : Layer(renderState, Api::Vulkan) {}
+
+    virtual ~VkLayer() {}
+
+    uint32_t getWidth() const override {
+        return mWidth;
+    }
+
+    uint32_t getHeight() const override {
+        return mHeight;
+    }
+
+    void setSize(uint32_t width, uint32_t height) override {
+        mWidth = width;
+        mHeight = height;
+    }
+
+    void setBlend(bool blend) override {
+        mBlend = blend;
+    }
+
+    bool isBlend() const override {
+        return mBlend;
+    }
+
+    sk_sp<SkSurface> getSurface() {
+        return mSurface;
+    }
+
+private:
+    int mWidth;
+    int mHeight;
+    bool mBlend;
+
+   sk_sp<SkSurface> mSurface;
+
+}; // struct VkLayer
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index f2af4a8..05d28e4 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "GlLayer.h"
 #include "LayerDrawable.h"
 #include "SkColorFilter.h"
 #include "gl/GrGLTypes.h"
@@ -35,12 +36,14 @@
         layer->getTransform().copyTo(transform);
         canvas->concat(transform);
     }
+
+    GlLayer* glLayer = static_cast<GlLayer*>(layer);
     GrGLTextureInfo externalTexture;
-    externalTexture.fTarget = layer->getRenderTarget();
-    externalTexture.fID = layer->getTextureId();
+    externalTexture.fTarget = glLayer->getRenderTarget();
+    externalTexture.fID = glLayer->getTextureId();
     GrBackendTextureDesc textureDescription;
-    textureDescription.fWidth = layer->getWidth();
-    textureDescription.fHeight = layer->getHeight();
+    textureDescription.fWidth = glLayer->getWidth();
+    textureDescription.fHeight = glLayer->getHeight();
     textureDescription.fConfig = kRGBA_8888_GrPixelConfig;
     textureDescription.fOrigin = kTopLeft_GrSurfaceOrigin;
     textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture);
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index c8258f7..65a1dc3 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -17,6 +17,7 @@
 #include "SkiaOpenGLPipeline.h"
 
 #include "DeferredLayerUpdater.h"
+#include "GlLayer.h"
 #include "LayerDrawable.h"
 #include "renderthread/EglManager.h"
 #include "renderthread/Frame.h"
@@ -136,7 +137,7 @@
 
 DeferredLayerUpdater* SkiaOpenGLPipeline::createTextureLayer() {
     mEglManager.initialize();
-    Layer* layer = new Layer(mRenderThread.renderState(), 0, 0);
+    GlLayer* layer = new GlLayer(mRenderThread.renderState(), 0, 0);
     layer->generateTexture();
     return new DeferredLayerUpdater(layer);
 }
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 0d3f4ef..910c339 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -22,6 +22,7 @@
 #include "renderstate/RenderState.h"
 #include "SkiaPipeline.h"
 #include "SkiaProfileRenderer.h"
+#include "VkLayer.h"
 
 #include <SkSurface.h>
 #include <SkTypes.h>
@@ -119,7 +120,8 @@
 
 DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
     mVkManager.initialize();
-    Layer* layer = new Layer(mRenderThread.renderState(), 0, 0);
+
+    VkLayer* layer = new VkLayer(mRenderThread.renderState(), 0, 0);
     return new DeferredLayerUpdater(layer);
 }
 
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 72af7c9..a23e676 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include "GlLayer.h"
 #include <GpuMemoryTracker.h>
 #include "renderstate/RenderState.h"
 
@@ -55,7 +56,9 @@
 }
 
 static void layerLostGlContext(Layer* layer) {
-    layer->onGlContextLost();
+    LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::OpenGL,
+            "layerLostGlContext on non GL layer");
+    static_cast<GlLayer*>(layer)->onGlContextLost();
 }
 
 void RenderState::onGLContextDestroyed() {
diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp
index df08599..df40a44 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.cpp
+++ b/libs/hwui/renderthread/OpenGLPipeline.cpp
@@ -19,6 +19,7 @@
 #include "DeferredLayerUpdater.h"
 #include "EglManager.h"
 #include "Frame.h"
+#include "GlLayer.h"
 #include "ProfileRenderer.h"
 #include "renderstate/RenderState.h"
 #include "OpenGLReadback.h"
@@ -120,12 +121,13 @@
 bool OpenGLPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
     ATRACE_CALL();
     layer->apply();
-    return OpenGLReadbackImpl::copyLayerInto(mRenderThread, *(layer->backingLayer()), bitmap);
+    return OpenGLReadbackImpl::copyLayerInto(mRenderThread,
+            static_cast<GlLayer&>(*layer->backingLayer()), bitmap);
 }
 
 DeferredLayerUpdater* OpenGLPipeline::createTextureLayer() {
     mEglManager.initialize();
-    Layer* layer = new Layer(mRenderThread.renderState(), 0, 0);
+    GlLayer* layer = new GlLayer(mRenderThread.renderState(), 0, 0);
     Caches::getInstance().textureState().activateTexture(0);
     layer->generateTexture();
 
diff --git a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
index 0326aa9..f1b8882 100644
--- a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
+++ b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "DeferredLayerUpdater.h"
+#include "GlLayer.h"
 
 #include "renderthread/OpenGLPipeline.h"
 #include "tests/common/TestUtils.h"
@@ -32,7 +33,10 @@
 
 
     // updates are deferred so the backing layer should still be in its default state
-    EXPECT_EQ((uint32_t)GL_NONE, layerUpdater->backingLayer()->getRenderTarget());
+    if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
+        GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
+        EXPECT_EQ((uint32_t)GL_NONE, glLayer->getRenderTarget());
+    }
     EXPECT_EQ(0u, layerUpdater->backingLayer()->getWidth());
     EXPECT_EQ(0u, layerUpdater->backingLayer()->getHeight());
     EXPECT_FALSE(layerUpdater->backingLayer()->getForceFilter());
@@ -45,7 +49,10 @@
     layerUpdater->updateLayer(true, GL_TEXTURE_EXTERNAL_OES, scaledMatrix.data);
 
     // the backing layer should now have all the properties applied.
-    EXPECT_EQ((uint32_t)GL_TEXTURE_EXTERNAL_OES, layerUpdater->backingLayer()->getRenderTarget());
+    if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
+        GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
+        EXPECT_EQ((uint32_t)GL_TEXTURE_EXTERNAL_OES, glLayer->getRenderTarget());
+    }
     EXPECT_EQ(100u, layerUpdater->backingLayer()->getWidth());
     EXPECT_EQ(100u, layerUpdater->backingLayer()->getHeight());
     EXPECT_TRUE(layerUpdater->backingLayer()->getForceFilter());
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 21394ae..71c7516 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -19,6 +19,7 @@
 #include <BakedOpState.h>
 #include <DeferredLayerUpdater.h>
 #include <FrameBuilder.h>
+#include <GlLayer.h>
 #include <LayerUpdateQueue.h>
 #include <RecordedOp.h>
 #include <RecordingCanvas.h>
@@ -698,7 +699,10 @@
 RENDERTHREAD_TEST(FrameBuilder, textureLayer_reject) {
     auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
             SkMatrix::MakeTrans(5, 5));
-    layerUpdater->backingLayer()->setRenderTarget(GL_NONE); // Should be rejected
+    if (layerUpdater->backingLayer()->getApi() != Layer::Api::OpenGL) return;
+
+    GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
+    glLayer->setRenderTarget(GL_NONE); // Should be rejected
 
     auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
             [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {