| /* |
| * Copyright (C) 2016 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. |
| */ |
| |
| #pragma once |
| |
| #include "DisplayList.h" |
| #include "GLFunctorDrawable.h" |
| #include "RenderNodeDrawable.h" |
| |
| #include <deque> |
| #include <SkLiteDL.h> |
| #include <SkLiteRecorder.h> |
| |
| namespace android { |
| namespace uirenderer { |
| |
| class Outline; |
| |
| namespace skiapipeline { |
| |
| /** |
| * This class is intended to be self contained, but still subclasses from |
| * DisplayList to make it easier to support switching between the two at |
| * runtime. The downside of this inheritance is that we pay for the overhead |
| * of the parent class construction/destruction without any real benefit. |
| */ |
| class SkiaDisplayList : public DisplayList { |
| public: |
| SkiaDisplayList() { SkASSERT(projectionReceiveIndex == -1); } |
| virtual ~SkiaDisplayList() { |
| /* Given that we are using a LinearStdAllocator to store some of the |
| * SkDrawable contents we must ensure that any other object that is |
| * holding a reference to those drawables is destroyed prior to their |
| * deletion. |
| */ |
| mDisplayList.reset(); |
| } |
| |
| /** |
| * This resets the DisplayList so that it behaves as if the object were newly |
| * constructed. The reuse avoids any overhead associated with destroying |
| * the SkLiteDL as well as the deques and vectors. |
| */ |
| void reset(); |
| |
| /** |
| * Use the linear allocator to create any SkDrawables needed by the display |
| * list. This could be dangerous as these objects are ref-counted, so we |
| * need to monitor that they don't extend beyond the lifetime of the class |
| * that creates them. Allocator dtor invokes all SkDrawable dtors. |
| */ |
| template<class T, typename... Params> |
| SkDrawable* allocateDrawable(Params&&... params) { |
| return allocator.create<T>(std::forward<Params>(params)...); |
| } |
| |
| bool isSkiaDL() const override { return true; } |
| |
| /** |
| * Returns true if the DisplayList does not have any recorded content |
| */ |
| bool isEmpty() const override { return mDisplayList.empty(); } |
| |
| /** |
| * Returns true if this list directly contains a GLFunctor drawing command. |
| */ |
| bool hasFunctor() const override { return !mChildFunctors.empty(); } |
| |
| /** |
| * Returns true if this list directly contains a VectorDrawable drawing command. |
| */ |
| bool hasVectorDrawables() const override { return !mVectorDrawables.empty(); } |
| |
| /** |
| * Attempts to reset and reuse this DisplayList. |
| * |
| * @return true if the displayList will be reused and therefore should not be deleted |
| */ |
| bool reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) override; |
| |
| /** |
| * ONLY to be called by RenderNode::syncDisplayList so that we can notify any |
| * contained VectorDrawables or GLFunctors to sync their state. |
| * |
| * NOTE: This function can be folded into RenderNode when we no longer need |
| * to subclass from DisplayList |
| */ |
| void syncContents() override; |
| |
| /** |
| * ONLY to be called by RenderNode::prepareTree in order to prepare this |
| * list while the UI thread is blocked. Here we can upload mutable bitmaps |
| * and notify our parent if any of our content has been invalidated and in |
| * need of a redraw. If the renderNode has any children then they are also |
| * call in order to prepare them. |
| * |
| * @return true if any content change requires the node to be invalidated |
| * |
| * NOTE: This function can be folded into RenderNode when we no longer need |
| * to subclass from DisplayList |
| */ |
| |
| bool prepareListAndChildren(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer, |
| std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) override; |
| |
| /** |
| * Calls the provided function once for each child of this DisplayList |
| */ |
| void updateChildren(std::function<void(RenderNode*)> updateFn) override; |
| |
| /** |
| * Returns true if there is a child render node that is a projection receiver. |
| */ |
| inline bool containsProjectionReceiver() const { return mProjectionReceiver; } |
| |
| void attachRecorder(SkLiteRecorder* recorder, const SkIRect& bounds) { |
| recorder->reset(&mDisplayList, bounds); |
| } |
| |
| void draw(SkCanvas* canvas) { mDisplayList.draw(canvas); } |
| |
| void output(std::ostream& output, uint32_t level) override; |
| |
| /** |
| * We use std::deque here because (1) we need to iterate through these |
| * elements and (2) mDisplayList holds pointers to the elements, so they |
| * cannot relocate. |
| */ |
| std::deque<RenderNodeDrawable> mChildNodes; |
| std::deque<GLFunctorDrawable> mChildFunctors; |
| std::vector<SkImage*> mMutableImages; |
| std::vector<VectorDrawableRoot*> mVectorDrawables; |
| SkLiteDL mDisplayList; |
| |
| //mProjectionReceiver points to a child node (stored in mChildNodes) that is as a projection |
| //receiver. It is set at record time and used at both prepare and draw tree traversals to |
| //make sure backward projected nodes are found and drawn immediately after mProjectionReceiver. |
| RenderNodeDrawable* mProjectionReceiver = nullptr; |
| |
| //mProjectedOutline is valid only when render node tree is traversed during the draw pass. |
| //Render nodes that have a child receiver node, will store a pointer to their outline in |
| //mProjectedOutline. Child receiver node will apply the clip before any backward projected |
| //node is drawn. |
| const Outline* mProjectedOutline = nullptr; |
| |
| //mProjectedReceiverParentMatrix is valid when render node tree is traversed during the draw |
| //pass. Render nodes that have a child receiver node, will store their matrix in |
| //mProjectedReceiverParentMatrix. Child receiver node will set the matrix and then clip with the |
| //outline of their parent. |
| SkMatrix mProjectedReceiverParentMatrix; |
| }; |
| |
| }; // namespace skiapipeline |
| }; // namespace uirenderer |
| }; // namespace android |