diff options
author | 2017-01-19 15:37:02 -0800 | |
---|---|---|
committer | 2017-01-30 16:42:41 -0800 | |
commit | 3e9999bd866fac71c72e6b484a9836c87c328a08 (patch) | |
tree | 5f4f3303c211e618bb8daed4b62f8ebfecccd530 | |
parent | df9a4f9a7c599ccd2348d429e6a6f0a5a415f780 (diff) |
Explicitly destroy Layer in DeferredLayerUpdater on destroyHardwareResources()
Change-Id: I0987104eabda9a2a302b9e765213aad48f93aea4
Test: refactoring CL. Existing tests still pass
bug:33753499
-rw-r--r-- | libs/hwui/BakedOpDispatcher.cpp | 13 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.cpp | 34 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.h | 31 | ||||
-rw-r--r-- | libs/hwui/FrameBuilder.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/GlLayer.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/GlLayer.h | 3 | ||||
-rw-r--r-- | libs/hwui/Layer.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/Layer.h | 9 | ||||
-rw-r--r-- | libs/hwui/RecordedOp.h | 10 | ||||
-rw-r--r-- | libs/hwui/RecordingCanvas.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/VkLayer.h | 8 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp | 12 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/renderstate/RenderState.cpp | 9 | ||||
-rw-r--r-- | libs/hwui/renderstate/RenderState.h | 12 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 1 | ||||
-rw-r--r-- | libs/hwui/renderthread/OpenGLPipeline.cpp | 13 | ||||
-rw-r--r-- | libs/hwui/tests/common/TestUtils.cpp | 1 |
18 files changed, 139 insertions, 52 deletions
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp index 6079d5def1f8..03a397c1084d 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::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); } diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index 0ae50e96fc39..ee7764302c38 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::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); diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h index 3814be2cbec4..064b724c5e5f 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 @@ 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(); diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp index 1d8b021274fe..35ff635930ab 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::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); diff --git a/libs/hwui/GlLayer.cpp b/libs/hwui/GlLayer.cpp index c0ab895260ab..8174bcc35d97 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 54bf5adc3ace..23dfd9dfc0c1 100644 --- a/libs/hwui/GlLayer.h +++ b/libs/hwui/GlLayer.h @@ -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 { diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index 331bb81208b1..b58dfce787ef 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 3b639ee49334..e5520ea0e811 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -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. diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h index dea2be68c8db..3b87aef942b6 100644 --- a/libs/hwui/RecordedOp.h +++ b/libs/hwui/RecordedOp.h @@ -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; }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index b5e5d6801f99..2e33609665b0 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -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, diff --git a/libs/hwui/VkLayer.h b/libs/hwui/VkLayer.h index 39522b3c0dda..7e41ad1d0e9c 100644 --- a/libs/hwui/VkLayer.h +++ b/libs/hwui/VkLayer.h @@ -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() {} diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp index 65a1dc38ab8e..de80ee3ca229 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp @@ -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() { diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp index 910c339c4d1c..c63dce1035e7 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp @@ -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() { diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp index 17ee390c90bd..0d567f7601f2 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 @@ 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) {} diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h index d183a15f3842..a44fa9d11247 100644 --- a/libs/hwui/renderstate/RenderState.h +++ b/libs/hwui/renderstate/RenderState.h @@ -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; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index a53e5e0d919a..5a7de1dcb32b 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -570,6 +570,7 @@ void CanvasContext::destroyHardwareResources() { } 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 df40a44a16cb..8a5d9ccf759c 100644 --- a/libs/hwui/renderthread/OpenGLPipeline.cpp +++ b/libs/hwui/renderthread/OpenGLPipeline.cpp @@ -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() { diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp index 0916d72a5184..3e52c39b5c1f 100644 --- a/libs/hwui/tests/common/TestUtils.cpp +++ b/libs/hwui/tests/common/TestUtils.cpp @@ -60,6 +60,7 @@ sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater( pipeline = new skiapipeline::SkiaVulkanPipeline(renderThread); } sp<DeferredLayerUpdater> layerUpdater = pipeline->createTextureLayer(); + layerUpdater->apply(); delete pipeline; return layerUpdater; } |