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();
}