Explicitly destroy Layer in DeferredLayerUpdater on destroyHardwareResources()
Change-Id: I0987104eabda9a2a302b9e765213aad48f93aea4 Test: refactoring CL. Existing tests still pass bug:33753499
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -570,6 +570,7 @@ void CanvasContext::destroyHardwareResources() {
|
||||
}
|
||||
mRenderPipeline->onDestroyHardwareResources();
|
||||
}
|
||||
mRenderThread.renderState().destroyLayersInUpdater();
|
||||
}
|
||||
|
||||
void CanvasContext::trimMemory(RenderThread& thread, int level) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -60,6 +60,7 @@ sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater(
|
||||
pipeline = new skiapipeline::SkiaVulkanPipeline(renderThread);
|
||||
}
|
||||
sp<DeferredLayerUpdater> layerUpdater = pipeline->createTextureLayer();
|
||||
layerUpdater->apply();
|
||||
delete pipeline;
|
||||
return layerUpdater;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user