Fast path translate() in SkCanvas and SkLiteDL.
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
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index e5ad3b8..e039c60 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1444,9 +1444,14 @@
/////////////////////////////////////////////////////////////////////////////
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) {
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp
index c634d48..c3bf976 100644
--- a/src/core/SkLiteDL.cpp
+++ b/src/core/SkLiteDL.cpp
@@ -52,7 +52,7 @@
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 @@
}
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 @@
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) {
diff --git a/src/core/SkLiteDL.h b/src/core/SkLiteDL.h
index 38a0812..e80548c 100644
--- a/src/core/SkLiteDL.h
+++ b/src/core/SkLiteDL.h
@@ -29,6 +29,7 @@
void concat (const SkMatrix&);
void setMatrix (const SkMatrix&);
+ void translate(SkScalar, SkScalar);
void translateZ(SkScalar);
void clipPath (const SkPath&, SkRegion::Op, bool aa);
diff --git a/src/core/SkLiteRecorder.cpp b/src/core/SkLiteRecorder.cpp
index b61dd8f..049ccd1 100644
--- a/src/core/SkLiteRecorder.cpp
+++ b/src/core/SkLiteRecorder.cpp
@@ -29,8 +29,9 @@
}
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);
diff --git a/src/core/SkLiteRecorder.h b/src/core/SkLiteRecorder.h
index a924378..6ca03cd 100644
--- a/src/core/SkLiteRecorder.h
+++ b/src/core/SkLiteRecorder.h
@@ -25,6 +25,7 @@
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;
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index 0fd8020..fb0c69d 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -290,7 +290,12 @@
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::mapRectScaleTranslate(SkRect* dst, const SkRect& src) const {
SkASSERT(dst);
SkASSERT(this->isScaleTranslate());
-
+
SkScalar sx = fMat[kMScaleX];
SkScalar sy = fMat[kMScaleY];
SkScalar tx = fMat[kMTransX];
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index dcfc0fb..4d27fb6 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -83,6 +83,7 @@
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 @@
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 @@
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) {
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index b961c7d..92bb6ae 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -380,6 +380,10 @@
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);
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index ba171a1..d039e20 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -60,6 +60,7 @@
void didConcat(const SkMatrix&) override;
void didSetMatrix(const SkMatrix&) override;
+ void didTranslate(SkScalar, SkScalar) override;
#ifdef SK_EXPERIMENTAL_SHADOWING
void didTranslateZ(SkScalar) override;