1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef GPU_COMMAND_BUFFER_SERVICE_QUERY_MANAGER_H_
6 #define GPU_COMMAND_BUFFER_SERVICE_QUERY_MANAGER_H_
10 #include "base/atomicops.h"
11 #include "base/basictypes.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "gpu/command_buffer/service/feature_info.h"
17 #include "gpu/gpu_export.h"
21 class GPUTimingClient
;
32 // This class keeps track of the queries and their state
33 // As Queries are not shared there is one QueryManager per context.
34 class GPU_EXPORT QueryManager
{
36 class GPU_EXPORT Query
: public base::RefCounted
<Query
> {
39 QueryManager
* manager
, GLenum target
, int32 shm_id
, uint32 shm_offset
);
41 GLenum
target() const {
45 bool IsDeleted() const {
49 bool IsValid() const {
50 return target() && !IsDeleted();
53 bool IsActive() const {
54 return query_state_
== kQueryState_Active
;
57 bool IsPaused() const {
58 return query_state_
== kQueryState_Paused
;
61 bool IsPending() const {
62 return query_state_
== kQueryState_Pending
;
65 bool IsFinished() const {
66 return query_state_
== kQueryState_Finished
;
69 int32
shm_id() const {
73 uint32
shm_offset() const {
77 // Returns false if shared memory for sync is invalid.
78 virtual bool Begin() = 0;
80 // Returns false if shared memory for sync is invalid.
81 virtual bool End(base::subtle::Atomic32 submit_count
) = 0;
83 // Returns false if shared memory for sync is invalid.
84 virtual bool QueryCounter(base::subtle::Atomic32 submit_count
) = 0;
86 // Returns false if shared memory for sync is invalid.
87 virtual bool Process(bool did_finish
) = 0;
89 // Pauses active query to be resumed later.
90 virtual void Pause() = 0;
92 // Resume from a paused active query.
93 virtual void Resume() = 0;
95 virtual void Destroy(bool have_context
) = 0;
97 void AddCallback(base::Closure callback
);
102 QueryManager
* manager() const {
106 void MarkAsDeleted() {
110 void MarkAsActive() {
111 DCHECK(query_state_
== kQueryState_Initialize
||
112 query_state_
== kQueryState_Paused
||
113 query_state_
== kQueryState_Finished
);
114 query_state_
= kQueryState_Active
;
117 void MarkAsPaused() {
118 DCHECK(query_state_
== kQueryState_Active
);
119 query_state_
= kQueryState_Paused
;
122 void MarkAsPending(base::subtle::Atomic32 submit_count
) {
123 DCHECK(query_state_
== kQueryState_Active
);
124 query_state_
= kQueryState_Pending
;
125 submit_count_
= submit_count
;
128 // Returns false if shared memory for sync is invalid.
129 bool MarkAsCompleted(uint64 result
);
131 void UnmarkAsPending() {
132 DCHECK(query_state_
== kQueryState_Pending
);
133 query_state_
= kQueryState_Finished
;
136 // Returns false if shared memory for sync is invalid.
137 bool AddToPendingQueue(base::subtle::Atomic32 submit_count
) {
138 return manager_
->AddPendingQuery(this, submit_count
);
141 // Returns false if shared memory for sync is invalid.
142 bool AddToPendingTransferQueue(base::subtle::Atomic32 submit_count
) {
143 return manager_
->AddPendingTransferQuery(this, submit_count
);
146 void BeginQueryHelper(GLenum target
, GLuint id
) {
147 manager_
->BeginQueryHelper(target
, id
);
150 void EndQueryHelper(GLenum target
) {
151 manager_
->EndQueryHelper(target
);
154 void SafelyResetDisjointValue() {
155 manager_
->SafelyResetDisjointValue();
158 void UpdateDisjointValue() {
159 manager_
->UpdateDisjointValue();
162 void BeginContinualDisjointUpdate() {
163 manager_
->update_disjoints_continually_
= true;
166 base::subtle::Atomic32
submit_count() const { return submit_count_
; }
169 friend class QueryManager
;
170 friend class QueryManagerTest
;
171 friend class base::RefCounted
<Query
>;
175 // The manager that owns this Query.
176 QueryManager
* manager_
;
178 // The type of query.
181 // The shared memory used with this Query.
185 // Count to set process count do when completed.
186 base::subtle::Atomic32 submit_count_
;
188 // Current state of the query.
190 kQueryState_Initialize
, // Has not been queried yet.
191 kQueryState_Active
, // Query began but has not ended.
192 kQueryState_Paused
, // Query was active but is now paused.
193 kQueryState_Pending
, // Query ended, waiting for result.
194 kQueryState_Finished
, // Query received result.
200 // List of callbacks to run when result is available.
201 std::vector
<base::Closure
> callbacks_
;
205 GLES2Decoder
* decoder
,
206 FeatureInfo
* feature_info
);
209 // Must call before destruction.
210 void Destroy(bool have_context
);
212 // Sets up a location to be incremented whenever a disjoint is detected.
213 void SetDisjointSync(int32 shm_id
, uint32 shm_offset
);
215 // Creates a Query for the given query.
217 GLenum target
, GLuint client_id
, int32 shm_id
, uint32 shm_offset
);
219 // Gets the query info for the given query.
220 Query
* GetQuery(GLuint client_id
);
222 // Gets the currently active query for a target.
223 Query
* GetActiveQuery(GLenum target
);
225 // Removes a query info for the given query.
226 void RemoveQuery(GLuint client_id
);
228 // Returns false if any query is pointing to invalid shared memory.
229 bool BeginQuery(Query
* query
);
231 // Returns false if any query is pointing to invalid shared memory.
232 bool EndQuery(Query
* query
, base::subtle::Atomic32 submit_count
);
234 // Returns false if any query is pointing to invalid shared memory.
235 bool QueryCounter(Query
* query
, base::subtle::Atomic32 submit_count
);
238 void ResumeQueries();
240 // Processes pending queries. Returns false if any queries are pointing
241 // to invalid shared memory. |did_finish| is true if this is called as
242 // a result of calling glFinish().
243 bool ProcessPendingQueries(bool did_finish
);
245 // True if there are pending queries.
246 bool HavePendingQueries();
248 // Processes pending transfer queries. Returns false if any queries are
249 // pointing to invalid shared memory.
250 bool ProcessPendingTransferQueries();
252 // True if there are pending transfer queries.
253 bool HavePendingTransferQueries();
255 // Do any updates we need to do when the frame has begun.
256 void ProcessFrameBeginUpdates();
258 GLES2Decoder
* decoder() const {
262 scoped_ptr
<gfx::GPUTimer
> CreateGPUTimer(bool elapsed_time
);
263 bool GPUTimingAvailable();
265 void GenQueries(GLsizei n
, const GLuint
* queries
);
266 bool IsValidQuery(GLuint id
);
269 void StartTracking(Query
* query
);
270 void StopTracking(Query
* query
);
272 // Wrappers for BeginQueryARB and EndQueryARB to hide differences between
273 // ARB_occlusion_query2 and EXT_occlusion_query_boolean.
274 void BeginQueryHelper(GLenum target
, GLuint id
);
275 void EndQueryHelper(GLenum target
);
277 // Adds to queue of queries waiting for completion.
278 // Returns false if any query is pointing to invalid shared memory.
279 bool AddPendingQuery(Query
* query
, base::subtle::Atomic32 submit_count
);
281 // Adds to queue of transfer queries waiting for completion.
282 // Returns false if any query is pointing to invalid shared memory.
283 bool AddPendingTransferQuery(Query
* query
,
284 base::subtle::Atomic32 submit_count
);
286 // Removes a query from the queue of pending queries.
287 // Returns false if any query is pointing to invalid shared memory.
288 bool RemovePendingQuery(Query
* query
);
290 // Returns a target used for the underlying GL extension
291 // used to emulate a query.
292 GLenum
AdjustTargetForEmulation(GLenum target
);
294 // Checks and notifies if a disjoint occurred.
295 void UpdateDisjointValue();
297 // Safely resets the disjoint value if no queries are active.
298 void SafelyResetDisjointValue();
300 // Used to validate shared memory and get GL errors.
301 GLES2Decoder
* decoder_
;
303 bool use_arb_occlusion_query2_for_occlusion_query_boolean_
;
304 bool use_arb_occlusion_query_for_occlusion_query_boolean_
;
306 // Whether we are tracking disjoint values every frame.
307 bool update_disjoints_continually_
;
309 // The shared memory used for disjoint notifications.
310 int32_t disjoint_notify_shm_id_
;
311 uint32_t disjoint_notify_shm_offset_
;
313 // Current number of disjoints notified.
314 uint32_t disjoints_notified_
;
316 // Counts the number of Queries allocated with 'this' as their manager.
317 // Allows checking no Query will outlive this.
318 unsigned query_count_
;
320 // Info for each query in the system.
321 typedef base::hash_map
<GLuint
, scoped_refptr
<Query
> > QueryMap
;
324 typedef base::hash_set
<GLuint
> GeneratedQueryIds
;
325 GeneratedQueryIds generated_query_ids_
;
327 // A map of targets -> Query for current active queries.
328 typedef std::map
<GLenum
, scoped_refptr
<Query
> > ActiveQueryMap
;
329 ActiveQueryMap active_queries_
;
331 // Queries waiting for completion.
332 typedef std::deque
<scoped_refptr
<Query
> > QueryQueue
;
333 QueryQueue pending_queries_
;
335 // Async pixel transfer queries waiting for completion.
336 QueryQueue pending_transfer_queries_
;
338 scoped_refptr
<gfx::GPUTimingClient
> gpu_timing_client_
;
340 DISALLOW_COPY_AND_ASSIGN(QueryManager
);
346 #endif // GPU_COMMAND_BUFFER_SERVICE_QUERY_MANAGER_H_