From a3a704afa3a344dc6fdb6fcb082bd7686ed0a6dc Mon Sep 17 00:00:00 2001 From: Mike Reed Date: Fri, 10 Jan 2020 17:21:40 -0500 Subject: [PATCH] Override didTranslate, and add virtual for didScale This completes pushing through the new virtual didConcat44() to our subclasses, and introduces didScale() for future optimizations. We don't call didScale yet, until external subclasses are also updated. This was derived from https://skia-review.googlesource.com/c/skia/+/263349 bug: skia: 9768 Change-Id: Ia26b48e76e323037082e8f2ee83673c26b99ebed Reviewed-on: https://skia-review.googlesource.com/c/skia/+/263702 Reviewed-by: Mike Reed Commit-Queue: Mike Reed --- gm/3d.cpp | 81 ++++++++++++++++++++++++++++++++++ gn/gm.gni | 1 + include/core/SkCanvas.h | 3 ++ include/private/SkM44.h | 3 ++ include/utils/SkLuaCanvas.h | 3 ++ include/utils/SkNWayCanvas.h | 3 +- src/core/SkPictureFlat.h | 3 +- src/core/SkPicturePlayback.cpp | 10 +++++ src/core/SkPictureRecord.cpp | 19 ++++++++ src/core/SkPictureRecord.h | 3 ++ src/core/SkRecordDraw.cpp | 6 +++ src/core/SkRecorder.cpp | 8 ++++ src/core/SkRecorder.h | 2 + src/core/SkRecords.h | 16 +++++++ src/utils/SkLuaCanvas.cpp | 9 ++++ src/utils/SkNWayCanvas.cpp | 11 ++++- tools/debugger/DebugCanvas.cpp | 13 ++++++ tools/debugger/DebugCanvas.h | 4 +- 18 files changed, 193 insertions(+), 5 deletions(-) create mode 100644 gm/3d.cpp diff --git a/gm/3d.cpp b/gm/3d.cpp new file mode 100644 index 0000000000..3bbed2d336 --- /dev/null +++ b/gm/3d.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2020 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gm/gm.h" +#include "include/core/SkCanvas.h" +#include "include/utils/Sk3D.h" + +struct Info { + float fNear = 0.05f; + float fFar = 4; + float fAngle = SK_ScalarPI / 4; + + SkPoint3 fEye { 0, 0, 1.0f/tan(fAngle/2) - 1 }; + SkPoint3 fCOA { 0, 0, 0 }; + SkPoint3 fUp { 0, 1, 0 }; +}; + +static SkMatrix44 inv(const SkMatrix44& m) { + SkMatrix44 inverse; + m.invert(&inverse); + return inverse; +} + +static SkMatrix44 make_ctm(const Info& info, const SkMatrix44& model, SkSize size) { + SkMatrix44 camera, + perspective, + viewport; + + SkScalar w = size.width(); + SkScalar h = size.height(); + + Sk3Perspective(&perspective, info.fNear, info.fFar, info.fAngle); + Sk3LookAt(&camera, info.fEye, info.fCOA, info.fUp); + viewport.setScale(w*0.5f, h*0.5f, 1);//.postTranslate(r.centerX(), r.centerY(), 0); + + return viewport * perspective * camera * model * inv(viewport); +} + +#include "include/core/SkPicture.h" +#include "include/core/SkPictureRecorder.h" + +static void do_draw(SkCanvas* canvas, SkColor color) { + SkAutoCanvasRestore acr(canvas, true); + + Info info; + + SkMatrix44 m; + m.setRotateDegreesAbout(0, 1, 0, 30); + + canvas->concat(make_ctm(info, m, {300, 300})); + + canvas->translate(150, 150); + SkPaint paint; + paint.setColor(color); + canvas->drawRect({-100, -100, 100, 100}, paint); +} + +/* + * Test calling drawables w/ translate and matrices + */ +DEF_SIMPLE_GM(sk3d_simple, real_canvas, 300, 300) { + do_draw(real_canvas, 0xFFFF0000); + + SkPictureRecorder recorder; + SkCanvas* canvas = recorder.beginRecording(300, 300); + + do_draw(canvas, 0x880000FF); + + auto pic = recorder.finishRecordingAsPicture(); + if (true) { + real_canvas->drawPicture(pic); + } else { + auto data = pic->serialize(); + auto pic2 = SkPicture::MakeFromData(data.get()); + real_canvas->drawPicture(pic2); + } +} diff --git a/gn/gm.gni b/gn/gm.gni index 24de9f0a6e..65451d9046 100644 --- a/gn/gm.gni +++ b/gn/gm.gni @@ -7,6 +7,7 @@ _gm = get_path_info("../gm", "abspath") gm_sources = [ + "$_gm/3d.cpp", "$_gm/aaa.cpp", "$_gm/aaclip.cpp", "$_gm/aarectmodes.cpp", diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index 36b9c46983..d27be55924 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -2557,10 +2557,13 @@ protected: virtual void didConcat(const SkMatrix& ) {} virtual void didSetMatrix(const SkMatrix& ) {} virtual void didTranslate(SkScalar dx, SkScalar dy) { + // TODO: update all subclasses to override this, so we can remove default impl. this->didConcat(SkMatrix::MakeTrans(dx, dy)); } // just pass an array for now, until we decide on the "public" form for the matrix virtual void didConcat44(const SkScalar[]) {} + // This is not called by SkCanvas yet. Waiting for subclasses to override it first. + virtual void didScale(SkScalar, SkScalar) {} // NOTE: If you are adding a new onDraw virtual to SkCanvas, PLEASE add an override to // SkCanvasVirtualEnforcer (in SkCanvasVirtualEnforcer.h). This ensures that subclasses using diff --git a/include/private/SkM44.h b/include/private/SkM44.h index 7fd7945946..93a1dd15c6 100644 --- a/include/private/SkM44.h +++ b/include/private/SkM44.h @@ -159,6 +159,9 @@ public: SkM44& preTranslate(SkScalar x, SkScalar y); SkM44& preConcat(const SkMatrix&); + const SkScalar* asColMajor() const { return fMat; } + SkScalar* asColMajor() { return fMat; } + private: /* Stored in column-major. * Indices diff --git a/include/utils/SkLuaCanvas.h b/include/utils/SkLuaCanvas.h index f75c8f219c..5ae4fd1e27 100644 --- a/include/utils/SkLuaCanvas.h +++ b/include/utils/SkLuaCanvas.h @@ -27,8 +27,11 @@ protected: bool onDoSaveBehind(const SkRect*) override; void willRestore() override; + void didConcat44(const SkScalar[16]) override; void didConcat(const SkMatrix&) override; void didSetMatrix(const SkMatrix&) override; + void didScale(SkScalar, SkScalar) override; + void didTranslate(SkScalar, SkScalar) override; void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override; virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, diff --git a/include/utils/SkNWayCanvas.h b/include/utils/SkNWayCanvas.h index 4f46a006ca..1b2673eebb 100644 --- a/include/utils/SkNWayCanvas.h +++ b/include/utils/SkNWayCanvas.h @@ -32,8 +32,9 @@ protected: void didConcat44(const SkScalar[16]) override; void didConcat(const SkMatrix&) override; - void didTranslate(SkScalar x, SkScalar y) override; void didSetMatrix(const SkMatrix&) override; + void didScale(SkScalar, SkScalar) override; + void didTranslate(SkScalar, SkScalar) override; void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override; virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h index 715d131f97..7a8863b8dd 100644 --- a/src/core/SkPictureFlat.h +++ b/src/core/SkPictureFlat.h @@ -104,8 +104,9 @@ enum DrawType { DRAW_EDGEAA_QUAD, DRAW_BEHIND_PAINT, + CONCAT44, - LAST_DRAWTYPE_ENUM = DRAW_BEHIND_PAINT, + LAST_DRAWTYPE_ENUM = CONCAT44, }; enum DrawVertexFlags { diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index 8ce9bcaf9d..315049873f 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -174,6 +174,16 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader, canvas->concat(matrix); break; } + case CONCAT44: { + const SkScalar* colMaj = reader->skipT(16); + BREAK_ON_READ_ERROR(reader); + canvas->concat44(colMaj); + + SkMatrix44 m; + m.setColMajor(colMaj); + m.dump(); + break; + } case DRAW_ANNOTATION: { SkRect rect; reader->readRect(&rect); diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp index 46ba4a42d2..23fe725d1f 100644 --- a/src/core/SkPictureRecord.cpp +++ b/src/core/SkPictureRecord.cpp @@ -219,6 +219,25 @@ void SkPictureRecord::recordScale(const SkMatrix& m) { this->validate(initialOffset, size); } +void SkPictureRecord::didConcat44(const SkScalar m[16]) { + this->validate(fWriter.bytesWritten(), 0); + // op + matrix + size_t size = kUInt32Size + 16 * sizeof(SkScalar); + size_t initialOffset = this->addDraw(CONCAT44, &size); + fWriter.write(m, 16 * sizeof(SkScalar)); + this->validate(initialOffset, size); + + this->INHERITED::didConcat44(m); +} + +void SkPictureRecord::didScale(SkScalar x, SkScalar y) { + this->didConcat(SkMatrix::MakeScale(x, y)); +} + +void SkPictureRecord::didTranslate(SkScalar x, SkScalar y) { + this->didConcat(SkMatrix::MakeTrans(x, y)); +} + void SkPictureRecord::didConcat(const SkMatrix& matrix) { switch (matrix.getType()) { case SkMatrix::kTranslate_Mask: diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h index b83eec2893..3b9d45af63 100644 --- a/src/core/SkPictureRecord.h +++ b/src/core/SkPictureRecord.h @@ -162,8 +162,11 @@ protected: bool onDoSaveBehind(const SkRect*) override; void willRestore() override; + void didConcat44(const SkScalar[16]) override; void didConcat(const SkMatrix&) override; void didSetMatrix(const SkMatrix&) override; + void didScale(SkScalar, SkScalar) override; + void didTranslate(SkScalar, SkScalar) override; void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override; diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp index 16827f07a4..a3e998aad5 100644 --- a/src/core/SkRecordDraw.cpp +++ b/src/core/SkRecordDraw.cpp @@ -93,8 +93,10 @@ template <> void Draw::draw(const DrawBehind& r) { } DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix))); +DRAW(Concat44, concat44(r.matrix.asColMajor())); DRAW(Concat, concat(r.matrix)); DRAW(Translate, translate(r.dx, r.dy)); +DRAW(Scale, scale(r.sx, r.sy)); DRAW(ClipPath, clipPath(r.path, r.opAA.op(), r.opAA.aa())); DRAW(ClipRRect, clipRRect(r.rrect, r.opAA.op(), r.opAA.aa())); @@ -246,7 +248,9 @@ private: template void updateCTM(const T&) {} void updateCTM(const Restore& op) { fCTM = op.matrix; } void updateCTM(const SetMatrix& op) { fCTM = op.matrix; } + void updateCTM(const Concat44& op) { fCTM.preConcat(op.matrix.asM33()); } void updateCTM(const Concat& op) { fCTM.preConcat(op.matrix); } + void updateCTM(const Scale& op) { fCTM.preScale(op.sx, op.sy); } void updateCTM(const Translate& op) { fCTM.preTranslate(op.dx, op.dy); } // The bounds of these ops must be calculated when we hit the Restore @@ -258,6 +262,8 @@ private: void trackBounds(const SetMatrix&) { this->pushControl(); } void trackBounds(const Concat&) { this->pushControl(); } + void trackBounds(const Concat44&) { this->pushControl(); } + void trackBounds(const Scale&) { this->pushControl(); } void trackBounds(const Translate&) { this->pushControl(); } void trackBounds(const ClipRect&) { this->pushControl(); } void trackBounds(const ClipRRect&) { this->pushControl(); } diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp index df584499bb..bc94cfcec6 100644 --- a/src/core/SkRecorder.cpp +++ b/src/core/SkRecorder.cpp @@ -370,6 +370,10 @@ void SkRecorder::didRestore() { this->append(this->getTotalMatrix()); } +void SkRecorder::didConcat44(const SkScalar m[16]) { + this->append(m); +} + void SkRecorder::didConcat(const SkMatrix& matrix) { this->append(matrix); } @@ -378,6 +382,10 @@ void SkRecorder::didSetMatrix(const SkMatrix& matrix) { this->append(matrix); } +void SkRecorder::didScale(SkScalar sx, SkScalar sy) { + this->append(sx, sy); +} + void SkRecorder::didTranslate(SkScalar dx, SkScalar dy) { this->append(dx, dy); } diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h index c20f84cf8c..f15ee1b462 100644 --- a/src/core/SkRecorder.h +++ b/src/core/SkRecorder.h @@ -67,8 +67,10 @@ public: void willRestore() override {} void didRestore() override; + void didConcat44(const SkScalar[16]) override; void didConcat(const SkMatrix&) override; void didSetMatrix(const SkMatrix&) override; + void didScale(SkScalar, SkScalar) override; void didTranslate(SkScalar, SkScalar) override; void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override; diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h index 2c246961bc..e97a13543f 100644 --- a/src/core/SkRecords.h +++ b/src/core/SkRecords.h @@ -23,6 +23,7 @@ #include "include/core/SkString.h" #include "include/core/SkTextBlob.h" #include "include/core/SkVertices.h" +#include "include/private/SkM44.h" #include "src/core/SkDrawShadowInfo.h" namespace SkRecords { @@ -46,7 +47,9 @@ namespace SkRecords { M(SaveBehind) \ M(SetMatrix) \ M(Translate) \ + M(Scale) \ M(Concat) \ + M(Concat44) \ M(ClipPath) \ M(ClipRRect) \ M(ClipRect) \ @@ -153,6 +156,13 @@ struct TypedMatrix : public SkMatrix { TypedMatrix(const SkMatrix& matrix); }; +struct Matrix44 : public SkM44 { + Matrix44() {} + Matrix44(const SkScalar m[16]) { + this->setColMajor(m); + } +}; + enum Tags { kDraw_Tag = 1, // May draw something (usually named DrawFoo). kHasImage_Tag = 2, // Contains an SkImage or SkBitmap. @@ -191,11 +201,17 @@ RECORD(SetMatrix, 0, TypedMatrix matrix); RECORD(Concat, 0, TypedMatrix matrix); +RECORD(Concat44, 0, + Matrix44 matrix); RECORD(Translate, 0, SkScalar dx; SkScalar dy); +RECORD(Scale, 0, + SkScalar sx; + SkScalar sy); + struct ClipOpAndAA { ClipOpAndAA() {} ClipOpAndAA(SkClipOp op, bool aa) : fOp(static_cast(op)), fAA(aa) {} diff --git a/src/utils/SkLuaCanvas.cpp b/src/utils/SkLuaCanvas.cpp index f756ee6c6e..060a1e16d3 100644 --- a/src/utils/SkLuaCanvas.cpp +++ b/src/utils/SkLuaCanvas.cpp @@ -110,6 +110,15 @@ void SkLuaCanvas::willRestore() { this->INHERITED::willRestore(); } +void SkLuaCanvas::didConcat44(const SkScalar m[16]) { + // TODO +} +void SkLuaCanvas::didScale(SkScalar x, SkScalar y) { + this->didConcat(SkMatrix::MakeScale(x, y)); +} +void SkLuaCanvas::didTranslate(SkScalar x, SkScalar y) { + this->didConcat(SkMatrix::MakeTrans(x, y)); +} void SkLuaCanvas::didConcat(const SkMatrix& matrix) { switch (matrix.getType()) { case SkMatrix::kTranslate_Mask: { diff --git a/src/utils/SkNWayCanvas.cpp b/src/utils/SkNWayCanvas.cpp index d338eac41a..bdd9b72b5b 100644 --- a/src/utils/SkNWayCanvas.cpp +++ b/src/utils/SkNWayCanvas.cpp @@ -106,6 +106,13 @@ void SkNWayCanvas::didConcat(const SkMatrix& matrix) { } } +void SkNWayCanvas::didSetMatrix(const SkMatrix& matrix) { + Iter iter(fList); + while (iter.next()) { + iter->setMatrix(matrix); + } +} + void SkNWayCanvas::didTranslate(SkScalar x, SkScalar y) { Iter iter(fList); while (iter.next()) { @@ -113,10 +120,10 @@ void SkNWayCanvas::didTranslate(SkScalar x, SkScalar y) { } } -void SkNWayCanvas::didSetMatrix(const SkMatrix& matrix) { +void SkNWayCanvas::didScale(SkScalar x, SkScalar y) { Iter iter(fList); while (iter.next()) { - iter->setMatrix(matrix); + iter->scale(x, y); } } diff --git a/tools/debugger/DebugCanvas.cpp b/tools/debugger/DebugCanvas.cpp index 578b001c25..14a94bbc01 100644 --- a/tools/debugger/DebugCanvas.cpp +++ b/tools/debugger/DebugCanvas.cpp @@ -312,6 +312,19 @@ void DebugCanvas::onClipRegion(const SkRegion& region, SkClipOp op) { this->addDrawCommand(new ClipRegionCommand(region, op)); } +void DebugCanvas::didConcat44(const SkScalar m[16]) { + // TODO + this->INHERITED::didConcat44(m); +} + +void DebugCanvas::didScale(SkScalar x, SkScalar y) { + this->didConcat(SkMatrix::MakeScale(x, y)); +} + +void DebugCanvas::didTranslate(SkScalar x, SkScalar y) { + this->didConcat(SkMatrix::MakeTrans(x, y)); +} + void DebugCanvas::didConcat(const SkMatrix& matrix) { this->addDrawCommand(new ConcatCommand(matrix)); this->INHERITED::didConcat(matrix); diff --git a/tools/debugger/DebugCanvas.h b/tools/debugger/DebugCanvas.h index 9053f7cd56..d7ddafca89 100644 --- a/tools/debugger/DebugCanvas.h +++ b/tools/debugger/DebugCanvas.h @@ -129,9 +129,11 @@ protected: bool onDoSaveBehind(const SkRect*) override; void willRestore() override; + void didConcat44(const SkScalar[16]) override; void didConcat(const SkMatrix&) override; - void didSetMatrix(const SkMatrix&) override; + void didScale(SkScalar, SkScalar) override; + void didTranslate(SkScalar, SkScalar) override; void onDrawAnnotation(const SkRect&, const char[], SkData*) override; void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;