Merge changes I1d7806aa,Ie906e628,Idf5a4acc

* changes:
  Convert DisplayList to a value-type wrapper
  Remove forward-decleration of SkiaDisplayList
  Avoid DisplayList* hitting the JNI layer
This commit is contained in:
John Reck
2021-01-14 18:02:57 +00:00
committed by Android (Google) Code Review
26 changed files with 230 additions and 131 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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"

View File

@@ -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(); });
}
}

View File

@@ -100,16 +100,17 @@ public:
// See flags defined in DisplayList.java
enum ReplayFlag { kReplayFlag_ClipChildren = 0x1 };
void setStagingDisplayList(DisplayList* newData);
void setStagingDisplayList(DisplayList&& newData);
void discardStagingDisplayList();
void output();
int getUsageSize();
int getAllocatedSize();
bool isRenderable() const { return mDisplayList && !mDisplayList->isEmpty(); }
bool isRenderable() const { return mDisplayList.hasContent(); }
bool hasProjectionReceiver() const {
return mDisplayList && mDisplayList->containsProjectionReceiver();
return mDisplayList.containsProjectionReceiver();
}
const char* getName() const { return mName.string(); }
@@ -168,12 +169,14 @@ public:
bool nothingToDraw() const {
const Outline& outline = properties().getOutline();
return mDisplayList == nullptr || properties().getAlpha() <= 0 ||
return !mDisplayList.isValid() || properties().getAlpha() <= 0 ||
(outline.getShouldClip() && outline.isEmpty()) || properties().getScaleX() == 0 ||
properties().getScaleY() == 0;
}
const DisplayList* getDisplayList() const { return mDisplayList; }
const DisplayList& getDisplayList() const { return mDisplayList; }
// TODO: can this be cleaned up?
DisplayList& getDisplayList() { return mDisplayList; }
// Note: The position callbacks are relying on the listener using
// the frameNumber to appropriately batch/synchronize these transactions.
@@ -252,8 +255,8 @@ private:
bool mNeedsDisplayListSync;
// WARNING: Do not delete this directly, you must go through deleteDisplayList()!
DisplayList* mDisplayList;
DisplayList* mStagingDisplayList;
DisplayList mDisplayList;
DisplayList mStagingDisplayList;
int64_t mDamageGenerationId;

View File

