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