Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f0b5b1a0 authored by John Reck's avatar John Reck Committed by Android (Google) Code Review
Browse files

Merge changes I1d7806aa,Ie906e628,Idf5a4acc

* changes:
  Convert DisplayList to a value-type wrapper
  Remove forward-decleration of SkiaDisplayList
  Avoid DisplayList* hitting the JNI layer
parents afa2ec89 be67195c
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -71,8 +71,8 @@ public final class RecordingCanvas extends BaseRecordingCanvas {
    }

    /*package*/
    long finishRecording() {
        return nFinishRecording(mNativeCanvasWrapper);
    void finishRecording(RenderNode node) {
        nFinishRecording(mNativeCanvasWrapper, node.mNativeRenderNode);
    }

    ///////////////////////////////////////////////////////////////////////////
@@ -271,7 +271,7 @@ public final class RecordingCanvas extends BaseRecordingCanvas {
    @CriticalNative
    private static native void nEnableZ(long renderer, boolean enableZ);
    @CriticalNative
    private static native long nFinishRecording(long renderer);
    private static native void nFinishRecording(long renderer, long renderNode);
    @CriticalNative
    private static native void nDrawRenderNode(long renderer, long renderNode);
    @CriticalNative
+5 −13
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.view.View;
import com.android.internal.util.ArrayUtils;

import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;

import libcore.util.NativeAllocationRegistry;

@@ -406,8 +405,7 @@ public final class RenderNode {
        }
        RecordingCanvas canvas = mCurrentRecordingCanvas;
        mCurrentRecordingCanvas = null;
        long displayList = canvas.finishRecording();
        nSetDisplayList(mNativeRenderNode, displayList);
        canvas.finishRecording(this);
        canvas.recycle();
    }

@@ -438,7 +436,7 @@ public final class RenderNode {
     * obsolete resources after related resources are gone.
     */
    public void discardDisplayList() {
        nSetDisplayList(mNativeRenderNode, 0);
        nDiscardDisplayList(mNativeRenderNode);
    }

    /**
@@ -1528,19 +1526,13 @@ public final class RenderNode {

    private static native void nEndAllAnimators(long renderNode);


    ///////////////////////////////////////////////////////////////////////////
    // @FastNative methods
    ///////////////////////////////////////////////////////////////////////////

    @FastNative
    private static native void nSetDisplayList(long renderNode, long newData);


    ///////////////////////////////////////////////////////////////////////////
    // @CriticalNative methods
    ///////////////////////////////////////////////////////////////////////////

    @CriticalNative
    private static native void nDiscardDisplayList(long renderNode);

    @CriticalNative
    private static native boolean nIsValid(long renderNode);

+117 −4
Original line number Diff line number Diff line
@@ -16,21 +16,134 @@

#pragma once

#include "pipeline/skia/SkiaDisplayList.h"

#include <memory>

namespace android {
namespace uirenderer {

namespace VectorDrawable {
class Tree;
};
namespace skiapipeline {
class SkiaDisplayList;
}
typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;

/**
 * Data structure that holds the list of commands used in display list stream
 */
using DisplayList = skiapipeline::SkiaDisplayList;
//using DisplayList = skiapipeline::SkiaDisplayList;
class DisplayList {
public:
    // Constructs an empty (invalid) DisplayList
    explicit DisplayList() {}

    // Constructs a DisplayList from a SkiaDisplayList
    explicit DisplayList(std::unique_ptr<skiapipeline::SkiaDisplayList> impl)
        : mImpl(std::move(impl)) {}

    // Move support
    DisplayList(DisplayList&& other) : mImpl(std::move(other.mImpl)) {}
    DisplayList& operator=(DisplayList&& other) {
        mImpl = std::move(other.mImpl);
        return *this;
    }

    // No copy support
    DisplayList(const DisplayList& other) = delete;
    DisplayList& operator=(const DisplayList&) = delete;

    void updateChildren(std::function<void(RenderNode*)> updateFn) {
        mImpl->updateChildren(std::move(updateFn));
    }

    [[nodiscard]] explicit operator bool() const {
        return mImpl.get() != nullptr;
    }

    // If true this DisplayList contains a backing content, even if that content is empty
    // If false, there this DisplayList is in an "empty" state
    [[nodiscard]] bool isValid() const {
        return mImpl.get() != nullptr;
    }

    [[nodiscard]] bool isEmpty() const {
        return !hasContent();
    }

    [[nodiscard]] bool hasContent() const {
        return mImpl && !(mImpl->isEmpty());
    }

    [[nodiscard]] bool containsProjectionReceiver() const {
        return mImpl && mImpl->containsProjectionReceiver();
    }

    [[nodiscard]] skiapipeline::SkiaDisplayList* asSkiaDl() {
        return mImpl.get();
    }

    [[nodiscard]] const skiapipeline::SkiaDisplayList* asSkiaDl() const {
        return mImpl.get();
    }

    [[nodiscard]] bool hasVectorDrawables() const {
        return mImpl && mImpl->hasVectorDrawables();
    }

    void clear(RenderNode* owningNode = nullptr) {
        if (mImpl && owningNode && mImpl->reuseDisplayList(owningNode)) {
            // TODO: This is a bit sketchy to have a unique_ptr temporarily owned twice
            // Do something to cleanup reuseDisplayList passing itself to the RenderNode
            mImpl.release();
        } else {
            mImpl = nullptr;
        }
    }

    [[nodiscard]] size_t getUsedSize() const {
        return mImpl ? mImpl->getUsedSize() : 0;
    }

    [[nodiscard]] size_t getAllocatedSize() const {
        return mImpl ? mImpl->getAllocatedSize() : 0;
    }

    void output(std::ostream& output, uint32_t level) const {
        if (mImpl) {
            mImpl->output(output, level);
        }
    }

    [[nodiscard]] bool hasFunctor() const {
        return mImpl && mImpl->hasFunctor();
    }

    bool prepareListAndChildren(
            TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
            std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
        return mImpl && mImpl->prepareListAndChildren(
                observer, info, functorsNeedLayer, std::move(childFn));
    }

    void syncContents(const WebViewSyncData& data) {
        if (mImpl) {
            mImpl->syncContents(data);
        }
    }

    [[nodiscard]] bool hasText() const {
        return mImpl && mImpl->hasText();
    }

    void applyColorTransform(ColorTransform transform) {
        if (mImpl) {
            mImpl->mDisplayList.applyColorTransform(transform);
        }
    }

private:
    std::unique_ptr<skiapipeline::SkiaDisplayList> mImpl;
};

}  // namespace uirenderer
}  // namespace android
+5 −2
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@

