• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include <map>
6 #include <set>
7 
8 #include "gpu/command_buffer/service/gpu_service_test.h"
9 #include "gpu/command_buffer/service/gpu_tracer.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "ui/gl/gl_mock.h"
12 
13 namespace gpu {
14 namespace gles2 {
15 
16 using ::testing::InvokeWithoutArgs;
17 using ::testing::Return;
18 using ::testing::ReturnRef;
19 using ::testing::ReturnPointee;
20 using ::testing::NotNull;
21 using ::testing::ElementsAreArray;
22 using ::testing::ElementsAre;
23 using ::testing::SetArrayArgument;
24 using ::testing::AtLeast;
25 using ::testing::SetArgPointee;
26 using ::testing::Pointee;
27 using ::testing::Unused;
28 using ::testing::Invoke;
29 using ::testing::_;
30 
31 class MockOutputter : public Outputter {
32  public:
MockOutputter()33   MockOutputter() {}
34   MOCK_METHOD3(Trace,
35                void(const std::string& name, int64 start_time, int64 end_time));
36 
37  protected:
~MockOutputter()38   ~MockOutputter() {}
39 };
40 
41 class GlFakeQueries {
42  public:
GlFakeQueries()43   GlFakeQueries() {}
44 
Reset()45   void Reset() {
46     current_time_ = 0;
47     next_query_id_ = 23;
48     alloced_queries_.clear();
49     query_timestamp_.clear();
50   }
51 
SetCurrentGLTime(GLint64 current_time)52   void SetCurrentGLTime(GLint64 current_time) { current_time_ = current_time; }
53 
GenQueriesARB(GLsizei n,GLuint * ids)54   void GenQueriesARB(GLsizei n, GLuint* ids) {
55     for (GLsizei i = 0; i < n; i++) {
56       ids[i] = next_query_id_++;
57       alloced_queries_.insert(ids[i]);
58     }
59   }
60 
DeleteQueriesARB(GLsizei n,const GLuint * ids)61   void DeleteQueriesARB(GLsizei n, const GLuint* ids) {
62     for (GLsizei i = 0; i < n; i++) {
63       alloced_queries_.erase(ids[i]);
64       query_timestamp_.erase(ids[i]);
65     }
66   }
67 
GetQueryObjectiv(GLuint id,GLenum pname,GLint * params)68   void GetQueryObjectiv(GLuint id, GLenum pname, GLint* params) {
69     switch (pname) {
70       case GL_QUERY_RESULT_AVAILABLE: {
71         std::map<GLuint, GLint64>::iterator it = query_timestamp_.find(id);
72         if (it != query_timestamp_.end() && it->second <= current_time_)
73           *params = 1;
74         else
75           *params = 0;
76         break;
77       }
78       default:
79         ASSERT_TRUE(false);
80     }
81   }
82 
QueryCounter(GLuint id,GLenum target)83   void QueryCounter(GLuint id, GLenum target) {
84     switch (target) {
85       case GL_TIMESTAMP:
86         ASSERT_TRUE(alloced_queries_.find(id) != alloced_queries_.end());
87         query_timestamp_[id] = current_time_;
88         break;
89       default:
90         ASSERT_TRUE(false);
91     }
92   }
93 
GetQueryObjectui64v(GLuint id,GLenum pname,GLuint64 * params)94   void GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) {
95     switch (pname) {
96       case GL_QUERY_RESULT:
97         ASSERT_TRUE(query_timestamp_.find(id) != query_timestamp_.end());
98         *params = query_timestamp_.find(id)->second;
99         break;
100       default:
101         ASSERT_TRUE(false);
102     }
103   }
104 
105  protected:
106   GLint64 current_time_;
107   GLuint next_query_id_;
108   std::set<GLuint> alloced_queries_;
109   std::map<GLuint, GLint64> query_timestamp_;
110 };
111 
112 class BaseGpuTracerTest : public GpuServiceTest {
113  public:
BaseGpuTracerTest()114   BaseGpuTracerTest() {}
115 
116   ///////////////////////////////////////////////////////////////////////////
117 
DoTraceTest()118   void DoTraceTest() {
119     MockOutputter* outputter = new MockOutputter();
120     scoped_refptr<Outputter> outputter_ref = outputter;
121 
122     SetupTimerQueryMocks();
123 
124     // Expected results
125     const std::string trace_name("trace_test");
126     const int64 offset_time = 3231;
127     const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
128     const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond;
129     const int64 expect_start_time =
130         (start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
131         offset_time;
132     const int64 expect_end_time =
133         (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
134 
135     // Expected Outputter::Trace call
136     EXPECT_CALL(*outputter,
137                 Trace(trace_name, expect_start_time, expect_end_time));
138 
139     scoped_refptr<GPUTrace> trace =
140         new GPUTrace(outputter_ref, trace_name, offset_time,
141                      GetTracerType());
142 
143     gl_fake_queries_.SetCurrentGLTime(start_timestamp);
144     trace->Start();
145 
146     // Shouldn't be available before End() call
147     gl_fake_queries_.SetCurrentGLTime(end_timestamp);
148     EXPECT_FALSE(trace->IsAvailable());
149 
150     trace->End();
151 
152     // Shouldn't be available until the queries complete
153     gl_fake_queries_.SetCurrentGLTime(end_timestamp -
154                                       base::Time::kNanosecondsPerMicrosecond);
155     EXPECT_FALSE(trace->IsAvailable());
156 
157     // Now it should be available
158     gl_fake_queries_.SetCurrentGLTime(end_timestamp);
159     EXPECT_TRUE(trace->IsAvailable());
160 
161     // Proces should output expected Trace results to MockOutputter
162     trace->Process();
163   }
164 
165  protected:
SetUp()166   virtual void SetUp() {
167     GpuServiceTest::SetUp();
168     gl_fake_queries_.Reset();
169   }
170 
TearDown()171   virtual void TearDown() {
172     gl_.reset();
173     gl_fake_queries_.Reset();
174     GpuServiceTest::TearDown();
175   }
176 
SetupTimerQueryMocks()177   virtual void SetupTimerQueryMocks() {
178     // Delegate query APIs used by GPUTrace to a GlFakeQueries
179     EXPECT_CALL(*gl_, GenQueriesARB(_, NotNull())).Times(AtLeast(1)).WillOnce(
180         Invoke(&gl_fake_queries_, &GlFakeQueries::GenQueriesARB));
181 
182     EXPECT_CALL(*gl_, GetQueryObjectiv(_, GL_QUERY_RESULT_AVAILABLE, NotNull()))
183         .Times(AtLeast(2))
184         .WillRepeatedly(
185              Invoke(&gl_fake_queries_, &GlFakeQueries::GetQueryObjectiv));
186 
187     EXPECT_CALL(*gl_, QueryCounter(_, GL_TIMESTAMP))
188         .Times(AtLeast(2))
189         .WillRepeatedly(
190              Invoke(&gl_fake_queries_, &GlFakeQueries::QueryCounter));
191 
192     EXPECT_CALL(*gl_, GetQueryObjectui64v(_, GL_QUERY_RESULT, NotNull()))
193         .Times(AtLeast(2))
194         .WillRepeatedly(
195              Invoke(&gl_fake_queries_, &GlFakeQueries::GetQueryObjectui64v));
196 
197     EXPECT_CALL(*gl_, DeleteQueriesARB(2, NotNull()))
198         .Times(AtLeast(1))
199         .WillRepeatedly(
200              Invoke(&gl_fake_queries_, &GlFakeQueries::DeleteQueriesARB));
201   }
202 
203   virtual GpuTracerType GetTracerType() = 0;
204 
205   GlFakeQueries gl_fake_queries_;
206 };
207 
208 class GpuARBTimerTracerTest : public BaseGpuTracerTest {
209  protected:
GetTracerType()210   virtual GpuTracerType GetTracerType() OVERRIDE {
211     return kTracerTypeARBTimer;
212   }
213 };
214 
215 class GpuDisjointTimerTracerTest : public BaseGpuTracerTest {
216  protected:
GetTracerType()217   virtual GpuTracerType GetTracerType() OVERRIDE {
218     return kTracerTypeDisjointTimer;
219   }
220 };
221 
TEST_F(GpuARBTimerTracerTest,GPUTrace)222 TEST_F(GpuARBTimerTracerTest, GPUTrace) {
223   // Test basic timer query functionality
224   {
225     DoTraceTest();
226   }
227 }
228 
TEST_F(GpuDisjointTimerTracerTest,GPUTrace)229 TEST_F(GpuDisjointTimerTracerTest, GPUTrace) {
230   // Test basic timer query functionality
231   {
232     DoTraceTest();
233   }
234 }
235 
236 }  // namespace gles2
237 }  // namespace gpu
238