// 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 "flutter/display_list/benchmarking/dl_benchmarks.h"
#include "flutter/display_list/dl_builder.h"
#include "flutter/display_list/dl_op_flags.h"
#include "flutter/display_list/skia/dl_sk_canvas.h"

#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkTextBlob.h"

namespace flutter {
namespace testing {

DlPaint GetPaintForRun(unsigned attributes) {
  DlPaint paint;

  if (attributes & kStrokedStyle_Flag && attributes & kFilledStyle_Flag) {
    // Not currently exposed by Flutter, but we can probably benchmark this in
    // the future
    paint.setDrawStyle(DlDrawStyle::kStrokeAndFill);
  } else if (attributes & kStrokedStyle_Flag) {
    paint.setDrawStyle(DlDrawStyle::kStroke);
  } else if (attributes & kFilledStyle_Flag) {
    paint.setDrawStyle(DlDrawStyle::kFill);
  }

  if (attributes & kHairlineStroke_Flag) {
    paint.setStrokeWidth(0.0f);
  } else {
    paint.setStrokeWidth(1.0f);
  }

  paint.setAntiAlias(attributes & kAntiAliasing_Flag);
  return paint;
}

void AnnotateAttributes(unsigned attributes,
                        benchmark::State& state,
                        const DisplayListAttributeFlags flags) {
  if (flags.always_stroked()) {
    state.counters["HairlineStroke"] =
        attributes & kHairlineStroke_Flag ? 1 : 0;
  }
  if (flags.applies_style()) {
    state.counters["HairlineStroke"] =
        attributes & kHairlineStroke_Flag ? 1 : 0;
    state.counters["StrokedStyle"] = attributes & kStrokedStyle_Flag ? 1 : 0;
    state.counters["FilledStyle"] = attributes & kFilledStyle_Flag ? 1 : 0;
  }
  if (flags.applies_anti_alias()) {
    state.counters["AntiAliasing"] = attributes & kAntiAliasing_Flag ? 1 : 0;
  }
}

// Constants chosen to produce benchmark results in the region of 1-50ms
constexpr size_t kLinesToDraw = 10000;
constexpr size_t kRectsToDraw = 5000;
constexpr size_t kOvalsToDraw = 1000;
constexpr size_t kCirclesToDraw = 5000;
constexpr size_t kRRectsToDraw = 5000;
constexpr size_t kDRRectsToDraw = 2000;
constexpr size_t kArcSweepSetsToDraw = 1000;
constexpr size_t kImagesToDraw = 500;
constexpr size_t kFixedCanvasSize = 1024;

// Draw a series of diagonal lines across a square canvas of width/height of
// the length requested. The lines will start from the top left corner to the
// bottom right corner, and move from left to right (at the top) and from right
// to left (at the bottom) until 10,000 lines are drawn.
//
// The resulting image will be an hourglass shape.
void BM_DrawLine(benchmark::State& state,
                 BackendType backend_type,
                 unsigned attributes) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawLineFlags);

  size_t length = state.range(0);

  surface_provider->InitializeSurface(length, length);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  state.counters["DrawCallCount"] = kLinesToDraw;
  for (size_t i = 0; i < kLinesToDraw; i++) {
    builder.DrawLine(SkPoint::Make(i % length, 0),
                     SkPoint::Make(length - i % length, length), paint);
  }

  auto display_list = builder.Build();

  // We only want to time the actual rasterization.
  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawLine-" +
                  std::to_string(state.range(0)) + ".png";
  surface_provider->Snapshot(filename);
}

// Draws a series of square rects of the requested width across
// the canvas and repeats until `kRectsToDraw` rects have been drawn.
//
// Half the drawn rects will not have an integral offset.
void BM_DrawRect(benchmark::State& state,
                 BackendType backend_type,
                 unsigned attributes) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawRectFlags);

  size_t length = state.range(0);
  size_t canvas_size = length * 2;
  surface_provider->InitializeSurface(canvas_size, canvas_size);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  // As rects have SkScalar dimensions, we want to ensure that we also
  // draw rects with non-integer position and size
  const SkScalar offset = 0.5f;
  SkRect rect = SkRect::MakeLTRB(0, 0, length, length);

  state.counters["DrawCallCount"] = kRectsToDraw;
  for (size_t i = 0; i < kRectsToDraw; i++) {
    builder.DrawRect(rect, paint);
    rect.offset(offset, offset);
    if (rect.right() > canvas_size) {
      rect.offset(-canvas_size, 0);
    }
    if (rect.bottom() > canvas_size) {
      rect.offset(0, -canvas_size);
    }
  }

  auto display_list = builder.Build();

  // We only want to time the actual rasterization.
  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawRect-" +
                  std::to_string(state.range(0)) + ".png";
  surface_provider->Snapshot(filename);
}

// Draws a series of ovals of the requested height with aspect ratio 3:2 across
// the canvas and repeats until `kOvalsToDraw` ovals have been drawn.
//
// Half the drawn ovals will not have an integral offset.
void BM_DrawOval(benchmark::State& state,
                 BackendType backend_type,
                 unsigned attributes) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawOvalFlags);

  size_t length = state.range(0);
  size_t canvas_size = length * 2;
  surface_provider->InitializeSurface(canvas_size, canvas_size);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  SkRect rect = SkRect::MakeXYWH(0, 0, length * 1.5f, length);
  const SkScalar offset = 0.5f;

  state.counters["DrawCallCount"] = kOvalsToDraw;
  for (size_t i = 0; i < kOvalsToDraw; i++) {
    builder.DrawOval(rect, paint);
    rect.offset(offset, offset);
    if (rect.right() > canvas_size) {
      rect.offset(-canvas_size, 0);
    }
    if (rect.bottom() > canvas_size) {
      rect.offset(0, -canvas_size);
    }
  }
  auto display_list = builder.Build();

  // We only want to time the actual rasterization.
  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawOval-" +
                  std::to_string(state.range(0)) + ".png";
  surface_provider->Snapshot(filename);
}