#include "CanvasTransform.h"
#include "hwui/Bitmap.h"
#include "hwui/Canvas.h"
#include "utils/Macros.h"
#include "utils/TypeLogic.h"

@@ -29,7 +28,6 @@
#include "SkPaint.h"
#include "SkPath.h"
#include "SkRect.h"
#include "SkTemplates.h"

#include <vector>

@@ -40,6 +38,11 @@ namespace skiapipeline {
class FunctorDrawable;
}

namespace VectorDrawable {
class Tree;
}
typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;

enum class DisplayListOpType : uint8_t {
#define X(T) T,
#include "DisplayListOps.in"
+31 −40
Original line number Diff line number Diff line
@@ -70,15 +70,17 @@ RenderNode::RenderNode()
RenderNode::~RenderNode() {
    ImmediateRemoved observer(nullptr);
    deleteDisplayList(observer);
    delete mStagingDisplayList;
    LOG_ALWAYS_FATAL_IF(hasLayer(), "layer missed detachment!");
}

void RenderNode::setStagingDisplayList(DisplayList* displayList) {
    mValid = (displayList != nullptr);
void RenderNode::setStagingDisplayList(DisplayList&& newData) {
    mValid = newData.isValid();
    mNeedsDisplayListSync = true;
    delete mStagingDisplayList;
    mStagingDisplayList = displayList;
    mStagingDisplayList = std::move(newData);
}

void RenderNode::discardStagingDisplayList() {
    setStagingDisplayList(DisplayList());
}

/**
@@ -101,32 +103,22 @@ void RenderNode::output(std::ostream& output, uint32_t level) {

    properties().debugOutputProperties(output, level + 1);

    if (mDisplayList) {
        mDisplayList->output(output, level);
    }
    mDisplayList.output(output, level);
    output << std::string(level * 2, ' ') << "/RenderNode(" << getName() << " " << this << ")";
    output << std::endl;
}

int RenderNode::getUsageSize() {
    int size = sizeof(RenderNode);
    if (mStagingDisplayList) {
        size += mStagingDisplayList->getUsedSize();
    }
    if (mDisplayList && mDisplayList != mStagingDisplayList) {
        size += mDisplayList->getUsedSize();
    }
    size += mStagingDisplayList.getUsedSize();
    size += mDisplayList.getUsedSize();
    return size;
}

int RenderNode::getAllocatedSize() {
    int size = sizeof(RenderNode);
    if (mStagingDisplayList) {
        size += mStagingDisplayList->getAllocatedSize();
    }
    if (mDisplayList && mDisplayList != mStagingDisplayList) {
        size += mDisplayList->getAllocatedSize();
    }
    size += mStagingDisplayList.getAllocatedSize();
    size += mDisplayList.getAllocatedSize();
    return size;
}

@@ -242,9 +234,9 @@ void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool fu

    bool willHaveFunctor = false;
    if (info.mode == TreeInfo::MODE_FULL && mStagingDisplayList) {
        willHaveFunctor = mStagingDisplayList->hasFunctor();
        willHaveFunctor = mStagingDisplayList.hasFunctor();
    } else if (mDisplayList) {
        willHaveFunctor = mDisplayList->hasFunctor();
        willHaveFunctor = mDisplayList.hasFunctor();
    }
    bool childFunctorsNeedLayer =
            mProperties.prepareForFunctorPresence(willHaveFunctor, functorsNeedLayer);
@@ -259,8 +251,8 @@ void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool fu
    }

    if (mDisplayList) {
        info.out.hasFunctors |= mDisplayList->hasFunctor();
        bool isDirty = mDisplayList->prepareListAndChildren(
        info.out.hasFunctors |= mDisplayList.hasFunctor();
        bool isDirty = mDisplayList.prepareListAndChildren(
                observer, info, childFunctorsNeedLayer,
                [](RenderNode* child, TreeObserver& observer, TreeInfo& info,
                   bool functorsNeedLayer) {
@@ -314,16 +306,15 @@ void RenderNode::syncDisplayList(TreeObserver& observer, TreeInfo* info) {
    // Make sure we inc first so that we don't fluctuate between 0 and 1,
    // which would thrash the layer cache
    if (mStagingDisplayList) {
        mStagingDisplayList->updateChildren([](RenderNode* child) { child->incParentRefCount(); });
        mStagingDisplayList.updateChildren([](RenderNode* child) { child->incParentRefCount(); });
    }
    deleteDisplayList(observer, info);
    mDisplayList = mStagingDisplayList;
    mStagingDisplayList = nullptr;
    mDisplayList = std::move(mStagingDisplayList);
    if (mDisplayList) {
        WebViewSyncData syncData {
            .applyForceDark = info && !info->disableForceDark
        };
        mDisplayList->syncContents(syncData);
        mDisplayList.syncContents(syncData);
        handleForceDark(info);
    }
}
@@ -333,15 +324,18 @@ void RenderNode::handleForceDark(android::uirenderer::TreeInfo *info) {
        return;
    }
    auto usage = usageHint();
    const auto& children = mDisplayList->mChildNodes;
    if (mDisplayList->hasText()) {
    FatVector<RenderNode*, 6> children;
    mDisplayList.updateChildren([&children](RenderNode* node) {
        children.push_back(node);
    });
    if (mDisplayList.hasText()) {
        usage = UsageHint::Foreground;
    }
    if (usage == UsageHint::Unknown) {
        if (children.size() > 1) {
            usage = UsageHint::Background;
        } else if (children.size() == 1 &&
                children.front().getRenderNode()->usageHint() !=
                children.front()->usageHint() !=
                        UsageHint::Background) {
            usage = UsageHint::Background;
        }
@@ -350,7 +344,7 @@ void RenderNode::handleForceDark(android::uirenderer::TreeInfo *info) {
        // Crude overlap check
        SkRect drawn = SkRect::MakeEmpty();
        for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
            const auto& child = iter->getRenderNode();
            const auto& child = *iter;
            // We use stagingProperties here because we haven't yet sync'd the children
            SkRect bounds = SkRect::MakeXYWH(child->stagingProperties().getX(), child->stagingProperties().getY(),
                    child->stagingProperties().getWidth(), child->stagingProperties().getHeight());
@@ -361,7 +355,7 @@ void RenderNode::handleForceDark(android::uirenderer::TreeInfo *info) {
            drawn.join(bounds);
        }
    }
    mDisplayList->mDisplayList.applyColorTransform(
    mDisplayList.applyColorTransform(
            usage == UsageHint::Background ? ColorTransform::Dark : ColorTransform::Light);
}

@@ -378,20 +372,17 @@ void RenderNode::pushStagingDisplayListChanges(TreeObserver& observer, TreeInfo&

void RenderNode::deleteDisplayList(TreeObserver& observer, TreeInfo* info) {
    if (mDisplayList) {
        mDisplayList->updateChildren(
        mDisplayList.updateChildren(
                [&observer, info](RenderNode* child) { child->decParentRefCount(observer, info); });
        if (!mDisplayList->reuseDisplayList(this)) {
            delete mDisplayList;
        }
        mDisplayList.clear(this);
    }
    mDisplayList = nullptr;
}

void RenderNode::destroyHardwareResources(TreeInfo* info) {
    if (hasLayer()) {
        this->setLayerSurface(nullptr);
    }
    setStagingDisplayList(nullptr);
    discardStagingDisplayList();

    ImmediateRemoved observer(info);
    deleteDisplayList(observer, info);
@@ -402,7 +393,7 @@ void RenderNode::destroyLayers() {
        this->setLayerSurface(nullptr);
    }
    if (mDisplayList) {
        mDisplayList->updateChildren([](RenderNode* child) { child->destroyLayers(); });
        mDisplayList.updateChildren([](RenderNode* child) { child->destroyLayers(); });
    }
}

Loading