// Copyright (c) 2015 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. #ifndef UI_GL_GPU_TIMING_H_ #define UI_GL_GPU_TIMING_H_ #include #include #include #include "base/callback.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "ui/gl/gl_export.h" // The gpu_timing classes handles the abstraction of GL GPU Timing extensions // into a common set of functions. Currently the different timer extensions that // are supported are EXT_timer_query, ARB_timer_query and // EXT_disjoint_timer_query. // // Explanation of Classes: // GPUTiming - GPU Timing is a private class which is only owned by the // underlying GLContextReal class. This class handles any GL Context level // states which may need to be redistributed to users of GPUTiming. For // example, there exists only a single disjoint flag for each real GL // Context. Once the disjoint flag is checked, internally it is reset to // false. In order to support multiple virtual contexts each checking the // disjoint flag seperately, GPUTiming is in charge of checking the // disjoint flag and broadcasting out the disjoint state to all the // various users of GPUTiming (GPUTimingClient below). // GPUTimingClient - The GLContextReal holds the GPUTiming class and is the // factory that creates GPUTimingClient objects. If a user would like to // obtain various GPU times they would access CreateGPUTimingClient() from // their GLContext and use the returned object for their timing calls. // Each virtual context as well as any other classes which need GPU times // will hold one of these. When they want to time a set of GL commands they // will create GPUTimer objects. // GPUTimer - Once a user decides to time something, the user creates a new // GPUTimer object from a GPUTimingClient and issue Start() and Stop() calls // around various GL calls. Once IsAvailable() returns true, the GPU times // will be available through the various time stamp related functions. // The constructor and destructor of this object handles the actual // creation and deletion of the GL Queries within GL. namespace gfx { class GLContextReal; class GPUTimingClient; class GPUTimingImpl; class QueryResult; class GPUTiming { public: enum TimerType { kTimerTypeInvalid = -1, kTimerTypeEXT, // EXT_timer_query kTimerTypeARB, // ARB_timer_query kTimerTypeDisjoint // EXT_disjoint_timer_query }; protected: friend std::default_delete; friend class GLContextReal; static GPUTiming* CreateGPUTiming(GLContextReal* context); GPUTiming(); virtual ~GPUTiming(); virtual scoped_refptr CreateGPUTimingClient() = 0; DISALLOW_COPY_AND_ASSIGN(GPUTiming); }; // Class to compute the amount of time it takes to fully // complete a set of GL commands class GL_EXPORT GPUTimer { public: static void DisableTimestampQueries(); ~GPUTimer(); // Destroy the timer object. This must be explicitly called before destroying // this object. void Destroy(bool have_context); // Clears current queries. void Reset(); // Start an instant timer, start and end will be equal. void QueryTimeStamp(); // Start a timer range. void Start(); void End(); bool IsAvailable(); void GetStartEndTimestamps(int64_t* start, int64_t* end); int64_t GetDeltaElapsed(); private: friend class GPUTimingClient; explicit GPUTimer(scoped_refptr gpu_timing_client, bool use_elapsed_timer); bool use_elapsed_timer_ = false; enum TimerState { kTimerState_Ready, kTimerState_WaitingForEnd, kTimerState_WaitingForResult, kTimerState_ResultAvailable } timer_state_ = kTimerState_Ready; scoped_refptr gpu_timing_client_; scoped_refptr time_stamp_result_; scoped_refptr elapsed_timer_result_; DISALLOW_COPY_AND_ASSIGN(GPUTimer); }; // GPUTimingClient contains all the gl timing logic that is not specific // to a single GPUTimer. class GL_EXPORT GPUTimingClient : public base::RefCounted { public: explicit GPUTimingClient(GPUTimingImpl* gpu_timing = nullptr); scoped_ptr CreateGPUTimer(bool prefer_elapsed_time); bool IsAvailable(); const char* GetTimerTypeName() const; // CheckAndResetTimerErrors has to be called before reading timestamps // from GPUTimers instances and after making sure all the timers // were available. // If the returned value is false, all the previous timers should be // discarded. bool CheckAndResetTimerErrors(); int64_t GetCurrentCPUTime(); void SetCpuTimeForTesting(const base::Callback& cpu_time); bool IsForceTimeElapsedQuery(); void ForceTimeElapsedQuery(); private: friend class base::RefCounted; friend class GPUTimer; virtual ~GPUTimingClient(); GPUTimingImpl* gpu_timing_; GPUTiming::TimerType timer_type_ = GPUTiming::kTimerTypeInvalid; uint32_t disjoint_counter_ = 0; DISALLOW_COPY_AND_ASSIGN(GPUTimingClient); }; } // namespace gfx #endif // UI_GL_GPU_TIMING_H_