// Draws a series of circles of the requested radius across
// the canvas and repeats until `kCirclesToDraw` circles have been drawn.
//
// Half the drawn circles will not have an integral center point.
void BM_DrawCircle(benchmark::State& state,
                   BackendType backend_type,
                   unsigned attributes) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawCircleFlags);

  size_t length = state.range(0);
  size_t canvas_size = length * 2;
  surface_provider->InitializeSurface(canvas_size, canvas_size);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  SkScalar radius = length / 2.0f;
  const SkScalar offset = 0.5f;

  SkPoint center = SkPoint::Make(radius, radius);

  state.counters["DrawCallCount"] = kCirclesToDraw;
  for (size_t i = 0; i < kCirclesToDraw; i++) {
    builder.DrawCircle(center, radius, paint);
    center.offset(offset, offset);
    if (center.x() + radius > canvas_size) {
      center.set(radius, center.y());
    }
    if (center.y() + radius > canvas_size) {
      center.set(center.x(), radius);
    }
  }
  auto display_list = builder.Build();

  // We only want to time the actual rasterization.
  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawCircle-" +
                  std::to_string(state.range(0)) + ".png";
  surface_provider->Snapshot(filename);
}

// Draws a series of rounded rects of the requested width across
// the canvas and repeats until `kRRectsToDraw` rects have been drawn.
//
// Half the drawn rounded rects will not have an integral offset.
void BM_DrawRRect(benchmark::State& state,
                  BackendType backend_type,
                  unsigned attributes,
                  SkRRect::Type type) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawRRectFlags);

  size_t length = state.range(0);
  size_t canvas_size = length * 2;
  surface_provider->InitializeSurface(canvas_size, canvas_size);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  SkVector radii[4] = {};
  switch (type) {
    case SkRRect::Type::kSimple_Type:
      radii[0] = SkVector::Make(5.0f, 5.0f);
      radii[1] = SkVector::Make(5.0f, 5.0f);
      radii[2] = SkVector::Make(5.0f, 5.0f);
      radii[3] = SkVector::Make(5.0f, 5.0f);
      break;
    case SkRRect::Type::kNinePatch_Type:
      radii[0] = SkVector::Make(5.0f, 2.0f);
      radii[1] = SkVector::Make(3.0f, 2.0f);
      radii[2] = SkVector::Make(3.0f, 4.0f);
      radii[3] = SkVector::Make(5.0f, 4.0f);
      break;
    case SkRRect::Type::kComplex_Type:
      radii[0] = SkVector::Make(5.0f, 4.0f);
      radii[1] = SkVector::Make(4.0f, 5.0f);
      radii[2] = SkVector::Make(3.0f, 6.0f);
      radii[3] = SkVector::Make(2.0f, 7.0f);
      break;
    default:
      break;
  }

  const SkScalar offset = 0.5f;
  const SkScalar multiplier = length / 16.0f;
  SkRRect rrect;

  SkVector set_radii[4];
  for (size_t i = 0; i < 4; i++) {
    set_radii[i] = radii[i] * multiplier;
  }
  rrect.setRectRadii(SkRect::MakeLTRB(0, 0, length, length), set_radii);

  state.counters["DrawCallCount"] = kRRectsToDraw;
  for (size_t i = 0; i < kRRectsToDraw; i++) {
    builder.DrawRRect(rrect, paint);
    rrect.offset(offset, offset);
    if (rrect.rect().right() > canvas_size) {
      rrect.offset(-canvas_size, 0);
    }
    if (rrect.rect().bottom() > canvas_size) {
      rrect.offset(0, -canvas_size);
    }
  }
  auto display_list = builder.Build();

  // We only want to time the actual rasterization.
  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawRRect-" +
                  std::to_string(state.range(0)) + ".png";
  surface_provider->Snapshot(filename);
}

