Home | History | Annotate | Download | only in service
      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