1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "base/test/launcher/unit_test_launcher.h"
8 #include "base/test/test_suite.h"
9 #include "base/timer/lap_timer.h"
10 #include "cc/paint/paint_op_buffer.h"
11 #include "cc/paint/paint_op_buffer_serializer.h"
12 #include "cc/paint/paint_shader.h"
13 #include "cc/test/test_options_provider.h"
14 #include "testing/perf/perf_result_reporter.h"
15 #include "third_party/skia/include/core/SkMaskFilter.h"
16 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
17 #include "third_party/skia/include/effects/SkDashPathEffect.h"
18 #include "third_party/skia/include/effects/SkLayerDrawLooper.h"
23 static const int kTimeLimitMillis = 2000;
24 static const int kNumWarmupRuns = 20;
25 static const int kTimeCheckInterval = 1;
27 static const size_t kMaxSerializedBufferBytes = 100000;
29 class PaintOpPerfTest : public testing::Test {
32 : timer_(kNumWarmupRuns,
33 base::Milliseconds(kTimeLimitMillis),
35 serialized_data_(static_cast<char*>(
36 base::AlignedAlloc(kMaxSerializedBufferBytes,
37 PaintOpBuffer::PaintOpAlign))),
38 deserialized_data_(static_cast<char*>(
39 base::AlignedAlloc(sizeof(LargestPaintOp),
40 PaintOpBuffer::PaintOpAlign))) {}
42 void RunTest(const std::string& name, const PaintOpBuffer& buffer) {
43 TestOptionsProvider test_options_provider;
45 size_t bytes_written = 0u;
46 PaintOpBufferSerializer::Preamble preamble;
50 SimpleBufferSerializer serializer(
51 serialized_data_.get(), kMaxSerializedBufferBytes,
52 test_options_provider.serialize_options());
53 serializer.Serialize(&buffer, nullptr, preamble);
54 bytes_written = serializer.written();
56 // Force client paint cache entries to be written every time.
57 test_options_provider.client_paint_cache()->PurgeAll();
59 } while (!timer_.HasTimeLimitExpired());
60 CHECK_GT(bytes_written, 0u);
62 perf_test::PerfResultReporter reporter(name, " serialize");
63 reporter.RegisterImportantMetric("", "runs/s");
64 reporter.AddResult("", timer_.LapsPerSecond());
66 size_t bytes_read = 0;
68 test_options_provider.PushFonts();
71 size_t remaining_read_bytes = bytes_written;
72 char* to_read = serialized_data_.get();
75 PaintOp* deserialized_op = PaintOp::Deserialize(
76 to_read, remaining_read_bytes, deserialized_data_.get(),
77 sizeof(LargestPaintOp), &bytes_read,
78 test_options_provider.deserialize_options());
79 CHECK(deserialized_op);
80 deserialized_op->DestroyThis();
82 DCHECK_GE(remaining_read_bytes, bytes_read);
83 if (remaining_read_bytes == bytes_read)
86 remaining_read_bytes -= bytes_read;
87 to_read += bytes_read;
91 } while (!timer_.HasTimeLimitExpired());
93 reporter = perf_test::PerfResultReporter(name, "deserialize");
94 reporter.RegisterImportantMetric("", "runs/s");
95 reporter.AddResult("", timer_.LapsPerSecond());
99 base::LapTimer timer_;
100 std::unique_ptr<char, base::AlignedFreeDeleter> serialized_data_;
101 std::unique_ptr<char, base::AlignedFreeDeleter> deserialized_data_;
104 // Ops that can be memcopied both when serializing and deserializing.
105 TEST_F(PaintOpPerfTest, SimpleOps) {
106 PaintOpBuffer buffer;
107 for (size_t i = 0; i < 100; ++i)
108 buffer.push<ConcatOp>(SkM44());
109 RunTest("simple", buffer);
112 // Drawing ops with flags that don't have nested objects.
113 TEST_F(PaintOpPerfTest, DrawOps) {
114 PaintOpBuffer buffer;
116 for (size_t i = 0; i < 100; ++i)
117 buffer.push<DrawRectOp>(SkRect::MakeXYWH(1, 1, 1, 1), flags);
118 RunTest("draw", buffer);
121 // Ops with worst case flags.
122 TEST_F(PaintOpPerfTest, ManyFlagsOps) {
123 PaintOpBuffer buffer;
126 SkScalar intervals[] = {1.f, 1.f};
127 flags.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
128 flags.setMaskFilter(SkMaskFilter::MakeBlur(
129 SkBlurStyle::kOuter_SkBlurStyle, 4.3));
130 flags.setColorFilter(
131 SkColorMatrixFilter::MakeLightingFilter(SK_ColorYELLOW, SK_ColorGREEN));
133 SkLayerDrawLooper::Builder looper_builder;
134 looper_builder.addLayer();
135 looper_builder.addLayer(2.3f, 4.5f);
136 SkLayerDrawLooper::LayerInfo layer_info;
137 looper_builder.addLayer(layer_info);
138 flags.setLooper(looper_builder.detach());
140 sk_sp<PaintShader> shader = PaintShader::MakeColor(SkColors::kTransparent);
141 flags.setShader(std::move(shader));
144 path.addCircle(2, 2, 5);
145 path.addCircle(3, 4, 2);
146 path.addArc(SkRect::MakeXYWH(1, 2, 3, 4), 5, 6);
148 for (size_t i = 0; i < 100; ++i)
149 buffer.push<DrawPathOp>(path, flags);
150 RunTest("flags", buffer);
154 TEST_F(PaintOpPerfTest, TextOps) {
155 PaintOpBuffer buffer;
157 auto typeface = SkTypeface::MakeDefault();
160 font.setTypeface(typeface);
162 SkTextBlobBuilder builder;
164 const auto& run = builder.allocRun(font, glyph_count, 1.2f, 2.3f);
165 std::fill(run.glyphs, run.glyphs + glyph_count, 0);
166 auto blob = builder.make();
169 for (size_t i = 0; i < 100; ++i)
170 buffer.push<DrawTextBlobOp>(blob, 0.f, 0.f, flags);
172 RunTest("text", buffer);