Initial refactoring to enable reuse of SkiaDisplayList
on a per RenderNode basis. With Skia renderer we see 30% speed improvement in Invalidate Tree UI Jank test, when SkiaDisplayList objects are reused. Test: manually built and run on angler-eng. Change-Id: Ie4ec50ddb2015150e3ec678dde7ebed0c8d90067
This commit is contained in:
@@ -52,9 +52,10 @@ public class DisplayListCanvas extends Canvas {
|
||||
if (node == null) throw new IllegalArgumentException("node cannot be null");
|
||||
DisplayListCanvas canvas = sPool.acquire();
|
||||
if (canvas == null) {
|
||||
canvas = new DisplayListCanvas(width, height);
|
||||
canvas = new DisplayListCanvas(node, width, height);
|
||||
} else {
|
||||
nResetDisplayListCanvas(canvas.mNativeCanvasWrapper, width, height);
|
||||
nResetDisplayListCanvas(canvas.mNativeCanvasWrapper, node.mNativeRenderNode,
|
||||
width, height);
|
||||
}
|
||||
canvas.mNode = node;
|
||||
canvas.mWidth = width;
|
||||
@@ -80,8 +81,8 @@ public class DisplayListCanvas extends Canvas {
|
||||
// Constructors
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private DisplayListCanvas(int width, int height) {
|
||||
super(nCreateDisplayListCanvas(width, height));
|
||||
private DisplayListCanvas(@NonNull RenderNode node, int width, int height) {
|
||||
super(nCreateDisplayListCanvas(node.mNativeRenderNode, width, height));
|
||||
mDensity = 0; // disable bitmap density scaling
|
||||
}
|
||||
|
||||
@@ -231,9 +232,10 @@ public class DisplayListCanvas extends Canvas {
|
||||
}
|
||||
|
||||
@FastNative
|
||||
private static native long nCreateDisplayListCanvas(int width, int height);
|
||||
private static native long nCreateDisplayListCanvas(long node, int width, int height);
|
||||
@FastNative
|
||||
private static native void nResetDisplayListCanvas(long canvas, int width, int height);
|
||||
private static native void nResetDisplayListCanvas(long canvas, long node,
|
||||
int width, int height);
|
||||
@FastNative
|
||||
private static native int nGetMaximumTextureWidth();
|
||||
@FastNative
|
||||
|
||||
@@ -169,14 +169,16 @@ static jlong android_view_DisplayListCanvas_finishRecording(JNIEnv* env,
|
||||
}
|
||||
|
||||
static jlong android_view_DisplayListCanvas_createDisplayListCanvas(JNIEnv* env, jobject clazz,
|
||||
jint width, jint height) {
|
||||
return reinterpret_cast<jlong>(Canvas::create_recording_canvas(width, height));
|
||||
jlong renderNodePtr, jint width, jint height) {
|
||||
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
|
||||
return reinterpret_cast<jlong>(Canvas::create_recording_canvas(width, height, renderNode));
|
||||
}
|
||||
|
||||
static void android_view_DisplayListCanvas_resetDisplayListCanvas(JNIEnv* env, jobject clazz,
|
||||
jlong canvasPtr, jint width, jint height) {
|
||||
jlong canvasPtr, jlong renderNodePtr, jint width, jint height) {
|
||||
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
|
||||
canvas->resetRecording(width, height);
|
||||
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
|
||||
canvas->resetRecording(width, height, renderNode);
|
||||
}
|
||||
|
||||
|
||||
@@ -229,8 +231,8 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "nFinishRecording", "(J)J", (void*) android_view_DisplayListCanvas_finishRecording },
|
||||
{ "nDrawRenderNode", "(JJ)V", (void*) android_view_DisplayListCanvas_drawRenderNode },
|
||||
|
||||
{ "nCreateDisplayListCanvas", "(II)J", (void*) android_view_DisplayListCanvas_createDisplayListCanvas },
|
||||
{ "nResetDisplayListCanvas", "(JII)V", (void*) android_view_DisplayListCanvas_resetDisplayListCanvas },
|
||||
{ "nCreateDisplayListCanvas", "(JII)J", (void*) android_view_DisplayListCanvas_createDisplayListCanvas },
|
||||
{ "nResetDisplayListCanvas", "(JJII)V", (void*) android_view_DisplayListCanvas_resetDisplayListCanvas },
|
||||
|
||||
{ "nDrawLayer", "(JJ)V", (void*) android_view_DisplayListCanvas_drawLayer },
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ RecordingCanvas::~RecordingCanvas() {
|
||||
"Destroyed a RecordingCanvas during a record!");
|
||||
}
|
||||
|
||||
void RecordingCanvas::resetRecording(int width, int height) {
|
||||
void RecordingCanvas::resetRecording(int width, int height, RenderNode* node) {
|
||||
LOG_ALWAYS_FATAL_IF(mDisplayList,
|
||||
"prepareDirty called a second time during a recording!");
|
||||
mDisplayList = new DisplayList();
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
RecordingCanvas(size_t width, size_t height);
|
||||
virtual ~RecordingCanvas();
|
||||
|
||||
virtual void resetRecording(int width, int height) override;
|
||||
virtual void resetRecording(int width, int height, RenderNode* node = nullptr) override;
|
||||
virtual WARN_UNUSED_RESULT DisplayList* finishRecording() override;
|
||||
// ----------------------------------------------------------------------------
|
||||
// MISC HWUI OPERATIONS - TODO: CATEGORIZE
|
||||
|
||||
@@ -48,7 +48,8 @@ public:
|
||||
return mCanvas.get();
|
||||
}
|
||||
|
||||
virtual void resetRecording(int width, int height) override {
|
||||
virtual void resetRecording(int width, int height,
|
||||
uirenderer::RenderNode* renderNode) override {
|
||||
LOG_ALWAYS_FATAL("SkiaCanvas cannot be reset as a recording canvas");
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "Canvas.h"
|
||||
|
||||
#include "RecordingCanvas.h"
|
||||
#include "RenderNode.h"
|
||||
#include "MinikinUtils.h"
|
||||
#include "Paint.h"
|
||||
#include "Typeface.h"
|
||||
@@ -25,7 +26,7 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
Canvas* Canvas::create_recording_canvas(int width, int height) {
|
||||
Canvas* Canvas::create_recording_canvas(int width, int height, uirenderer::RenderNode* renderNode) {
|
||||
return new uirenderer::RecordingCanvas(width, height);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,23 @@ public:
|
||||
|
||||
static Canvas* create_canvas(const SkBitmap& bitmap);
|
||||
|
||||
static WARN_UNUSED_RESULT Canvas* create_recording_canvas(int width, int height);
|
||||
/**
|
||||
* Create a new Canvas object that records view system drawing operations for deferred
|
||||
* rendering. A canvas returned by this call supports calls to the resetRecording(...) and
|
||||
* finishRecording() calls. The latter call returns a DisplayList that is specific to the
|
||||
* RenderPipeline defined by Properties::getRenderPipelineType().
|
||||
*
|
||||
* @param width of the requested Canvas.
|
||||
* @param height of the requested Canvas.
|
||||
* @param renderNode is an optional parameter that specifies the node that will consume the
|
||||
* DisplayList produced by the returned Canvas. This enables the reuse of select C++
|
||||
* objects as a speed optimization.
|
||||
* @return new non-null Canvas Object. The type of DisplayList produced by this canvas is
|
||||
determined based on Properties::getRenderPipelineType().
|
||||
*
|
||||
*/
|
||||
static WARN_UNUSED_RESULT Canvas* create_recording_canvas(int width, int height,
|
||||
uirenderer::RenderNode* renderNode = nullptr);
|
||||
|
||||
/**
|
||||
* Create a new Canvas object which delegates to an SkCanvas.
|
||||
@@ -83,7 +99,8 @@ public:
|
||||
* delegated to this object. This function will call ref() on the
|
||||
* SkCanvas, and the returned Canvas will unref() it upon
|
||||
* destruction.
|
||||
* @return new Canvas object. Will not return NULL.
|
||||
* @return new non-null Canvas Object. The type of DisplayList produced by this canvas is
|
||||
* determined based on Properties::getRenderPipelineType().
|
||||
*/
|
||||
static Canvas* create_canvas(SkCanvas* skiaCanvas);
|
||||
|
||||
@@ -112,7 +129,8 @@ public:
|
||||
// View System operations (not exposed in public Canvas API)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
virtual void resetRecording(int width, int height) = 0;
|
||||
virtual void resetRecording(int width, int height,
|
||||
uirenderer::RenderNode* renderNode = nullptr) = 0;
|
||||
virtual uirenderer::DisplayList* finishRecording() = 0;
|
||||
virtual void insertReorderBarrier(bool enableReorder) = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user