// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <functional>

#include "flutter/benchmarking/benchmarking.h"

#include "flutter/impeller/geometry/matrix.h"
#include "flutter/impeller/geometry/rect.h"
#include "third_party/skia/include/core/SkM44.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkPoint3.h"

namespace flutter {

namespace {

static constexpr float kPiOver4 = impeller::kPiOver4;

static constexpr float kSimplePerspective[16] = {
    // clang-format off
    2.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 2.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 3.0f
    // clang-format on
};

// The following matrices slowly slide a perspective-skewed transform of
// the rect past the near clipping plane. Keeping the Y perspective factor
// at -0.006 allows the X perspective factor to slowly move the transformed
// rectangle into the clipping pane over the range of [-0.01, to -0.025].
static constexpr float kClipOneCornerPerspective[16] = {
    // clang-format off
    2.0f, 0.0f, 0.0f, -0.01f,
    0.0f, 2.0f, 0.0f, -0.006f,
    0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 3.0f
    // clang-format on
};

static constexpr float kClipTwoCornersPerspective[16] = {
    // clang-format off
    2.0f, 0.0f, 0.0f, -.015f,
    0.0f, 2.0f, 0.0f, -.006f,
    0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 3.0f
    // clang-format on
};

static constexpr float kClipThreeCornersPerspective[16] = {
    // clang-format off
    2.0f, 0.0f, 0.0f, -.02f,
    0.0f, 2.0f, 0.0f, -.006f,
    0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 3.0f
    // clang-format on
};

static constexpr float kClipFourCornersPerspective[16] = {
    // clang-format off
    2.0f, 0.0f, 0.0f, -.025f,
    0.0f, 2.0f, 0.0f, -.006f,
    0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 3.0f
    // clang-format on
};

enum class AdapterType {
  kSkMatrix,
  kSkM44,
  kImpellerMatrix,
};

union TestPoint {
  TestPoint() {}

  SkPoint sk_point;
  impeller::Point impeller_point;
};

union TestRect {
  TestRect() {}

  SkRect sk_rect;
  impeller::Rect impeller_rect;
};

union TestTransform {
  TestTransform() {}

  SkMatrix sk_matrix;
  SkM44 sk_m44;
  impeller::Matrix impeller_matrix;
};

// We use a virtual adapter class rather than templating the BM_* methods
// to prevent the compiler from optimizing the benchmark bodies into a
// null set of instructions because the calculation can be proven to have
// no side effects and the result is never used.
class TransformAdapter {
 public:
  TransformAdapter() = default;
  virtual ~TransformAdapter() = default;

  // Two methods to test the overhead of just calling a virtual method on
  // the adapter (should be the same for all inheriting subclasses) and
  // for a method that does a conversion to and from the TestRect object
  // (which should be the same as the method call overhead since it does
  // no work).
  virtual void DoNothing(TestTransform& ignored) const = 0;

  virtual void InitRectLTRB(TestRect& rect,
                            float left,
                            float top,
                            float right,
                            float bottom) const = 0;
  virtual void InitPoint(TestPoint& point, float x, float y) const = 0;

  // The actual methods that do work and are the meat of the benchmarks.
  virtual void InitTransformIdentity(TestTransform& result) const = 0;
  virtual void InitTransformColMatrix(TestTransform& result,
                                      const float m[16]) const = 0;

  virtual void Translate(TestTransform& result, float tx, float ty) const = 0;
  virtual void Scale(TestTransform& result, float sx, float sy) const = 0;
  virtual void RotateRadians(TestTransform& result, float radians) const = 0;

  virtual void Concat(const TestTransform& a,
                      const TestTransform& b,
                      TestTransform& result) const = 0;

  virtual void TransformPoint(const TestTransform& transform,
                              const TestPoint& in,
                              TestPoint& out) const = 0;
  virtual void TransformPoints(const TestTransform& transform,
                               const TestPoint in[],
                               TestPoint out[],
                               int n) const = 0;
  virtual void TransformRectFast(const TestTransform& transform,
                                 const TestRect& in,
                                 TestRect& out) const = 0;
  virtual void TransformAndClipRect(const TestTransform& transform,
                                    const TestRect& in,
                                    TestRect& out) const = 0;
  virtual int CountClippedCorners(const TestTransform& transform,
                                  const TestRect& rect) const = 0;
  virtual void InvertUnchecked(const TestTransform& transform,
                               TestTransform& result) const = 0;
  virtual bool InvertAndCheck(const TestTransform& transform,
                              TestTransform& result) const = 0;
};

class SkiaAdapterBase : public TransformAdapter {
 public:
  // DoNothing methods used to measure overhead for various operations
  void DoNothing(TestTransform& ignored) const override {}