@@ -53,9 +53,9 @@ public:
LOG_ALWAYS_FATAL("SkiaCanvas cannot be reset as a recording canvas");
}
virtual uirenderer::DisplayList* finishRecording() override {
virtual uirenderer::DisplayList finishRecording() override {
LOG_ALWAYS_FATAL("SkiaCanvas does not produce a DisplayList");
return nullptr;
return uirenderer::DisplayList();
}
virtual void enableZ(bool enableZ) override {
LOG_ALWAYS_FATAL("SkiaCanvas does not support enableZ");

View File

@@ -19,11 +19,11 @@
#include <private/hwui/WebViewFunctor.h>
#ifdef __ANDROID__ // Layoutlib does not support render thread
#include <renderthread/RenderProxy.h>
#else
#include <utils/Log.h>
#endif
#include <utils/LightRefBase.h>
#include <utils/Log.h>
#include <utils/StrongPointer.h>
#include <mutex>
#include <vector>

View File

@@ -118,7 +118,7 @@ public:
virtual void resetRecording(int width, int height,
uirenderer::RenderNode* renderNode = nullptr) = 0;
virtual uirenderer::DisplayList* finishRecording() = 0;
[[nodiscard]] virtual uirenderer::DisplayList finishRecording() = 0;
virtual void enableZ(bool enableZ) = 0;
bool isHighContrastText() const { return uirenderer::Properties::enableHighContrastText; }

View File

@@ -3,11 +3,12 @@
#include "Bitmap.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkColorSpace.h"
#include "SkPixelRef.h"
#include "SkImageEncoder.h"
#include "SkImageInfo.h"
#include "SkColor.h"
#include "SkColorSpace.h"
#include "GraphicsJNI.h"
#include "SkStream.h"
#include "SkWebpEncoder.h"

View File

@@ -8,9 +8,11 @@
#include "MimeType.h"
#include "NinePatchPeeker.h"
#include "SkAndroidCodec.h"
#include "SkCanvas.h"
#include "SkMath.h"
#include "SkPixelRef.h"
#include "SkStream.h"
#include "SkString.h"
#include "SkUtils.h"
#include "Utils.h"

View File

@@ -24,6 +24,7 @@ namespace android {
namespace skia {
class BitmapRegionDecoder;
}
class Canvas;
class Paint;
struct Typeface;
}

View File

@@ -98,9 +98,11 @@ static void android_view_DisplayListCanvas_enableZ(CRITICAL_JNI_PARAMS_COMMA jlo
canvas->enableZ(reorderEnable);
}
static jlong android_view_DisplayListCanvas_finishRecording(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr) {
static void android_view_DisplayListCanvas_finishRecording(
CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jlong renderNodePtr) {
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
return reinterpret_cast<jlong>(canvas->finishRecording());
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->setStagingDisplayList(canvas->finishRecording());
}
static void android_view_DisplayListCanvas_drawRenderNode(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jlong renderNodePtr) {
@@ -172,7 +174,7 @@ static JNINativeMethod gMethods[] = {
{ "nGetMaximumTextureWidth", "()I", (void*) android_view_DisplayListCanvas_getMaxTextureSize },
{ "nGetMaximumTextureHeight", "()I", (void*) android_view_DisplayListCanvas_getMaxTextureSize },
{ "nEnableZ", "(JZ)V", (void*) android_view_DisplayListCanvas_enableZ },
{ "nFinishRecording", "(J)J", (void*) android_view_DisplayListCanvas_finishRecording },
{ "nFinishRecording", "(JJ)V", (void*) android_view_DisplayListCanvas_finishRecording },
{ "nDrawRenderNode", "(JJ)V", (void*) android_view_DisplayListCanvas_drawRenderNode },
{ "nDrawTextureLayer", "(JJ)V", (void*) android_view_DisplayListCanvas_drawTextureLayer },
{ "nDrawCircle", "(JJJJJ)V", (void*) android_view_DisplayListCanvas_drawCircleProps },

View File

@@ -76,11 +76,9 @@ static jlong android_view_RenderNode_getNativeFinalizer(JNIEnv* env,
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&releaseRenderNode));
}
static void android_view_RenderNode_setDisplayList(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jlong displayListPtr) {
static void android_view_RenderNode_discardDisplayList(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr);
renderNode->setStagingDisplayList(newData);
renderNode->discardStagingDisplayList();
}
static jboolean android_view_RenderNode_isValid(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
@@ -657,18 +655,11 @@ static const JNINativeMethod gMethods[] = {
{ "nAddAnimator", "(JJ)V", (void*) android_view_RenderNode_addAnimator },
{ "nEndAllAnimators", "(J)V", (void*) android_view_RenderNode_endAllAnimators },
{ "nRequestPositionUpdates", "(JLandroid/graphics/RenderNode$PositionUpdateListener;)V", (void*) android_view_RenderNode_requestPositionUpdates },
{ "nSetDisplayList", "(JJ)V", (void*) android_view_RenderNode_setDisplayList },
// ----------------------------------------------------------------------------
// Fast JNI via @CriticalNative annotation in RenderNode.java
// ----------------------------------------------------------------------------
{ "nSetDisplayList", "(JJ)V", (void*) android_view_RenderNode_setDisplayList },
// ----------------------------------------------------------------------------
// Critical JNI via @CriticalNative annotation in RenderNode.java
// ----------------------------------------------------------------------------
{ "nDiscardDisplayList", "(J)V", (void*) android_view_RenderNode_discardDisplayList },
{ "nIsValid", "(J)Z", (void*) android_view_RenderNode_isValid },
{ "nSetLayerType", "(JI)Z", (void*) android_view_RenderNode_setLayerType },
{ "nGetLayerType", "(J)I", (void*) android_view_RenderNode_getLayerType },

View File

@@ -29,7 +29,7 @@ namespace skiapipeline {
*/
class DumpOpsCanvas : public SkCanvas {
public:
DumpOpsCanvas(std::ostream& output, int level, SkiaDisplayList& displayList)
DumpOpsCanvas(std::ostream& output, int level, const SkiaDisplayList& displayList)
: mOutput(output)
, mLevel(level)
, mDisplayList(displayList)
@@ -127,7 +127,7 @@ protected:
}
private:
RenderNodeDrawable* getRenderNodeDrawable(SkDrawable* drawable) {
const RenderNodeDrawable* getRenderNodeDrawable(SkDrawable* drawable) {
for (auto& child : mDisplayList.mChildNodes) {
if (drawable == &child) {
return &child;
@@ -147,7 +147,7 @@ private:
std::ostream& mOutput;
int mLevel;
SkiaDisplayList& mDisplayList;
const SkiaDisplayList& mDisplayList;
std::string mIdent;
};

View File

@@ -61,12 +61,11 @@ void RenderNodeDrawable::drawBackwardsProjectedNodes(SkCanvas* canvas,
SkAutoCanvasRestore acr(canvas, true);
SkMatrix nodeMatrix;
mat4 hwuiMatrix(child.getRecordedMatrix());
auto childNode = child.getRenderNode();
const RenderNode* childNode = child.getRenderNode();
childNode->applyViewPropertyTransforms(hwuiMatrix);
hwuiMatrix.copyTo(nodeMatrix);
canvas->concat(nodeMatrix);
SkiaDisplayList* childDisplayList = static_cast<SkiaDisplayList*>(
(const_cast<DisplayList*>(childNode->getDisplayList())));
const SkiaDisplayList* childDisplayList = childNode->getDisplayList().asSkiaDl();
if (childDisplayList) {
drawBackwardsProjectedNodes(canvas, *childDisplayList, nestLevel + 1);
}
@@ -144,7 +143,7 @@ void RenderNodeDrawable::forceDraw(SkCanvas* canvas) const {
return;
}
SkiaDisplayList* displayList = (SkiaDisplayList*)renderNode->getDisplayList();
SkiaDisplayList* displayList = renderNode->getDisplayList().asSkiaDl();
SkAutoCanvasRestore acr(canvas, true);
const RenderProperties& properties = this->getNodeProperties();
@@ -213,14 +212,14 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {
if (mComposeLayer) {
setViewProperties(properties, canvas, &alphaMultiplier);
}
SkiaDisplayList* displayList = (SkiaDisplayList*)mRenderNode->getDisplayList();
SkiaDisplayList* displayList = mRenderNode->getDisplayList().asSkiaDl();
displayList->mParentMatrix = canvas->getTotalMatrix();
// TODO should we let the bound of the drawable do this for us?
const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
bool quickRejected = properties.getClipToBounds() && canvas->quickReject(bounds);
if (!quickRejected) {
SkiaDisplayList* displayList = (SkiaDisplayList*)renderNode->getDisplayList();
SkiaDisplayList* displayList = renderNode->getDisplayList().asSkiaDl();
const LayerProperties& layerProperties = properties.layerProperties();
// composing a hardware layer
if (renderNode->getLayerSurface() && mComposeLayer) {

View File

@@ -172,7 +172,7 @@ void SkiaDisplayList::reset() {
new (&allocator) LinearAllocator();
}
void SkiaDisplayList::output(std::ostream& output, uint32_t level) {
void SkiaDisplayList::output(std::ostream& output, uint32_t level) const {
DumpOpsCanvas canvas(output, level, *this);
mDisplayList.draw(&canvas);
}

View File

@@ -142,7 +142,7 @@ public:
void draw(SkCanvas* canvas) { mDisplayList.draw(canvas); }
void output(std::ostream& output, uint32_t level);
void output(std::ostream& output, uint32_t level) const;
LinearAllocator allocator;

View File

@@ -98,7 +98,7 @@ void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque)
continue;
}
SkASSERT(layerNode->getLayerSurface());
SkiaDisplayList* displayList = (SkiaDisplayList*)layerNode->getDisplayList();
SkiaDisplayList* displayList = layerNode->getDisplayList().asSkiaDl();
if (!displayList || displayList->isEmpty()) {
ALOGE("%p drawLayers(%s) : missing drawable", layerNode, layerNode->getName());
return;
@@ -288,7 +288,7 @@ bool SkiaPipeline::setupMultiFrameCapture() {
// recurse through the rendernode's children, add any nodes which are layers to the queue.
static void collectLayers(RenderNode* node, LayerUpdateQueue* layers) {
SkiaDisplayList* dl = (SkiaDisplayList*)node->getDisplayList();
SkiaDisplayList* dl = node->getDisplayList().asSkiaDl();
if (dl) {
const auto& prop = node->properties();
if (node->hasLayer()) {

View File

@@ -55,11 +55,11 @@ void SkiaRecordingCanvas::initDisplayList(uirenderer::RenderNode* renderNode, in
SkiaCanvas::reset(&mRecorder);
}
uirenderer::DisplayList* SkiaRecordingCanvas::finishRecording() {
uirenderer::DisplayList SkiaRecordingCanvas::finishRecording() {
// close any existing chunks if necessary
enableZ(false);
mRecorder.restoreToCount(1);
return mDisplayList.release();
return uirenderer::DisplayList(std::move(mDisplayList));
}
// ----------------------------------------------------------------------------

View File

@@ -43,7 +43,7 @@ public:
initDisplayList(renderNode, width, height);
}
virtual uirenderer::DisplayList* finishRecording() override;
virtual uirenderer::DisplayList finishRecording() override;
virtual void drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) override;
virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const Paint* paint) override;

View File

@@ -210,7 +210,8 @@ public:
int left, int top, int right, int bottom,
std::function<void(RenderProperties& props, skiapipeline::SkiaRecordingCanvas& canvas)>
setup,
const char* name = nullptr, skiapipeline::SkiaDisplayList* displayList = nullptr) {
const char* name = nullptr,
std::unique_ptr<skiapipeline::SkiaDisplayList> displayList = nullptr) {
sp<RenderNode> node = new RenderNode();
if (name) {
node->setName(name);
@@ -218,7 +219,7 @@ public:
RenderProperties& props = node->mutateStagingProperties();
props.setLeftTopRightBottom(left, top, right, bottom);
if (displayList) {
node->setStagingDisplayList(displayList);
node->setStagingDisplayList(DisplayList(std::move(displayList)));
}
if (setup) {
std::unique_ptr<skiapipeline::SkiaRecordingCanvas> canvas(
@@ -346,13 +347,11 @@ private:
node->mNeedsDisplayListSync = false;
node->syncDisplayList(observer, nullptr);
}
auto displayList = node->getDisplayList();
auto& displayList = node->getDisplayList();
if (displayList) {
for (auto&& childDr :
static_cast<skiapipeline::SkiaDisplayList*>(const_cast<DisplayList*>(displayList))
->mChildNodes) {
syncHierarchyPropertiesAndDisplayListImpl(childDr.getRenderNode());
}
displayList.updateChildren([](RenderNode* child) {
syncHierarchyPropertiesAndDisplayListImpl(child);
});
}
}

View File

@@ -45,19 +45,19 @@ BENCHMARK(BM_DisplayList_alloc_theoretical);
void BM_DisplayListCanvas_record_empty(benchmark::State& benchState) {
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
delete canvas->finishRecording();
static_cast<void>(canvas->finishRecording());
while (benchState.KeepRunning()) {
canvas->resetRecording(100, 100);
benchmark::DoNotOptimize(canvas.get());
delete canvas->finishRecording();
static_cast<void>(canvas->finishRecording());
}
}
BENCHMARK(BM_DisplayListCanvas_record_empty);
void BM_DisplayListCanvas_record_saverestore(benchmark::State& benchState) {
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
delete canvas->finishRecording();
static_cast<void>(canvas->finishRecording());
while (benchState.KeepRunning()) {
canvas->resetRecording(100, 100);
@@ -66,20 +66,20 @@ void BM_DisplayListCanvas_record_saverestore(benchmark::State& benchState) {
benchmark::DoNotOptimize(canvas.get());
canvas->restore();
canvas->restore();
delete canvas->finishRecording();
static_cast<void>(canvas->finishRecording());
}
}
BENCHMARK(BM_DisplayListCanvas_record_saverestore);
void BM_DisplayListCanvas_record_translate(benchmark::State& benchState) {
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
delete canvas->finishRecording();
static_cast<void>(canvas->finishRecording());
while (benchState.KeepRunning()) {
canvas->resetRecording(100, 100);
canvas->scale(10, 10);
benchmark::DoNotOptimize(canvas.get());
delete canvas->finishRecording();
static_cast<void>(canvas->finishRecording());
}
}
BENCHMARK(BM_DisplayListCanvas_record_translate);
@@ -92,7 +92,7 @@ BENCHMARK(BM_DisplayListCanvas_record_translate);
*/
void BM_DisplayListCanvas_record_simpleBitmapView(benchmark::State& benchState) {
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
delete canvas->finishRecording();
static_cast<void>(canvas->finishRecording());
Paint rectPaint;
sk_sp<Bitmap> iconBitmap(TestUtils::createBitmap(80, 80));
@@ -111,7 +111,7 @@ void BM_DisplayListCanvas_record_simpleBitmapView(benchmark::State& benchState)
canvas->restore();
}
benchmark::DoNotOptimize(canvas.get());
delete canvas->finishRecording();
static_cast<void>(canvas->finishRecording());
}
}
BENCHMARK(BM_DisplayListCanvas_record_simpleBitmapView);
@@ -122,7 +122,7 @@ void BM_DisplayListCanvas_basicViewGroupDraw(benchmark::State& benchState) {
});
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
delete canvas->finishRecording();
static_cast<void>(canvas->finishRecording());
while (benchState.KeepRunning()) {
canvas->resetRecording(200, 200);
@@ -143,7 +143,7 @@ void BM_DisplayListCanvas_basicViewGroupDraw(benchmark::State& benchState) {
canvas->enableZ(false);
canvas->restoreToCount(clipRestoreCount);
delete canvas->finishRecording();
static_cast<void>(canvas->finishRecording());
}
}
BENCHMARK(BM_DisplayListCanvas_basicViewGroupDraw)->Arg(1)->Arg(5)->Arg(10);

View File

@@ -16,6 +16,7 @@
#include <benchmark/benchmark.h>
#include "hwui/Canvas.h"
#include "RenderNode.h"
using namespace android;
@@ -34,7 +35,7 @@ BENCHMARK(BM_RenderNode_create);
void BM_RenderNode_recordSimple(benchmark::State& state) {
sp<RenderNode> node = new RenderNode();
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
delete canvas->finishRecording();
static_cast<void>(canvas->finishRecording());
while (state.KeepRunning()) {
canvas->resetRecording(100, 100, node.get());
@@ -47,12 +48,12 @@ BENCHMARK(BM_RenderNode_recordSimple);
void BM_RenderNode_recordSimpleWithReuse(benchmark::State& state) {
sp<RenderNode> node = new RenderNode();
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
delete canvas->finishRecording();
static_cast<void>(canvas->finishRecording());
while (state.KeepRunning()) {
canvas->resetRecording(100, 100, node.get());
canvas->drawColor(0x00000000, SkBlendMode::kSrcOver);
canvas->finishRecording()->reuseDisplayList(node.get());
canvas->finishRecording().clear(node.get());
}
}
BENCHMARK(BM_RenderNode_recordSimpleWithReuse);

View File

@@ -326,7 +326,7 @@ RENDERTHREAD_TEST(DISABLED_RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
// Check that the VD is in the dislay list, and the layer update queue contains the correct
// damage rect.
EXPECT_TRUE(rootNode->getDisplayList()->hasVectorDrawables());
EXPECT_TRUE(rootNode->getDisplayList().hasVectorDrawables());
ASSERT_FALSE(info.layerUpdateQueue->entries().empty());
EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode.get());
EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);

View File

@@ -38,12 +38,13 @@ TEST(SkiaDisplayList, create) {
}
TEST(SkiaDisplayList, reset) {
std::unique_ptr<SkiaDisplayList> skiaDL;
DisplayList displayList;
{
SkiaRecordingCanvas canvas{nullptr, 1, 1};
canvas.drawColor(0, SkBlendMode::kSrc);
skiaDL.reset(canvas.finishRecording());
displayList = canvas.finishRecording();
}
SkiaDisplayList* skiaDL = displayList.asSkiaDl();
SkCanvas dummyCanvas;
RenderNodeDrawable drawable(nullptr, &dummyCanvas);