// Copyright (c) 2012 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 GPU_COMMAND_BUFFER_CLIENT_QUERY_TRACKER_H_ #define GPU_COMMAND_BUFFER_CLIENT_QUERY_TRACKER_H_ #include <GLES2/gl2.h> #include <deque> #include <list> #include "base/atomicops.h" #include "base/containers/hash_tables.h" #include "gles2_impl_export.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" namespace gpu { class CommandBufferHelper; class MappedMemoryManager; namespace gles2 { class GLES2Implementation; // Manages buckets of QuerySync instances in mapped memory. class GLES2_IMPL_EXPORT QuerySyncManager { public: static const size_t kSyncsPerBucket = 4096; struct Bucket { explicit Bucket(QuerySync* sync_mem) : syncs(sync_mem), used_query_count(0) { } QuerySync* syncs; unsigned used_query_count; }; struct QueryInfo { QueryInfo(Bucket* bucket, int32 id, uint32 offset, QuerySync* sync_mem) : bucket(bucket), shm_id(id), shm_offset(offset), sync(sync_mem) { } QueryInfo() : bucket(NULL), shm_id(0), shm_offset(0), sync(NULL) { } Bucket* bucket; int32 shm_id; uint32 shm_offset; QuerySync* sync; }; explicit QuerySyncManager(MappedMemoryManager* manager); ~QuerySyncManager(); bool Alloc(QueryInfo* info); void Free(const QueryInfo& sync); void Shrink(); private: MappedMemoryManager* mapped_memory_; std::deque<Bucket*> buckets_; std::deque<QueryInfo> free_queries_; DISALLOW_COPY_AND_ASSIGN(QuerySyncManager); }; // Tracks queries for client side of command buffer. class GLES2_IMPL_EXPORT QueryTracker { public: class GLES2_IMPL_EXPORT Query { public: enum State { kUninitialized, // never used kActive, // between begin - end kPending, // not yet complete kComplete // completed }; Query(GLuint id, GLenum target, const QuerySyncManager::QueryInfo& info); GLenum target() const { return target_; } GLenum id() const { return id_; } int32 shm_id() const { return info_.shm_id; } uint32 shm_offset() const { return info_.shm_offset; } void MarkAsActive() { state_ = kActive; ++submit_count_; if (submit_count_ == INT_MAX) submit_count_ = 1; } void MarkAsPending(int32 token) { token_ = token; state_ = kPending; } base::subtle::Atomic32 submit_count() const { return submit_count_; } int32 token() const { return token_; } bool NeverUsed() const { return state_ == kUninitialized; } bool Pending() const { return state_ == kPending; } bool CheckResultsAvailable(CommandBufferHelper* helper); uint32 GetResult() const; void Begin(GLES2Implementation* gl); void End(GLES2Implementation* gl); private: friend class QueryTracker; friend class QueryTrackerTest; GLuint id_; GLenum target_; QuerySyncManager::QueryInfo info_; State state_; base::subtle::Atomic32 submit_count_; int32 token_; uint32 flush_count_; uint64 client_begin_time_us_; // Only used for latency query target. uint32 result_; }; QueryTracker(MappedMemoryManager* manager); ~QueryTracker(); Query* CreateQuery(GLuint id, GLenum target); Query* GetQuery(GLuint id); void RemoveQuery(GLuint id); void Shrink(); void FreeCompletedQueries(); private: typedef base::hash_map<GLuint, Query*> QueryMap; typedef std::list<Query*> QueryList; QueryMap queries_; QueryList removed_queries_; QuerySyncManager query_sync_manager_; DISALLOW_COPY_AND_ASSIGN(QueryTracker); }; } // namespace gles2 } // namespace gpu #endif // GPU_COMMAND_BUFFER_CLIENT_QUERY_TRACKER_H_