  void InitPoint(TestPoint& point, float x, float y) const override {
    point.sk_point.set(x, y);
  }

  void InitRectLTRB(TestRect& rect,
                    float left,
                    float top,
                    float right,
                    float bottom) const override {
    rect.sk_rect.setLTRB(left, top, right, bottom);
  }
};

class SkMatrixAdapter : public SkiaAdapterBase {
 public:
  SkMatrixAdapter() = default;
  ~SkMatrixAdapter() = default;

  void InitTransformIdentity(TestTransform& result) const override {
    result.sk_matrix.setIdentity();
  }

  virtual void InitTransformColMatrix(TestTransform& result,
                                      const float m[16]) const override {
    result.sk_matrix = SkM44::ColMajor(m).asM33();
  }

  void Translate(TestTransform& result, float tx, float ty) const override {
    result.sk_matrix.preTranslate(tx, ty);
  }

  void Scale(TestTransform& result, float sx, float sy) const override {
    result.sk_matrix.preScale(sx, sy);
  }

  void RotateRadians(TestTransform& result, float radians) const override {
    result.sk_matrix.preRotate(SkRadiansToDegrees(radians));
  }

  void Concat(const TestTransform& a,
              const TestTransform& b,
              TestTransform& result) const override {
    result.sk_matrix = SkMatrix::Concat(a.sk_matrix, b.sk_matrix);
  }

  void TransformPoint(const TestTransform& transform,
                      const TestPoint& in,
                      TestPoint& out) const override {
    out.sk_point = transform.sk_matrix.mapPoint(in.sk_point);
  }

  void TransformPoints(const TestTransform& transform,
                       const TestPoint in[],
                       TestPoint out[],
                       int n) const override {
    static_assert(sizeof(TestPoint) == sizeof(SkPoint));
    transform.sk_matrix.mapPoints(reinterpret_cast<SkPoint*>(out),
                                  reinterpret_cast<const SkPoint*>(in), n);
  }

  void TransformRectFast(const TestTransform& transform,
                         const TestRect& in,
                         TestRect& out) const override {
    out.sk_rect =
        transform.sk_matrix.mapRect(in.sk_rect, SkApplyPerspectiveClip::kNo);
  }

  void TransformAndClipRect(const TestTransform& transform,
                            const TestRect& in,
                            TestRect& out) const override {
    out.sk_rect =
        transform.sk_matrix.mapRect(in.sk_rect, SkApplyPerspectiveClip::kYes);
  }

  int CountClippedCorners(const TestTransform& transform,
                          const TestRect& rect) const {
    SkPoint3 homogenous[4];
    SkPoint corners[4];
    rect.sk_rect.toQuad(corners);
    transform.sk_matrix.mapHomogeneousPoints(homogenous, corners, 4);
    int count = 0;
    for (SkPoint3 hpt : homogenous) {
      if (hpt.fZ <= 0) {
        count++;
      }
    }
    return count;
  }

  void InvertUnchecked(const TestTransform& transform,
                       TestTransform& result) const override {
    [[maybe_unused]]
    bool ret = transform.sk_matrix.invert(&result.sk_matrix);
  }

  bool InvertAndCheck(const TestTransform& transform,
                      TestTransform& result) const override {
    return transform.sk_matrix.invert(&result.sk_matrix);
  }
};

class SkM44Adapter : public SkiaAdapterBase {
 public:
  SkM44Adapter() = default;
  ~SkM44Adapter() = default;

  void InitTransformIdentity(TestTransform& storage) const override {
    storage.sk_m44.setIdentity();
  }

  virtual void InitTransformColMatrix(TestTransform& result,
                                      const float m[16]) const override {
    result.sk_m44 = SkM44::ColMajor(m);
  }

  void Translate(TestTransform& storage, float tx, float ty) const override {
    storage.sk_m44.preTranslate(tx, ty);
  }

