Fast path translate() in SkCanvas and SkLiteDL.
authormtklein <mtklein@chromium.org>
Fri, 19 Aug 2016 16:05:27 +0000 (09:05 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 19 Aug 2016 16:05:27 +0000 (09:05 -0700)
This adds didTranslate() so that SkLiteDL (and other canvas recorders)
can record the translate rather than the full concat.

It also adds a case to SkMatrix::preTranslate() to fast path
translate x translate -> translate (i.e. +=).

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2255283002

Committed: https://skia.googlesource.com/skia/+/5fa47f4fd13b3158de4599414c86d17649c2dd1c

Misc bots failing in pictureimagefilter replay modes.
https://luci-milo.appspot.com/swarming/task/30b8e53f3a1f4f10/steps/dm/0/stdout

Problem is FMA vs. not.

CQ_INCLUDE_TRYBOTS=master.client.skia:
Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-Fast-Trybot

Review-Url: https://codereview.chromium.org/2255283002

include/core/SkCanvas.h
include/private/SkRecords.h
src/core/SkCanvas.cpp
src/core/SkLiteDL.cpp
src/core/SkLiteDL.h
src/core/SkLiteRecorder.cpp
src/core/SkLiteRecorder.h
src/core/SkMatrix.cpp
src/core/SkRecordDraw.cpp
src/core/SkRecorder.cpp
src/core/SkRecorder.h

index a32d27b4d9c2c9f502e179b23c2f60a8e60a7f52..52a322576e6ad55d40e2beb43b75c5d24625e137 100644 (file)
@@ -1352,6 +1352,9 @@ protected:
     virtual void didRestore() {}
     virtual void didConcat(const SkMatrix&) {}
     virtual void didSetMatrix(const SkMatrix&) {}
+    virtual void didTranslate(SkScalar dx, SkScalar dy) {
+        this->didConcat(SkMatrix::MakeTrans(dx, dy));
+    }
 
 #ifdef SK_EXPERIMENTAL_SHADOWING
     virtual void didTranslateZ(SkScalar) {}
index a095452d1cb23883f985a3e51d4a38f5754e8ea2..90a82ee04d431696f92a2045b736c9b0371b17e3 100644 (file)
@@ -47,6 +47,7 @@ namespace SkRecords {
     M(Save)                                                         \
     M(SaveLayer)                                                    \
     M(SetMatrix)                                                    \
+    M(Translate)                                                    \
     M(TranslateZ)                                                   \
     M(Concat)                                                       \
     M(ClipPath)                                                     \
@@ -182,6 +183,9 @@ RECORD(SetMatrix, 0,
 RECORD(Concat, 0,
         TypedMatrix matrix);
 
+RECORD(Translate, 0,
+        SkScalar dx;
+        SkScalar dy);
 RECORD(TranslateZ, 0, SkScalar z);
 
 struct RegionOpAndAA {
index e5ad3b80ef9f47750388b74948f61a070a7300ae..e039c60e0a4586ce0816ee575adf7a797e3073c0 100644 (file)
@@ -1444,9 +1444,14 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPa
 /////////////////////////////////////////////////////////////////////////////
 
 void SkCanvas::translate(SkScalar dx, SkScalar dy) {
-    SkMatrix m;
-    m.setTranslate(dx, dy);
-    this->concat(m);
+    this->checkForDeferredSave();
+    fDeviceCMDirty = true;
+    fMCRec->fMatrix.preTranslate(dx,dy);
+
+    // Translate shouldn't affect the is-scale-translateness of the matrix.
+    SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
+
+    this->didTranslate(dx,dy);
 }
 
 void SkCanvas::scale(SkScalar sx, SkScalar sy) {
index c634d4825a33a724fa230444fbe7e2466351eeaf..c3bf976a888d61e6abaac0293ccfc06fa26282d1 100644 (file)
@@ -52,7 +52,7 @@ static void make_threadsafe(SkPath* path, SkMatrix* matrix) {
 namespace {
 #define TYPES(M)                                                                \
     M(Save) M(Restore) M(SaveLayer)                                             \
-    M(Concat) M(SetMatrix) M(TranslateZ)                                        \
+    M(Concat) M(SetMatrix) M(Translate) M(TranslateZ)                           \
     M(ClipPath) M(ClipRect) M(ClipRRect) M(ClipRegion)                          \
     M(DrawPaint) M(DrawPath) M(DrawRect) M(DrawOval) M(DrawRRect) M(DrawDRRect) \
     M(DrawAnnotation) M(DrawDrawable) M(DrawPicture) M(DrawShadowedPicture)     \
@@ -115,6 +115,14 @@ namespace {
         }
         void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
     };
+    struct Translate final : Op {
+        static const auto kType = Type::Translate;
+        Translate(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {}
+        SkScalar dx,dy;
+        void draw(SkCanvas* c, const SkMatrix&) {
+            c->translate(dx, dy);
+        }
+    };
     struct TranslateZ final : Op {
         static const auto kType = Type::TranslateZ;
         TranslateZ(SkScalar dz) : dz(dz) {}
@@ -539,8 +547,9 @@ void SkLiteDL::saveLayer(const SkRect* bounds, const SkPaint* paint,
     this->push<SaveLayer>(0, bounds, paint, backdrop, flags);
 }
 
-void SkLiteDL::   concat(const SkMatrix& matrix) { this->push   <Concat>(0, matrix); }
-void SkLiteDL::setMatrix(const SkMatrix& matrix) { this->push<SetMatrix>(0, matrix); }
+void SkLiteDL::   concat(const SkMatrix& matrix)   { this->push   <Concat>(0, matrix); }
+void SkLiteDL::setMatrix(const SkMatrix& matrix)   { this->push<SetMatrix>(0, matrix); }
+void SkLiteDL::translate(SkScalar dx, SkScalar dy) { this->push<Translate>(0, dx, dy); }
 void SkLiteDL::translateZ(SkScalar dz) { this->push<TranslateZ>(0, dz); }
 
 void SkLiteDL::clipPath(const SkPath& path, SkRegion::Op op, bool aa) {
index 38a08129ac6a70791fb1b3899b439e94438710ff..e80548cecd69edb49830f9c8f9c00afd796e5c68 100644 (file)
@@ -29,6 +29,7 @@ public:
 
     void    concat (const SkMatrix&);
     void setMatrix (const SkMatrix&);
+    void translate(SkScalar, SkScalar);
     void translateZ(SkScalar);
 
     void clipPath  (const   SkPath&, SkRegion::Op, bool aa);
index b61dd8f582ccf191381802cc7648fcddb915280b..049ccd1afe615676451c44b34914a4603e24b2a0 100644 (file)
@@ -29,8 +29,9 @@ SkCanvas::SaveLayerStrategy SkLiteRecorder::getSaveLayerStrategy(const SaveLayer
 }
 void SkLiteRecorder::willRestore() { fDL->restore(); }
 
-void SkLiteRecorder::didConcat   (const SkMatrix& matrix) { fDL->   concat(matrix); }
-void SkLiteRecorder::didSetMatrix(const SkMatrix& matrix) { fDL->setMatrix(matrix); }
+void SkLiteRecorder::didConcat   (const SkMatrix& matrix)   { fDL->   concat(matrix); }
+void SkLiteRecorder::didSetMatrix(const SkMatrix& matrix)   { fDL->setMatrix(matrix); }
+void SkLiteRecorder::didTranslate(SkScalar dx, SkScalar dy) { fDL->translate(dx, dy); }
 
 void SkLiteRecorder::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle style) {
     fDL->clipRect(rect, op, style==kSoft_ClipEdgeStyle);
index a9243788460a7fb5b801d164e8c4d20346c56be7..6ca03cd46c04ca43bec69db9d2e95c4a9b4d53ff 100644 (file)
@@ -25,6 +25,7 @@ public:
 
     void didConcat(const SkMatrix&) override;
     void didSetMatrix(const SkMatrix&) override;
+    void didTranslate(SkScalar, SkScalar) override;
 
     void onClipRect  (const   SkRect&, SkRegion::Op, ClipEdgeStyle) override;
     void onClipRRect (const  SkRRect&, SkRegion::Op, ClipEdgeStyle) override;
index 0fd802087fc0c5f52e6da2be56edbfb1b9fcc442..fb0c69d7c7287d8428e9de233c85e38280374a69 100644 (file)
@@ -290,7 +290,12 @@ void SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {
         return;
     }
 
-    if (this->hasPerspective()) {
+    if (fTypeMask <= kTranslate_Mask) {
+        fMat[kMTransX] += dx;
+        fMat[kMTransY] += dy;
+        this->setTypeMask((fMat[kMTransX] != 0 || fMat[kMTransY] != 0) ? kTranslate_Mask
+                                                                       : kIdentity_Mask);
+    } else if (this->hasPerspective()) {
         SkMatrix    m;
         m.setTranslate(dx, dy);
         this->preConcat(m);
@@ -1100,7 +1105,7 @@ void SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const {
 void SkMatrix::mapRectScaleTranslate(SkRect* dst, const SkRect& src) const {
     SkASSERT(dst);
     SkASSERT(this->isScaleTranslate());
-    
+
     SkScalar sx = fMat[kMScaleX];
     SkScalar sy = fMat[kMScaleY];
     SkScalar tx = fMat[kMTransX];
index dcfc0fbf900cfa9a7f3db184043362f8c7e1cba7..4d27fb6968337a02931f2ccdd73ffa5ce5b0a8ee 100644 (file)
@@ -83,6 +83,7 @@ DRAW(SaveLayer, saveLayer(SkCanvas::SaveLayerRec(r.bounds,
                                                  r.saveLayerFlags)));
 DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix)));
 DRAW(Concat, concat(r.matrix));
+DRAW(Translate, translate(r.dx, r.dy));
 
 DRAW(ClipPath, clipPath(r.path, r.opAA.op, r.opAA.aa));
 DRAW(ClipRRect, clipRRect(r.rrect, r.opAA.op, r.opAA.aa));
@@ -241,11 +242,12 @@ private:
         SkMatrix ctm;
     };
 
-    // Only Restore, SetMatrix, and Concat change the CTM.
+    // Only Restore, SetMatrix, Concat, and Translate change the CTM.
     template <typename T> void updateCTM(const T&) {}
     void updateCTM(const Restore& op)   { fCTM = op.matrix; }
     void updateCTM(const SetMatrix& op) { fCTM = op.matrix; }
     void updateCTM(const Concat& op)    { fCTM.preConcat(op.matrix); }
+    void updateCTM(const Translate& op) { fCTM.preTranslate(op.dx, op.dy); }
 
     // Most ops don't change the clip.
     template <typename T> void updateClipBounds(const T&) {}
@@ -299,12 +301,13 @@ private:
 
     void trackBounds(const SetMatrix&)         { this->pushControl(); }
     void trackBounds(const Concat&)            { this->pushControl(); }
+    void trackBounds(const Translate&)         { this->pushControl(); }
+    void trackBounds(const TranslateZ&)        { this->pushControl(); }
     void trackBounds(const ClipRect&)          { this->pushControl(); }
     void trackBounds(const ClipRRect&)         { this->pushControl(); }
     void trackBounds(const ClipPath&)          { this->pushControl(); }
     void trackBounds(const ClipRegion&)        { this->pushControl(); }
 
-    void trackBounds(const TranslateZ&)              { this->pushControl(); }
 
     // For all other ops, we can calculate and store the bounds directly now.
     template <typename T> void trackBounds(const T& op) {
index b961c7d1e79a0a186af157c669e3645f24805d8c..92bb6aee5df05bffe89f3ecfbf162d9ea8aab7a9 100644 (file)
@@ -380,6 +380,10 @@ void SkRecorder::didSetMatrix(const SkMatrix& matrix) {
     APPEND(SetMatrix, matrix);
 }
 
+void SkRecorder::didTranslate(SkScalar dx, SkScalar dy) {
+    APPEND(Translate, dx, dy);
+}
+
 void SkRecorder::didTranslateZ(SkScalar z) {
 #ifdef SK_EXPERIMENTAL_SHADOWING
     APPEND(TranslateZ, z);
index ba171a17eeed25e380dcedd63e2f1d153f6c38f1..d039e20e2934e4a0d621a39845d02e1885f2c894 100644 (file)
@@ -60,6 +60,7 @@ public:
 
     void didConcat(const SkMatrix&) override;
     void didSetMatrix(const SkMatrix&) override;
+    void didTranslate(SkScalar, SkScalar) override;
 
 #ifdef SK_EXPERIMENTAL_SHADOWING
     void didTranslateZ(SkScalar) override;