// Draws a series of "DR" rects of the requested width across
// the canvas and repeats until `kRRectsToDraw` rects have been drawn.
//
// A "DR" rect is a shape consisting of the difference between two
// rounded rects.
//
// Half the drawn DR rects will not have an integral offset.
void BM_DrawDRRect(benchmark::State& state,
                   BackendType backend_type,
                   unsigned attributes,
                   SkRRect::Type type) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawDRRectFlags);

  size_t length = state.range(0);
  size_t canvas_size = length * 2;
  surface_provider->InitializeSurface(canvas_size, canvas_size);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  SkVector radii[4] = {};
  switch (type) {
    case SkRRect::Type::kSimple_Type:
      radii[0] = SkVector::Make(5.0f, 5.0f);
      radii[1] = SkVector::Make(5.0f, 5.0f);
      radii[2] = SkVector::Make(5.0f, 5.0f);
      radii[3] = SkVector::Make(5.0f, 5.0f);
      break;
    case SkRRect::Type::kNinePatch_Type:
      radii[0] = SkVector::Make(5.0f, 7.0f);
      radii[1] = SkVector::Make(3.0f, 7.0f);
      radii[2] = SkVector::Make(3.0f, 4.0f);
      radii[3] = SkVector::Make(5.0f, 4.0f);
      break;
    case SkRRect::Type::kComplex_Type:
      radii[0] = SkVector::Make(5.0f, 4.0f);
      radii[1] = SkVector::Make(4.0f, 5.0f);
      radii[2] = SkVector::Make(3.0f, 6.0f);
      radii[3] = SkVector::Make(8.0f, 7.0f);
      break;
    default:
      break;
  }

  const SkScalar offset = 0.5f;
  const SkScalar multiplier = length / 16.0f;
  SkRRect rrect, rrect_2;

  SkVector set_radii[4];
  for (size_t i = 0; i < 4; i++) {
    set_radii[i] = radii[i] * multiplier;
  }
  rrect.setRectRadii(SkRect::MakeLTRB(0, 0, length, length), set_radii);

  state.counters["DrawCallCount"] = kDRRectsToDraw;
  for (size_t i = 0; i < kDRRectsToDraw; i++) {
    rrect.inset(0.1f * length, 0.1f * length, &rrect_2);
    builder.DrawDRRect(rrect, rrect_2, paint);
    rrect.offset(offset, offset);
    if (rrect.rect().right() > canvas_size) {
      rrect.offset(-canvas_size, 0);
    }
    if (rrect.rect().bottom() > canvas_size) {
      rrect.offset(0, -canvas_size);
    }
  }
  auto display_list = builder.Build();

  // We only want to time the actual rasterization.
  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawDRRect-" +
                  std::to_string(state.range(0)) + ".png";
  surface_provider->Snapshot(filename);
}

void BM_DrawArc(benchmark::State& state,
                BackendType backend_type,
                unsigned attributes) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state,
                     DisplayListOpFlags::kDrawArcNoCenterFlags);

  size_t length = state.range(0);
  size_t canvas_size = length * 2;
  surface_provider->InitializeSurface(canvas_size, canvas_size);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  SkScalar starting_angle = 0.0f;
  SkScalar offset = 0.5f;

  // Just some random sweeps that will mostly circumnavigate the circle
  std::vector<SkScalar> segment_sweeps = {5.5f,  -10.0f, 42.0f, 71.7f, 90.0f,
                                          37.5f, 17.9f,  32.0f, 379.4f};

  SkRect bounds = SkRect::MakeLTRB(0, 0, length, length);

  state.counters["DrawCallCount"] = kArcSweepSetsToDraw * segment_sweeps.size();
  for (size_t i = 0; i < kArcSweepSetsToDraw; i++) {
    for (SkScalar sweep : segment_sweeps) {
      builder.DrawArc(bounds, starting_angle, sweep, false, paint);
      starting_angle += sweep + 5.0f;
    }
    bounds.offset(offset, offset);
    if (bounds.right() > canvas_size) {
      bounds.offset(-canvas_size, 0);
    }
    if (bounds.bottom() > canvas_size) {
      bounds.offset(0, -canvas_size);
    }
  }

  auto display_list = builder.Build();

  // We only want to time the actual rasterization.
  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawArc-" +
                  std::to_string(state.range(0)) + ".png";
  surface_provider->Snapshot(filename);
}

// Returns a list of SkPoints that represent `n` points equally spaced out
// along the circumference of a circle with radius `r` and centered on `center`.
std::vector<SkPoint> GetPolygonPoints(size_t n, SkPoint center, SkScalar r) {
  std::vector<SkPoint> points;
  SkScalar x, y;
  float angle;
  float full_circle = 2.0f * M_PI;
  for (size_t i = 0; i < n; i++) {
    angle = (full_circle / static_cast<float>(n)) * static_cast<float>(i);
    x = center.x() + r * std::cosf(angle);
    y = center.y() + r * std::sinf(angle);
    points.push_back(SkPoint::Make(x, y));
  }
  return points;
}

// Creates a path that represents a regular polygon with `sides` sides,
// centered on `center` with a radius of `radius`. The control points are
// equally spaced out along the circumference of the circle described by
// `radius` and `center`.
//
// The path segment connecting each control point is a line segment.
void GetLinesPath(SkPath& path, size_t sides, SkPoint center, float radius) {
  std::vector<SkPoint> points = GetPolygonPoints(sides, center, radius);
  path.moveTo(points[0]);
  for (size_t i = 1; i < sides; i++) {
    path.lineTo(points[i]);
  }
  path.lineTo(points[0]);
  path.close();
}

// Creates a path that represents a regular polygon with `sides` sides,
// centered on `center` with a radius of `radius`. The control points are
// equally spaced out along the circumference of the circle described by
// `radius` and `center`.
//
// The path segment connecting each control point is a quad bezier, with the
// bezier control point being on a circle with 80% of `radius` and with the
// control point angle half way between the start and end point angles for the
// polygon segment.
void GetQuadsPath(SkPath& path, size_t sides, SkPoint center, float radius) {
  std::vector<SkPoint> points = GetPolygonPoints(sides, center, radius);
  std::vector<SkPoint> control_points =
      GetPolygonPoints(sides * 2, center, radius * 0.8f);

  path.moveTo(points[0]);
  for (size_t i = 1; i < sides; i++) {
    path.quadTo(control_points[2 * i - 1], points[i]);
  }
  path.quadTo(control_points[2 * sides - 1], points[0]);
  path.close();
}