  void Scale(TestTransform& storage, float sx, float sy) const override {
    storage.sk_m44.preScale(sx, sy);
  }

  void RotateRadians(TestTransform& storage, float radians) const override {
    storage.sk_m44.preConcat(SkM44::Rotate({0, 0, 1}, radians));
  }

  void Concat(const TestTransform& a,
              const TestTransform& b,
              TestTransform& result) const override {
    result.sk_m44.setConcat(a.sk_m44, b.sk_m44);
  }

  void TransformPoint(const TestTransform& transform,
                      const TestPoint& in,
                      TestPoint& out) const override {
    out.sk_point = transform.sk_m44.asM33().mapPoint(in.sk_point);
  }

  void TransformPoints(const TestTransform& transform,
                       const TestPoint in[],
                       TestPoint out[],
                       int n) const override {
    static_assert(sizeof(TestPoint) == sizeof(SkPoint));
    transform.sk_m44.asM33().mapPoints(reinterpret_cast<SkPoint*>(out),
                                       reinterpret_cast<const SkPoint*>(in), n);
  }

  void TransformRectFast(const TestTransform& transform,
                         const TestRect& in,
                         TestRect& out) const override {
    // clang-format off
    out.sk_rect = transform.sk_m44
                      .asM33()
                      .mapRect(in.sk_rect, SkApplyPerspectiveClip::kNo);
    // clang-format on
  }

  void TransformAndClipRect(const TestTransform& transform,
                            const TestRect& in,
                            TestRect& out) const override {
    // clang-format off
    out.sk_rect = transform.sk_m44
                      .asM33()
                      .mapRect(in.sk_rect, SkApplyPerspectiveClip::kYes);
    // clang-format on
  }

  int CountClippedCorners(const TestTransform& transform,
                          const TestRect& rect) const {
    SkPoint3 homogenous[4];
    SkPoint corners[4];
    rect.sk_rect.toQuad(corners);
    transform.sk_m44.asM33().mapHomogeneousPoints(homogenous, corners, 4);
    int count = 0;
    for (SkPoint3 hpt : homogenous) {
      if (hpt.fZ <= 0) {
        count++;
      }
    }
    return count;
  }

  void InvertUnchecked(const TestTransform& transform,
                       TestTransform& result) const override {
    [[maybe_unused]]
    bool ret = transform.sk_m44.invert(&result.sk_m44);
  }

  bool InvertAndCheck(const TestTransform& transform,
                      TestTransform& result) const override {
    return transform.sk_m44.invert(&result.sk_m44);
  }
};

class ImpellerMatrixAdapter : public TransformAdapter {
 public:
  ImpellerMatrixAdapter() = default;
  ~ImpellerMatrixAdapter() = default;

  void DoNothing(TestTransform& ignored) const override {}

  void InitPoint(TestPoint& point, float x, float y) const override {
    point.impeller_point = impeller::Point(x, y);
  }

  void InitRectLTRB(TestRect& rect,
                    float left,
                    float top,
                    float right,
                    float bottom) const override {
    rect.impeller_rect = impeller::Rect::MakeLTRB(left, top, right, bottom);
  }

  void InitTransformIdentity(TestTransform& storage) const override {
    storage.impeller_matrix = impeller::Matrix();
  }

  virtual void InitTransformColMatrix(TestTransform& result,
                                      const float m[16]) const override {
    // clang-format off
    result.impeller_matrix = impeller::Matrix::MakeColumn(
        m[ 0], m[ 1], m[ 2], m[ 3],
        m[ 4], m[ 5], m[ 6], m[ 7],
        m[ 8], m[ 9], m[10], m[11],
        m[12], m[13], m[14], m[15]
    );
    // clang-format on
  }

  void Translate(TestTransform& storage, float tx, float ty) const override {
    storage.impeller_matrix = storage.impeller_matrix.Translate({tx, ty});
  }

  void Scale(TestTransform& storage, float sx, float sy) const override {
    storage.impeller_matrix = storage.impeller_matrix.Scale({sx, sy, 1.0f});
  }

  void RotateRadians(TestTransform& storage, float radians) const override {
    storage.impeller_matrix =
        storage.impeller_matrix *
        impeller::Matrix::MakeRotationZ(impeller::Radians(radians));
  }

