11#include "third_party/skia/include/core/SkM44.h"
12#include "third_party/skia/include/core/SkMatrix.h"
13#include "third_party/skia/include/core/SkPoint3.h"
21static constexpr float kSimplePerspective[16] = {
23 2.0f, 0.0f, 0.0f, 0.0f,
24 0.0f, 2.0f, 0.0f, 0.0f,
25 0.0f, 0.0f, 1.0f, 0.0f,
26 0.0f, 0.0f, 0.0f, 3.0f
34static constexpr float kClipOneCornerPerspective[16] = {
36 2.0f, 0.0f, 0.0f, -0.01f,
37 0.0f, 2.0f, 0.0f, -0.006f,
38 0.0f, 0.0f, 1.0f, 0.0f,
39 0.0f, 0.0f, 0.0f, 3.0f
43static constexpr float kClipTwoCornersPerspective[16] = {
45 2.0f, 0.0f, 0.0f, -.015f,
46 0.0f, 2.0f, 0.0f, -.006f,
47 0.0f, 0.0f, 1.0f, 0.0f,
48 0.0f, 0.0f, 0.0f, 3.0f
52static constexpr float kClipThreeCornersPerspective[16] = {
54 2.0f, 0.0f, 0.0f, -.02f,
55 0.0f, 2.0f, 0.0f, -.006f,
56 0.0f, 0.0f, 1.0f, 0.0f,
57 0.0f, 0.0f, 0.0f, 3.0f
61static constexpr float kClipFourCornersPerspective[16] = {
63 2.0f, 0.0f, 0.0f, -.025f,
64 0.0f, 2.0f, 0.0f, -.006f,
65 0.0f, 0.0f, 1.0f, 0.0f,
66 0.0f, 0.0f, 0.0f, 3.0f
70enum class AdapterType {
102class TransformAdapter {
104 TransformAdapter() =
default;
105 virtual ~TransformAdapter() =
default;
112 virtual void DoNothing(TestTransform& ignored)
const = 0;
114 virtual void InitRectLTRB(TestRect& rect,
118 float bottom)
const = 0;
119 virtual void InitPoint(TestPoint& point,
float x,
float y)
const = 0;
122 virtual void InitTransformIdentity(TestTransform& result)
const = 0;
123 virtual void InitTransformColMatrix(TestTransform& result,
124 const float m[16])
const = 0;
126 virtual void Translate(TestTransform& result,
float tx,
float ty)
const = 0;
127 virtual void Scale(TestTransform& result,
float sx,
float sy)
const = 0;
128 virtual void RotateRadians(TestTransform& result,
float radians)
const = 0;
130 virtual void Concat(
const TestTransform& a,
131 const TestTransform&
b,
132 TestTransform& result)
const = 0;
134 virtual void TransformPoint(
const TestTransform&
transform,
136 TestPoint& out)
const = 0;
137 virtual void TransformPoints(
const TestTransform&
transform,
138 const TestPoint in[],
141 virtual void TransformRectFast(
const TestTransform&
transform,
143 TestRect& out)
const = 0;
144 virtual void TransformAndClipRect(
const TestTransform&
transform,
146 TestRect& out)
const = 0;
147 virtual int CountClippedCorners(
const TestTransform&
transform,
148 const TestRect& rect)
const = 0;
149 virtual void InvertUnchecked(
const TestTransform&
transform,
150 TestTransform& result)
const = 0;
151 virtual bool InvertAndCheck(
const TestTransform&
transform,
152 TestTransform& result)
const = 0;
155class SkiaAdapterBase :
public TransformAdapter {
158 void DoNothing(TestTransform& ignored)
const override {}
160 void InitPoint(TestPoint& point,
float x,
float y)
const override {
161 point.sk_point.set(
x,
y);
164 void InitRectLTRB(TestRect& rect,
168 float bottom)
const override {
169 rect.sk_rect.setLTRB(left, top, right, bottom);
173class SkMatrixAdapter :
public SkiaAdapterBase {
175 SkMatrixAdapter() =
default;
176 ~SkMatrixAdapter() =
default;
178 void InitTransformIdentity(TestTransform& result)
const override {
179 result.sk_matrix.setIdentity();
182 virtual void InitTransformColMatrix(TestTransform& result,
183 const float m[16])
const override {
184 result.sk_matrix = SkM44::ColMajor(m).asM33();
187 void Translate(TestTransform& result,
float tx,
float ty)
const override {
188 result.sk_matrix.preTranslate(tx, ty);
191 void Scale(TestTransform& result,
float sx,
float sy)
const override {
192 result.sk_matrix.preScale(sx, sy);
195 void RotateRadians(TestTransform& result,
float radians)
const override {
196 result.sk_matrix.preRotate(SkRadiansToDegrees(radians));
199 void Concat(
const TestTransform& a,
200 const TestTransform& b,
201 TestTransform& result)
const override {
202 result.sk_matrix = SkMatrix::Concat(a.sk_matrix,
b.sk_matrix);
205 void TransformPoint(
const TestTransform&
transform,
207 TestPoint& out)
const override {
208 out.sk_point =
transform.sk_matrix.mapPoint(in.sk_point);
211 void TransformPoints(
const TestTransform&
transform,
212 const TestPoint in[],
214 int n)
const override {
215 static_assert(
sizeof(TestPoint) ==
sizeof(SkPoint));
216 transform.sk_matrix.mapPoints({
reinterpret_cast<SkPoint*
>(out), n},
217 {
reinterpret_cast<const SkPoint*
>(in), n});
220 void TransformRectFast(
const TestTransform&
transform,
222 TestRect& out)
const override {
223 out.sk_rect =
transform.sk_matrix.mapRect(in.sk_rect);
226 void TransformAndClipRect(
const TestTransform&
transform,
228 TestRect& out)
const override {
229 out.sk_rect =
transform.sk_matrix.mapRect(in.sk_rect);
232 int CountClippedCorners(
const TestTransform&
transform,
233 const TestRect& rect)
const {
234 SkPoint3 homogenous[4];
236 rect.sk_rect.toQuad(corners);
237 transform.sk_matrix.mapPointsToHomogeneous({homogenous, 4}, {corners, 4});
239 for (SkPoint3 hpt : homogenous) {
247 void InvertUnchecked(
const TestTransform&
transform,
248 TestTransform& result)
const override {
250 bool ret =
transform.sk_matrix.invert(&result.sk_matrix);
253 bool InvertAndCheck(
const TestTransform&
transform,
254 TestTransform& result)
const override {
255 return transform.sk_matrix.invert(&result.sk_matrix);
259class SkM44Adapter :
public SkiaAdapterBase {
261 SkM44Adapter() =
default;
262 ~SkM44Adapter() =
default;
264 void InitTransformIdentity(TestTransform& storage)
const override {
265 storage.sk_m44.setIdentity();
268 virtual void InitTransformColMatrix(TestTransform& result,
269 const float m[16])
const override {
270 result.sk_m44 = SkM44::ColMajor(m);
273 void Translate(TestTransform& storage,
float tx,
float ty)
const override {
274 storage.sk_m44.preTranslate(tx, ty);
277 void Scale(TestTransform& storage,
float sx,
float sy)
const override {
278 storage.sk_m44.preScale(sx, sy);
281 void RotateRadians(TestTransform& storage,
float radians)
const override {
282 storage.sk_m44.preConcat(SkM44::Rotate({0, 0, 1}, radians));
285 void Concat(
const TestTransform& a,
286 const TestTransform& b,
287 TestTransform& result)
const override {
288 result.sk_m44.setConcat(a.sk_m44,
b.sk_m44);
291 void TransformPoint(
const TestTransform&
transform,
293 TestPoint& out)
const override {
294 out.sk_point =
transform.sk_m44.asM33().mapPoint(in.sk_point);
297 void TransformPoints(
const TestTransform&
transform,
298 const TestPoint in[],
300 int n)
const override {
301 static_assert(
sizeof(TestPoint) ==
sizeof(SkPoint));
303 {
reinterpret_cast<SkPoint*
>(out), n},
304 {
reinterpret_cast<const SkPoint*
>(in), n});
307 void TransformRectFast(
const TestTransform&
transform,
309 TestRect& out)
const override {
313 .mapRect(in.sk_rect);
317 void TransformAndClipRect(
const TestTransform&
transform,
319 TestRect& out)
const override {
323 .mapRect(in.sk_rect);
327 int CountClippedCorners(
const TestTransform&
transform,
328 const TestRect& rect)
const {
329 SkPoint3 homogenous[4];
331 rect.sk_rect.toQuad(corners);
332 transform.sk_m44.asM33().mapPointsToHomogeneous({homogenous, 4},
335 for (SkPoint3 hpt : homogenous) {
343 void InvertUnchecked(
const TestTransform&
transform,
344 TestTransform& result)
const override {
346 bool ret =
transform.sk_m44.invert(&result.sk_m44);
349 bool InvertAndCheck(
const TestTransform&
transform,
350 TestTransform& result)
const override {
351 return transform.sk_m44.invert(&result.sk_m44);
355class ImpellerMatrixAdapter :
public TransformAdapter {
357 ImpellerMatrixAdapter() =
default;
358 ~ImpellerMatrixAdapter() =
default;
360 void DoNothing(TestTransform& ignored)
const override {}
362 void InitPoint(TestPoint& point,
float x,
float y)
const override {
366 void InitRectLTRB(TestRect& rect,
370 float bottom)
const override {
374 void InitTransformIdentity(TestTransform& storage)
const override {
378 virtual void InitTransformColMatrix(TestTransform& result,
379 const float m[16])
const override {
382 m[ 0], m[ 1], m[ 2], m[ 3],
383 m[ 4], m[ 5], m[ 6], m[ 7],
384 m[ 8], m[ 9], m[10], m[11],
385 m[12], m[13], m[14], m[15]
390 void Translate(TestTransform& storage,
float tx,
float ty)
const override {
391 storage.impeller_matrix = storage.impeller_matrix.Translate({tx, ty});
394 void Scale(TestTransform& storage,
float sx,
float sy)
const override {
395 storage.impeller_matrix = storage.impeller_matrix.Scale({sx, sy, 1.0f});
398 void RotateRadians(TestTransform& storage,
float radians)
const override {
399 storage.impeller_matrix =
400 storage.impeller_matrix *
404 void Concat(
const TestTransform& a,
405 const TestTransform& b,
406 TestTransform& result)
const override {
407 result.impeller_matrix = a.impeller_matrix *
b.impeller_matrix;
410 void TransformPoint(
const TestTransform&
transform,
412 TestPoint& out)
const override {
413 out.impeller_point =
transform.impeller_matrix * in.impeller_point;
416 void TransformPoints(
const TestTransform&
transform,
417 const TestPoint in[],
419 int n)
const override {
420 for (
int i = 0;
i < n;
i++) {
421 out[
i].impeller_point =
transform.impeller_matrix * in[
i].impeller_point;
425 void TransformRectFast(
const TestTransform&
transform,
427 TestRect& out)
const override {
429 in.impeller_rect.TransformBounds(
transform.impeller_matrix);
432 void TransformAndClipRect(
const TestTransform&
transform,
434 TestRect& out)
const override {
436 in.impeller_rect.TransformAndClipBounds(
transform.impeller_matrix);
439 int CountClippedCorners(
const TestTransform&
transform,
440 const TestRect& rect)
const {
441 auto corners = rect.impeller_rect.GetPoints();
443 for (
auto pt : corners) {
444 auto hpt =
transform.impeller_matrix.TransformHomogenous(pt);
452 void InvertUnchecked(
const TestTransform&
transform,
453 TestTransform& result)
const override {
454 result.impeller_matrix =
transform.impeller_matrix.Invert();
457 bool InvertAndCheck(
const TestTransform&
transform,
458 TestTransform& result)
const override {
459 result.impeller_matrix =
transform.impeller_matrix.Invert();
460 return transform.impeller_matrix.IsInvertible();
468 std::function<void(TransformAdapter*, TestTransform&,
const TestRect*)>;
470static void SetupIdentity(
const TransformAdapter* adapter,
472 const TestRect* rect) {
473 adapter->InitTransformIdentity(
transform);
476static void SetupTranslate(
const TransformAdapter* adapter,
478 const TestRect* rect) {
479 adapter->InitTransformIdentity(
transform);
480 adapter->Translate(
transform, 10.2, 12.3);
483static void SetupScale(
const TransformAdapter* adapter,
485 const TestRect* rect) {
486 adapter->InitTransformIdentity(
transform);
490static void SetupScaleTranslate(
const TransformAdapter* adapter,
492 const TestRect* rect) {
493 adapter->InitTransformIdentity(
transform);
495 adapter->Translate(
transform, 10.2, 12.3);
498static void SetupRotate(
const TransformAdapter* adapter,
500 const TestRect* rect) {
501 adapter->InitTransformIdentity(
transform);
505static void SetupPerspective(
const TransformAdapter* adapter,
507 const TestRect* rect) {
508 adapter->InitTransformColMatrix(
transform, kSimplePerspective);
514static void SetupPerspectiveClipNone(
const TransformAdapter* adapter,
516 const TestRect* rect) {
517 adapter->InitTransformColMatrix(
transform, kSimplePerspective);
523static void SetupPerspectiveClipOne(
const TransformAdapter* adapter,
525 const TestRect* rect) {
526 adapter->InitTransformColMatrix(
transform, kClipOneCornerPerspective);
532static void SetupPerspectiveClipTwo(
const TransformAdapter* adapter,
534 const TestRect* rect) {
535 adapter->InitTransformColMatrix(
transform, kClipTwoCornersPerspective);
541static void SetupPerspectiveClipThree(
const TransformAdapter* adapter,
543 const TestRect* rect) {
544 adapter->InitTransformColMatrix(
transform, kClipThreeCornersPerspective);
550static void SetupPerspectiveClipFour(
const TransformAdapter* adapter,
552 const TestRect* rect) {
553 adapter->InitTransformColMatrix(
transform, kClipFourCornersPerspective);
563static std::unique_ptr<TransformAdapter> GetAdapter(AdapterType
type) {
565 case AdapterType::kSkMatrix:
566 return std::make_unique<SkMatrixAdapter>();
567 case AdapterType::kSkM44:
568 return std::make_unique<SkM44Adapter>();
569 case AdapterType::kImpellerMatrix:
570 return std::make_unique<ImpellerMatrixAdapter>();
579 auto adapter = GetAdapter(
type);
581 while (state.KeepRunning()) {
587 auto adapter = GetAdapter(
type);
589 while (state.KeepRunning()) {
590 adapter->InitTransformIdentity(
transform);
595 auto adapter = GetAdapter(
type);
597 while (state.KeepRunning()) {
598 adapter->InitTransformColMatrix(
transform, kSimplePerspective);
606 auto adapter = GetAdapter(
type);
608 adapter->InitTransformIdentity(
transform);
610 while (state.KeepRunning()) {
620static void BM_Scale(benchmark::State& state, AdapterType
type,
float scale) {
621 auto adapter = GetAdapter(
type);
623 adapter->InitTransformIdentity(
transform);
624 float inv_scale = 1.0f / scale;
626 while (state.KeepRunning()) {
630 adapter->Scale(
transform, inv_scale, inv_scale);
639 auto adapter = GetAdapter(
type);
641 adapter->InitTransformIdentity(
transform);
642 while (state.KeepRunning()) {
643 adapter->RotateRadians(
transform, radians);
649 const SetupFunction& a_setup,
650 const SetupFunction& b_setup) {
651 auto adapter = GetAdapter(
type);
652 TestTransform a, b, result;
653 a_setup(adapter.get(), a,
nullptr);
654 b_setup(adapter.get(), b,
nullptr);
655 while (state.KeepRunning()) {
656 adapter->Concat(a, b, result);
662 const SetupFunction& setup) {
663 auto adapter = GetAdapter(
type);
665 setup(adapter.get(),
transform,
nullptr);
666 TestPoint point, result;
667 adapter->InitPoint(point, 25.7, 32.4);
668 while (state.KeepRunning()) {
669 adapter->TransformPoint(
transform, point, result);
675 const SetupFunction& setup) {
676 auto adapter = GetAdapter(
type);
678 setup(adapter.get(),
transform,
nullptr);
681 const int N = Xs * Ys;
683 for (
int i = 0;
i < Xs;
i++) {
684 for (
int j = 0; j < Ys; j++) {
685 int index =
i * Xs + j;
687 adapter->InitPoint(
points[index],
i * 23.3 + 17, j * 32.7 + 12);
690 TestPoint results[N];
691 int64_t item_count = 0;
692 while (state.KeepRunning()) {
696 state.SetItemsProcessed(item_count);
701 const SetupFunction& setup) {
702 auto adapter = GetAdapter(
type);
704 TestRect rect, result;
705 adapter->InitRectLTRB(rect, 100, 100, 200, 200);
707 while (state.KeepRunning()) {
708 adapter->TransformRectFast(
transform, rect, result);
714 const SetupFunction& setup) {
715 auto adapter = GetAdapter(
type);
717 TestRect rect, result;
718 adapter->InitRectLTRB(rect, 100, 100, 200, 200);
720 while (state.KeepRunning()) {
721 adapter->TransformAndClipRect(
transform, rect, result);
727 const SetupFunction& setup) {
728 auto adapter = GetAdapter(
type);
730 setup(adapter.get(),
transform,
nullptr);
731 TestTransform result;
732 while (state.KeepRunning()) {
733 adapter->InvertUnchecked(
transform, result);
739 const SetupFunction& setup) {
740 auto adapter = GetAdapter(
type);
742 setup(adapter.get(),
transform,
nullptr);
743 TestTransform result;
744 while (state.KeepRunning()) {
745 adapter->InvertAndCheck(
transform, result);
749#define BENCHMARK_CAPTURE_TYPE(name, type) \
750 BENCHMARK_CAPTURE(name, type, AdapterType::k##type)
752#define BENCHMARK_CAPTURE_TYPE_ARGS(name, type, ...) \
753 BENCHMARK_CAPTURE(name, type, AdapterType::k##type, __VA_ARGS__)
755#define BENCHMARK_CAPTURE_ALL(name) \
756 BENCHMARK_CAPTURE_TYPE(name, SkMatrix); \
757 BENCHMARK_CAPTURE_TYPE(name, SkM44); \
758 BENCHMARK_CAPTURE_TYPE(name, ImpellerMatrix)
760#define BENCHMARK_CAPTURE_ALL_ARGS(name, ...) \
761 BENCHMARK_CAPTURE_TYPE_ARGS(name, SkMatrix, __VA_ARGS__); \
762 BENCHMARK_CAPTURE_TYPE_ARGS(name, SkM44, __VA_ARGS__); \
763 BENCHMARK_CAPTURE_TYPE_ARGS(name, ImpellerMatrix, __VA_ARGS__)
774#define BENCHMARK_CAPTURE_TYPE_SETUP(name, type, setup) \
775 BENCHMARK_CAPTURE(name, setup/type, AdapterType::k##type, Setup##setup)
778#define BENCHMARK_CAPTURE_ALL_SETUP(name, setup) \
779 BENCHMARK_CAPTURE_TYPE_SETUP(name, SkMatrix, setup); \
780 BENCHMARK_CAPTURE_TYPE_SETUP(name, SkM44, setup); \
781 BENCHMARK_CAPTURE_TYPE_SETUP(name, ImpellerMatrix, setup)
784#define BENCHMARK_CAPTURE_TYPE_SETUP2(name, type, setup1, setup2) \
785 BENCHMARK_CAPTURE(name, setup1*setup2/type, AdapterType::k##type, \
786 Setup##setup1, Setup##setup2)
789#define BENCHMARK_CAPTURE_ALL_SETUP2(name, setup1, setup2) \
790 BENCHMARK_CAPTURE_TYPE_SETUP2(name, SkMatrix, setup1, setup2); \
791 BENCHMARK_CAPTURE_TYPE_SETUP2(name, SkM44, setup1, setup2); \
792 BENCHMARK_CAPTURE_TYPE_SETUP2(name, ImpellerMatrix, setup1, setup2)
#define FML_CHECK(condition)
#define FML_UNREACHABLE()
static void BM_InvertUnchecked(benchmark::State &state, AdapterType type, const SetupFunction &setup)
static void BM_Concat(benchmark::State &state, AdapterType type, const SetupFunction &a_setup, const SetupFunction &b_setup)
static void BM_Rotate(benchmark::State &state, AdapterType type, float radians)
static void BM_TransformPoint(benchmark::State &state, AdapterType type, const SetupFunction &setup)
static void BM_SetIdentity(benchmark::State &state, AdapterType type)
static void BM_SetPerspective(benchmark::State &state, AdapterType type)
static void BM_TransformRectFast(benchmark::State &state, AdapterType type, const SetupFunction &setup)
static void BM_TransformPoints(benchmark::State &state, AdapterType type, const SetupFunction &setup)
static void BM_Scale(benchmark::State &state, AdapterType type, float scale)
static void BM_AdapterDispatchOverhead(benchmark::State &state, AdapterType type)
static void BM_InvertAndCheck(benchmark::State &state, AdapterType type, const SetupFunction &setup)
static void BM_TransformAndClipRect(benchmark::State &state, AdapterType type, const SetupFunction &setup)
static void BM_Translate(benchmark::State &state, AdapterType type, float tx, float ty)
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeColumn(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
static Matrix MakeRotationZ(Radians r)
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
std::vector< Point > points