// 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_SERVICE_QUERY_MANAGER_H_ #define GPU_COMMAND_BUFFER_SERVICE_QUERY_MANAGER_H_ #include #include #include "base/basictypes.h" #include "base/containers/hash_tables.h" #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/gpu_export.h" namespace gpu { class GLES2Decoder; namespace gles2 { class FeatureInfo; // This class keeps track of the queries and their state // As Queries are not shared there is one QueryManager per context. class GPU_EXPORT QueryManager { public: class GPU_EXPORT Query : public base::RefCounted { public: Query( QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset); GLenum target() const { return target_; } bool IsDeleted() const { return deleted_; } bool IsValid() const { return target() && !IsDeleted(); } bool pending() const { return pending_; } int32 shm_id() const { return shm_id_; } uint32 shm_offset() const { return shm_offset_; } // Returns false if shared memory for sync is invalid. virtual bool Begin() = 0; // Returns false if shared memory for sync is invalid. virtual bool End(uint32 submit_count) = 0; // Returns false if shared memory for sync is invalid. virtual bool Process() = 0; virtual void Destroy(bool have_context) = 0; void AddCallback(base::Closure callback); protected: virtual ~Query(); QueryManager* manager() const { return manager_; } void MarkAsDeleted() { deleted_ = true; } // Returns false if shared memory for sync is invalid. bool MarkAsCompleted(uint64 result); void MarkAsPending(uint32 submit_count) { DCHECK(!pending_); pending_ = true; submit_count_ = submit_count; } void UnmarkAsPending() { DCHECK(pending_); pending_ = false; } // Returns false if shared memory for sync is invalid. bool AddToPendingQueue(uint32 submit_count) { return manager_->AddPendingQuery(this, submit_count); } // Returns false if shared memory for sync is invalid. bool AddToPendingTransferQueue(uint32 submit_count) { return manager_->AddPendingTransferQuery(this, submit_count); } void BeginQueryHelper(GLenum target, GLuint id) { manager_->BeginQueryHelper(target, id); } void EndQueryHelper(GLenum target) { manager_->EndQueryHelper(target); } uint32 submit_count() const { return submit_count_; } private: friend class QueryManager; friend class QueryManagerTest; friend class base::RefCounted; void RunCallbacks(); // The manager that owns this Query. QueryManager* manager_; // The type of query. GLenum target_; // The shared memory used with this Query. int32 shm_id_; uint32 shm_offset_; // Count to set process count do when completed. uint32 submit_count_; // True if in the queue. bool pending_; // True if deleted. bool deleted_; // List of callbacks to run when result is available. std::vector callbacks_; }; QueryManager( GLES2Decoder* decoder, FeatureInfo* feature_info); ~QueryManager(); // Must call before destruction. void Destroy(bool have_context); // Creates a Query for the given query. Query* CreateQuery( GLenum target, GLuint client_id, int32 shm_id, uint32 shm_offset); // Gets the query info for the given query. Query* GetQuery(GLuint client_id); // Removes a query info for the given query. void RemoveQuery(GLuint client_id); // Returns false if any query is pointing to invalid shared memory. bool BeginQuery(Query* query); // Returns false if any query is pointing to invalid shared memory. bool EndQuery(Query* query, uint32 submit_count); // Processes pending queries. Returns false if any queries are pointing // to invalid shared memory. bool ProcessPendingQueries(); // True if there are pending queries. bool HavePendingQueries(); // Processes pending transfer queries. Returns false if any queries are // pointing to invalid shared memory. bool ProcessPendingTransferQueries(); // True if there are pending transfer queries. bool HavePendingTransferQueries(); GLES2Decoder* decoder() const { return decoder_; } private: void StartTracking(Query* query); void StopTracking(Query* query); // Wrappers for BeginQueryARB and EndQueryARB to hide differences between // ARB_occlusion_query2 and EXT_occlusion_query_boolean. void BeginQueryHelper(GLenum target, GLuint id); void EndQueryHelper(GLenum target); // Adds to queue of queries waiting for completion. // Returns false if any query is pointing to invalid shared memory. bool AddPendingQuery(Query* query, uint32 submit_count); // Adds to queue of transfer queries waiting for completion. // Returns false if any query is pointing to invalid shared memory. bool AddPendingTransferQuery(Query* query, uint32 submit_count); // Removes a query from the queue of pending queries. // Returns false if any query is pointing to invalid shared memory. bool RemovePendingQuery(Query* query); // Returns a target used for the underlying GL extension // used to emulate a query. GLenum AdjustTargetForEmulation(GLenum target); // Used to validate shared memory and get GL errors. GLES2Decoder* decoder_; bool use_arb_occlusion_query2_for_occlusion_query_boolean_; bool use_arb_occlusion_query_for_occlusion_query_boolean_; // Counts the number of Queries allocated with 'this' as their manager. // Allows checking no Query will outlive this. unsigned query_count_; // Info for each query in the system. typedef base::hash_map > QueryMap; QueryMap queries_; // Queries waiting for completion. typedef std::deque > QueryQueue; QueryQueue pending_queries_; // Async pixel transfer queries waiting for completion. QueryQueue pending_transfer_queries_; DISALLOW_COPY_AND_ASSIGN(QueryManager); }; } // namespace gles2 } // namespace gpu #endif // GPU_COMMAND_BUFFER_SERVICE_QUERY_MANAGER_H_