7#include "flutter/benchmarking/benchmarking.h"
9#include "flutter/impeller/geometry/matrix.h"
10#include "flutter/impeller/geometry/rect.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 {
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 {
199 void Concat(
const TestTransform&
a,
200 const TestTransform&
b,
201 TestTransform&
result)
const override {
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));
217 reinterpret_cast<const SkPoint*
>(in), n);
220 void TransformRectFast(
const TestTransform&
transform,
222 TestRect&
out)
const override {
227 void TransformAndClipRect(
const TestTransform&
transform,
229 TestRect&
out)
const override {
234 int CountClippedCorners(
const TestTransform&
transform,
235 const TestRect&
rect)
const {
238 rect.sk_rect.toQuad(corners);
239 transform.sk_matrix.mapHomogeneousPoints(homogenous, corners, 4);
249 void InvertUnchecked(
const TestTransform&
transform,
250 TestTransform&
result)
const override {
255 bool InvertAndCheck(
const TestTransform&
transform,
256 TestTransform&
result)
const override {
261class SkM44Adapter :
public SkiaAdapterBase {
263 SkM44Adapter() =
default;
264 ~SkM44Adapter() =
default;
266 void InitTransformIdentity(TestTransform& storage)
const override {
267 storage.sk_m44.setIdentity();
270 virtual void InitTransformColMatrix(TestTransform&
result,
271 const float m[16])
const override {
275 void Translate(TestTransform& storage,
float tx,
float ty)
const override {
276 storage.sk_m44.preTranslate(tx, ty);
279 void Scale(TestTransform& storage,
float sx,
float sy)
const override {
280 storage.sk_m44.preScale(sx, sy);
283 void RotateRadians(TestTransform& storage,
float radians)
const override {
287 void Concat(
const TestTransform&
a,
288 const TestTransform&
b,
289 TestTransform&
result)
const override {
290 result.sk_m44.setConcat(
a.sk_m44,
b.sk_m44);
293 void TransformPoint(
const TestTransform&
transform,
295 TestPoint&
out)
const override {
296 out.sk_point =
transform.sk_m44.asM33().mapPoint(in.sk_point);
299 void TransformPoints(
const TestTransform&
transform,
300 const TestPoint in[],
302 int n)
const override {
303 static_assert(
sizeof(TestPoint) ==
sizeof(
SkPoint));
305 reinterpret_cast<const SkPoint*
>(in), n);
308 void TransformRectFast(
const TestTransform&
transform,
310 TestRect&
out)
const override {
318 void TransformAndClipRect(
const TestTransform&
transform,
320 TestRect&
out)
const override {
328 int CountClippedCorners(
const TestTransform&
transform,
329 const TestRect&
rect)
const {
332 rect.sk_rect.toQuad(corners);
333 transform.sk_m44.asM33().mapHomogeneousPoints(homogenous, corners, 4);
343 void InvertUnchecked(
const TestTransform&
transform,
344 TestTransform&
result)
const override {
349 bool InvertAndCheck(
const TestTransform&
transform,
350 TestTransform&
result)
const override {
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 {
457 bool InvertAndCheck(
const TestTransform&
transform,
458 TestTransform&
result)
const override {
460 return transform.impeller_matrix.GetDeterminant() != 0.0f;
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()) {
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);
653 a_setup(adapter.get(),
a,
nullptr);
654 b_setup(adapter.get(),
b,
nullptr);
655 while (
state.KeepRunning()) {
662 const SetupFunction&
setup) {
663 auto adapter = GetAdapter(
type);
667 adapter->InitPoint(point, 25.7, 32.4);
668 while (
state.KeepRunning()) {
675 const SetupFunction&
setup) {
676 auto adapter = GetAdapter(
type);
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);
705 adapter->InitRectLTRB(
rect, 100, 100, 200, 200);
707 while (
state.KeepRunning()) {
714 const SetupFunction&
setup) {
715 auto adapter = GetAdapter(
type);
718 adapter->InitRectLTRB(
rect, 100, 100, 200, 200);
720 while (
state.KeepRunning()) {
727 const SetupFunction&
setup) {
728 auto adapter = GetAdapter(
type);
732 while (
state.KeepRunning()) {
739 const SetupFunction&
setup) {
740 auto adapter = GetAdapter(
type);
744 while (
state.KeepRunning()) {
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)
static const int points[]
@ kYes
Do pre-clip the geometry before applying the (perspective) matrix.
@ kNo
Don't pre-clip the geometry before applying the (perspective) matrix.
#define SkRadiansToDegrees(radians)
static SkM44 ColMajor(const SkScalar c[16])
static SkM44 Rotate(SkV3 axis, SkScalar radians)
static SkMatrix Concat(const SkMatrix &a, const SkMatrix &b)
#define FML_CHECK(condition)
#define FML_UNREACHABLE()
Dart_NativeFunction function
sk_sp< SkBlender > blender SkRect rect
static const char * Concat(const char *a, const char *b)
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)
BENCHMARK_CAPTURE_ALL_SETUP(BM_InvertUnchecked, Identity)
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)
BENCHMARK_CAPTURE_ALL_SETUP2(BM_Concat, Scale, Translate)
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)
BENCHMARK_CAPTURE_ALL(BM_AdapterDispatchOverhead)
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)
BENCHMARK_CAPTURE_ALL_ARGS(BM_Translate, 10.0f, 15.0f)
static void BM_Translate(benchmark::State &state, AdapterType type, float tx, float ty)
SK_API sk_sp< PrecompileColorFilter > Matrix()
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
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)
static void setup(SkCanvas *canvas, SkPaint *paint, const SkBitmap &bm, SkFilterMode fm, SkTileMode tmx, SkTileMode tmy)