blob: e9b7fcdafd45856b4f2a56e704b7ed54d3d5bdfa [file] [log] [blame]
// 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 <stdint.h>
#include <memory>
#include <queue>
#include "base/callback.h"
#include "base/macros.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 gl {
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<GPUTiming>;
friend class GLContextReal;
static GPUTiming* CreateGPUTiming(GLContextReal* context);
GPUTiming();
virtual ~GPUTiming();
virtual scoped_refptr<GPUTimingClient> 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<GPUTimingClient> 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<GPUTimingClient> gpu_timing_client_;
scoped_refptr<QueryResult> time_stamp_result_;
scoped_refptr<QueryResult> 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<GPUTimingClient> {
public:
explicit GPUTimingClient(GPUTimingImpl* gpu_timing = nullptr);
std::unique_ptr<GPUTimer> 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 true, all the previous timers should be
// discarded.
bool CheckAndResetTimerErrors();
int64_t GetCurrentCPUTime();
void SetCpuTimeForTesting(base::RepeatingCallback<int64_t(void)> cpu_time);
bool IsForceTimeElapsedQuery();
void ForceTimeElapsedQuery();
private:
friend class base::RefCounted<GPUTimingClient>;
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 gl
#endif // UI_GL_GPU_TIMING_H_