diff options
author | 2017-01-04 14:27:00 -0500 | |
---|---|---|
committer | 2017-01-10 15:54:14 -0500 | |
commit | 45ec62ba72c5017fae7d8baab20bfb0d4c99c627 (patch) | |
tree | ad2314dad22323b16837f7ec219e1bdef3e2290c | |
parent | 8cd3edfa15cc9cdbffa935d19ab894426b08d174 (diff) |
Add support for dummy draws for Vulkan webview and texture views.
Test: manual testing
Change-Id: Iaec8c3a34367673c281665ff6c6e97d1ce532265
-rw-r--r-- | libs/hwui/Android.mk | 1 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.cpp | 67 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.h | 4 | ||||
-rw-r--r-- | libs/hwui/GpuMemoryTracker.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/GpuMemoryTracker.h | 4 | ||||
-rw-r--r-- | libs/hwui/VkLayer.cpp | 40 | ||||
-rw-r--r-- | libs/hwui/VkLayer.h | 14 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/GLFunctorDrawable.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/LayerDrawable.cpp | 34 | ||||
-rw-r--r-- | libs/hwui/renderstate/RenderState.cpp | 27 | ||||
-rw-r--r-- | libs/hwui/renderstate/RenderState.h | 7 | ||||
-rw-r--r-- | libs/hwui/renderthread/VulkanManager.cpp | 10 | ||||
-rw-r--r-- | libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp | 4 |
13 files changed, 177 insertions, 48 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index f24c1fb7c06d..8f7787bd5d15 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -116,6 +116,7 @@ hwui_src_files := \ 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 21aa6e1f5705..3e8e8a1a1ca3 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 @@ void DeferredLayerUpdater::apply() { 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::doUpdateTexImage() { } } +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, GLenum renderTarget, } } +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 9be415f4d216..ead83144f4d4 100644 --- a/libs/hwui/DeferredLayerUpdater.h +++ b/libs/hwui/DeferredLayerUpdater.h @@ -63,8 +63,8 @@ public: 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 @@ private: 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 4fb57019264d..a52ec8738015 100644 --- a/libs/hwui/GpuMemoryTracker.cpp +++ b/libs/hwui/GpuMemoryTracker.cpp @@ -67,13 +67,13 @@ void GpuMemoryTracker::stopTrackingObject() { 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 bfb1bf1ba098..f94fe2862a31 100644 --- a/libs/hwui/GpuMemoryTracker.h +++ b/libs/hwui/GpuMemoryTracker.h @@ -43,8 +43,8 @@ public: 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 000000000000..391acf13acd0 --- /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 353939f73b69..39522b3c0dda 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 @@ public: 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 fb2134c51e22..419c8a99fe74 100644 --- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp +++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp @@ -52,6 +52,11 @@ void GLFunctorDrawable::onDraw(SkCanvas* canvas) { 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 05d28e40f71c..2ebfbcc1f18e 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 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer 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 a23e676ea996..17ee390c90bd 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 @@ RenderState::~RenderState() { 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 @@ void RenderState::onGLContextDestroyed() { 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 3d119dc9e290..d183a15f3842 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 @@ public: void onGLContextCreated(); void onGLContextDestroyed(); + void onVkContextCreated(); + void onVkContextDestroyed(); + void flush(Caches::FlushMode flushMode); void setViewport(GLsizei width, GLsizei height); @@ -98,6 +103,8 @@ public: 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 68c04afb2e08..2b9074499c2a 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 @@ VulkanManager::VulkanManager(RenderThread& thread) : mRenderThread(thread) { 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 @@ void VulkanManager::initialize() { 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 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) { 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 aa1dcb2ea51b..8cbd24edbde2 100644 --- a/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp +++ b/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp @@ -51,7 +51,7 @@ static void destroyEglContext() { 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 @@ TEST(GpuMemoryTracker, sizeCheck) { } ASSERT_EQ(0, GpuMemoryTracker::getTotalSize(GpuObjectType::Texture)); ASSERT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::Texture)); - GpuMemoryTracker::onGLContextDestroyed(); + GpuMemoryTracker::onGpuContextDestroyed(); } |