speed up maprect for scale+trans case
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2111703002 Review-Url: https://codereview.chromium.org/2111703002
This commit is contained in:
parent
501ca7f538
commit
47df89ebfd
@ -297,3 +297,37 @@ DEF_BENCH( return new MapPointsMatrixBench("mappoints_identity", SkMatrix::I());
|
|||||||
DEF_BENCH( return new MapPointsMatrixBench("mappoints_trans", make_trans()); )
|
DEF_BENCH( return new MapPointsMatrixBench("mappoints_trans", make_trans()); )
|
||||||
DEF_BENCH( return new MapPointsMatrixBench("mappoints_scale", make_scale()); )
|
DEF_BENCH( return new MapPointsMatrixBench("mappoints_scale", make_scale()); )
|
||||||
DEF_BENCH( return new MapPointsMatrixBench("mappoints_affine", make_afine()); )
|
DEF_BENCH( return new MapPointsMatrixBench("mappoints_affine", make_afine()); )
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class MapRectMatrixBench : public MatrixBench {
|
||||||
|
SkMatrix fM;
|
||||||
|
SkRect fR;
|
||||||
|
bool fScaleTrans;
|
||||||
|
|
||||||
|
enum { MEGA_LOOP = 1000 * 1000 };
|
||||||
|
public:
|
||||||
|
MapRectMatrixBench(const char name[], bool scale_trans)
|
||||||
|
: MatrixBench(name), fScaleTrans(scale_trans)
|
||||||
|
{
|
||||||
|
fM.setScale(2, 3);
|
||||||
|
fM.postTranslate(1, 2);
|
||||||
|
|
||||||
|
fR.set(10, 10, 100, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void performTest() override {
|
||||||
|
SkRect dst;
|
||||||
|
if (fScaleTrans) {
|
||||||
|
for (int i = 0; i < MEGA_LOOP; ++i) {
|
||||||
|
fM.mapRectScaleTranslate(&dst, fR);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < MEGA_LOOP; ++i) {
|
||||||
|
fM.mapRect(&dst, fR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
DEF_BENCH( return new MapRectMatrixBench("maprect", false); )
|
||||||
|
DEF_BENCH( return new MapRectMatrixBench("maprectscaletrans", true); )
|
||||||
|
@ -561,6 +561,12 @@ public:
|
|||||||
this->mapPoints(dst, 4);
|
this->mapPoints(dst, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps a rect to another rect, asserting (in debug mode) that the matrix only contains
|
||||||
|
* scale and translate elements. If it contains other elements, the results are undefined.
|
||||||
|
*/
|
||||||
|
void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const;
|
||||||
|
|
||||||
/** Return the mean radius of a circle after it has been mapped by
|
/** Return the mean radius of a circle after it has been mapped by
|
||||||
this matrix. NOTE: in perspective this value assumes the circle
|
this matrix. NOTE: in perspective this value assumes the circle
|
||||||
has its center at the origin.
|
has its center at the origin.
|
||||||
|
@ -1097,12 +1097,32 @@ 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];
|
||||||
|
SkScalar ty = fMat[kMTransY];
|
||||||
|
Sk4f scale(sx, sy, sx, sy);
|
||||||
|
Sk4f trans(tx, ty, tx, ty);
|
||||||
|
|
||||||
|
Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
|
||||||
|
// need to sort so we're not inverted
|
||||||
|
Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
|
||||||
|
Sk4f min = Sk4f::Min(ltrb, rblt);
|
||||||
|
Sk4f max = Sk4f::Max(ltrb, rblt);
|
||||||
|
// We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
|
||||||
|
// ARM this sequence generates the fastest (a single instruction).
|
||||||
|
Sk4f(min[2], min[3], max[0], max[1]).store(&dst->fLeft);
|
||||||
|
}
|
||||||
|
|
||||||
bool SkMatrix::mapRect(SkRect* dst, const SkRect& src) const {
|
bool SkMatrix::mapRect(SkRect* dst, const SkRect& src) const {
|
||||||
SkASSERT(dst);
|
SkASSERT(dst);
|
||||||
|
|
||||||
if (this->rectStaysRect()) {
|
if (this->isScaleTranslate()) {
|
||||||
this->mapPoints((SkPoint*)dst, (const SkPoint*)&src, 2);
|
this->mapRectScaleTranslate(dst, src);
|
||||||
dst->sort();
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
SkPoint quad[4];
|
SkPoint quad[4];
|
||||||
|
@ -953,3 +953,29 @@ DEF_TEST(Matrix_Concat, r) {
|
|||||||
|
|
||||||
REPORTER_ASSERT(r, expected == SkMatrix::Concat(a, b));
|
REPORTER_ASSERT(r, expected == SkMatrix::Concat(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that all variants of maprect are correct.
|
||||||
|
DEF_TEST(Matrix_maprects, r) {
|
||||||
|
const SkScalar scale = 1000;
|
||||||
|
|
||||||
|
SkMatrix mat;
|
||||||
|
mat.setScale(2, 3);
|
||||||
|
mat.postTranslate(1, 4);
|
||||||
|
|
||||||
|
SkRandom rand;
|
||||||
|
for (int i = 0; i < 10000; ++i) {
|
||||||
|
SkRect src = SkRect::MakeLTRB(rand.nextSScalar1() * scale,
|
||||||
|
rand.nextSScalar1() * scale,
|
||||||
|
rand.nextSScalar1() * scale,
|
||||||
|
rand.nextSScalar1() * scale);
|
||||||
|
SkRect dst[3];
|
||||||
|
|
||||||
|
mat.mapPoints((SkPoint*)&dst[0].fLeft, (SkPoint*)&src.fLeft, 2);
|
||||||
|
dst[0].sort();
|
||||||
|
mat.mapRect(&dst[1], src);
|
||||||
|
mat.mapRectScaleTranslate(&dst[2], src);
|
||||||
|
|
||||||
|
REPORTER_ASSERT(r, dst[0] == dst[1]);
|
||||||
|
REPORTER_ASSERT(r, dst[0] == dst[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user