Explicitly destroy Layer in DeferredLayerUpdater on destroyHardwareResources()

Change-Id: I0987104eabda9a2a302b9e765213aad48f93aea4
Test: refactoring CL. Existing tests still pass
bug:33753499
This commit is contained in:
sergeyv
2017-01-19 15:37:02 -08:00
parent df9a4f9a7c
commit 3e9999bd86
18 changed files with 139 additions and 52 deletions

View File

@@ -18,6 +18,7 @@
#include "BakedOpRenderer.h"
#include "Caches.h"
#include "DeferredLayerUpdater.h"
#include "Glop.h"
#include "GlopBuilder.h"
#include "Patch.h"
@@ -762,15 +763,19 @@ void BakedOpDispatcher::onTextOnPathOp(BakedOpRenderer& renderer, const TextOnPa
}
void BakedOpDispatcher::onTextureLayerOp(BakedOpRenderer& renderer, const TextureLayerOp& op, const BakedOpState& state) {
const bool tryToSnap = !op.layer->getForceFilter();
float alpha = (op.layer->getAlpha() / 255.0f) * state.alpha;
GlLayer* layer = static_cast<GlLayer*>(op.layerHandle->backingLayer());
if (!layer) {
return;
}
const bool tryToSnap = layer->getForceFilter();
float alpha = (layer->getAlpha() / 255.0f) * state.alpha;
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
.setRoundRectClipState(state.roundRectClipState)
.setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
.setFillTextureLayer(*(op.layer), alpha)
.setFillTextureLayer(*(layer), alpha)
.setTransform(state.computedState.transform, TransformFlags::None)
.setModelViewMapUnitToRectOptionalSnap(tryToSnap, Rect(op.layer->getWidth(), op.layer->getHeight()))
.setModelViewMapUnitToRectOptionalSnap(tryToSnap, Rect(layer->getWidth(), layer->getHeight()))
.build();
renderer.renderGlop(state, glop);
}

View File