  void Concat(const TestTransform& a,
              const TestTransform& b,
              TestTransform& result) const override {
    result.impeller_matrix = a.impeller_matrix * b.impeller_matrix;
  }

  void TransformPoint(const TestTransform& transform,
                      const TestPoint& in,
                      TestPoint& out) const override {
    out.impeller_point = transform.impeller_matrix * in.impeller_point;
  }

  void TransformPoints(const TestTransform& transform,
                       const TestPoint in[],
                       TestPoint out[],
                       int n) const override {
    for (int i = 0; i < n; i++) {
      out[i].impeller_point = transform.impeller_matrix * in[i].impeller_point;
    }
  }

  void TransformRectFast(const TestTransform& transform,
                         const TestRect& in,
                         TestRect& out) const override {
    out.impeller_rect =
        in.impeller_rect.TransformBounds(transform.impeller_matrix);
  }

  void TransformAndClipRect(const TestTransform& transform,
                            const TestRect& in,
                            TestRect& out) const override {
    out.impeller_rect =
        in.impeller_rect.TransformAndClipBounds(transform.impeller_matrix);
  }

  int CountClippedCorners(const TestTransform& transform,
                          const TestRect& rect) const {
    auto corners = rect.impeller_rect.GetPoints();
    int count = 0;
    for (auto pt : corners) {
      auto hpt = transform.impeller_matrix.TransformHomogenous(pt);
      if (hpt.z <= 0) {
        count++;
      }
    }
    return count;
  }

  void InvertUnchecked(const TestTransform& transform,
                       TestTransform& result) const override {
    result.impeller_matrix = transform.impeller_matrix.Invert();
  }

