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: 33 MockOutputter() {} 34 MOCK_METHOD3(Trace, 35 void(const std::string& name, int64 start_time, int64 end_time)); 36 37 protected: 38 ~MockOutputter() {} 39 }; 40 41 class GlFakeQueries { 42 public: 43 GlFakeQueries() {} 44 45 void Reset() { 46 current_time_ = 0; 47 next_query_id_ = 23; 48 alloced_queries_.clear(); 49 query_timestamp_.clear(); 50 } 51 52 void SetCurrentGLTime(GLint64 current_time) { current_time_ = current_time; } 53 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 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 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 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 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: 114 BaseGpuTracerTest() {} 115 116 /////////////////////////////////////////////////////////////////////////// 117 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: 166 virtual void SetUp() { 167 GpuServiceTest::SetUp(); 168 gl_fake_queries_.Reset(); 169 } 170 171 virtual void TearDown() { 172 gl_.reset(); 173 gl_fake_queries_.Reset(); 174 GpuServiceTest::TearDown(); 175 } 176 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: 210 virtual GpuTracerType GetTracerType() OVERRIDE { 211 return kTracerTypeARBTimer; 212 } 213 }; 214 215 class GpuDisjointTimerTracerTest : public BaseGpuTracerTest { 216 protected: 217 virtual GpuTracerType GetTracerType() OVERRIDE { 218 return kTracerTypeDisjointTimer; 219 } 220 }; 221 222 TEST_F(GpuARBTimerTracerTest, GPUTrace) { 223 // Test basic timer query functionality 224 { 225 DoTraceTest(); 226 } 227 } 228 229 TEST_F(GpuDisjointTimerTracerTest, GPUTrace) { 230 // Test basic timer query functionality 231 { 232 DoTraceTest(); 233 } 234 } 235 236 } // namespace gles2 237 } // namespace gpu 238