Rewrite AndroidSyncSettings to be significantly simpler.
[chromium-blink-merge.git] / gpu / command_buffer / service / gpu_tracer_unittest.cc
blob6566f6acf0cf0043ea006f72562b08141ecdb550
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <map>
6 #include <set>
8 #include "base/bind.h"
9 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
10 #include "gpu/command_buffer/service/gpu_service_test.h"
11 #include "gpu/command_buffer/service/gpu_tracer.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/gl/gl_mock.h"
14 #include "ui/gl/gpu_timing.h"
16 namespace gpu {
17 namespace gles2 {
18 namespace {
20 using ::testing::_;
21 using ::testing::AtLeast;
22 using ::testing::AtMost;
23 using ::testing::Exactly;
24 using ::testing::Invoke;
25 using ::testing::NotNull;
26 using ::testing::Return;
28 int64 g_fakeCPUTime = 0;
29 int64 FakeCpuTime() {
30 return g_fakeCPUTime;
33 class MockOutputter : public Outputter {
34 public:
35 MockOutputter() {}
36 MOCK_METHOD4(TraceDevice,
37 void(const std::string& category, const std::string& name,
38 int64 start_time, int64 end_time));
40 MOCK_METHOD2(TraceServiceBegin,
41 void(const std::string& category, const std::string& name));
43 MOCK_METHOD2(TraceServiceEnd,
44 void(const std::string& category, const std::string& name));
46 protected:
47 ~MockOutputter() {}
50 class GlFakeQueries {
51 public:
52 GlFakeQueries() {}
54 void Reset() {
55 current_time_ = 0;
56 next_query_id_ = 23;
57 alloced_queries_.clear();
58 query_timestamp_.clear();
61 void SetCurrentGLTime(GLint64 current_time) { current_time_ = current_time; }
62 void SetDisjoint() { disjointed_ = true; }
64 void GenQueriesARB(GLsizei n, GLuint* ids) {
65 for (GLsizei i = 0; i < n; i++) {
66 ids[i] = next_query_id_++;
67 alloced_queries_.insert(ids[i]);
71 void DeleteQueriesARB(GLsizei n, const GLuint* ids) {
72 for (GLsizei i = 0; i < n; i++) {
73 alloced_queries_.erase(ids[i]);
74 query_timestamp_.erase(ids[i]);
78 void GetQueryObjectivARB(GLuint id, GLenum pname, GLint* params) {
79 switch (pname) {
80 case GL_QUERY_RESULT_AVAILABLE: {
81 std::map<GLuint, GLint64>::iterator it = query_timestamp_.find(id);
82 if (it != query_timestamp_.end() && it->second <= current_time_)
83 *params = 1;
84 else
85 *params = 0;
86 break;
88 default:
89 FAIL() << "Invalid variable passed to GetQueryObjectivARB: " << pname;
93 void QueryCounter(GLuint id, GLenum target) {
94 switch (target) {
95 case GL_TIMESTAMP:
96 ASSERT_TRUE(alloced_queries_.find(id) != alloced_queries_.end());
97 query_timestamp_[id] = current_time_;
98 break;
99 default:
100 FAIL() << "Invalid variable passed to QueryCounter: " << target;
104 void GetInteger64v(GLenum pname, GLint64 * data) {
105 switch (pname) {
106 case GL_TIMESTAMP:
107 *data = current_time_;
108 break;
109 default:
110 FAIL() << "Invalid variable passed to GetInteger64v: " << pname;
114 void GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) {
115 switch (pname) {
116 case GL_QUERY_RESULT:
117 ASSERT_TRUE(query_timestamp_.find(id) != query_timestamp_.end());
118 *params = query_timestamp_.find(id)->second;
119 break;
120 default:
121 FAIL() << "Invalid variable passed to GetQueryObjectui64v: " << pname;
125 void GetIntegerv(GLenum pname, GLint* params) {
126 switch (pname) {
127 case GL_GPU_DISJOINT_EXT:
128 *params = static_cast<GLint>(disjointed_);
129 disjointed_ = false;
130 break;
131 default:
132 FAIL() << "Invalid variable passed to GetIntegerv: " << pname;
136 void Finish() {
139 GLenum GetError() {
140 return GL_NO_ERROR;
143 protected:
144 bool disjointed_ = false;
145 GLint64 current_time_ = 0;
146 GLuint next_query_id_ = 0;
147 std::set<GLuint> alloced_queries_;
148 std::map<GLuint, GLint64> query_timestamp_;
151 class GPUTracerTester : public GPUTracer {
152 public:
153 explicit GPUTracerTester(gles2::GLES2Decoder* decoder)
154 : GPUTracer(decoder), tracing_enabled_(0) {
155 gpu_timing_client_->SetCpuTimeForTesting(base::Bind(&FakeCpuTime));
157 // Force tracing to be dependent on our mock variable here.
158 gpu_trace_srv_category = &tracing_enabled_;
159 gpu_trace_dev_category = &tracing_enabled_;
162 ~GPUTracerTester() override {}
164 void SetTracingEnabled(bool enabled) {
165 tracing_enabled_ = enabled ? 1 : 0;
168 void SetOutputter(scoped_refptr<Outputter> outputter) {
169 set_outputter_ = outputter;
172 protected:
173 scoped_refptr<Outputter> CreateOutputter(const std::string& name) override {
174 if (set_outputter_.get()) {
175 return set_outputter_;
177 return new MockOutputter();
180 void PostTask() override {
181 // Process synchronously.
182 Process();
185 unsigned char tracing_enabled_;
187 scoped_refptr<Outputter> set_outputter_;
190 class BaseGpuTest : public GpuServiceTest {
191 public:
192 explicit BaseGpuTest(gfx::GPUTiming::TimerType test_timer_type)
193 : test_timer_type_(test_timer_type) {
196 protected:
197 void SetUp() override {
198 g_fakeCPUTime = 0;
199 const char* gl_version = "3.2";
200 const char* extensions = "";
201 if (GetTimerType() == gfx::GPUTiming::kTimerTypeDisjoint) {
202 gl_version = "opengl es 3.0";
203 extensions = "GL_EXT_disjoint_timer_query";
204 } else if (GetTimerType() == gfx::GPUTiming::kTimerTypeARB) {
205 // TODO(sievers): The tracer should not depend on ARB_occlusion_query.
206 // Try merge Query APIs (core, ARB, EXT) into a single binding each.
207 extensions = "GL_ARB_timer_query GL_ARB_occlusion_query";
209 GpuServiceTest::SetUpWithGLVersion(gl_version, extensions);
210 gpu_timing_client_ = GetGLContext()->CreateGPUTimingClient();
211 gpu_timing_client_->SetCpuTimeForTesting(base::Bind(&FakeCpuTime));
212 gl_fake_queries_.Reset();
214 outputter_ref_ = new MockOutputter();
217 void TearDown() override {
218 outputter_ref_ = NULL;
220 gl_fake_queries_.Reset();
221 GpuServiceTest::TearDown();
224 void ExpectTraceQueryMocks() {
225 if (GetTimerType() != gfx::GPUTiming::kTimerTypeInvalid) {
226 // Delegate query APIs used by GPUTrace to a GlFakeQueries
227 EXPECT_CALL(*gl_, GenQueriesARB(2, NotNull())).Times(AtLeast(1))
228 .WillRepeatedly(
229 Invoke(&gl_fake_queries_, &GlFakeQueries::GenQueriesARB));
231 EXPECT_CALL(*gl_, GetQueryObjectivARB(_, GL_QUERY_RESULT_AVAILABLE,
232 NotNull()))
233 .WillRepeatedly(
234 Invoke(&gl_fake_queries_, &GlFakeQueries::GetQueryObjectivARB));
236 EXPECT_CALL(*gl_, GetInteger64v(GL_TIMESTAMP, _))
237 .WillRepeatedly(
238 Invoke(&gl_fake_queries_, &GlFakeQueries::GetInteger64v));
240 EXPECT_CALL(*gl_, QueryCounter(_, GL_TIMESTAMP)).Times(AtLeast(2))
241 .WillRepeatedly(
242 Invoke(&gl_fake_queries_, &GlFakeQueries::QueryCounter));
244 EXPECT_CALL(*gl_, GetQueryObjectui64v(_, GL_QUERY_RESULT, NotNull()))
245 .WillRepeatedly(
246 Invoke(&gl_fake_queries_,
247 &GlFakeQueries::GetQueryObjectui64v));
249 EXPECT_CALL(*gl_, DeleteQueriesARB(2, NotNull())).Times(AtLeast(1))
250 .WillRepeatedly(
251 Invoke(&gl_fake_queries_, &GlFakeQueries::DeleteQueriesARB));
255 void ExpectOutputterBeginMocks(MockOutputter* outputter,
256 const std::string& category,
257 const std::string& name) {
258 EXPECT_CALL(*outputter,
259 TraceServiceBegin(category, name));
262 void ExpectOutputterEndMocks(MockOutputter* outputter,
263 const std::string& category,
264 const std::string& name, int64 expect_start_time,
265 int64 expect_end_time,
266 bool trace_device) {
267 EXPECT_CALL(*outputter,
268 TraceServiceEnd(category, name));
270 if (trace_device) {
271 EXPECT_CALL(*outputter,
272 TraceDevice(category, name,
273 expect_start_time, expect_end_time))
274 .Times(Exactly(1));
275 } else {
276 EXPECT_CALL(*outputter, TraceDevice(category, name,
277 expect_start_time, expect_end_time))
278 .Times(Exactly(0));
282 void ExpectOutputterMocks(MockOutputter* outputter,
283 const std::string& category,
284 const std::string& name, int64 expect_start_time,
285 int64 expect_end_time) {
286 ExpectOutputterBeginMocks(outputter, category, name);
287 bool valid_timer = GetTimerType() != gfx::GPUTiming::kTimerTypeInvalid;
288 ExpectOutputterEndMocks(outputter, category, name, expect_start_time,
289 expect_end_time, valid_timer);
292 void ExpectTracerOffsetQueryMocks() {
293 // Disjoint check should only be called by kTracerTypeDisjointTimer type.
294 if (GetTimerType() == gfx::GPUTiming::kTimerTypeDisjoint) {
295 EXPECT_CALL(*gl_, GetIntegerv(GL_GPU_DISJOINT_EXT, _)).Times(AtLeast(1))
296 .WillRepeatedly(
297 Invoke(&gl_fake_queries_, &GlFakeQueries::GetIntegerv));
298 } else {
299 EXPECT_CALL(*gl_, GetIntegerv(GL_GPU_DISJOINT_EXT, _)).Times(Exactly(0));
302 if (GetTimerType() != gfx::GPUTiming::kTimerTypeARB) {
303 EXPECT_CALL(*gl_, GetInteger64v(GL_TIMESTAMP, NotNull()))
304 .Times(Exactly(0));
305 } else {
306 EXPECT_CALL(*gl_, GetInteger64v(GL_TIMESTAMP, NotNull()))
307 .Times(AtMost(1))
308 .WillRepeatedly(
309 Invoke(&gl_fake_queries_, &GlFakeQueries::GetInteger64v));
313 gfx::GPUTiming::TimerType GetTimerType() { return test_timer_type_; }
315 gfx::GPUTiming::TimerType test_timer_type_;
316 GlFakeQueries gl_fake_queries_;
318 scoped_refptr<gfx::GPUTimingClient> gpu_timing_client_;
319 scoped_refptr<MockOutputter> outputter_ref_;
322 // Test GPUTrace calls all the correct gl calls.
323 class BaseGpuTraceTest : public BaseGpuTest {
324 public:
325 explicit BaseGpuTraceTest(gfx::GPUTiming::TimerType test_timer_type)
326 : BaseGpuTest(test_timer_type) {}
328 void DoTraceTest() {
329 // Expected results
330 const std::string category_name("trace_category");
331 const std::string trace_name("trace_test");
332 const int64 offset_time = 3231;
333 const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
334 const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond;
335 const int64 expect_start_time =
336 (start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
337 offset_time;
338 const int64 expect_end_time =
339 (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
341 ExpectTraceQueryMocks();
342 ExpectOutputterMocks(outputter_ref_.get(), category_name, trace_name,
343 expect_start_time, expect_end_time);
345 scoped_refptr<GPUTrace> trace = new GPUTrace(
346 outputter_ref_, gpu_timing_client_.get(),
347 category_name, trace_name, true);
349 gl_fake_queries_.SetCurrentGLTime(start_timestamp);
350 g_fakeCPUTime = expect_start_time;
351 trace->Start(true);
353 // Shouldn't be available before End() call
354 gl_fake_queries_.SetCurrentGLTime(end_timestamp);
355 g_fakeCPUTime = expect_end_time;
356 EXPECT_FALSE(trace->IsAvailable());
358 trace->End(true);
360 // Shouldn't be available until the queries complete
361 gl_fake_queries_.SetCurrentGLTime(end_timestamp -
362 base::Time::kNanosecondsPerMicrosecond);
363 EXPECT_FALSE(trace->IsAvailable());
365 // Now it should be available
366 gl_fake_queries_.SetCurrentGLTime(end_timestamp);
367 EXPECT_TRUE(trace->IsAvailable());
369 // Proces should output expected Trace results to MockOutputter
370 trace->Process();
372 outputter_ref_ = NULL;
376 class GpuARBTimerTraceTest : public BaseGpuTraceTest {
377 public:
378 GpuARBTimerTraceTest() : BaseGpuTraceTest(gfx::GPUTiming::kTimerTypeARB) {}
381 class GpuDisjointTimerTraceTest : public BaseGpuTraceTest {
382 public:
383 GpuDisjointTimerTraceTest()
384 : BaseGpuTraceTest(gfx::GPUTiming::kTimerTypeDisjoint) {}
387 TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTest) {
388 DoTraceTest();
391 TEST_F(GpuDisjointTimerTraceTest, DisjointTimerTraceTest) {
392 DoTraceTest();
395 // Test GPUTracer calls all the correct gl calls.
396 class BaseGpuTracerTest : public BaseGpuTest {
397 public:
398 explicit BaseGpuTracerTest(gfx::GPUTiming::TimerType test_timer_type)
399 : BaseGpuTest(test_timer_type) {}
401 void DoBasicTracerTest() {
402 ExpectTracerOffsetQueryMocks();
404 MockGLES2Decoder decoder;
405 EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
406 GPUTracerTester tracer(&decoder);
407 tracer.SetTracingEnabled(true);
409 tracer.SetOutputter(outputter_ref_);
411 ASSERT_TRUE(tracer.BeginDecoding());
412 ASSERT_TRUE(tracer.EndDecoding());
414 outputter_ref_ = NULL;
417 void DoTracerMarkersTest() {
418 ExpectTracerOffsetQueryMocks();
420 EXPECT_CALL(*gl_, GetError()).Times(AtLeast(0))
421 .WillRepeatedly(
422 Invoke(&gl_fake_queries_, &GlFakeQueries::GetError));
424 const std::string category_name("trace_category");
425 const std::string trace_name("trace_test");
426 const int64 offset_time = 3231;
427 const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
428 const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond;
429 const int64 expect_start_time =
430 (start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
431 offset_time;
432 const int64 expect_end_time =
433 (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
435 MockGLES2Decoder decoder;
436 EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
437 GPUTracerTester tracer(&decoder);
438 tracer.SetTracingEnabled(true);
440 tracer.SetOutputter(outputter_ref_);
442 gl_fake_queries_.SetCurrentGLTime(start_timestamp);
443 g_fakeCPUTime = expect_start_time;
445 ASSERT_TRUE(tracer.BeginDecoding());
447 ExpectTraceQueryMocks();
449 // This will test multiple marker sources which overlap one another.
450 for (int i = 0; i < NUM_TRACER_SOURCES; ++i) {
451 // Set times so each source has a different time.
452 gl_fake_queries_.SetCurrentGLTime(
453 start_timestamp +
454 (i * base::Time::kNanosecondsPerMicrosecond));
455 g_fakeCPUTime = expect_start_time + i;
457 // Each trace name should be different to differentiate.
458 const char num_char = static_cast<char>('0' + i);
459 std::string source_category = category_name + num_char;
460 std::string source_trace_name = trace_name + num_char;
462 ExpectOutputterBeginMocks(outputter_ref_.get(),
463 source_category, source_trace_name);
465 const GpuTracerSource source = static_cast<GpuTracerSource>(i);
466 ASSERT_TRUE(tracer.Begin(source_category, source_trace_name, source));
469 for (int i = 0; i < NUM_TRACER_SOURCES; ++i) {
470 // Set times so each source has a different time.
471 gl_fake_queries_.SetCurrentGLTime(
472 end_timestamp +
473 (i * base::Time::kNanosecondsPerMicrosecond));
474 g_fakeCPUTime = expect_end_time + i;
476 // Each trace name should be different to differentiate.
477 const char num_char = static_cast<char>('0' + i);
478 std::string source_category = category_name + num_char;
479 std::string source_trace_name = trace_name + num_char;
481 bool valid_timer = GetTimerType() != gfx::GPUTiming::kTimerTypeInvalid;
482 ExpectOutputterEndMocks(outputter_ref_.get(), source_category,
483 source_trace_name, expect_start_time + i,
484 expect_end_time + i, valid_timer);
486 const GpuTracerSource source = static_cast<GpuTracerSource>(i);
488 // Check if the current category/name are correct for this source.
489 ASSERT_EQ(source_category, tracer.CurrentCategory(source));
490 ASSERT_EQ(source_trace_name, tracer.CurrentName(source));
492 ASSERT_TRUE(tracer.End(source));
495 ASSERT_TRUE(tracer.EndDecoding());
497 outputter_ref_ = NULL;
500 void DoDisjointTest() {
501 // Cause a disjoint in a middle of a trace and expect no output calls.
502 ExpectTracerOffsetQueryMocks();
504 EXPECT_CALL(*gl_, GetError()).Times(AtLeast(0))
505 .WillRepeatedly(
506 Invoke(&gl_fake_queries_, &GlFakeQueries::GetError));
508 const std::string category_name("trace_category");
509 const std::string trace_name("trace_test");
510 const GpuTracerSource source = static_cast<GpuTracerSource>(0);
511 const int64 offset_time = 3231;
512 const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
513 const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond;
514 const int64 expect_start_time =
515 (start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
516 offset_time;
517 const int64 expect_end_time =
518 (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
520 MockGLES2Decoder decoder;
521 EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
522 GPUTracerTester tracer(&decoder);
523 tracer.SetTracingEnabled(true);
525 tracer.SetOutputter(outputter_ref_);
527 gl_fake_queries_.SetCurrentGLTime(start_timestamp);
528 g_fakeCPUTime = expect_start_time;
530 ASSERT_TRUE(tracer.BeginDecoding());
532 ExpectTraceQueryMocks();
534 ExpectOutputterBeginMocks(outputter_ref_.get(),
535 category_name, trace_name);
536 ASSERT_TRUE(tracer.Begin(category_name, trace_name, source));
538 gl_fake_queries_.SetCurrentGLTime(end_timestamp);
539 g_fakeCPUTime = expect_end_time;
540 gl_fake_queries_.SetDisjoint();
542 ExpectOutputterEndMocks(outputter_ref_.get(), category_name, trace_name,
543 expect_start_time, expect_end_time, false);
545 ASSERT_TRUE(tracer.End(source));
546 ASSERT_TRUE(tracer.EndDecoding());
548 outputter_ref_ = NULL;
552 class InvalidTimerTracerTest : public BaseGpuTracerTest {
553 public:
554 InvalidTimerTracerTest()
555 : BaseGpuTracerTest(gfx::GPUTiming::kTimerTypeInvalid) {}
558 class GpuARBTimerTracerTest : public BaseGpuTracerTest {
559 public:
560 GpuARBTimerTracerTest()
561 : BaseGpuTracerTest(gfx::GPUTiming::kTimerTypeARB) {}
564 class GpuDisjointTimerTracerTest : public BaseGpuTracerTest {
565 public:
566 GpuDisjointTimerTracerTest()
567 : BaseGpuTracerTest(gfx::GPUTiming::kTimerTypeDisjoint) {}
570 TEST_F(InvalidTimerTracerTest, InvalidTimerBasicTracerTest) {
571 DoBasicTracerTest();
574 TEST_F(GpuARBTimerTracerTest, ARBTimerBasicTracerTest) {
575 DoBasicTracerTest();
578 TEST_F(GpuDisjointTimerTracerTest, DisjointTimerBasicTracerTest) {
579 DoBasicTracerTest();
582 TEST_F(InvalidTimerTracerTest, InvalidTimerTracerMarkersTest) {
583 DoTracerMarkersTest();
586 TEST_F(GpuARBTimerTracerTest, ARBTimerBasicTracerMarkersTest) {
587 DoTracerMarkersTest();
590 TEST_F(GpuDisjointTimerTracerTest, DisjointTimerBasicTracerMarkersTest) {
591 DoTracerMarkersTest();
594 TEST_F(GpuDisjointTimerTracerTest, DisjointTimerDisjointTraceTest) {
595 DoDisjointTest();
598 class GPUTracerTest : public GpuServiceTest {
599 protected:
600 void SetUp() override {
601 g_fakeCPUTime = 0;
602 GpuServiceTest::SetUpWithGLVersion("3.2", "");
603 decoder_.reset(new MockGLES2Decoder());
604 EXPECT_CALL(*decoder_, GetGLContext())
605 .Times(AtMost(1))
606 .WillRepeatedly(Return(GetGLContext()));
607 tracer_tester_.reset(new GPUTracerTester(decoder_.get()));
610 void TearDown() override {
611 tracer_tester_ = nullptr;
612 decoder_ = nullptr;
613 GpuServiceTest::TearDown();
615 scoped_ptr<MockGLES2Decoder> decoder_;
616 scoped_ptr<GPUTracerTester> tracer_tester_;
619 TEST_F(GPUTracerTest, IsTracingTest) {
620 EXPECT_FALSE(tracer_tester_->IsTracing());
621 tracer_tester_->SetTracingEnabled(true);
622 EXPECT_TRUE(tracer_tester_->IsTracing());
624 // Test basic functionality of the GPUTracerTester.
625 TEST_F(GPUTracerTest, DecodeTest) {
626 ASSERT_TRUE(tracer_tester_->BeginDecoding());
627 EXPECT_FALSE(tracer_tester_->BeginDecoding());
628 ASSERT_TRUE(tracer_tester_->EndDecoding());
629 EXPECT_FALSE(tracer_tester_->EndDecoding());
632 TEST_F(GPUTracerTest, TraceDuringDecodeTest) {
633 const std::string category_name("trace_category");
634 const std::string trace_name("trace_test");
636 EXPECT_FALSE(
637 tracer_tester_->Begin(category_name, trace_name, kTraceGroupMarker));
639 ASSERT_TRUE(tracer_tester_->BeginDecoding());
640 EXPECT_TRUE(
641 tracer_tester_->Begin(category_name, trace_name, kTraceGroupMarker));
642 ASSERT_TRUE(tracer_tester_->EndDecoding());
645 } // namespace
646 } // namespace gles2
647 } // namespace gpu