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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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(); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace android {
|
||||
namespace skia {
|
||||
class BitmapRegionDecoder;
|
||||
}
|
||||
class Canvas;
|
||||
class Paint;
|
||||
struct Typeface;
|
||||
}
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user