// Creates a path that represents a regular polygon with `sides` sides,
// centered on `center` with a radius of `radius`. The control points are
// equally spaced out along the circumference of the circle described by
// `radius` and `center`.
//
// The path segment connecting each control point is a conic, with the
// control point being on a circle with 80% of `radius` and with the
// control point angle half way between the start and end point angles for the
// polygon segment, and the conic weight set to 3.7f.
void GetConicsPath(SkPath& path, size_t sides, SkPoint center, float radius) {
  std::vector<SkPoint> points = GetPolygonPoints(sides, center, radius);
  std::vector<SkPoint> control_points =
      GetPolygonPoints(sides * 2, center, radius * 0.8f);

  path.moveTo(points[0]);
  for (size_t i = 1; i < sides; i++) {
    path.conicTo(control_points[2 * i - 1], points[i], 3.7f);
  }
  path.conicTo(control_points[2 * sides - 1], points[0], 3.7f);
  path.close();
}

// Creates a path that represents a regular polygon with `sides` sides,
// centered on `center` with a radius of `radius`. The control points are
// equally spaced out along the circumference of the circle described by
// `radius` and `center`.
//
// The path segment connecting each control point is a cubic, with the first
// control point being on a circle with 80% of `radius` and with the second
// control point being on a circle with 120% of `radius`. The first
// control point is 1/3, and the second control point is 2/3, of the angle
// between the start and end point angles for the polygon segment.
void GetCubicsPath(SkPath& path, size_t sides, SkPoint center, float radius) {
  std::vector<SkPoint> points = GetPolygonPoints(sides, center, radius);
  std::vector<SkPoint> inner_control_points =
      GetPolygonPoints(sides * 3, center, radius * 0.8f);
  std::vector<SkPoint> outer_control_points =
      GetPolygonPoints(sides * 3, center, radius * 1.2f);

  path.moveTo(points[0]);
  for (size_t i = 1; i < sides; i++) {
    path.cubicTo(inner_control_points[3 * i - 2],
                 outer_control_points[3 * i - 1], points[i]);
  }
  path.cubicTo(inner_control_points[3 * sides - 2],
               outer_control_points[3 * sides - 1], points[0]);
  path.close();
}

// Returns a path generated by one of the above path generators
// which is multiplied `number` times centered on each of the `number` control
// points along the circumference of a circle centered on `center` with radius
// `radius`.
//
// Each of the polygons will have `sides` sides, and the resulting path will be
// bounded by a circle with radius of 150% of `radius` (or another 20% on top of
// that for cubics)
void MultiplyPath(SkPath& path,
                  SkPath::Verb type,
                  SkPoint center,
                  size_t sides,
                  size_t number,
                  float radius) {
  std::vector<SkPoint> center_points =
      GetPolygonPoints(number, center, radius / 2.0f);

  for (SkPoint p : center_points) {
    switch (type) {
      case SkPath::Verb::kLine_Verb:
        GetLinesPath(path, sides, p, radius);
        break;
      case SkPath::Verb::kQuad_Verb:
        GetQuadsPath(path, sides, p, radius);
        break;
      case SkPath::Verb::kConic_Verb:
        GetConicsPath(path, sides, p, radius);
        break;
      case SkPath::Verb::kCubic_Verb:
        GetCubicsPath(path, sides, p, radius);
        break;
      default:
        break;
    }
  }
}

std::string VerbToString(SkPath::Verb type) {
  switch (type) {
    case SkPath::Verb::kLine_Verb:
      return "Lines";
    case SkPath::Verb::kQuad_Verb:
      return "Quads";
    case SkPath::Verb::kConic_Verb:
      return "Conics";
    case SkPath::Verb::kCubic_Verb:
      return "Cubics";
    default:
      return "Unknown";
  }
}

// Draws a series of overlapping 20-sided polygons where the path segment
// between each point is one of the verb types defined in SkPath.
//
// The number of polygons drawn will be varied to get an overall path
// with approximately 20*N verbs, so we can get an idea of the fixed
// cost of using drawPath as well as an idea of how the cost varies according
// to the verb count.
void BM_DrawPath(benchmark::State& state,
                 BackendType backend_type,
                 unsigned attributes,
                 SkPath::Verb type) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawPathFlags);

  size_t length = kFixedCanvasSize;
  surface_provider->InitializeSurface(length, length);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  SkPath path;

  std::string label = VerbToString(type);
  SkPoint center = SkPoint::Make(length / 2.0f, length / 2.0f);
  float radius = length * 0.25f;
  state.SetComplexityN(state.range(0));

  MultiplyPath(path, type, center, 20, state.range(0), radius);

  state.counters["VerbCount"] = path.countVerbs();
  state.counters["DrawCallCount"] = 1;

  builder.DrawPath(path, paint);
  auto display_list = builder.Build();

  // We only want to time the actual rasterization.
  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawPath-" + label +
                  "-" + std::to_string(state.range(0)) + ".png";
  surface_provider->Snapshot(filename);
}

