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