@@ -17,6 +17,7 @@
#include "GlLayer.h"
#include "VkLayer.h"
#include "renderstate/RenderState.h"
#include "renderthread/EglManager.h"
#include "renderthread/RenderTask.h"
#include "utils/PaintUtils.h"
@@ -24,25 +25,32 @@
namespace android {
namespace uirenderer {
DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer)
: mSurfaceTexture(nullptr)
DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState, CreateLayerFn createLayerFn,
Layer::Api layerApi)
: mRenderState(renderState)
, mBlend(false)
, mSurfaceTexture(nullptr)
, mTransform(nullptr)
, mNeedsGLContextAttach(false)
, mUpdateTexImage(false)
, mLayer(layer) {
mWidth = mLayer->getWidth();
mHeight = mLayer->getHeight();
mBlend = mLayer->isBlend();
mColorFilter = SkSafeRef(mLayer->getColorFilter());
mAlpha = mLayer->getAlpha();
mMode = mLayer->getMode();
, mLayer(nullptr)
, mLayerApi(layerApi)
, mCreateLayerFn(createLayerFn) {
renderState.registerDeferredLayerUpdater(this);
}
DeferredLayerUpdater::~DeferredLayerUpdater() {
SkSafeUnref(mColorFilter);
setTransform(nullptr);
mLayer->postDecStrong();
mLayer = nullptr;
mRenderState.unregisterDeferredLayerUpdater(this);
destroyLayer();
}
void DeferredLayerUpdater::destroyLayer() {
if (mLayer) {
mLayer->postDecStrong();
mLayer = nullptr;
}
}
void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
@@ -53,6 +61,10 @@ void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
}
void DeferredLayerUpdater::apply() {
if (!mLayer) {
mLayer = mCreateLayerFn(mRenderState, mWidth, mHeight, mColorFilter, mAlpha, mMode, mBlend);
}
mLayer->setColorFilter(mColorFilter);
mLayer->setAlpha(mAlpha, mMode);

View File

@@ -32,13 +32,20 @@
namespace android {
namespace uirenderer {
class RenderState;
// Container to hold the properties a layer should be set to at the start
// of a render pass
class DeferredLayerUpdater : public VirtualLightRefBase {
public:
// Note that DeferredLayerUpdater assumes it is taking ownership of the layer
// and will not call incrementRef on it as a result.
ANDROID_API explicit DeferredLayerUpdater(Layer* layer);
typedef std::function<Layer*(RenderState& renderState, uint32_t layerWidth,
uint32_t layerHeight, SkColorFilter* colorFilter, int alpha,
SkBlendMode mode, bool blend)> CreateLayerFn;
ANDROID_API explicit DeferredLayerUpdater(RenderState& renderState,
CreateLayerFn createLayerFn, Layer::Api layerApi);
ANDROID_API ~DeferredLayerUpdater();
ANDROID_API bool setSize(int width, int height) {
@@ -97,20 +104,30 @@ public:
void updateLayer(bool forceFilter, GLenum renderTarget, const float* textureTransform);
void destroyLayer();
Layer::Api getBackingLayerApi() {
return mLayerApi;
}
private:
RenderState& mRenderState;
// Generic properties
int mWidth;
int mHeight;
bool mBlend;
SkColorFilter* mColorFilter;
int mAlpha;
SkBlendMode mMode;
int mWidth = 0;
int mHeight = 0;
bool mBlend = false;
SkColorFilter* mColorFilter = nullptr;
int mAlpha = 255;
SkBlendMode mMode = SkBlendMode::kSrcOver;
sp<GLConsumer> mSurfaceTexture;
SkMatrix* mTransform;
bool mNeedsGLContextAttach;
bool mUpdateTexImage;
Layer* mLayer;
Layer::Api mLayerApi;
CreateLayerFn mCreateLayerFn;
void doUpdateTexImage();
void doUpdateVkTexImage();

View File

@@ -16,6 +16,7 @@
#include "FrameBuilder.h"
#include "DeferredLayerUpdater.h"
#include "LayerUpdateQueue.h"
#include "RenderNode.h"
#include "VectorDrawable.h"
@@ -784,14 +785,15 @@ void FrameBuilder::deferTextOnPathOp(const TextOnPathOp& op) {
}
void FrameBuilder::deferTextureLayerOp(const TextureLayerOp& op) {
if (CC_UNLIKELY(!op.layer->isRenderable())) return;
GlLayer* layer = static_cast<GlLayer*>(op.layerHandle->backingLayer());
if (CC_UNLIKELY(!layer || !layer->isRenderable())) return;
const TextureLayerOp* textureLayerOp = &op;
// Now safe to access transform (which was potentially unready at record time)
if (!op.layer->getTransform().isIdentity()) {
if (!layer->getTransform().isIdentity()) {
// non-identity transform present, so 'inject it' into op by copying + replacing matrix
Matrix4 combinedMatrix(op.localMatrix);
combinedMatrix.multiply(op.layer->getTransform());
combinedMatrix.multiply(layer->getTransform());
textureLayerOp = mAllocator.create<TextureLayerOp>(op, combinedMatrix);
}
BakedOpState* bakedState = tryBakeOpState(*textureLayerOp);

View File

@@ -32,12 +32,14 @@
namespace android {
namespace uirenderer {
GlLayer::GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight)
: Layer(renderState, Api::OpenGL)
GlLayer::GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend)
: Layer(renderState, Api::OpenGL, colorFilter, alpha, mode)
, caches(Caches::getInstance())
, texture(caches) {
texture.mWidth = layerWidth;
texture.mHeight = layerHeight;
texture.blend = blend;
}
GlLayer::~GlLayer() {

View File

@@ -31,7 +31,8 @@ class Caches;
*/
class GlLayer : public Layer {
public:
GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight);
GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend);
virtual ~GlLayer();
uint32_t getWidth() const override {

View File

@@ -23,10 +23,14 @@
namespace android {
namespace uirenderer {
Layer::Layer(RenderState& renderState, Api api)
Layer::Layer(RenderState& renderState, Api api, SkColorFilter* colorFilter, int alpha,
SkBlendMode mode)
: GpuMemoryTracker(GpuObjectType::Layer)
, mRenderState(renderState)
, mApi(api) {
, mApi(api)
, colorFilter(nullptr)
, alpha(alpha)
, mode(mode) {
// 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);

View File

@@ -105,7 +105,8 @@ public:
void postDecStrong();
protected:
Layer(RenderState& renderState, Api api);
Layer(RenderState& renderState, Api api, SkColorFilter* colorFilter, int alpha,
SkBlendMode mode);
RenderState& mRenderState;
@@ -115,7 +116,7 @@ private:
/**
* Color filter used to draw this layer. Optional.
*/
SkColorFilter* colorFilter = nullptr;
SkColorFilter* colorFilter;
/**
* Indicates raster data backing the layer is scaled, requiring filtration.
@@ -125,12 +126,12 @@ private:
/**
* Opacity of the layer.
*/
int alpha = 255;
int alpha;
/**
* Blending mode of the layer.
*/
SkBlendMode mode = SkBlendMode::kSrcOver;
SkBlendMode mode;
/**
* Optional texture coordinates transform.

View File

@@ -37,6 +37,8 @@ namespace uirenderer {
struct ClipBase;
class OffscreenBuffer;
class RenderNode;
class DeferredLayerUpdater;
struct Vertex;
namespace VectorDrawable {
@@ -414,18 +416,18 @@ struct TextOnPathOp : RecordedOp {
};
struct TextureLayerOp : RecordedOp {
TextureLayerOp(BASE_PARAMS_PAINTLESS, GlLayer* layer)
TextureLayerOp(BASE_PARAMS_PAINTLESS, DeferredLayerUpdater* layer)
: SUPER_PAINTLESS(TextureLayerOp)
, layer(layer) {}
, layerHandle(layer) {}
// Copy an existing TextureLayerOp, replacing the underlying matrix
TextureLayerOp(const TextureLayerOp& op, const Matrix4& replacementMatrix)
: RecordedOp(RecordedOpId::TextureLayerOp, op.unmappedBounds, replacementMatrix,
op.localClip, op.paint)
, layer(op.layer) {
, layerHandle(op.layerHandle) {
}
GlLayer* layer;
DeferredLayerUpdater* layerHandle;
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -606,14 +606,13 @@ void RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) {
// 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);
LOG_ALWAYS_FATAL_IF(layerHandle->getBackingLayerApi() != 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(),
static_cast<GlLayer*>(layerHandle->backingLayer())));
getRecordedClip(), layerHandle));
}
void RecordingCanvas::callDrawGLFunction(Functor* functor,

View File

@@ -27,8 +27,12 @@ namespace uirenderer {
*/
class VkLayer : public Layer {
public:
VkLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight)
: Layer(renderState, Api::Vulkan) {}
VkLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend)
: Layer(renderState, Api::Vulkan, colorFilter, alpha, mode)
, mWidth(layerWidth)
, mHeight(layerHeight)
, mBlend(blend) {}
virtual ~VkLayer() {}

View File

@@ -135,11 +135,17 @@ bool SkiaOpenGLPipeline::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBi
return LayerDrawable::DrawLayer(mRenderThread.getGrContext(), &canvas, layer);
}
static Layer* createLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend) {
GlLayer* layer = new GlLayer(renderState, layerWidth, layerHeight, colorFilter, alpha,
mode, blend);
layer->generateTexture();
return layer;
}
DeferredLayerUpdater* SkiaOpenGLPipeline::createTextureLayer() {
mEglManager.initialize();
GlLayer* layer = new GlLayer(mRenderThread.renderState(), 0, 0);
layer->generateTexture();
return new DeferredLayerUpdater(layer);
return new DeferredLayerUpdater(mRenderThread.renderState(), createLayer, Layer::Api::OpenGL);
}
void SkiaOpenGLPipeline::onStop() {

View File

@@ -118,11 +118,15 @@ bool SkiaVulkanPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bi
return false;
}
static Layer* createLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend) {
return new VkLayer(renderState, layerWidth, layerHeight, colorFilter, alpha, mode, blend);
}
DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
mVkManager.initialize();
VkLayer* layer = new VkLayer(mRenderThread.renderState(), 0, 0);
return new DeferredLayerUpdater(layer);
return new DeferredLayerUpdater(mRenderThread.renderState(), createLayer, Layer::Api::Vulkan);
}
void SkiaVulkanPipeline::onStop() {

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "DeferredLayerUpdater.h"
#include "GlLayer.h"
#include "VkLayer.h"
#include <GpuMemoryTracker.h>
@@ -209,6 +210,14 @@ void RenderState::debugOverdraw(bool enable, bool clear) {
}
}
static void destroyLayerInUpdater(DeferredLayerUpdater* layerUpdater) {
layerUpdater->destroyLayer();
}
void RenderState::destroyLayersInUpdater() {
std::for_each(mActiveLayerUpdaters.begin(), mActiveLayerUpdaters.end(), destroyLayerInUpdater);
}
class DecStrongTask : public renderthread::RenderTask {
public:
explicit DecStrongTask(VirtualLightRefBase* object) : mObject(object) {}

View File

@@ -42,6 +42,7 @@ namespace uirenderer {
class Caches;
class Layer;
class DeferredLayerUpdater;
namespace renderthread {
class CanvasContext;
@@ -90,6 +91,16 @@ public:
mRegisteredContexts.erase(context);
}
void registerDeferredLayerUpdater(DeferredLayerUpdater* layerUpdater) {
mActiveLayerUpdaters.insert(layerUpdater);
}
void unregisterDeferredLayerUpdater(DeferredLayerUpdater* layerUpdater) {
mActiveLayerUpdaters.erase(layerUpdater);
}
void destroyLayersInUpdater();
// TODO: This system is a little clunky feeling, this could use some
// more thinking...
void postDecStrong(VirtualLightRefBase* object);
@@ -126,6 +137,7 @@ private:
OffscreenBufferPool mLayerPool;
std::set<Layer*> mActiveLayers;
std::set<DeferredLayerUpdater*> mActiveLayerUpdaters;
std::set<renderthread::CanvasContext*> mRegisteredContexts;
GLsizei mViewportWidth;

View File

@@ -570,6 +570,7 @@ void CanvasContext::destroyHardwareResources() {
}
mRenderPipeline->onDestroyHardwareResources();
}
mRenderThread.renderState().destroyLayersInUpdater();
}
void CanvasContext::trimMemory(RenderThread& thread, int level) {

View File

@@ -125,13 +125,18 @@ bool OpenGLPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap
static_cast<GlLayer&>(*layer->backingLayer()), bitmap);
}
DeferredLayerUpdater* OpenGLPipeline::createTextureLayer() {
mEglManager.initialize();
GlLayer* layer = new GlLayer(mRenderThread.renderState(), 0, 0);
static Layer* createLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend) {
GlLayer* layer = new GlLayer(renderState, layerWidth, layerHeight, colorFilter, alpha,
mode, blend);
Caches::getInstance().textureState().activateTexture(0);
layer->generateTexture();
return layer;
}
return new DeferredLayerUpdater(layer);
DeferredLayerUpdater* OpenGLPipeline::createTextureLayer() {
mEglManager.initialize();
return new DeferredLayerUpdater(mRenderThread.renderState(), createLayer, Layer::Api::OpenGL);
}
void OpenGLPipeline::onStop() {

View File

@@ -60,6 +60,7 @@ sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater(
pipeline = new skiapipeline::SkiaVulkanPipeline(renderThread);
}
sp<DeferredLayerUpdater> layerUpdater = pipeline->createTextureLayer();
layerUpdater->apply();
delete pipeline;
return layerUpdater;
}