• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "gpu/command_buffer/service/query_manager.h"
6 
7 #include "base/atomicops.h"
8 #include "base/bind.h"
9 #include "base/logging.h"
10 #include "base/memory/shared_memory.h"
11 #include "base/synchronization/lock.h"
12 #include "base/time/time.h"
13 #include "gpu/command_buffer/common/gles2_cmd_format.h"
14 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
15 #include "gpu/command_buffer/service/error_state.h"
16 #include "gpu/command_buffer/service/feature_info.h"
17 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
18 
19 namespace gpu {
20 namespace gles2 {
21 
22 namespace {
23 
24 class AsyncPixelTransferCompletionObserverImpl
25     : public AsyncPixelTransferCompletionObserver {
26  public:
AsyncPixelTransferCompletionObserverImpl(uint32 submit_count)27   AsyncPixelTransferCompletionObserverImpl(uint32 submit_count)
28       : submit_count_(submit_count),
29         cancelled_(false) {}
30 
Cancel()31   void Cancel() {
32     base::AutoLock locked(lock_);
33     cancelled_ = true;
34   }
35 
DidComplete(const AsyncMemoryParams & mem_params)36   virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE {
37     base::AutoLock locked(lock_);
38     if (!cancelled_) {
39       DCHECK(mem_params.shared_memory);
40       DCHECK(mem_params.shared_memory->memory());
41       void* data = static_cast<int8*>(mem_params.shared_memory->memory()) +
42                    mem_params.shm_data_offset;
43       QuerySync* sync = static_cast<QuerySync*>(data);
44 
45       // Need a MemoryBarrier here to ensure that upload completed before
46       // submit_count was written to sync->process_count.
47       base::subtle::MemoryBarrier();
48       sync->process_count = submit_count_;
49     }
50   }
51 
52  private:
~AsyncPixelTransferCompletionObserverImpl()53   virtual ~AsyncPixelTransferCompletionObserverImpl() {}
54 
55   uint32 submit_count_;
56 
57   base::Lock lock_;
58   bool cancelled_;
59 
60   DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferCompletionObserverImpl);
61 };
62 
63 class AsyncPixelTransfersCompletedQuery
64     : public QueryManager::Query,
65       public base::SupportsWeakPtr<AsyncPixelTransfersCompletedQuery> {
66  public:
67   AsyncPixelTransfersCompletedQuery(
68       QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset);
69 
70   virtual bool Begin() OVERRIDE;
71   virtual bool End(uint32 submit_count) OVERRIDE;
72   virtual bool Process() OVERRIDE;
73   virtual void Destroy(bool have_context) OVERRIDE;
74 
75  protected:
76   virtual ~AsyncPixelTransfersCompletedQuery();
77 
78   scoped_refptr<AsyncPixelTransferCompletionObserverImpl> observer_;
79 };
80 
AsyncPixelTransfersCompletedQuery(QueryManager * manager,GLenum target,int32 shm_id,uint32 shm_offset)81 AsyncPixelTransfersCompletedQuery::AsyncPixelTransfersCompletedQuery(
82     QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset)
83     : Query(manager, target, shm_id, shm_offset) {
84 }
85 
Begin()86 bool AsyncPixelTransfersCompletedQuery::Begin() {
87   return true;
88 }
89 
End(uint32 submit_count)90 bool AsyncPixelTransfersCompletedQuery::End(uint32 submit_count) {
91   AsyncMemoryParams mem_params;
92   // Get the real shared memory since it might need to be duped to prevent
93   // use-after-free of the memory.
94   Buffer buffer = manager()->decoder()->GetSharedMemoryBuffer(shm_id());
95   if (!buffer.shared_memory)
96     return false;
97   mem_params.shared_memory = buffer.shared_memory;
98   mem_params.shm_size = buffer.size;
99   mem_params.shm_data_offset = shm_offset();
100   mem_params.shm_data_size = sizeof(QuerySync);
101   uint32 end = mem_params.shm_data_offset + mem_params.shm_data_size;
102   if (end > mem_params.shm_size || end < mem_params.shm_data_offset)
103     return false;
104 
105   observer_ = new AsyncPixelTransferCompletionObserverImpl(submit_count);
106 
107   // Ask AsyncPixelTransferDelegate to run completion callback after all
108   // previous async transfers are done. No guarantee that callback is run
109   // on the current thread.
110   manager()->decoder()->GetAsyncPixelTransferManager()
111       ->AsyncNotifyCompletion(mem_params, observer_);
112 
113   return AddToPendingTransferQueue(submit_count);
114 }
115 
Process()116 bool AsyncPixelTransfersCompletedQuery::Process() {
117   QuerySync* sync = manager()->decoder()->GetSharedMemoryAs<QuerySync*>(
118       shm_id(), shm_offset(), sizeof(*sync));
119   if (!sync)
120     return false;
121 
122   // Check if completion callback has been run. sync->process_count atomicity
123   // is guaranteed as this is already used to notify client of a completed
124   // query.
125   if (sync->process_count != submit_count())
126     return true;
127 
128   UnmarkAsPending();
129   return true;
130 }
131 
Destroy(bool)132 void AsyncPixelTransfersCompletedQuery::Destroy(bool /* have_context */) {
133   if (!IsDeleted()) {
134     MarkAsDeleted();
135   }
136 }
137 
~AsyncPixelTransfersCompletedQuery()138 AsyncPixelTransfersCompletedQuery::~AsyncPixelTransfersCompletedQuery() {
139   if (observer_)
140     observer_->Cancel();
141 }
142 
143 }  // namespace
144 
145 class AllSamplesPassedQuery : public QueryManager::Query {
146  public:
147   AllSamplesPassedQuery(
148       QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset,
149       GLuint service_id);
150   virtual bool Begin() OVERRIDE;
151   virtual bool End(uint32 submit_count) OVERRIDE;
152   virtual bool Process() OVERRIDE;
153   virtual void Destroy(bool have_context) OVERRIDE;
154 
155  protected:
156   virtual ~AllSamplesPassedQuery();
157 
158  private:
159   // Service side query id.
160   GLuint service_id_;
161 };
162 
AllSamplesPassedQuery(QueryManager * manager,GLenum target,int32 shm_id,uint32 shm_offset,GLuint service_id)163 AllSamplesPassedQuery::AllSamplesPassedQuery(
164     QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset,
165     GLuint service_id)
166     : Query(manager, target, shm_id, shm_offset),
167       service_id_(service_id) {
168 }
169 
Begin()170 bool AllSamplesPassedQuery::Begin() {
171   BeginQueryHelper(target(), service_id_);
172   return true;
173 }
174 
End(uint32 submit_count)175 bool AllSamplesPassedQuery::End(uint32 submit_count) {
176   EndQueryHelper(target());
177   return AddToPendingQueue(submit_count);
178 }
179 
Process()180 bool AllSamplesPassedQuery::Process() {
181   GLuint available = 0;
182   glGetQueryObjectuivARB(
183       service_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
184   if (!available) {
185     return true;
186   }
187   GLuint result = 0;
188   glGetQueryObjectuivARB(
189       service_id_, GL_QUERY_RESULT_EXT, &result);
190 
191   return MarkAsCompleted(result != 0);
192 }
193 
Destroy(bool have_context)194 void AllSamplesPassedQuery::Destroy(bool have_context) {
195   if (have_context && !IsDeleted()) {
196     glDeleteQueriesARB(1, &service_id_);
197     MarkAsDeleted();
198   }
199 }
200 
~AllSamplesPassedQuery()201 AllSamplesPassedQuery::~AllSamplesPassedQuery() {
202 }
203 
204 class CommandsIssuedQuery : public QueryManager::Query {
205  public:
206   CommandsIssuedQuery(
207       QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset);
208 
209   virtual bool Begin() OVERRIDE;
210   virtual bool End(uint32 submit_count) OVERRIDE;
211   virtual bool Process() OVERRIDE;
212   virtual void Destroy(bool have_context) OVERRIDE;
213 
214  protected:
215   virtual ~CommandsIssuedQuery();
216 
217  private:
218   base::TimeTicks begin_time_;
219 };
220 
CommandsIssuedQuery(QueryManager * manager,GLenum target,int32 shm_id,uint32 shm_offset)221 CommandsIssuedQuery::CommandsIssuedQuery(
222       QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset)
223     : Query(manager, target, shm_id, shm_offset) {
224 }
225 
Begin()226 bool CommandsIssuedQuery::Begin() {
227   begin_time_ = base::TimeTicks::HighResNow();
228   return true;
229 }
230 
End(uint32 submit_count)231 bool CommandsIssuedQuery::End(uint32 submit_count) {
232   base::TimeDelta elapsed = base::TimeTicks::HighResNow() - begin_time_;
233   MarkAsPending(submit_count);
234   return MarkAsCompleted(elapsed.InMicroseconds());
235 }
236 
Process()237 bool CommandsIssuedQuery::Process() {
238   NOTREACHED();
239   return true;
240 }
241 
Destroy(bool)242 void CommandsIssuedQuery::Destroy(bool /* have_context */) {
243   if (!IsDeleted()) {
244     MarkAsDeleted();
245   }
246 }
247 
~CommandsIssuedQuery()248 CommandsIssuedQuery::~CommandsIssuedQuery() {
249 }
250 
251 class CommandLatencyQuery : public QueryManager::Query {
252  public:
253   CommandLatencyQuery(
254       QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset);
255 
256   virtual bool Begin() OVERRIDE;
257   virtual bool End(uint32 submit_count) OVERRIDE;
258   virtual bool Process() OVERRIDE;
259   virtual void Destroy(bool have_context) OVERRIDE;
260 
261  protected:
262   virtual ~CommandLatencyQuery();
263 };
264 
CommandLatencyQuery(QueryManager * manager,GLenum target,int32 shm_id,uint32 shm_offset)265 CommandLatencyQuery::CommandLatencyQuery(
266       QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset)
267     : Query(manager, target, shm_id, shm_offset) {
268 }
269 
Begin()270 bool CommandLatencyQuery::Begin() {
271     return true;
272 }
273 
End(uint32 submit_count)274 bool CommandLatencyQuery::End(uint32 submit_count) {
275     base::TimeDelta now = base::TimeTicks::HighResNow() - base::TimeTicks();
276     MarkAsPending(submit_count);
277     return MarkAsCompleted(now.InMicroseconds());
278 }
279 
Process()280 bool CommandLatencyQuery::Process() {
281   NOTREACHED();
282   return true;
283 }
284 
Destroy(bool)285 void CommandLatencyQuery::Destroy(bool /* have_context */) {
286   if (!IsDeleted()) {
287     MarkAsDeleted();
288   }
289 }
290 
~CommandLatencyQuery()291 CommandLatencyQuery::~CommandLatencyQuery() {
292 }
293 
294 
295 class AsyncReadPixelsCompletedQuery
296     : public QueryManager::Query,
297       public base::SupportsWeakPtr<AsyncReadPixelsCompletedQuery> {
298  public:
299   AsyncReadPixelsCompletedQuery(
300       QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset);
301 
302   virtual bool Begin() OVERRIDE;
303   virtual bool End(uint32 submit_count) OVERRIDE;
304   virtual bool Process() OVERRIDE;
305   virtual void Destroy(bool have_context) OVERRIDE;
306 
307  protected:
308   void Complete();
309   virtual ~AsyncReadPixelsCompletedQuery();
310 };
311 
AsyncReadPixelsCompletedQuery(QueryManager * manager,GLenum target,int32 shm_id,uint32 shm_offset)312 AsyncReadPixelsCompletedQuery::AsyncReadPixelsCompletedQuery(
313     QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset)
314     : Query(manager, target, shm_id, shm_offset) {
315 }
316 
Begin()317 bool AsyncReadPixelsCompletedQuery::Begin() {
318   return true;
319 }
320 
End(uint32 submit_count)321 bool AsyncReadPixelsCompletedQuery::End(uint32 submit_count) {
322   if (!AddToPendingQueue(submit_count)) {
323     return false;
324   }
325   manager()->decoder()->WaitForReadPixels(
326       base::Bind(&AsyncReadPixelsCompletedQuery::Complete,
327                  AsWeakPtr()));
328 
329   return true;
330 }
331 
Complete()332 void AsyncReadPixelsCompletedQuery::Complete() {
333   MarkAsCompleted(1);
334 }
335 
Process()336 bool AsyncReadPixelsCompletedQuery::Process() {
337   return true;
338 }
339 
Destroy(bool)340 void AsyncReadPixelsCompletedQuery::Destroy(bool /* have_context */) {
341   if (!IsDeleted()) {
342     MarkAsDeleted();
343   }
344 }
345 
~AsyncReadPixelsCompletedQuery()346 AsyncReadPixelsCompletedQuery::~AsyncReadPixelsCompletedQuery() {
347 }
348 
349 
350 class GetErrorQuery : public QueryManager::Query {
351  public:
352   GetErrorQuery(
353       QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset);
354 
355   virtual bool Begin() OVERRIDE;
356   virtual bool End(uint32 submit_count) OVERRIDE;
357   virtual bool Process() OVERRIDE;
358   virtual void Destroy(bool have_context) OVERRIDE;
359 
360  protected:
361   virtual ~GetErrorQuery();
362 
363  private:
364 };
365 
GetErrorQuery(QueryManager * manager,GLenum target,int32 shm_id,uint32 shm_offset)366 GetErrorQuery::GetErrorQuery(
367       QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset)
368     : Query(manager, target, shm_id, shm_offset) {
369 }
370 
Begin()371 bool GetErrorQuery::Begin() {
372   return true;
373 }
374 
End(uint32 submit_count)375 bool GetErrorQuery::End(uint32 submit_count) {
376   MarkAsPending(submit_count);
377   return MarkAsCompleted(manager()->decoder()->GetErrorState()->GetGLError());
378 }
379 
Process()380 bool GetErrorQuery::Process() {
381   NOTREACHED();
382   return true;
383 }
384 
Destroy(bool)385 void GetErrorQuery::Destroy(bool /* have_context */) {
386   if (!IsDeleted()) {
387     MarkAsDeleted();
388   }
389 }
390 
~GetErrorQuery()391 GetErrorQuery::~GetErrorQuery() {
392 }
393 
QueryManager(GLES2Decoder * decoder,FeatureInfo * feature_info)394 QueryManager::QueryManager(
395     GLES2Decoder* decoder,
396     FeatureInfo* feature_info)
397     : decoder_(decoder),
398       use_arb_occlusion_query2_for_occlusion_query_boolean_(
399           feature_info->feature_flags(
400             ).use_arb_occlusion_query2_for_occlusion_query_boolean),
401       use_arb_occlusion_query_for_occlusion_query_boolean_(
402           feature_info->feature_flags(
403             ).use_arb_occlusion_query_for_occlusion_query_boolean),
404       query_count_(0) {
405   DCHECK(!(use_arb_occlusion_query_for_occlusion_query_boolean_ &&
406            use_arb_occlusion_query2_for_occlusion_query_boolean_));
407 }
408 
~QueryManager()409 QueryManager::~QueryManager() {
410   DCHECK(queries_.empty());
411 
412   // If this triggers, that means something is keeping a reference to
413   // a Query belonging to this.
414   CHECK_EQ(query_count_, 0u);
415 }
416 
Destroy(bool have_context)417 void QueryManager::Destroy(bool have_context) {
418   pending_queries_.clear();
419   pending_transfer_queries_.clear();
420   while (!queries_.empty()) {
421     Query* query = queries_.begin()->second.get();
422     query->Destroy(have_context);
423     queries_.erase(queries_.begin());
424   }
425 }
426 
CreateQuery(GLenum target,GLuint client_id,int32 shm_id,uint32 shm_offset)427 QueryManager::Query* QueryManager::CreateQuery(
428     GLenum target, GLuint client_id, int32 shm_id, uint32 shm_offset) {
429   scoped_refptr<Query> query;
430   switch (target) {
431     case GL_COMMANDS_ISSUED_CHROMIUM:
432       query = new CommandsIssuedQuery(this, target, shm_id, shm_offset);
433       break;
434     case GL_LATENCY_QUERY_CHROMIUM:
435       query = new CommandLatencyQuery(this, target, shm_id, shm_offset);
436       break;
437     case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
438       // Currently async pixel transfer delegates only support uploads.
439       query = new AsyncPixelTransfersCompletedQuery(
440           this, target, shm_id, shm_offset);
441       break;
442     case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
443       query = new AsyncReadPixelsCompletedQuery(
444           this, target, shm_id, shm_offset);
445       break;
446     case GL_GET_ERROR_QUERY_CHROMIUM:
447       query = new GetErrorQuery(this, target, shm_id, shm_offset);
448       break;
449     default: {
450       GLuint service_id = 0;
451       glGenQueriesARB(1, &service_id);
452       DCHECK_NE(0u, service_id);
453       query = new AllSamplesPassedQuery(
454           this, target, shm_id, shm_offset, service_id);
455       break;
456     }
457   }
458   std::pair<QueryMap::iterator, bool> result =
459       queries_.insert(std::make_pair(client_id, query));
460   DCHECK(result.second);
461   return query.get();
462 }
463 
GetQuery(GLuint client_id)464 QueryManager::Query* QueryManager::GetQuery(
465     GLuint client_id) {
466   QueryMap::iterator it = queries_.find(client_id);
467   return it != queries_.end() ? it->second.get() : NULL;
468 }
469 
RemoveQuery(GLuint client_id)470 void QueryManager::RemoveQuery(GLuint client_id) {
471   QueryMap::iterator it = queries_.find(client_id);
472   if (it != queries_.end()) {
473     Query* query = it->second.get();
474     RemovePendingQuery(query);
475     query->MarkAsDeleted();
476     queries_.erase(it);
477   }
478 }
479 
StartTracking(QueryManager::Query *)480 void QueryManager::StartTracking(QueryManager::Query* /* query */) {
481   ++query_count_;
482 }
483 
StopTracking(QueryManager::Query *)484 void QueryManager::StopTracking(QueryManager::Query* /* query */) {
485   --query_count_;
486 }
487 
AdjustTargetForEmulation(GLenum target)488 GLenum QueryManager::AdjustTargetForEmulation(GLenum target) {
489   switch (target) {
490     case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
491     case GL_ANY_SAMPLES_PASSED_EXT:
492       if (use_arb_occlusion_query2_for_occlusion_query_boolean_) {
493         // ARB_occlusion_query2 does not have a
494         // GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT
495         // target.
496         target = GL_ANY_SAMPLES_PASSED_EXT;
497       } else if (use_arb_occlusion_query_for_occlusion_query_boolean_) {
498         // ARB_occlusion_query does not have a
499         // GL_ANY_SAMPLES_PASSED_EXT
500         // target.
501         target = GL_SAMPLES_PASSED_ARB;
502       }
503       break;
504     default:
505       break;
506   }
507   return target;
508 }
509 
BeginQueryHelper(GLenum target,GLuint id)510 void QueryManager::BeginQueryHelper(GLenum target, GLuint id) {
511   target = AdjustTargetForEmulation(target);
512   glBeginQueryARB(target, id);
513 }
514 
EndQueryHelper(GLenum target)515 void QueryManager::EndQueryHelper(GLenum target) {
516   target = AdjustTargetForEmulation(target);
517   glEndQueryARB(target);
518 }
519 
Query(QueryManager * manager,GLenum target,int32 shm_id,uint32 shm_offset)520 QueryManager::Query::Query(
521      QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset)
522     : manager_(manager),
523       target_(target),
524       shm_id_(shm_id),
525       shm_offset_(shm_offset),
526       submit_count_(0),
527       pending_(false),
528       deleted_(false) {
529   DCHECK(manager);
530   manager_->StartTracking(this);
531 }
532 
RunCallbacks()533 void QueryManager::Query::RunCallbacks() {
534   for (size_t i = 0; i < callbacks_.size(); i++) {
535     callbacks_[i].Run();
536   }
537   callbacks_.clear();
538 }
539 
AddCallback(base::Closure callback)540 void QueryManager::Query::AddCallback(base::Closure callback) {
541   if (pending_) {
542     callbacks_.push_back(callback);
543   } else {
544     callback.Run();
545   }
546 }
547 
~Query()548 QueryManager::Query::~Query() {
549   // The query is getting deleted, either by the client or
550   // because the context was lost. Call any outstanding
551   // callbacks to avoid leaks.
552   RunCallbacks();
553   if (manager_) {
554     manager_->StopTracking(this);
555     manager_ = NULL;
556   }
557 }
558 
MarkAsCompleted(uint64 result)559 bool QueryManager::Query::MarkAsCompleted(uint64 result) {
560   DCHECK(pending_);
561   QuerySync* sync = manager_->decoder_->GetSharedMemoryAs<QuerySync*>(
562       shm_id_, shm_offset_, sizeof(*sync));
563   if (!sync) {
564     return false;
565   }
566 
567   pending_ = false;
568   sync->result = result;
569   // Need a MemoryBarrier here so that sync->result is written before
570   // sync->process_count.
571   base::subtle::MemoryBarrier();
572   sync->process_count = submit_count_;
573 
574   return true;
575 }
576 
ProcessPendingQueries()577 bool QueryManager::ProcessPendingQueries() {
578   while (!pending_queries_.empty()) {
579     Query* query = pending_queries_.front().get();
580     if (!query->Process()) {
581       return false;
582     }
583     if (query->pending()) {
584       break;
585     }
586     query->RunCallbacks();
587     pending_queries_.pop_front();
588   }
589 
590   return true;
591 }
592 
HavePendingQueries()593 bool QueryManager::HavePendingQueries() {
594   return !pending_queries_.empty();
595 }
596 
ProcessPendingTransferQueries()597 bool QueryManager::ProcessPendingTransferQueries() {
598   while (!pending_transfer_queries_.empty()) {
599     Query* query = pending_transfer_queries_.front().get();
600     if (!query->Process()) {
601       return false;
602     }
603     if (query->pending()) {
604       break;
605     }
606     query->RunCallbacks();
607     pending_transfer_queries_.pop_front();
608   }
609 
610   return true;
611 }
612 
HavePendingTransferQueries()613 bool QueryManager::HavePendingTransferQueries() {
614   return !pending_transfer_queries_.empty();
615 }
616 
AddPendingQuery(Query * query,uint32 submit_count)617 bool QueryManager::AddPendingQuery(Query* query, uint32 submit_count) {
618   DCHECK(query);
619   DCHECK(!query->IsDeleted());
620   if (!RemovePendingQuery(query)) {
621     return false;
622   }
623   query->MarkAsPending(submit_count);
624   pending_queries_.push_back(query);
625   return true;
626 }
627 
AddPendingTransferQuery(Query * query,uint32 submit_count)628 bool QueryManager::AddPendingTransferQuery(Query* query, uint32 submit_count) {
629   DCHECK(query);
630   DCHECK(!query->IsDeleted());
631   if (!RemovePendingQuery(query)) {
632     return false;
633   }
634   query->MarkAsPending(submit_count);
635   pending_transfer_queries_.push_back(query);
636   return true;
637 }
638 
RemovePendingQuery(Query * query)639 bool QueryManager::RemovePendingQuery(Query* query) {
640   DCHECK(query);
641   if (query->pending()) {
642     // TODO(gman): Speed this up if this is a common operation. This would only
643     // happen if you do being/end begin/end on the same query without waiting
644     // for the first one to finish.
645     for (QueryQueue::iterator it = pending_queries_.begin();
646          it != pending_queries_.end(); ++it) {
647       if (it->get() == query) {
648         pending_queries_.erase(it);
649         break;
650       }
651     }
652     for (QueryQueue::iterator it = pending_transfer_queries_.begin();
653          it != pending_transfer_queries_.end(); ++it) {
654       if (it->get() == query) {
655         pending_transfer_queries_.erase(it);
656         break;
657       }
658     }
659     if (!query->MarkAsCompleted(0)) {
660       return false;
661     }
662   }
663   return true;
664 }
665 
BeginQuery(Query * query)666 bool QueryManager::BeginQuery(Query* query) {
667   DCHECK(query);
668   if (!RemovePendingQuery(query)) {
669     return false;
670   }
671   return query->Begin();
672 }
673 
EndQuery(Query * query,uint32 submit_count)674 bool QueryManager::EndQuery(Query* query, uint32 submit_count) {
675   DCHECK(query);
676   if (!RemovePendingQuery(query)) {
677     return false;
678   }
679   return query->End(submit_count);
680 }
681 
682 }  // namespace gles2
683 }  // namespace gpu
684