Add support for dummy draws for Vulkan webview and texture views.
Test: manual testing Change-Id: Iaec8c3a34367673c281665ff6c6e97d1ce532265
This commit is contained in:
@@ -116,6 +116,7 @@ hwui_src_files := \
|
||||
Texture.cpp \
|
||||
TextureCache.cpp \
|
||||
VectorDrawable.cpp \
|
||||
VkLayer.cpp \
|
||||
protos/hwui.proto
|
||||
|
||||
hwui_test_common_src_files := \
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
40
libs/hwui/VkLayer.cpp
Normal file
40
libs/hwui/VkLayer.cpp
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user