#ifndef GPU_COMMAND_BUFFER_SERVICE_QUERY_MANAGER_H_
#define GPU_COMMAND_BUFFER_SERVICE_QUERY_MANAGER_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "base/atomicops.h"
#include "base/containers/circular_deque.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "gpu/command_buffer/common/buffer.h"
#include "gpu/command_buffer/common/common_cmd_format.h"
#include "gpu/command_buffer/common/gl2_types.h"
#include "gpu/gpu_gles2_export.h"
namespace gpu {
class GPU_GLES2_EXPORT QueryManager {
public:
class GPU_GLES2_EXPORT Query : public base::RefCounted<Query> {
public:
Query(QueryManager* manager,
GLenum target,
scoped_refptr<gpu::Buffer> buffer,
QuerySync* sync);
GLenum target() const {
return target_;
}
bool IsDeleted() const {
return deleted_;
}
bool IsValid() const {
return target() && !IsDeleted();
}
bool IsActive() const {
return query_state_ == kQueryState_Active;
}
bool IsPaused() const {
return query_state_ == kQueryState_Paused;
}
bool IsPending() const {
return query_state_ == kQueryState_Pending;
}
bool IsFinished() const {
return query_state_ == kQueryState_Finished;
}
const QuerySync* sync() const { return sync_; }
virtual void Begin() = 0;
virtual void End(base::subtle::Atomic32 submit_count) = 0;
virtual void QueryCounter(base::subtle::Atomic32 submit_count) = 0;
virtual void Process(bool did_finish) = 0;
virtual void Pause() = 0;
virtual void Resume() = 0;
virtual void Destroy(bool have_context) = 0;
virtual void BeginProcessingCommands() {}
virtual void EndProcessingCommands() {}
void AddCallback(base::OnceClosure callback);
protected:
virtual ~Query();
QueryManager* manager() const {
return manager_;
}
void MarkAsDeleted() {
deleted_ = true;
}
void MarkAsActive() {
DCHECK(query_state_ == kQueryState_Initialize ||
query_state_ == kQueryState_Paused ||
query_state_ == kQueryState_Finished);
query_state_ = kQueryState_Active;
}
void MarkAsPaused() {
DCHECK(query_state_ == kQueryState_Active);
query_state_ = kQueryState_Paused;
}
void MarkAsPending(base::subtle::Atomic32 submit_count) {
DCHECK(query_state_ == kQueryState_Active);
query_state_ = kQueryState_Pending;
submit_count_ = submit_count;
}
void MarkAsCompleted(uint64_t result);
void UnmarkAsPending() {
DCHECK(query_state_ == kQueryState_Pending);
query_state_ = kQueryState_Finished;
}
void AddToPendingQueue(base::subtle::Atomic32 submit_count) {
manager_->AddPendingQuery(this, submit_count);
}
void BeginQueryHelper(GLenum target, GLuint id) {
manager_->BeginQueryHelper(target, id);
}
void EndQueryHelper(GLenum target) {
manager_->EndQueryHelper(target);
}
base::subtle::Atomic32 submit_count() const { return submit_count_; }
private:
friend class QueryManager;
friend class QueryManagerTest;
friend class base::RefCounted<Query>;
void RunCallbacks();
raw_ptr<QueryManager> manager_;
GLenum target_;
scoped_refptr<gpu::Buffer> buffer_;
raw_ptr<QuerySync> sync_;
base::subtle::Atomic32 submit_count_;
enum QueryState {
kQueryState_Initialize,
kQueryState_Active,
kQueryState_Paused,
kQueryState_Pending,
kQueryState_Finished,
} query_state_;
bool deleted_;
std::vector<base::OnceClosure> callbacks_;
};
QueryManager();
QueryManager(const QueryManager&) = delete;
QueryManager& operator=(const QueryManager&) = delete;
virtual ~QueryManager();
void Destroy(bool have_context);
virtual Query* CreateQuery(GLenum target,
GLuint client_id,
scoped_refptr<gpu::Buffer> buffer,
QuerySync* sync);
Query* GetQuery(GLuint client_id);
Query* GetActiveQuery(GLenum target);
void RemoveQuery(GLuint client_id);
void BeginQuery(Query* query);
void EndQuery(Query* query, base::subtle::Atomic32 submit_count);
void QueryCounter(Query* query, base::subtle::Atomic32 submit_count);
void PauseQueries();
void ResumeQueries();
void BeginProcessingCommands();
void EndProcessingCommands();
void ProcessPendingQueries(bool did_finish);
bool HavePendingQueries();
void GenQueries(GLsizei n, const GLuint* queries);
bool IsValidQuery(GLuint id);
protected:
void StartTracking(Query* query);
void StopTracking(Query* query);
void BeginQueryHelper(GLenum target, GLuint id);
void EndQueryHelper(GLenum target);
void AddPendingQuery(Query* query, base::subtle::Atomic32 submit_count);
void RemovePendingQuery(Query* query);
virtual GLenum AdjustTargetForEmulation(GLenum target);
unsigned query_count_;
using QueryMap = std::unordered_map<GLuint, scoped_refptr<Query>>;
QueryMap queries_;
using GeneratedQueryIds = std::unordered_set<GLuint>;
GeneratedQueryIds generated_query_ids_;
using ActiveQueryMap = std::map<GLenum, scoped_refptr<Query>>;
ActiveQueryMap active_queries_;
using QueryQueue = base::circular_deque<scoped_refptr<Query>>;
QueryQueue pending_queries_;
};
}
#endif