// Returns a set of vertices that describe a circle that has a
// radius of `radius` and outer vertex count of approximately
// `vertex_count`. The final number of vertices will differ as we
// need to ensure the correct usage of vertices to ensure we do not
// request degenerate triangles be drawn. This final count is output
// through `final_vertex_count`.
//
// The resulting vertices will describe a disc consisting of a series
// of triangles with two vertices on the circumference of the disc,
// and the final vertex being the center point of the disc.
//
// Each vertex colour will alternate through Red, Green, Blue and Cyan.
std::shared_ptr<DlVertices> GetTestVertices(SkPoint center,
                                            float radius,
                                            size_t vertex_count,
                                            DlVertexMode mode,
                                            size_t& final_vertex_count) {
  size_t outer_vertex_count = vertex_count / 2;
  std::vector<SkPoint> outer_points =
      GetPolygonPoints(outer_vertex_count, center, radius);

  std::vector<SkPoint> vertices;
  std::vector<DlColor> colors;

  switch (mode) {
    case DlVertexMode::kTriangleFan:
      // Calling the points on the outer circle O_0, O_1, O_2, ..., and
      // the center point C, this should create a triangle fan with vertices
      // C, O_0, O_1, O_2, O_3, ...
      vertices.push_back(center);
      colors.push_back(SK_ColorCYAN);
      for (size_t i = 0; i <= outer_points.size(); i++) {
        vertices.push_back(outer_points[i % outer_points.size()]);
        if (i % 3 == 0) {
          colors.push_back(SK_ColorRED);
        } else if (i % 3 == 1) {
          colors.push_back(SK_ColorGREEN);
        } else {
          colors.push_back(SK_ColorBLUE);
        }
      }
      break;
    case DlVertexMode::kTriangles:
      // Calling the points on the outer circle O_0, O_1, O_2, ..., and
      // the center point C, this should create a series of triangles with
      // vertices O_0, O_1, C, O_1, O_2, C, O_2, O_3, C, ...
      for (size_t i = 0; i < outer_vertex_count; i++) {
        vertices.push_back(outer_points[i % outer_points.size()]);
        colors.push_back(SK_ColorRED);
        vertices.push_back(outer_points[(i + 1) % outer_points.size()]);
        colors.push_back(SK_ColorGREEN);
        vertices.push_back(center);
        colors.push_back(SK_ColorBLUE);
      }
      break;
    case DlVertexMode::kTriangleStrip:
      // Calling the points on the outer circle O_0, O_1, O_2, ..., and
      // the center point C, this should create a strip with vertices
      // O_0, O_1, C, O_2, O_3, C, O_4, O_5, C, ...
      for (size_t i = 0; i <= outer_vertex_count; i++) {
        vertices.push_back(outer_points[i % outer_points.size()]);
        colors.push_back(i % 2 ? SK_ColorRED : SK_ColorGREEN);
        if (i % 2 == 1) {
          vertices.push_back(center);
          colors.push_back(SK_ColorBLUE);
        }
      }
      break;
    default:
      break;
  }

  final_vertex_count = vertices.size();
  return DlVertices::Make(mode, vertices.size(), vertices.data(), nullptr,
                          colors.data());
}

std::string VertexModeToString(DlVertexMode mode) {
  switch (mode) {
    case DlVertexMode::kTriangleStrip:
      return "TriangleStrip";
    case DlVertexMode::kTriangleFan:
      return "TriangleFan";
    case DlVertexMode::kTriangles:
      return "Triangles";
  }
  return "Unknown";
}

// Draws a series of discs generated by `GetTestVertices()` with
// 50 vertices in each disc. The number of discs drawn will vary according
// to the benchmark input, and the benchmark will automatically calculate
// the Big-O complexity of `DrawVertices` with N being the number of vertices
// being drawn.
//
// The discs drawn will be centered on points along a circle with radius of 25%
// of the canvas width/height, with each point being equally spaced out.
void BM_DrawVertices(benchmark::State& state,
                     BackendType backend_type,
                     unsigned attributes,
                     DlVertexMode mode) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawVerticesFlags);

  size_t length = kFixedCanvasSize;
  surface_provider->InitializeSurface(length, length);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  SkPoint center = SkPoint::Make(length / 2.0f, length / 2.0f);

  float radius = length / 4.0f;

  size_t vertex_count, total_vertex_count = 0;
  size_t disc_count = state.range(0);

  std::vector<SkPoint> center_points =
      GetPolygonPoints(disc_count, center, radius / 4.0f);

  state.counters["DrawCallCount"] = center_points.size();
  for (SkPoint p : center_points) {
    std::shared_ptr<DlVertices> vertices =
        GetTestVertices(p, radius, 50, mode, vertex_count);
    total_vertex_count += vertex_count;
    builder.DrawVertices(vertices.get(), DlBlendMode::kSrc, paint);
  }

  state.counters["VertexCount"] = total_vertex_count;
  state.SetComplexityN(total_vertex_count);

  auto display_list = builder.Build();

  // We only want to time the actual rasterization.
  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawVertices-" +
                  std::to_string(disc_count) + "-" + VertexModeToString(mode) +
                  ".png";
  surface_provider->Snapshot(filename);
}

// Generate `count` test points.
//
// The points are distributed using some fixed constant offsets that were
// chosen to appear somewhat random.
//
// The points generated will wrap in x and y for the bounds of `canvas_size`.
std::vector<SkPoint> GetTestPoints(size_t count, SkISize canvas_size) {
  std::vector<SkPoint> points;

  // Some arbitrary offsets to use when building the list of points
  std::vector<SkScalar> delta_x = {10.0f, 6.3f, 15.0f, 3.5f, 22.6f, 4.7f};
  std::vector<SkScalar> delta_y = {9.3f, -5.4f, 8.5f, -12.0f, 19.2f, -19.6f};

  SkPoint current = SkPoint::Make(0.0f, 0.0f);
  for (size_t i = 0; i < count; i++) {
    points.push_back(current);
    current.offset(delta_x[i % delta_x.size()], delta_y[i % delta_y.size()]);
    if (current.x() > canvas_size.width()) {
      current.offset(-canvas_size.width(), 25.0f);
    }
    if (current.y() > canvas_size.height()) {
      current.offset(0.0f, -canvas_size.height());
    }
  }

  return points;
}

