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