  bool InvertAndCheck(const TestTransform& transform,
                      TestTransform& result) const override {
    result.impeller_matrix = transform.impeller_matrix.Invert();
    return transform.impeller_matrix.GetDeterminant() != 0.0f;
  }
};

// The rect argument is passed in by the TransformRect benchmarks so that
// the setup function can make sure that it sets up a transform that
// clips the desired number of corners during the bounds transform.
using SetupFunction =
    std::function<void(TransformAdapter*, TestTransform&, const TestRect*)>;

static void SetupIdentity(const TransformAdapter* adapter,
                          TestTransform& transform,
                          const TestRect* rect) {
  adapter->InitTransformIdentity(transform);
}

static void SetupTranslate(const TransformAdapter* adapter,
                           TestTransform& transform,
                           const TestRect* rect) {
  adapter->InitTransformIdentity(transform);
  adapter->Translate(transform, 10.2, 12.3);
}

static void SetupScale(const TransformAdapter* adapter,
                       TestTransform& transform,
                       const TestRect* rect) {
  adapter->InitTransformIdentity(transform);
  adapter->Scale(transform, 2.0, 2.0);
}

static void SetupScaleTranslate(const TransformAdapter* adapter,
                                TestTransform& transform,
                                const TestRect* rect) {
  adapter->InitTransformIdentity(transform);
  adapter->Scale(transform, 2.0, 2.0);
  adapter->Translate(transform, 10.2, 12.3);
}

static void SetupRotate(const TransformAdapter* adapter,
                        TestTransform& transform,
                        const TestRect* rect) {
  adapter->InitTransformIdentity(transform);
  adapter->RotateRadians(transform, kPiOver4);
}

static void SetupPerspective(const TransformAdapter* adapter,
                             TestTransform& transform,
                             const TestRect* rect) {
  adapter->InitTransformColMatrix(transform, kSimplePerspective);
  if (rect) {
    FML_CHECK(adapter->CountClippedCorners(transform, *rect) == 0);
  }
}

static void SetupPerspectiveClipNone(const TransformAdapter* adapter,
                                     TestTransform& transform,
                                     const TestRect* rect) {
  adapter->InitTransformColMatrix(transform, kSimplePerspective);
  if (rect) {
    FML_CHECK(adapter->CountClippedCorners(transform, *rect) == 0);
  }
}

static void SetupPerspectiveClipOne(const TransformAdapter* adapter,
                                    TestTransform& transform,
                                    const TestRect* rect) {
  adapter->InitTransformColMatrix(transform, kClipOneCornerPerspective);
  if (rect) {
    FML_CHECK(adapter->CountClippedCorners(transform, *rect) == 1);
  }
}

static void SetupPerspectiveClipTwo(const TransformAdapter* adapter,
                                    TestTransform& transform,
                                    const TestRect* rect) {
  adapter->InitTransformColMatrix(transform, kClipTwoCornersPerspective);
  if (rect) {
    FML_CHECK(adapter->CountClippedCorners(transform, *rect) == 2);
  }
}

static void SetupPerspectiveClipThree(const TransformAdapter* adapter,
                                      TestTransform& transform,
                                      const TestRect* rect) {
  adapter->InitTransformColMatrix(transform, kClipThreeCornersPerspective);
  if (rect) {
    FML_CHECK(adapter->CountClippedCorners(transform, *rect) == 3);
  }
}

static void SetupPerspectiveClipFour(const TransformAdapter* adapter,
                                     TestTransform& transform,
                                     const TestRect* rect) {
  adapter->InitTransformColMatrix(transform, kClipFourCornersPerspective);
  if (rect) {
    FML_CHECK(adapter->CountClippedCorners(transform, *rect) == 4);
  }
}

// We use a function to return the appropriate adapter so that all methods
// used in benchmarking are "pure virtual" and cannot be optimized out
// due to issues such as the arguments being constexpr and the result
// simplified to a constant value.
static std::unique_ptr<TransformAdapter> GetAdapter(AdapterType type) {
  switch (type) {
    case AdapterType::kSkMatrix:
      return std::make_unique<SkMatrixAdapter>();
    case AdapterType::kSkM44:
      return std::make_unique<SkM44Adapter>();
    case AdapterType::kImpellerMatrix:
      return std::make_unique<ImpellerMatrixAdapter>();
  }
  FML_UNREACHABLE();
}

}  // namespace

static void BM_AdapterDispatchOverhead(benchmark::State& state,
                                       AdapterType type) {
  auto adapter = GetAdapter(type);
  TestTransform transform;
  while (state.KeepRunning()) {
    adapter->DoNothing(transform);
  }
}

static void BM_SetIdentity(benchmark::State& state, AdapterType type) {
  auto adapter = GetAdapter(type);
  TestTransform transform;
  while (state.KeepRunning()) {
    adapter->InitTransformIdentity(transform);
  }
}

static void BM_SetPerspective(benchmark::State& state, AdapterType type) {
  auto adapter = GetAdapter(type);
  TestTransform transform;
  while (state.KeepRunning()) {
    adapter->InitTransformColMatrix(transform, kSimplePerspective);
  }
}

static void BM_Translate(benchmark::State& state,
                         AdapterType type,
                         float tx,
                         float ty) {
  auto adapter = GetAdapter(type);
  TestTransform transform;
  adapter->InitTransformIdentity(transform);
  bool flip = true;
  while (state.KeepRunning()) {
    if (flip) {
      adapter->Translate(transform, tx, ty);
    } else {
      adapter->Translate(transform, -tx, -ty);
    }
    flip = !flip;
  }
}

static void BM_Scale(benchmark::State& state, AdapterType type, float scale) {
  auto adapter = GetAdapter(type);
  TestTransform transform;
  adapter->InitTransformIdentity(transform);
  float inv_scale = 1.0f / scale;
  bool flip = true;
  while (state.KeepRunning()) {
    if (flip) {
      adapter->Scale(transform, scale, scale);
    } else {
      adapter->Scale(transform, inv_scale, inv_scale);
    }
    flip = !flip;
  }
}

static void BM_Rotate(benchmark::State& state,
                      AdapterType type,
                      float radians) {
  auto adapter = GetAdapter(type);
  TestTransform transform;
  adapter->InitTransformIdentity(transform);
  while (state.KeepRunning()) {
    adapter->RotateRadians(transform, radians);
  }
}

static void BM_Concat(benchmark::State& state,
                      AdapterType type,
                      const SetupFunction& a_setup,
                      const SetupFunction& b_setup) {
  auto adapter = GetAdapter(type);
  TestTransform a, b, result;
  a_setup(adapter.get(), a, nullptr);
  b_setup(adapter.get(), b, nullptr);
  while (state.KeepRunning()) {
    adapter->Concat(a, b, result);
  }
}

static void BM_TransformPoint(benchmark::State& state,
                              AdapterType type,
                              const SetupFunction& setup) {
  auto adapter = GetAdapter(type);
  TestTransform transform;
  setup(adapter.get(), transform, nullptr);
  TestPoint point, result;
  adapter->InitPoint(point, 25.7, 32.4);
  while (state.KeepRunning()) {
    adapter->TransformPoint(transform, point, result);
  }
}

static void BM_TransformPoints(benchmark::State& state,
                               AdapterType type,
                               const SetupFunction& setup) {
  auto adapter = GetAdapter(type);
  TestTransform transform;
  setup(adapter.get(), transform, nullptr);
  const int Xs = 10;
  const int Ys = 10;
  const int N = Xs * Ys;
  TestPoint points[N];
  for (int i = 0; i < Xs; i++) {
    for (int j = 0; j < Ys; j++) {
      int index = i * Xs + j;
      FML_CHECK(index < N);
      adapter->InitPoint(points[index], i * 23.3 + 17, j * 32.7 + 12);
    }
  }
  TestPoint results[N];
  int64_t item_count = 0;
  while (state.KeepRunning()) {
    adapter->TransformPoints(transform, points, results, N);
    item_count += N;
  }
  state.SetItemsProcessed(item_count);
}

static void BM_TransformRectFast(benchmark::State& state,
                                 AdapterType type,
                                 const SetupFunction& setup) {
  auto adapter = GetAdapter(type);
  TestTransform transform;
  TestRect rect, result;
  adapter->InitRectLTRB(rect, 100, 100, 200, 200);
  setup(adapter.get(), transform, &rect);
  while (state.KeepRunning()) {
    adapter->TransformRectFast(transform, rect, result);
  }
}

static void BM_TransformAndClipRect(benchmark::State& state,
                                    AdapterType type,
                                    const SetupFunction& setup) {
  auto adapter = GetAdapter(type);
  TestTransform transform;
  TestRect rect, result;
  adapter->InitRectLTRB(rect, 100, 100, 200, 200);
  setup(adapter.get(), transform, &rect);
  while (state.KeepRunning()) {
    adapter->TransformAndClipRect(transform, rect, result);
  }
}

static void BM_InvertUnchecked(benchmark::State& state,
                               AdapterType type,
                               const SetupFunction& setup) {
  auto adapter = GetAdapter(type);
  TestTransform transform;
  setup(adapter.get(), transform, nullptr);
  TestTransform result;
  while (state.KeepRunning()) {
    adapter->InvertUnchecked(transform, result);
  }
}

static void BM_InvertAndCheck(benchmark::State& state,
                              AdapterType type,
                              const SetupFunction& setup) {
  auto adapter = GetAdapter(type);
  TestTransform transform;
  setup(adapter.get(), transform, nullptr);
  TestTransform result;
  while (state.KeepRunning()) {
    adapter->InvertAndCheck(transform, result);
  }
}

#define BENCHMARK_CAPTURE_TYPE(name, type) \
  BENCHMARK_CAPTURE(name, type, AdapterType::k##type)

#define BENCHMARK_CAPTURE_TYPE_ARGS(name, type, ...) \
  BENCHMARK_CAPTURE(name, type, AdapterType::k##type, __VA_ARGS__)

#define BENCHMARK_CAPTURE_ALL(name)       \
  BENCHMARK_CAPTURE_TYPE(name, SkMatrix); \
  BENCHMARK_CAPTURE_TYPE(name, SkM44);    \
  BENCHMARK_CAPTURE_TYPE(name, ImpellerMatrix)

#define BENCHMARK_CAPTURE_ALL_ARGS(name, ...)               \
  BENCHMARK_CAPTURE_TYPE_ARGS(name, SkMatrix, __VA_ARGS__); \
  BENCHMARK_CAPTURE_TYPE_ARGS(name, SkM44, __VA_ARGS__);    \
  BENCHMARK_CAPTURE_TYPE_ARGS(name, ImpellerMatrix, __VA_ARGS__)

BENCHMARK_CAPTURE_ALL(BM_AdapterDispatchOverhead);

BENCHMARK_CAPTURE_ALL(BM_SetIdentity);
BENCHMARK_CAPTURE_ALL(BM_SetPerspective);
BENCHMARK_CAPTURE_ALL_ARGS(BM_Translate, 10.0f, 15.0f);
BENCHMARK_CAPTURE_ALL_ARGS(BM_Scale, 2.0f);
BENCHMARK_CAPTURE_ALL_ARGS(BM_Rotate, kPiOver4);

// clang-format off
#define BENCHMARK_CAPTURE_TYPE_SETUP(name, type, setup) \
  BENCHMARK_CAPTURE(name, setup/type, AdapterType::k##type, Setup##setup)
// clang-format on

#define BENCHMARK_CAPTURE_ALL_SETUP(name, setup)       \
  BENCHMARK_CAPTURE_TYPE_SETUP(name, SkMatrix, setup); \
  BENCHMARK_CAPTURE_TYPE_SETUP(name, SkM44, setup);    \
  BENCHMARK_CAPTURE_TYPE_SETUP(name, ImpellerMatrix, setup)

// clang-format off
#define BENCHMARK_CAPTURE_TYPE_SETUP2(name, type, setup1, setup2)   \
  BENCHMARK_CAPTURE(name, setup1*setup2/type, AdapterType::k##type, \
                    Setup##setup1, Setup##setup2)
// clang-format on

#define BENCHMARK_CAPTURE_ALL_SETUP2(name, setup1, setup2)       \
  BENCHMARK_CAPTURE_TYPE_SETUP2(name, SkMatrix, setup1, setup2); \
  BENCHMARK_CAPTURE_TYPE_SETUP2(name, SkM44, setup1, setup2);    \
  BENCHMARK_CAPTURE_TYPE_SETUP2(name, ImpellerMatrix, setup1, setup2)

BENCHMARK_CAPTURE_ALL_SETUP2(BM_Concat, Scale, Translate);
BENCHMARK_CAPTURE_ALL_SETUP2(BM_Concat, ScaleTranslate, ScaleTranslate);
BENCHMARK_CAPTURE_ALL_SETUP2(BM_Concat, ScaleTranslate, Rotate);
BENCHMARK_CAPTURE_ALL_SETUP2(BM_Concat, ScaleTranslate, Perspective);
BENCHMARK_CAPTURE_ALL_SETUP2(BM_Concat, Perspective, ScaleTranslate);

BENCHMARK_CAPTURE_ALL_SETUP(BM_InvertUnchecked, Identity);
BENCHMARK_CAPTURE_ALL_SETUP(BM_InvertUnchecked, Translate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_InvertUnchecked, Scale);
BENCHMARK_CAPTURE_ALL_SETUP(BM_InvertUnchecked, ScaleTranslate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_InvertUnchecked, Rotate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_InvertUnchecked, Perspective);

BENCHMARK_CAPTURE_ALL_SETUP(BM_InvertAndCheck, Identity);
BENCHMARK_CAPTURE_ALL_SETUP(BM_InvertAndCheck, Translate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_InvertAndCheck, Scale);
BENCHMARK_CAPTURE_ALL_SETUP(BM_InvertAndCheck, ScaleTranslate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_InvertAndCheck, Rotate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_InvertAndCheck, Perspective);

BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformPoint, Identity);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformPoint, Translate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformPoint, Scale);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformPoint, ScaleTranslate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformPoint, Rotate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformPoint, Perspective);

BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformPoints, Identity);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformPoints, Translate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformPoints, Scale);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformPoints, ScaleTranslate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformPoints, Rotate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformPoints, Perspective);

BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformRectFast, Identity);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformRectFast, Translate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformRectFast, Scale);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformRectFast, ScaleTranslate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformRectFast, Rotate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformRectFast, PerspectiveClipNone);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformRectFast, PerspectiveClipOne);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformRectFast, PerspectiveClipTwo);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformRectFast, PerspectiveClipThree);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformRectFast, PerspectiveClipFour);

BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformAndClipRect, Identity);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformAndClipRect, Translate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformAndClipRect, Scale);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformAndClipRect, ScaleTranslate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformAndClipRect, Rotate);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformAndClipRect, PerspectiveClipNone);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformAndClipRect, PerspectiveClipOne);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformAndClipRect, PerspectiveClipTwo);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformAndClipRect, PerspectiveClipThree);
BENCHMARK_CAPTURE_ALL_SETUP(BM_TransformAndClipRect, PerspectiveClipFour);

}  // namespace flutter