std::string PointModeToString(DlCanvas::PointMode mode) {
  switch (mode) {
    case DlCanvas::PointMode::kLines:
      return "Lines";
    case DlCanvas::PointMode::kPolygon:
      return "Polygon";
    case DlCanvas::PointMode::kPoints:
    default:
      return "Points";
  }
}

// Draws a series of points generated by `GetTestPoints()` above to
// a fixed-size canvas. The benchmark will vary the number of points drawn,
// and they can be drawn in one of three modes - Lines, Polygon or Points mode.
//
// This benchmark will automatically calculate the Big-O complexity of
// `DrawPoints` with N being the number of points being drawn.
void BM_DrawPoints(benchmark::State& state,
                   BackendType backend_type,
                   unsigned attributes,
                   DlCanvas::PointMode mode) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  switch (mode) {
    case DlCanvas::PointMode::kPoints:
      AnnotateAttributes(attributes, state,
                         DisplayListOpFlags::kDrawPointsAsPointsFlags);
      break;
    case DlCanvas::PointMode::kLines:
      AnnotateAttributes(attributes, state,
                         DisplayListOpFlags::kDrawPointsAsLinesFlags);
      break;
    case DlCanvas::PointMode::kPolygon:
      AnnotateAttributes(attributes, state,
                         DisplayListOpFlags::kDrawPointsAsPolygonFlags);
      break;
  }

  size_t length = kFixedCanvasSize;
  surface_provider->InitializeSurface(length, length);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  size_t point_count = state.range(0);
  state.SetComplexityN(point_count);
  state.counters["PointCount"] = point_count;
  state.counters["DrawCallCount"] = 1;

  std::vector<SkPoint> points =
      GetTestPoints(point_count, SkISize::Make(length, length));
  builder.DrawPoints(mode, points.size(), points.data(), paint);

  auto display_list = builder.Build();

  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawPoints-" +
                  PointModeToString(mode) + "-" + std::to_string(point_count) +
                  ".png";
  surface_provider->Snapshot(filename);
}

sk_sp<SkImage> ImageFromBitmapWithNewID(const SkBitmap& bitmap) {
  // If we create an SkPixmap with a ref to the SkBitmap's pixel data,
  // then create an SkImage from that, we always get a new generation ID,
  // so we will avoid hitting the cache.
  SkPixmap pixmap;
  bitmap.peekPixels(&pixmap);
  return SkImages::RasterFromPixmap(pixmap, nullptr, nullptr);
}

// Draws `kImagesToDraw` bitmaps to a canvas, either with texture-backed
// bitmaps or bitmaps that need to be uploaded to the GPU first.
void BM_DrawImage(benchmark::State& state,
                  BackendType backend_type,
                  unsigned attributes,
                  DlImageSampling options,
                  bool upload_bitmap) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state,
                     DisplayListOpFlags::kDrawImageWithPaintFlags);

  size_t bitmap_size = state.range(0);
  size_t canvas_size = 2 * bitmap_size;
  surface_provider->InitializeSurface(canvas_size, canvas_size);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  sk_sp<SkImage> image;
  std::shared_ptr<DlSurfaceInstance> offscreen_instance;
  sk_sp<SkSurface> offscreen;
  SkBitmap bitmap;

  if (upload_bitmap) {
    SkImageInfo info = SkImageInfo::Make(bitmap_size, bitmap_size,
                                         SkColorType::kRGBA_8888_SkColorType,
                                         SkAlphaType::kPremul_SkAlphaType);
    bitmap.allocPixels(info, 0);
    bitmap.eraseColor(SK_ColorBLUE);
  } else {
    offscreen_instance =
        surface_provider->MakeOffscreenSurface(bitmap_size, bitmap_size);
    offscreen = offscreen_instance->sk_surface();
    offscreen->getCanvas()->clear(SK_ColorRED);
  }

  SkScalar offset = 0.5f;
  SkPoint dst = SkPoint::Make(0, 0);

  state.counters["DrawCallCount"] = kImagesToDraw;
  for (size_t i = 0; i < kImagesToDraw; i++) {
    image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap)
                          : offscreen->makeImageSnapshot();
    builder.DrawImage(DlImage::Make(image), dst, options, &paint);

    dst.offset(offset, offset);
    if (dst.x() + bitmap_size > canvas_size) {
      dst.set(0, dst.y());
    }
    if (dst.y() + bitmap_size > canvas_size) {
      dst.set(dst.x(), 0);
    }
  }

  auto display_list = builder.Build();

  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawImage-" +
                  (upload_bitmap ? "Upload-" : "Texture-") +
                  std::to_string(bitmap_size) + ".png";
  surface_provider->Snapshot(filename);
}

std::string ConstraintToString(DlCanvas::SrcRectConstraint constraint) {
  switch (constraint) {
    case DlCanvas::SrcRectConstraint::kStrict:
      return "Strict";
    case DlCanvas::SrcRectConstraint::kFast:
      return "Fast";
    default:
      return "Unknown";
  }
}

