gpu_timing_fake.cc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. // Copyright 2015 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. #include "ui/gl/gpu_timing_fake.h"
  5. #include "base/time/time.h"
  6. #include "testing/gtest/include/gtest/gtest.h"
  7. #include "ui/gl/gl_mock.h"
  8. namespace gl {
  9. using ::testing::_;
  10. using ::testing::AtLeast;
  11. using ::testing::AtMost;
  12. using ::testing::Exactly;
  13. using ::testing::Invoke;
  14. using ::testing::NotNull;
  15. using ::testing::DoAll;
  16. using ::testing::Return;
  17. using ::testing::SetArgPointee;
  18. int64_t GPUTimingFake::fake_cpu_time_ = 0;
  19. GPUTimingFake::GPUTimingFake() {
  20. Reset();
  21. }
  22. GPUTimingFake::~GPUTimingFake() {
  23. }
  24. void GPUTimingFake::Reset() {
  25. current_gl_time_ = 0;
  26. gl_cpu_time_offset_ = 0;
  27. next_query_id_ = 23;
  28. allocated_queries_.clear();
  29. query_results_.clear();
  30. current_elapsed_query_.Reset();
  31. fake_cpu_time_ = 0;
  32. }
  33. int64_t GPUTimingFake::GetFakeCPUTime() {
  34. return fake_cpu_time_;
  35. }
  36. void GPUTimingFake::SetCPUGLOffset(int64_t offset) {
  37. gl_cpu_time_offset_ = offset;
  38. }
  39. void GPUTimingFake::SetCurrentCPUTime(int64_t current_time) {
  40. fake_cpu_time_ = current_time;
  41. current_gl_time_ = (fake_cpu_time_ + gl_cpu_time_offset_) *
  42. base::Time::kNanosecondsPerMicrosecond;
  43. }
  44. void GPUTimingFake::SetCurrentGLTime(GLint64 current_time) {
  45. current_gl_time_ = current_time;
  46. fake_cpu_time_ = (current_gl_time_ / base::Time::kNanosecondsPerMicrosecond) -
  47. gl_cpu_time_offset_;
  48. }
  49. void GPUTimingFake::SetDisjoint() {
  50. disjointed_ = true;
  51. }
  52. void GPUTimingFake::ExpectGetErrorCalls(MockGLInterface& gl) {
  53. EXPECT_CALL(gl, GetError()).Times(AtLeast(0))
  54. .WillRepeatedly(Invoke(this, &GPUTimingFake::FakeGLGetError));
  55. }
  56. void GPUTimingFake::ExpectDisjointCalls(MockGLInterface& gl) {
  57. EXPECT_CALL(gl, GetIntegerv(GL_GPU_DISJOINT_EXT, _)).Times(AtLeast(1))
  58. .WillRepeatedly(Invoke(this, &GPUTimingFake::FakeGLGetIntegerv));
  59. }
  60. void GPUTimingFake::ExpectNoDisjointCalls(MockGLInterface& gl) {
  61. EXPECT_CALL(gl, GetIntegerv(GL_GPU_DISJOINT_EXT, _)).Times(Exactly(0));
  62. }
  63. void GPUTimingFake::ExpectGPUTimeStampQuery(MockGLInterface& gl,
  64. bool elapsed_query) {
  65. EXPECT_CALL(gl, GenQueries(1, NotNull()))
  66. .WillOnce(Invoke(this, &GPUTimingFake::FakeGLGenQueries));
  67. EXPECT_CALL(gl, GetQueryiv(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, NotNull()))
  68. .WillRepeatedly(DoAll(SetArgPointee<2>(64), Return()));
  69. if (!elapsed_query) {
  70. // Time Stamp based queries.
  71. EXPECT_CALL(gl, GetInteger64v(GL_TIMESTAMP, _))
  72. .WillRepeatedly(
  73. Invoke(this, &GPUTimingFake::FakeGLGetInteger64v));
  74. EXPECT_CALL(gl, QueryCounter(_, GL_TIMESTAMP)).Times(Exactly(1))
  75. .WillRepeatedly(
  76. Invoke(this, &GPUTimingFake::FakeGLQueryCounter));
  77. } else {
  78. // Time Elapsed based queries.
  79. EXPECT_CALL(gl, BeginQuery(GL_TIME_ELAPSED, _)).Times(Exactly(1))
  80. .WillRepeatedly(
  81. Invoke(this, &GPUTimingFake::FakeGLBeginQuery));
  82. EXPECT_CALL(gl, EndQuery(GL_TIME_ELAPSED)).Times(Exactly(1))
  83. .WillRepeatedly(Invoke(this, &GPUTimingFake::FakeGLEndQuery));
  84. }
  85. EXPECT_CALL(gl, GetQueryObjectuiv(_, GL_QUERY_RESULT_AVAILABLE,
  86. NotNull()))
  87. .WillRepeatedly(
  88. Invoke(this, &GPUTimingFake::FakeGLGetQueryObjectuiv));
  89. EXPECT_CALL(gl, GetQueryObjectui64v(_, GL_QUERY_RESULT, NotNull()))
  90. .WillRepeatedly(
  91. Invoke(this, &GPUTimingFake::FakeGLGetQueryObjectui64v));
  92. EXPECT_CALL(gl, DeleteQueries(1, NotNull()))
  93. .WillOnce(Invoke(this, &GPUTimingFake::FakeGLDeleteQueries))
  94. .RetiresOnSaturation();
  95. }
  96. void GPUTimingFake::ExpectGPUTimerQuery(
  97. MockGLInterface& gl, bool elapsed_query) {
  98. EXPECT_CALL(gl, GenQueries(1, NotNull()))
  99. .Times(AtLeast(elapsed_query ? 1 : 2))
  100. .WillRepeatedly(Invoke(this, &GPUTimingFake::FakeGLGenQueries));
  101. if (!elapsed_query) {
  102. // Time Stamp based queries.
  103. EXPECT_CALL(gl, GetQueryiv(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, NotNull()))
  104. .WillRepeatedly(DoAll(SetArgPointee<2>(64), Return()));
  105. EXPECT_CALL(gl, GetInteger64v(GL_TIMESTAMP, _))
  106. .WillRepeatedly(
  107. Invoke(this, &GPUTimingFake::FakeGLGetInteger64v));
  108. EXPECT_CALL(gl, QueryCounter(_, GL_TIMESTAMP)).Times(AtLeast(1))
  109. .WillRepeatedly(
  110. Invoke(this, &GPUTimingFake::FakeGLQueryCounter));
  111. }
  112. // Time Elapsed based queries.
  113. EXPECT_CALL(gl, BeginQuery(GL_TIME_ELAPSED, _))
  114. .WillRepeatedly(
  115. Invoke(this, &GPUTimingFake::FakeGLBeginQuery));
  116. EXPECT_CALL(gl, EndQuery(GL_TIME_ELAPSED))
  117. .WillRepeatedly(Invoke(this, &GPUTimingFake::FakeGLEndQuery));
  118. EXPECT_CALL(gl, GetQueryObjectuiv(_, GL_QUERY_RESULT_AVAILABLE,
  119. NotNull()))
  120. .WillRepeatedly(
  121. Invoke(this, &GPUTimingFake::FakeGLGetQueryObjectuiv));
  122. EXPECT_CALL(gl, GetQueryObjectui64v(_, GL_QUERY_RESULT, NotNull()))
  123. .WillRepeatedly(
  124. Invoke(this, &GPUTimingFake::FakeGLGetQueryObjectui64v));
  125. EXPECT_CALL(gl, DeleteQueries(1, NotNull()))
  126. .Times(AtLeast(elapsed_query ? 1 : 2))
  127. .WillRepeatedly(
  128. Invoke(this, &GPUTimingFake::FakeGLDeleteQueries));
  129. }
  130. void GPUTimingFake::ExpectOffsetCalculationQuery(
  131. MockGLInterface& gl) {
  132. EXPECT_CALL(gl, GetInteger64v(GL_TIMESTAMP, NotNull()))
  133. .Times(AtMost(1))
  134. .WillRepeatedly(
  135. Invoke(this, &GPUTimingFake::FakeGLGetInteger64v));
  136. }
  137. void GPUTimingFake::ExpectNoOffsetCalculationQuery(
  138. MockGLInterface& gl) {
  139. EXPECT_CALL(gl, GetInteger64v(GL_TIMESTAMP, NotNull())).Times(Exactly(0));
  140. }
  141. void GPUTimingFake::FakeGLGenQueries(GLsizei n, GLuint* ids) {
  142. for (GLsizei i = 0; i < n; i++) {
  143. ids[i] = next_query_id_++;
  144. allocated_queries_.insert(ids[i]);
  145. }
  146. }
  147. void GPUTimingFake::FakeGLDeleteQueries(GLsizei n, const GLuint* ids) {
  148. for (GLsizei i = 0; i < n; i++) {
  149. allocated_queries_.erase(ids[i]);
  150. query_results_.erase(ids[i]);
  151. if (current_elapsed_query_.query_id_ == ids[i])
  152. current_elapsed_query_.Reset();
  153. }
  154. }
  155. void GPUTimingFake::FakeGLBeginQuery(GLenum target, GLuint id) {
  156. switch(target) {
  157. case GL_TIME_ELAPSED:
  158. ASSERT_FALSE(current_elapsed_query_.active_);
  159. current_elapsed_query_.Reset();
  160. current_elapsed_query_.active_ = true;
  161. current_elapsed_query_.query_id_ = id;
  162. current_elapsed_query_.begin_time_ = current_gl_time_;
  163. break;
  164. default:
  165. FAIL() << "Invalid target passed to BeginQuery: " << target;
  166. }
  167. }
  168. void GPUTimingFake::FakeGLEndQuery(GLenum target) {
  169. switch(target) {
  170. case GL_TIME_ELAPSED: {
  171. ASSERT_TRUE(current_elapsed_query_.active_);
  172. QueryResult& query = query_results_[current_elapsed_query_.query_id_];
  173. query.type_ = QueryResult::kQueryResultType_Elapsed;
  174. query.begin_time_ = current_elapsed_query_.begin_time_;
  175. query.value_ = current_gl_time_;
  176. current_elapsed_query_.active_ = false;
  177. } break;
  178. default:
  179. FAIL() << "Invalid target passed to BeginQuery: " << target;
  180. }
  181. }
  182. void GPUTimingFake::FakeGLGetQueryObjectuiv(GLuint id, GLenum pname,
  183. GLuint* params) {
  184. switch (pname) {
  185. case GL_QUERY_RESULT_AVAILABLE: {
  186. auto it = query_results_.find(id);
  187. if (it != query_results_.end() && it->second.value_ <= current_gl_time_)
  188. *params = 1;
  189. else
  190. *params = 0;
  191. } break;
  192. default:
  193. FAIL() << "Invalid variable passed to GetQueryObjectuiv: " << pname;
  194. }
  195. }
  196. void GPUTimingFake::FakeGLQueryCounter(GLuint id, GLenum target) {
  197. switch (target) {
  198. case GL_TIMESTAMP: {
  199. ASSERT_TRUE(allocated_queries_.find(id) != allocated_queries_.end());
  200. QueryResult& query = query_results_[id];
  201. query.type_ = QueryResult::kQueryResultType_TimeStamp;
  202. query.value_ = current_gl_time_;
  203. } break;
  204. default:
  205. FAIL() << "Invalid variable passed to QueryCounter: " << target;
  206. }
  207. }
  208. void GPUTimingFake::FakeGLGetInteger64v(GLenum pname, GLint64 * data) {
  209. switch (pname) {
  210. case GL_TIMESTAMP:
  211. *data = current_gl_time_;
  212. break;
  213. default:
  214. FAIL() << "Invalid variable passed to GetInteger64v: " << pname;
  215. }
  216. }
  217. void GPUTimingFake::FakeGLGetQueryObjectui64v(GLuint id, GLenum pname,
  218. GLuint64* params) {
  219. switch (pname) {
  220. case GL_QUERY_RESULT: {
  221. auto it = query_results_.find(id);
  222. ASSERT_TRUE(it != query_results_.end());
  223. switch (it->second.type_) {
  224. case QueryResult::kQueryResultType_TimeStamp:
  225. *params = it->second.value_;
  226. break;
  227. case QueryResult::kQueryResultType_Elapsed:
  228. *params = it->second.value_ - it->second.begin_time_;
  229. break;
  230. default:
  231. FAIL() << "Invalid Query Result Type: " << it->second.type_;
  232. }
  233. } break;
  234. default:
  235. FAIL() << "Invalid variable passed to GetQueryObjectui64v: " << pname;
  236. }
  237. }
  238. void GPUTimingFake::FakeGLGetIntegerv(GLenum pname, GLint* params) {
  239. switch (pname) {
  240. case GL_GPU_DISJOINT_EXT:
  241. *params = static_cast<GLint>(disjointed_);
  242. disjointed_ = false;
  243. break;
  244. default:
  245. FAIL() << "Invalid variable passed to GetIntegerv: " << pname;
  246. }
  247. }
  248. GLenum GPUTimingFake::FakeGLGetError() {
  249. return GL_NO_ERROR;
  250. }
  251. } // namespace gl