Explicitly destroy Layer in DeferredLayerUpdater on destroyHardwareResources()
Change-Id: I0987104eabda9a2a302b9e765213aad48f93aea4
Test: refactoring CL. Existing tests still pass
bug:33753499
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 6079d5d..03a397c 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -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::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);
}
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 0ae50e9..ee77643 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -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::apply() {
+ if (!mLayer) {
+ mLayer = mCreateLayerFn(mRenderState, mWidth, mHeight, mColorFilter, mAlpha, mMode, mBlend);
+ }
+
mLayer->setColorFilter(mColorFilter);
mLayer->setAlpha(mAlpha, mMode);
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 3814be2..064b724 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -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 @@
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();
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 1d8b021..35ff635 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -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::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);
diff --git a/libs/hwui/GlLayer.cpp b/libs/hwui/GlLayer.cpp
index c0ab895..8174bcc 100644
--- a/libs/hwui/GlLayer.cpp
+++ b/libs/hwui/GlLayer.cpp
@@ -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() {
diff --git a/libs/hwui/GlLayer.h b/libs/hwui/GlLayer.h
index 54bf5ad..23dfd9d 100644
--- a/libs/hwui/GlLayer.h
+++ b/libs/hwui/GlLayer.h
@@ -31,7 +31,8 @@
*/
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 {
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 331bb81..b58dfce 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -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);
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 3b639ee..e5520ea 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -105,7 +105,8 @@
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 @@
/**
* 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 @@
/**
* Opacity of the layer.
*/
- int alpha = 255;
+ int alpha;
/**
* Blending mode of the layer.
*/
- SkBlendMode mode = SkBlendMode::kSrcOver;
+ SkBlendMode mode;
/**
* Optional texture coordinates transform.
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index dea2be6..3b87aef 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -37,6 +37,8 @@
struct ClipBase;
class OffscreenBuffer;
class RenderNode;
+class DeferredLayerUpdater;
+
struct Vertex;
namespace VectorDrawable {
@@ -414,18 +416,18 @@
};
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;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index b5e5d68..2e33609 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -606,14 +606,13 @@
// 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,
diff --git a/libs/hwui/VkLayer.h b/libs/hwui/VkLayer.h
index 39522b3..7e41ad1 100644
--- a/libs/hwui/VkLayer.h
+++ b/libs/hwui/VkLayer.h
@@ -27,8 +27,12 @@
*/
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() {}
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 65a1dc3..de80ee3 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -135,11 +135,17 @@
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() {
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 910c339..c63dce1 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -118,11 +118,15 @@
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() {
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 17ee390..0d567f7 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -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 @@
}
}
+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) {}
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index d183a15..a44fa9d 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -42,6 +42,7 @@
class Caches;
class Layer;
+class DeferredLayerUpdater;
namespace renderthread {
class CanvasContext;
@@ -90,6 +91,16 @@
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 @@
OffscreenBufferPool mLayerPool;
std::set<Layer*> mActiveLayers;
+ std::set<DeferredLayerUpdater*> mActiveLayerUpdaters;
std::set<renderthread::CanvasContext*> mRegisteredContexts;
GLsizei mViewportWidth;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index a53e5e0..5a7de1d 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -570,6 +570,7 @@
}
mRenderPipeline->onDestroyHardwareResources();
}
+ mRenderThread.renderState().destroyLayersInUpdater();
}
void CanvasContext::trimMemory(RenderThread& thread, int level) {
diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp
index df40a44..8a5d9cc 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.cpp
+++ b/libs/hwui/renderthread/OpenGLPipeline.cpp
@@ -125,13 +125,18 @@
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() {
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 0916d72..3e52c39 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -60,6 +60,7 @@
pipeline = new skiapipeline::SkiaVulkanPipeline(renderThread);
}
sp<DeferredLayerUpdater> layerUpdater = pipeline->createTextureLayer();
+ layerUpdater->apply();
delete pipeline;
return layerUpdater;
}