Serializing display lists
This is a WIP prototype
Change-Id: Id4bfcf2b7bf905221c3734b7b6887c9b2efd37e6
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index f6119e2..420f7a1 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -407,6 +407,10 @@
nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
}
+ public void serializeDisplayListTree() {
+ nSerializeDisplayListTree(mNativeProxy);
+ }
+
@Override
protected void finalize() throws Throwable {
try {
@@ -532,6 +536,8 @@
private static native void nStopDrawing(long nativeProxy);
private static native void nNotifyFramePending(long nativeProxy);
+ private static native void nSerializeDisplayListTree(long nativeProxy);
+
private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
@DumpFlags int dumpFlags);
private static native void nDumpProfileData(byte[] data, FileDescriptor fd);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index aa20dfb..dde9cfa 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2276,6 +2276,9 @@
*/
void outputDisplayList(View view) {
view.mRenderNode.output();
+ if (mAttachInfo.mHardwareRenderer != null) {
+ ((ThreadedRenderer)mAttachInfo.mHardwareRenderer).serializeDisplayListTree();
+ }
}
/**
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 47132f4..6c3676b 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -418,6 +418,12 @@
proxy->notifyFramePending();
}
+static void android_view_ThreadedRenderer_serializeDisplayListTree(JNIEnv* env, jobject clazz,
+ jlong proxyPtr) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ proxy->serializeDisplayListTree();
+}
+
static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -483,6 +489,7 @@
{ "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
{ "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
{ "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
+ { "nSerializeDisplayListTree", "(J)V", (void*) android_view_ThreadedRenderer_serializeDisplayListTree },
{ "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
{ "nDumpProfileData", "([BLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileData },
{ "setupShadersDiskCache", "(Ljava/lang/String;)V",
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index b3b3479..676ab1c 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -75,7 +75,8 @@
TessellationCache.cpp \
TextDropShadowCache.cpp \
Texture.cpp \
- TextureCache.cpp
+ TextureCache.cpp \
+ protos/hwui.proto
hwui_cflags := \
-DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES \
@@ -92,6 +93,12 @@
hwui_cflags += -fno-omit-frame-pointer -marm -mapcs
endif
+# This has to be lazy-resolved because it depends on the LOCAL_MODULE_CLASS
+# which varies depending on what is being built
+define hwui_proto_include
+$(call local-generated-sources-dir)/proto/$(LOCAL_PATH)
+endef
+
hwui_c_includes += \
external/skia/src/core
@@ -104,6 +111,7 @@
libskia \
libui \
libgui \
+ libprotobuf-cpp-lite \
ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT))
hwui_cflags += -DANDROID_ENABLE_RENDERSCRIPT
@@ -126,7 +134,8 @@
LOCAL_SHARED_LIBRARIES := $(hwui_shared_libraries)
LOCAL_CFLAGS := $(hwui_cflags)
LOCAL_SRC_FILES := $(hwui_src_files)
-LOCAL_C_INCLUDES := $(hwui_c_includes)
+LOCAL_C_INCLUDES := $(hwui_c_includes) $(call hwui_proto_include)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(hwui_c_includes) $(call hwui_proto_include)
include $(BUILD_STATIC_LIBRARY)
@@ -153,7 +162,6 @@
LOCAL_MODULE_TAGS := tests
LOCAL_SHARED_LIBRARIES := $(hwui_shared_libraries)
LOCAL_STATIC_LIBRARIES := libhwui_static
-LOCAL_C_INCLUDES := $(hwui_c_includes)
LOCAL_CFLAGS := $(hwui_cflags)
LOCAL_SRC_FILES += \
@@ -172,16 +180,20 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/local/tmp
LOCAL_MODULE:= hwuitest
LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := hwuitest
LOCAL_MODULE_STEM_64 := hwuitest64
LOCAL_SHARED_LIBRARIES := $(hwui_shared_libraries)
LOCAL_CFLAGS := $(hwui_cflags)
-LOCAL_C_INCLUDES := $(hwui_c_includes)
HWUI_NULL_GPU := false
ifeq (true, $(HWUI_NULL_GPU))
+ # Only need to specify the includes if we are not linking against
+ # libhwui_static as libhwui_static exports the appropriate includes
+ LOCAL_C_INCLUDES := $(hwui_c_includes) $(call hwui_proto_include)
+
LOCAL_SRC_FILES := \
$(hwui_src_files) \
tests/nullegl.cpp \
diff --git a/libs/hwui/Outline.h b/libs/hwui/Outline.h
index 4bd4ae1..922ff7c 100644
--- a/libs/hwui/Outline.h
+++ b/libs/hwui/Outline.h
@@ -26,6 +26,13 @@
class Outline {
public:
+ enum class Type {
+ None = 0,
+ Empty = 1,
+ ConvexPath = 2,
+ RoundRect = 3
+ };
+
Outline()
: mShouldClip(false)
, mType(Type::None)
@@ -122,14 +129,19 @@
return &mPath;
}
-private:
- enum class Type {
- None = 0,
- Empty = 1,
- ConvexPath = 2,
- RoundRect = 3
- };
+ Type getType() const {
+ return mType;
+ }
+ const Rect& getBounds() const {
+ return mBounds;
+ }
+
+ float getRadius() const {
+ return mRadius;
+ }
+
+private:
bool mShouldClip;
Type mType;
Rect mBounds;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 7d09c0b..ddc7ecd 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -33,6 +33,9 @@
#include "utils/TraceUtils.h"
#include "renderthread/CanvasContext.h"
+#include "protos/hwui.pb.h"
+#include "protos/ProtoHelpers.h"
+
namespace android {
namespace uirenderer {
@@ -102,6 +105,78 @@
ALOGD("%*sDone (%p, %s)", (level - 1) * 2, "", this, getName());
}
+void RenderNode::copyTo(proto::RenderNode *pnode) {
+ pnode->set_id(static_cast<uint64_t>(
+ reinterpret_cast<uintptr_t>(this)));
+ pnode->set_name(mName.string(), mName.length());
+
+ proto::RenderProperties* pprops = pnode->mutable_properties();
+ pprops->set_left(properties().getLeft());
+ pprops->set_top(properties().getTop());
+ pprops->set_right(properties().getRight());
+ pprops->set_bottom(properties().getBottom());
+ pprops->set_clip_flags(properties().getClippingFlags());
+ pprops->set_alpha(properties().getAlpha());
+ pprops->set_translation_x(properties().getTranslationX());
+ pprops->set_translation_y(properties().getTranslationY());
+ pprops->set_translation_z(properties().getTranslationZ());
+ pprops->set_elevation(properties().getElevation());
+ pprops->set_rotation(properties().getRotation());
+ pprops->set_rotation_x(properties().getRotationX());
+ pprops->set_rotation_y(properties().getRotationY());
+ pprops->set_scale_x(properties().getScaleX());
+ pprops->set_scale_y(properties().getScaleY());
+ pprops->set_pivot_x(properties().getPivotX());
+ pprops->set_pivot_y(properties().getPivotY());
+ pprops->set_has_overlapping_rendering(properties().getHasOverlappingRendering());
+ pprops->set_pivot_explicitly_set(properties().isPivotExplicitlySet());
+ pprops->set_project_backwards(properties().getProjectBackwards());
+ pprops->set_projection_receiver(properties().isProjectionReceiver());
+ set(pprops->mutable_clip_bounds(), properties().getClipBounds());
+
+ const Outline& outline = properties().getOutline();
+ if (outline.getType() != Outline::Type::None) {
+ proto::Outline* poutline = pprops->mutable_outline();
+ poutline->clear_path();
+ if (outline.getType() == Outline::Type::Empty) {
+ poutline->set_type(proto::Outline_Type_Empty);
+ } else if (outline.getType() == Outline::Type::ConvexPath) {
+ poutline->set_type(proto::Outline_Type_ConvexPath);
+ if (const SkPath* path = outline.getPath()) {
+ set(poutline->mutable_path(), *path);
+ }
+ } else if (outline.getType() == Outline::Type::RoundRect) {
+ poutline->set_type(proto::Outline_Type_RoundRect);
+ } else {
+ ALOGW("Uknown outline type! %d", static_cast<int>(outline.getType()));
+ poutline->set_type(proto::Outline_Type_None);
+ }
+ poutline->set_should_clip(outline.getShouldClip());
+ poutline->set_alpha(outline.getAlpha());
+ poutline->set_radius(outline.getRadius());
+ set(poutline->mutable_bounds(), outline.getBounds());
+ } else {
+ pprops->clear_outline();
+ }
+
+ const RevealClip& revealClip = properties().getRevealClip();
+ if (revealClip.willClip()) {
+ proto::RevealClip* prevealClip = pprops->mutable_reveal_clip();
+ prevealClip->set_x(revealClip.getX());
+ prevealClip->set_y(revealClip.getY());
+ prevealClip->set_radius(revealClip.getRadius());
+ } else {
+ pprops->clear_reveal_clip();
+ }
+
+ pnode->clear_children();
+ if (mDisplayListData) {
+ for (auto&& child : mDisplayListData->children()) {
+ child->mRenderNode->copyTo(pnode->add_children());
+ }
+ }
+}
+
int RenderNode::getDebugSize() {
int size = sizeof(RenderNode);
if (mStagingDisplayListData) {
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 3bff2b3..88fc608 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -57,6 +57,10 @@
class DrawRenderNodeOp;
class TreeInfo;
+namespace proto {
+class RenderNode;
+}
+
/**
* Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display properties.
*
@@ -96,7 +100,6 @@
kReplayFlag_ClipChildren = 0x1
};
- static void outputLogBuffer(int fd);
void debugDumpLayers(const char* prefix);
ANDROID_API void setStagingDisplayList(DisplayListData* newData);
@@ -108,6 +111,7 @@
ANDROID_API void output(uint32_t level = 1);
ANDROID_API int getDebugSize();
+ void copyTo(proto::RenderNode* node);
bool isRenderable() const {
return mDisplayListData && !mDisplayListData->isEmpty();
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index a9ae9b5..ad74bff 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -70,23 +70,6 @@
return *this;
}
-RenderProperties::PrimitiveFields::PrimitiveFields()
- : mClippingFlags(CLIP_TO_BOUNDS)
- , mProjectBackwards(false)
- , mProjectionReceiver(false)
- , mAlpha(1)
- , mHasOverlappingRendering(true)
- , mElevation(0)
- , mTranslationX(0), mTranslationY(0), mTranslationZ(0)
- , mRotation(0), mRotationX(0), mRotationY(0)
- , mScaleX(1), mScaleY(1)
- , mPivotX(0), mPivotY(0)
- , mLeft(0), mTop(0), mRight(0), mBottom(0)
- , mWidth(0), mHeight(0)
- , mPivotExplicitlySet(false)
- , mMatrixOrPivotDirty(false) {
-}
-
RenderProperties::ComputedFields::ComputedFields()
: mTransformMatrix(nullptr) {
}
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 11abd70..71589c8 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -417,7 +417,7 @@
return false;
}
- float getLeft() const {
+ int getLeft() const {
return mPrimitiveFields.mLeft;
}
@@ -432,7 +432,7 @@
return false;
}
- float getTop() const {
+ int getTop() const {
return mPrimitiveFields.mTop;
}
@@ -447,7 +447,7 @@
return false;
}
- float getRight() const {
+ int getRight() const {
return mPrimitiveFields.mRight;
}
@@ -462,7 +462,7 @@
return false;
}
- float getBottom() const {
+ int getBottom() const {
return mPrimitiveFields.mBottom;
}
@@ -541,6 +541,10 @@
return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS;
}
+ const Rect& getClipBounds() const {
+ return mPrimitiveFields.mClipBounds;
+ }
+
void getClippingRectForFlags(uint32_t flags, Rect* outRect) const {
if (flags & CLIP_TO_BOUNDS) {
outRect->set(0, 0, getWidth(), getHeight());
@@ -621,25 +625,23 @@
private:
// Rendering properties
struct PrimitiveFields {
- PrimitiveFields();
-
+ int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0;
+ int mWidth = 0, mHeight = 0;
+ int mClippingFlags = CLIP_TO_BOUNDS;
+ float mAlpha = 1;
+ float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0;
+ float mElevation = 0;
+ float mRotation = 0, mRotationX = 0, mRotationY = 0;
+ float mScaleX = 1, mScaleY = 1;
+ float mPivotX = 0, mPivotY = 0;
+ bool mHasOverlappingRendering = false;
+ bool mPivotExplicitlySet = false;
+ bool mMatrixOrPivotDirty = false;
+ bool mProjectBackwards = false;
+ bool mProjectionReceiver = false;
+ Rect mClipBounds;
Outline mOutline;
RevealClip mRevealClip;
- int mClippingFlags;
- bool mProjectBackwards;
- bool mProjectionReceiver;
- float mAlpha;
- bool mHasOverlappingRendering;
- float mElevation;
- float mTranslationX, mTranslationY, mTranslationZ;
- float mRotation, mRotationX, mRotationY;
- float mScaleX, mScaleY;
- float mPivotX, mPivotY;
- int mLeft, mTop, mRight, mBottom;
- int mWidth, mHeight;
- bool mPivotExplicitlySet;
- bool mMatrixOrPivotDirty;
- Rect mClipBounds;
} mPrimitiveFields;
SkMatrix* mStaticMatrix;
diff --git a/libs/hwui/RevealClip.h b/libs/hwui/RevealClip.h
index 0084a8e..63821dd 100644
--- a/libs/hwui/RevealClip.h
+++ b/libs/hwui/RevealClip.h
@@ -51,7 +51,10 @@
outBounds->set(mX - mRadius, mY - mRadius,
mX + mRadius, mY + mRadius);
}
+
float getRadius() const { return mRadius; }
+ float getX() const { return mX; }
+ float getY() const { return mY; }
const SkPath* getPath() const {
if (!mShouldClip) return nullptr;
diff --git a/libs/hwui/protos/ProtoHelpers.h b/libs/hwui/protos/ProtoHelpers.h
new file mode 100644
index 0000000..832e312
--- /dev/null
+++ b/libs/hwui/protos/ProtoHelpers.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+#ifndef PROTOHELPERS_H
+#define PROTOHELPERS_H
+
+#include "Rect.h"
+#include "protos/hwui.pb.h"
+
+namespace android {
+namespace uirenderer {
+
+void set(proto::RectF* dest, const Rect& src) {
+ dest->set_left(src.left);
+ dest->set_top(src.top);
+ dest->set_right(src.right);
+ dest->set_bottom(src.bottom);
+}
+
+void set(std::string* dest, const SkPath& src) {
+ size_t size = src.writeToMemory(nullptr);
+ dest->resize(size);
+ src.writeToMemory(&*dest->begin());
+}
+
+} // namespace uirenderer
+} // namespace android
+
+#endif // PROTOHELPERS_H
diff --git a/libs/hwui/protos/hwui.proto b/libs/hwui/protos/hwui.proto
new file mode 100644
index 0000000..dcff80a
--- /dev/null
+++ b/libs/hwui/protos/hwui.proto
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+syntax = "proto2";
+
+package android.uirenderer.proto;
+
+option optimize_for = LITE_RUNTIME;
+
+message RenderNode {
+ required uint64 id = 1;
+ required string name = 2;
+ required RenderProperties properties = 3;
+ optional DisplayList display_list = 4;
+ repeated RenderNode children = 5;
+};
+
+message RenderProperties {
+ required int32 left = 1;
+ required int32 right = 2;
+ required int32 top = 3;
+ required int32 bottom = 4;
+ required int32 clip_flags = 5;
+ required float alpha = 6;
+ required float translation_x = 7;
+ required float translation_y = 8;
+ required float translation_z = 9;
+ required float elevation = 10;
+ required float rotation = 11;
+ required float rotation_x = 12;
+ required float rotation_y = 13;
+ required float scale_x = 14;
+ required float scale_y = 15;
+ required float pivot_x = 16;
+ required float pivot_y = 17;
+ required bool has_overlapping_rendering = 18;
+ required bool pivot_explicitly_set = 19;
+ required bool project_backwards = 20;
+ required bool projection_receiver = 21;
+ required RectF clip_bounds = 22;
+ optional Outline outline = 23;
+ optional RevealClip reveal_clip = 24;
+};
+
+message RectF {
+ required float left = 1;
+ required float right = 2;
+ required float top = 3;
+ required float bottom = 4;
+}
+
+message Outline {
+ required bool should_clip = 1;
+ enum Type {
+ None = 0;
+ Empty = 1;
+ ConvexPath = 2;
+ RoundRect = 3;
+ }
+ required Type type = 2;
+ required RectF bounds = 3;
+ required float radius = 4;
+ required float alpha = 5;
+ optional bytes path = 6;
+}
+
+message RevealClip {
+ required float x = 1;
+ required float y = 2;
+ required float radius = 3;
+}
+
+message DisplayList {
+ optional int32 projection_receive_index = 1;
+ repeated DrawOp draw_ops = 2;
+}
+
+message DrawOp {
+ oneof drawop {
+ DrawOp_RenderNode render_node = 1;
+ }
+}
+
+message DrawOp_RenderNode {
+ optional RenderNode node = 1;
+}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 7cb7738..1673802 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -26,15 +26,22 @@
#include "RenderThread.h"
#include "renderstate/RenderState.h"
#include "renderstate/Stencil.h"
+#include "protos/hwui.pb.h"
+
+#include <cutils/properties.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <private/hwui/DrawGlInfo.h>
+#include <strings.h>
#include <algorithm>
-#include <strings.h>
-#include <cutils/properties.h>
-#include <private/hwui/DrawGlInfo.h>
+#include <fcntl.h>
+#include <sys/stat.h>
#define TRIM_MEMORY_COMPLETE 80
#define TRIM_MEMORY_UI_HIDDEN 20
+#define ENABLE_RENDERNODE_SERIALIZATION false
+
#define LOG_FRAMETIME_MMA 0
#if LOG_FRAMETIME_MMA
@@ -480,6 +487,40 @@
mRenderThread.jankTracker().reset();
}
+void CanvasContext::serializeDisplayListTree() {
+#if ENABLE_RENDERNODE_SERIALIZATION
+ using namespace google::protobuf::io;
+ char package[128];
+ // Check whether tracing is enabled for this process.
+ FILE * file = fopen("/proc/self/cmdline", "r");
+ if (file) {
+ if (!fgets(package, 128, file)) {
+ ALOGE("Error reading cmdline: %s (%d)", strerror(errno), errno);
+ fclose(file);
+ return;
+ }
+ fclose(file);
+ } else {
+ ALOGE("Error opening /proc/self/cmdline: %s (%d)", strerror(errno),
+ errno);
+ return;
+ }
+ char path[1024];
+ snprintf(path, 1024, "/data/data/%s/cache/rendertree_dump", package);
+ int fd = open(path, O_CREAT | O_WRONLY, S_IRWXU | S_IRGRP | S_IROTH);
+ if (fd == -1) {
+ ALOGD("Failed to open '%s'", path);
+ return;
+ }
+ proto::RenderNode tree;
+ // TODO: Streaming writes?
+ mRootRenderNode->copyTo(&tree);
+ std::string data = tree.SerializeAsString();
+ write(fd, data.c_str(), data.length());
+ close(fd);
+#endif
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 0ceb9f1..6a79320 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -111,6 +111,8 @@
void setName(const std::string&& name) { mName = name; }
const std::string& name() { return mName; }
+ void serializeDisplayListTree();
+
private:
friend class RegisterFrameCallbackTask;
// TODO: Replace with something better for layer & other GL object
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index a3a0163..b838811 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -490,6 +490,17 @@
post(task);
}
+CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) {
+ args->context->serializeDisplayListTree();
+ return nullptr;
+}
+
+void RenderProxy::serializeDisplayListTree() {
+ SETUP_TASK(serializeDisplayListTree);
+ args->context = mContext;
+ post(task);
+}
+
void RenderProxy::post(RenderTask* task) {
mRenderThread.queue(task);
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 0d2c7be..e7356db 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -104,6 +104,8 @@
ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size);
ANDROID_API void setProcessStatsBuffer(int fd);
+ ANDROID_API void serializeDisplayListTree();
+
private:
RenderThread& mRenderThread;
CanvasContext* mContext;
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index 483fb35..0bbf08c 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -26,6 +26,8 @@
#include "TestContext.h"
+#include "protos/hwui.pb.h"
+
#include <stdio.h>
#include <unistd.h>