// Draws `kImagesToDraw` bitmaps to a canvas, either with texture-backed
// bitmaps or bitmaps that need to be uploaded to the GPU first.
//
// The bitmaps are shrunk down to 75% of their size when rendered to the canvas.
void BM_DrawImageRect(benchmark::State& state,
                      BackendType backend_type,
                      unsigned attributes,
                      DlImageSampling options,
                      DlCanvas::SrcRectConstraint constraint,
                      bool upload_bitmap) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state,
                     DisplayListOpFlags::kDrawImageRectWithPaintFlags);

  size_t bitmap_size = state.range(0);
  size_t canvas_size = 2 * bitmap_size;
  surface_provider->InitializeSurface(canvas_size, canvas_size);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  sk_sp<SkImage> image;
  std::shared_ptr<DlSurfaceInstance> offscreen_instance;
  sk_sp<SkSurface> offscreen;
  SkBitmap bitmap;

  if (upload_bitmap) {
    SkImageInfo info = SkImageInfo::Make(bitmap_size, bitmap_size,
                                         SkColorType::kRGBA_8888_SkColorType,
                                         SkAlphaType::kPremul_SkAlphaType);
    bitmap.allocPixels(info, 0);
    bitmap.eraseColor(SK_ColorBLUE);
  } else {
    offscreen_instance =
        surface_provider->MakeOffscreenSurface(bitmap_size, bitmap_size);
    offscreen = offscreen_instance->sk_surface();
    offscreen->getCanvas()->clear(SK_ColorRED);
  }

  SkScalar offset = 0.5f;
  SkRect src = SkRect::MakeXYWH(bitmap_size / 4.0f, bitmap_size / 4.0f,
                                bitmap_size / 2.0f, bitmap_size / 2.0f);
  SkRect dst =
      SkRect::MakeXYWH(0.0f, 0.0f, bitmap_size * 0.75f, bitmap_size * 0.75f);

  state.counters["DrawCallCount"] = kImagesToDraw;
  for (size_t i = 0; i < kImagesToDraw; i++) {
    image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap)
                          : offscreen->makeImageSnapshot();
    builder.DrawImageRect(DlImage::Make(image), src, dst, options, &paint,
                          constraint);
    dst.offset(offset, offset);
    if (dst.right() > canvas_size) {
      dst.offsetTo(0, dst.y());
    }
    if (dst.bottom() > canvas_size) {
      dst.offsetTo(dst.x(), 0);
    }
  }

  auto display_list = builder.Build();

  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawImageRect-" +
                  (upload_bitmap ? "Upload-" : "Texture-") +
                  ConstraintToString(constraint) + "-" +
                  std::to_string(bitmap_size) + ".png";
  surface_provider->Snapshot(filename);
}

std::string FilterModeToString(const DlFilterMode mode) {
  switch (mode) {
    case DlFilterMode::kNearest:
      return "Nearest";
    case DlFilterMode::kLinear:
      return "Linear";
    default:
      return "Unknown";
  }
}

// Draws `kImagesToDraw` bitmaps to a canvas, either with texture-backed
// bitmaps or bitmaps that need to be uploaded to the GPU first.
//
// The image is split into 9 sub-rects and stretched proportionally for final
// rendering.
void BM_DrawImageNine(benchmark::State& state,
                      BackendType backend_type,
                      unsigned attributes,
                      const DlFilterMode filter,
                      bool upload_bitmap) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state,
                     DisplayListOpFlags::kDrawImageNineWithPaintFlags);

  size_t bitmap_size = state.range(0);
  size_t canvas_size = 2 * bitmap_size;
  surface_provider->InitializeSurface(canvas_size, canvas_size);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  SkIRect center = SkIRect::MakeXYWH(bitmap_size / 4, bitmap_size / 4,
                                     bitmap_size / 2, bitmap_size / 2);

  sk_sp<SkImage> image;
  std::shared_ptr<DlSurfaceInstance> offscreen_instance;
  sk_sp<SkSurface> offscreen;
  SkBitmap bitmap;

  if (upload_bitmap) {
    SkImageInfo info = SkImageInfo::Make(bitmap_size, bitmap_size,
                                         SkColorType::kRGBA_8888_SkColorType,
                                         SkAlphaType::kPremul_SkAlphaType);
    bitmap.allocPixels(info, 0);
    bitmap.eraseColor(SK_ColorBLUE);
  } else {
    offscreen_instance =
        surface_provider->MakeOffscreenSurface(bitmap_size, bitmap_size);
    offscreen = offscreen_instance->sk_surface();
    offscreen->getCanvas()->clear(SK_ColorRED);
  }

  SkScalar offset = 0.5f;
  SkRect dst =
      SkRect::MakeXYWH(0.0f, 0.0f, bitmap_size * 0.75f, bitmap_size * 0.75f);

  state.counters["DrawCallCount"] = kImagesToDraw;
  for (size_t i = 0; i < kImagesToDraw; i++) {
    image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap)
                          : offscreen->makeImageSnapshot();
    builder.DrawImageNine(DlImage::Make(image), center, dst, filter, &paint);
    dst.offset(offset, offset);
    if (dst.right() > canvas_size) {
      dst.offsetTo(0, dst.y());
    }
    if (dst.bottom() > canvas_size) {
      dst.offsetTo(dst.x(), 0);
    }
  }

  auto display_list = builder.Build();

  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawImageNine-" +
                  (upload_bitmap ? "Upload-" : "Texture-") +
                  FilterModeToString(filter) + "-" +
                  std::to_string(bitmap_size) + ".png";
  surface_provider->Snapshot(filename);
}

