Update Canvas API with view system calls.

Refactor DisplayListCanvas, RecordingCanvas, and SkiaCanvas
to share a common API.

Change-Id: I0268ec2749ea5d13a3a72bb2784ed6a9911383d9
This commit is contained in:
Derek Sollenberger
2015-07-30 10:00:39 -04:00
parent 5d30450389
commit 6f485569fa
9 changed files with 191 additions and 51 deletions

View File

@@ -27,13 +27,8 @@
#include <SkBitmap.h>
#include <SkRegion.h>
#if HWUI_NEW_OPS
#include <RecordingCanvas.h>
typedef android::uirenderer::RecordingCanvas canvas_t;
#else
#include <DisplayListCanvas.h>
typedef android::uirenderer::DisplayListCanvas canvas_t;
#endif
#include <Canvas.h>
#include <Rect.h>
#include <RenderNode.h>
#include <CanvasProperty.h>
@@ -52,7 +47,7 @@ using namespace uirenderer;
static void android_view_DisplayListCanvas_insertReorderBarrier(JNIEnv* env, jobject clazz,
jlong canvasPtr, jboolean reorderEnable) {
canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
canvas->insertReorderBarrier(reorderEnable);
}
@@ -62,7 +57,7 @@ static void android_view_DisplayListCanvas_insertReorderBarrier(JNIEnv* env, job
static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
jlong canvasPtr, jlong functorPtr) {
canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
Functor* functor = reinterpret_cast<Functor*>(functorPtr);
canvas->callDrawGLFunction(functor);
}
@@ -92,7 +87,7 @@ static jint android_view_DisplayListCanvas_getMaxTextureHeight(JNIEnv* env, jobj
static void android_view_DisplayListCanvas_drawRoundRectProps(JNIEnv* env, jobject clazz,
jlong canvasPtr, jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr,
jlong bottomPropPtr, jlong rxPropPtr, jlong ryPropPtr, jlong paintPropPtr) {
canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
CanvasPropertyPrimitive* leftProp = reinterpret_cast<CanvasPropertyPrimitive*>(leftPropPtr);
CanvasPropertyPrimitive* topProp = reinterpret_cast<CanvasPropertyPrimitive*>(topPropPtr);
CanvasPropertyPrimitive* rightProp = reinterpret_cast<CanvasPropertyPrimitive*>(rightPropPtr);
@@ -105,7 +100,7 @@ static void android_view_DisplayListCanvas_drawRoundRectProps(JNIEnv* env, jobje
static void android_view_DisplayListCanvas_drawCircleProps(JNIEnv* env, jobject clazz,
jlong canvasPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
@@ -119,25 +114,25 @@ static void android_view_DisplayListCanvas_drawCircleProps(JNIEnv* env, jobject
static jlong android_view_DisplayListCanvas_finishRecording(JNIEnv* env,
jobject clazz, jlong canvasPtr) {
canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
return reinterpret_cast<jlong>(canvas->finishRecording());
}
static jlong android_view_DisplayListCanvas_createDisplayListCanvas(JNIEnv* env, jobject clazz,
jint width, jint height) {
return reinterpret_cast<jlong>(new canvas_t(width, height));
return reinterpret_cast<jlong>(Canvas::create_recording_canvas(width, height));
}
static void android_view_DisplayListCanvas_resetDisplayListCanvas(JNIEnv* env, jobject clazz,
jlong canvasPtr, jint width, jint height) {
canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
canvas->reset(width, height);
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
canvas->resetRecording(width, height);
}
static void android_view_DisplayListCanvas_drawRenderNode(JNIEnv* env,
jobject clazz, jlong canvasPtr, jlong renderNodePtr) {
canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
canvas->drawRenderNode(renderNode);
}
@@ -148,7 +143,7 @@ static void android_view_DisplayListCanvas_drawRenderNode(JNIEnv* env,
static void android_view_DisplayListCanvas_drawLayer(JNIEnv* env, jobject clazz,
jlong canvasPtr, jlong layerPtr) {
canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
canvas->drawLayer(layer);
}

View File

@@ -16,10 +16,20 @@
#include "Canvas.h"
#include "DisplayListCanvas.h"
#include "RecordingCanvas.h"
#include <SkDrawFilter.h>
namespace android {
Canvas* Canvas::create_recording_canvas(int width, int height) {
#if HWUI_NEW_OPS
return new uirenderer::RecordingCanvas(width, height);
#else
return new uirenderer::DisplayListCanvas(width, height);
#endif
}
void Canvas::drawTextDecorations(float x, float y, float length, const SkPaint& paint) {
uint32_t flags;
SkDrawFilter* drawFilter = getDrawFilter();

View File

@@ -18,6 +18,7 @@
#define ANDROID_GRAPHICS_CANVAS_H
#include <cutils/compiler.h>
#include <utils/Functor.h>
#include "utils/NinePatch.h"
@@ -27,6 +28,14 @@
namespace android {
namespace uirenderer {
class CanvasPropertyPaint;
class CanvasPropertyPrimitive;
class DeferredLayerUpdater;
class DisplayList;
class RenderNode;
}
namespace SaveFlags {
// These must match the corresponding Canvas API constants.
@@ -56,6 +65,8 @@ public:
static Canvas* create_canvas(const SkBitmap& bitmap);
static Canvas* create_recording_canvas(int width, int height);
/**
* Create a new Canvas object which delegates to an SkCanvas.
*
@@ -81,15 +92,36 @@ public:
*/
virtual SkCanvas* asSkCanvas() = 0;
virtual void setBitmap(const SkBitmap& bitmap) = 0;
virtual bool isOpaque() = 0;
virtual int width() = 0;
virtual int height() = 0;
// ----------------------------------------------------------------------------
// View System operations (not exposed in public Canvas API)
// ----------------------------------------------------------------------------
virtual void resetRecording(int width, int height) = 0;
virtual uirenderer::DisplayList* finishRecording() = 0;
virtual void insertReorderBarrier(bool enableReorder) = 0;
virtual void setHighContrastText(bool highContrastText) = 0;
virtual bool isHighContrastText() = 0;
virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) = 0;
virtual void drawCircle(uirenderer::CanvasPropertyPrimitive* x,
uirenderer::CanvasPropertyPrimitive* y, uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint) = 0;
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) = 0;
virtual void drawRenderNode(uirenderer::RenderNode* renderNode) = 0;
virtual void callDrawGLFunction(Functor* functor) = 0;
// ----------------------------------------------------------------------------
// Canvas state operations
// ----------------------------------------------------------------------------

View File

@@ -42,7 +42,7 @@ DisplayListCanvas::DisplayListCanvas(int width, int height)
, mDeferredBarrierType(kBarrier_None)
, mHighContrastText(false)
, mRestoreSaveCount(-1) {
reset(width, height);
resetRecording(width, height);
}
DisplayListCanvas::~DisplayListCanvas() {
@@ -50,7 +50,7 @@ DisplayListCanvas::~DisplayListCanvas() {
"Destroyed a DisplayListCanvas during a record!");
}
void DisplayListCanvas::reset(int width, int height) {
void DisplayListCanvas::resetRecording(int width, int height) {
LOG_ALWAYS_FATAL_IF(mDisplayList,
"prepareDirty called a second time during a recording!");
mDisplayList = new DisplayList();

View File

@@ -67,36 +67,33 @@ public:
DisplayListCanvas(int width, int height);
virtual ~DisplayListCanvas();
void reset(int width, int height);
WARN_UNUSED_RESULT DisplayList* finishRecording();
virtual void resetRecording(int width, int height) override;
virtual WARN_UNUSED_RESULT DisplayList* finishRecording() override;
// ----------------------------------------------------------------------------
// HWUI Canvas state operations
// ----------------------------------------------------------------------------
void insertReorderBarrier(bool enableReorder);
virtual void insertReorderBarrier(bool enableReorder) override;
// ----------------------------------------------------------------------------
// HWUI Canvas draw operations
// ----------------------------------------------------------------------------
// Shapes
void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
virtual void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
CanvasPropertyPaint* paint);
void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint);
CanvasPropertyPaint* paint) override;
virtual void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) override;
// ----------------------------------------------------------------------------
// HWUI Canvas draw operations - special
// ----------------------------------------------------------------------------
void drawLayer(DeferredLayerUpdater* layerHandle);
void drawRenderNode(RenderNode* renderNode);
// TODO: rename for consistency
void callDrawGLFunction(Functor* functor);
virtual void drawLayer(DeferredLayerUpdater* layerHandle) override;
virtual void drawRenderNode(RenderNode* renderNode) override;
virtual void callDrawGLFunction(Functor* functor) override;
// ----------------------------------------------------------------------------
// CanvasStateClient interface

View File

@@ -27,7 +27,7 @@ namespace uirenderer {
RecordingCanvas::RecordingCanvas(size_t width, size_t height)
: mState(*this)
, mResourceCache(ResourceCache::getInstance()) {
reset(width, height);
resetRecording(width, height);
}
RecordingCanvas::~RecordingCanvas() {
@@ -35,7 +35,7 @@ RecordingCanvas::~RecordingCanvas() {
"Destroyed a RecordingCanvas during a record!");
}
void RecordingCanvas::reset(int width, int height) {
void RecordingCanvas::resetRecording(int width, int height) {
LOG_ALWAYS_FATAL_IF(mDisplayList,
"prepareDirty called a second time during a recording!");
mDisplayList = new DisplayList();

View File

@@ -50,22 +50,19 @@ public:
RecordingCanvas(size_t width, size_t height);
virtual ~RecordingCanvas();
void reset(int width, int height);
WARN_UNUSED_RESULT DisplayList* finishRecording();
virtual void resetRecording(int width, int height) override;
virtual WARN_UNUSED_RESULT DisplayList* finishRecording() override;
// ----------------------------------------------------------------------------
// MISC HWUI OPERATIONS - TODO: CATEGORIZE
// ----------------------------------------------------------------------------
void insertReorderBarrier(bool enableReorder) {
virtual void insertReorderBarrier(bool enableReorder) override {
mDeferredBarrierType = enableReorder
? DeferredBarrierType::OutOfOrder : DeferredBarrierType::InOrder;
}
void drawLayer(DeferredLayerUpdater* layerHandle);
void drawRenderNode(RenderNode* renderNode);
// TODO: rename for consistency
void callDrawGLFunction(Functor* functor);
virtual void drawLayer(DeferredLayerUpdater* layerHandle) override;
virtual void drawRenderNode(RenderNode* renderNode) override;
virtual void callDrawGLFunction(Functor* functor) override;
// ----------------------------------------------------------------------------
// CanvasStateClient interface
@@ -78,12 +75,12 @@ public:
// HWUI Canvas draw operations
// ----------------------------------------------------------------------------
void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
virtual void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
CanvasPropertyPaint* paint);
void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint);
CanvasPropertyPaint* paint) override;
virtual void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) override;
// ----------------------------------------------------------------------------
// android/graphics/Canvas interface

View File

@@ -15,13 +15,18 @@
*/
#include "Canvas.h"
#include "CanvasProperty.h"
#include "Layer.h"
#include "RenderNode.h"
#include <SkCanvas.h>
#include <SkClipStack.h>
#include <SkDrawable.h>
#include <SkDevice.h>
#include <SkDeque.h>
#include <SkDrawFilter.h>
#include <SkGraphics.h>
#include <SkImage.h>
#include <SkShader.h>
#include <SkTArray.h>
#include <SkTLazy.h>
@@ -54,6 +59,18 @@ public:
return mCanvas.get();
}
virtual void resetRecording(int width, int height) override {
LOG_ALWAYS_FATAL("SkiaCanvas cannot be reset as a recording canvas");
}
virtual uirenderer::DisplayList* finishRecording() override {
LOG_ALWAYS_FATAL("SkiaCanvas does not produce a DisplayList");
return nullptr;
}
virtual void insertReorderBarrier(bool enableReorder) override {
LOG_ALWAYS_FATAL("SkiaCanvas does not support reordering barriers");
}
virtual void setBitmap(const SkBitmap& bitmap) override;
virtual bool isOpaque() override;
@@ -140,6 +157,18 @@ public:
virtual bool drawTextAbsolutePos() const override { return true; }
virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) override;
virtual void drawCircle(uirenderer::CanvasPropertyPrimitive* x,
uirenderer::CanvasPropertyPrimitive* y, uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint) override;
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override;
virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override;
virtual void callDrawGLFunction(Functor* functor) override;
private:
struct SaveRec {
int saveCount;
@@ -748,4 +777,84 @@ void SkiaCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath&
mCanvas->drawTextOnPathHV(glyphs, count << 1, path, hOffset, vOffset, paint);
}
// ----------------------------------------------------------------------------
// Canvas draw operations: Animations
// ----------------------------------------------------------------------------
class AnimatedRoundRect : public SkDrawable {
public:
AnimatedRoundRect(uirenderer::CanvasPropertyPrimitive* left,
uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* p) :
mLeft(left), mTop(top), mRight(right), mBottom(bottom), mRx(rx), mRy(ry), mPaint(p) {}
protected:
virtual SkRect onGetBounds() override {
return SkRect::MakeLTRB(mLeft->value, mTop->value, mRight->value, mBottom->value);
}
virtual void onDraw(SkCanvas* canvas) override {
SkRect rect = SkRect::MakeLTRB(mLeft->value, mTop->value, mRight->value, mBottom->value);
canvas->drawRoundRect(rect, mRx->value, mRy->value, mPaint->value);
}
private:
sp<uirenderer::CanvasPropertyPrimitive> mLeft;
sp<uirenderer::CanvasPropertyPrimitive> mTop;
sp<uirenderer::CanvasPropertyPrimitive> mRight;
sp<uirenderer::CanvasPropertyPrimitive> mBottom;
sp<uirenderer::CanvasPropertyPrimitive> mRx;
sp<uirenderer::CanvasPropertyPrimitive> mRy;
sp<uirenderer::CanvasPropertyPaint> mPaint;
};
class AnimatedCircle : public SkDrawable {
public:
AnimatedCircle(uirenderer::CanvasPropertyPrimitive* x, uirenderer::CanvasPropertyPrimitive* y,
uirenderer::CanvasPropertyPrimitive* radius, uirenderer::CanvasPropertyPaint* paint) :
mX(x), mY(y), mRadius(radius), mPaint(paint) {}
protected:
virtual SkRect onGetBounds() override {
const float x = mX->value;
const float y = mY->value;
const float radius = mRadius->value;
return SkRect::MakeLTRB(x - radius, y - radius, x + radius, y + radius);
}
virtual void onDraw(SkCanvas* canvas) override {
canvas->drawCircle(mX->value, mY->value, mRadius->value, mPaint->value);
}
private:
sp<uirenderer::CanvasPropertyPrimitive> mX;
sp<uirenderer::CanvasPropertyPrimitive> mY;
sp<uirenderer::CanvasPropertyPrimitive> mRadius;
sp<uirenderer::CanvasPropertyPaint> mPaint;
};
void SkiaCanvas::drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) {
SkAutoTUnref<AnimatedRoundRect> drawable(
new AnimatedRoundRect(left, top, right, bottom, rx, ry, paint));
mCanvas->drawDrawable(drawable.get());
}
void SkiaCanvas::drawCircle(uirenderer::CanvasPropertyPrimitive* x, uirenderer::CanvasPropertyPrimitive* y,
uirenderer::CanvasPropertyPrimitive* radius, uirenderer::CanvasPropertyPaint* paint) {
SkAutoTUnref<AnimatedCircle> drawable(new AnimatedCircle(x, y, radius, paint));
mCanvas->drawDrawable(drawable.get());
}
// ----------------------------------------------------------------------------
// Canvas draw operations: View System
// ----------------------------------------------------------------------------
void SkiaCanvas::drawLayer(uirenderer::DeferredLayerUpdater* layer) { }
void SkiaCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) { }
void SkiaCanvas::callDrawGLFunction(Functor* functor) { }
} // namespace android

View File

@@ -63,7 +63,7 @@ void BM_DisplayListCanvas_record_empty::Run(int iters) {
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
canvas.reset(100, 100);
canvas.resetRecording(100, 100);
MicroBench::DoNotOptimize(&canvas);
delete canvas.finishRecording();
}
@@ -77,7 +77,7 @@ void BM_DisplayListCanvas_record_saverestore::Run(int iters) {
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
canvas.reset(100, 100);
canvas.resetRecording(100, 100);
canvas.save(SaveFlags::MatrixClip);
canvas.save(SaveFlags::MatrixClip);
MicroBench::DoNotOptimize(&canvas);
@@ -95,7 +95,7 @@ void BM_DisplayListCanvas_record_translate::Run(int iters) {
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
canvas.reset(100, 100);
canvas.resetRecording(100, 100);
canvas.scale(10, 10);
MicroBench::DoNotOptimize(&canvas);
delete canvas.finishRecording();
@@ -119,7 +119,7 @@ void BM_DisplayListCanvas_record_simpleBitmapView::Run(int iters) {
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
canvas.reset(100, 100);
canvas.resetRecording(100, 100);
{
canvas.save(SaveFlags::MatrixClip);
canvas.drawRect(0, 0, 100, 100, rectPaint);