// Draws a series of glyph runs with 32 glyphs in each run. The number of runs
// may vary according to the benchmark parameters. The text will start in the
// upper left corner of the canvas and advance from left to right and wrap at
// the canvas boundaries in both x and y.
//
// This benchmark will automatically calculate the Big-O complexity of
// `DrawTextBlob` with N being the number of glyphs being drawn.
void BM_DrawTextBlob(benchmark::State& state,
                     BackendType backend_type,
                     unsigned attributes) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawTextBlobFlags);

  size_t draw_calls = state.range(0);
  size_t canvas_size = kFixedCanvasSize;
  surface_provider->InitializeSurface(canvas_size, canvas_size);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  state.counters["DrawCallCount_Varies"] = draw_calls;
  state.counters["GlyphCount"] = draw_calls;
  char character[2] = {'A', '\0'};

  for (size_t i = 0; i < draw_calls; i++) {
    character[0] = 'A' + (i % 26);
    auto blob = SkTextBlob::MakeFromString(character, SkFont());
    builder.DrawTextBlob(blob, 50.0f, 50.0f, paint);
  }

  auto display_list = builder.Build();

  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawTextBlob-" +
                  std::to_string(draw_calls) + ".png";
  surface_provider->Snapshot(filename);
}

// Draw the shadow for a 10-sided regular polygon where the polygon's
// sides are denoted by one of a Line, Quad, Conic or Cubic path segment.
//
// The elevation of the light source will vary according to the benchmark
// paremeters.
//
// The benchmark can be run with either a transparent occluder or an opaque
// occluder.
void BM_DrawShadow(benchmark::State& state,
                   BackendType backend_type,
                   unsigned attributes,
                   bool transparent_occluder,
                   SkPath::Verb type) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawShadowFlags);

  size_t length = kFixedCanvasSize;
  surface_provider->InitializeSurface(length, length);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  SkPath path;

  SkPoint center = SkPoint::Make(length / 2.0f, length / 2.0f);
  float radius = length * 0.25f;

  switch (type) {
    case SkPath::Verb::kLine_Verb:
      GetLinesPath(path, 10, center, radius);
      break;
    case SkPath::Verb::kQuad_Verb:
      GetQuadsPath(path, 10, center, radius);
      break;
    case SkPath::Verb::kConic_Verb:
      GetConicsPath(path, 10, center, radius);
      break;
    case SkPath::Verb::kCubic_Verb:
      GetCubicsPath(path, 10, center, radius);
      break;
    default:
      break;
  }

  float elevation = state.range(0);
  state.counters["DrawCallCount"] = 1;

  // We can hardcode dpr to 1.0f as we're varying elevation, and dpr is only
  // ever used in conjunction with elevation.
  builder.DrawShadow(path, SK_ColorBLUE, elevation, transparent_occluder, 1.0f);
  auto display_list = builder.Build();

  // We only want to time the actual rasterization.
  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-DrawShadow-" +
                  VerbToString(type) + "-" +
                  (transparent_occluder ? "Transparent-" : "Opaque-") +
                  std::to_string(elevation) + "-" + ".png";
  surface_provider->Snapshot(filename);
}

// Calls saveLayer N times from the root canvas layer, and optionally calls
// saveLayer a further M times nested inside that top saveLayer call.
//
// The total number of saveLayer calls will be N * (M+1).
//
// In each saveLayer call, simply draw the colour red with no clip rect.
void BM_SaveLayer(benchmark::State& state,
                  BackendType backend_type,
                  unsigned attributes,
                  size_t save_depth) {
  auto surface_provider = DlSurfaceProvider::Create(backend_type);
  DisplayListBuilder builder;
  DlPaint paint = GetPaintForRun(attributes);

  AnnotateAttributes(attributes, state, DisplayListOpFlags::kSaveLayerFlags);

  size_t length = kFixedCanvasSize;
  surface_provider->InitializeSurface(length, length);
  auto surface = surface_provider->GetPrimarySurface()->sk_surface();
  auto canvas = DlSkCanvasAdapter(surface->getCanvas());

  size_t save_layer_calls = state.range(0);

  // Ensure we draw two overlapping rects to avoid any peephole optimisations
  SkRect rect1 = SkRect::MakeLTRB(0, 0, 0.75f * length, 0.75f * length);
  SkRect rect2 =
      SkRect::MakeLTRB(0.25f * length, 0.25f * length, length, length);

  state.counters["DrawCallCount_Varies"] = save_layer_calls * save_depth;
  for (size_t i = 0; i < save_layer_calls; i++) {
    for (size_t j = 0; j < save_depth; j++) {
      builder.SaveLayer(nullptr, nullptr);
      builder.DrawRect(rect1, paint);
      builder.DrawRect(rect2, paint);
    }
    for (size_t j = 0; j < save_depth; j++) {
      builder.Restore();
    }
  }
  auto display_list = builder.Build();

  // We only want to time the actual rasterization.
  for ([[maybe_unused]] auto _ : state) {
    canvas.DrawDisplayList(display_list);
    surface->flushAndSubmit(true);
  }

  auto filename = surface_provider->backend_name() + "-SaveLayer-" +
                  std::to_string(save_depth) + "-" +
                  std::to_string(save_layer_calls) + ".png";
  surface_provider->Snapshot(filename);
}

#ifdef ENABLE_SOFTWARE_BENCHMARKS
RUN_DISPLAYLIST_BENCHMARKS(Software)
#endif

#ifdef ENABLE_OPENGL_BENCHMARKS
RUN_DISPLAYLIST_BENCHMARKS(OpenGL)
#endif

#ifdef ENABLE_METAL_BENCHMARKS
RUN_DISPLAYLIST_BENCHMARKS(Metal)
#endif

}  // namespace testing
}  // namespace flutter
