| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "gpu/command_buffer/service/query_manager.h" | 5 #include "gpu/command_buffer/service/query_manager.h" | 
| 6 #include "base/atomicops.h" | 6 #include "base/atomicops.h" | 
| 7 #include "base/logging.h" | 7 #include "base/logging.h" | 
|  | 8 #include "base/time.h" | 
| 8 #include "gpu/command_buffer/common/gles2_cmd_format.h" | 9 #include "gpu/command_buffer/common/gles2_cmd_format.h" | 
| 9 #include "gpu/command_buffer/service/common_decoder.h" | 10 #include "gpu/command_buffer/service/common_decoder.h" | 
| 10 | 11 | 
| 11 namespace gpu { | 12 namespace gpu { | 
| 12 namespace gles2 { | 13 namespace gles2 { | 
| 13 | 14 | 
| 14 QueryManager::QueryManager() | 15 class AllSamplesPassedQuery : public QueryManager::Query { | 
| 15     : query_count_(0) { | 16  public: | 
|  | 17   AllSamplesPassedQuery( | 
|  | 18       QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset, | 
|  | 19       GLuint service_id); | 
|  | 20   virtual ~AllSamplesPassedQuery(); | 
|  | 21   virtual bool Begin() OVERRIDE; | 
|  | 22   virtual bool End(uint32 submit_count) OVERRIDE; | 
|  | 23   virtual bool Process() OVERRIDE; | 
|  | 24   virtual void Destroy(bool have_context) OVERRIDE; | 
|  | 25 | 
|  | 26  private: | 
|  | 27   // Service side query id. | 
|  | 28   GLuint service_id_; | 
|  | 29 }; | 
|  | 30 | 
|  | 31 AllSamplesPassedQuery::AllSamplesPassedQuery( | 
|  | 32     QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset, | 
|  | 33     GLuint service_id) | 
|  | 34     : Query(manager, target, shm_id, shm_offset), | 
|  | 35       service_id_(service_id) { | 
|  | 36 } | 
|  | 37 | 
|  | 38 AllSamplesPassedQuery::~AllSamplesPassedQuery() { | 
|  | 39 } | 
|  | 40 | 
|  | 41 void AllSamplesPassedQuery::Destroy(bool have_context) { | 
|  | 42   if (have_context && !IsDeleted()) { | 
|  | 43     glDeleteQueriesARB(1, &service_id_); | 
|  | 44     MarkAsDeleted(); | 
|  | 45   } | 
|  | 46 } | 
|  | 47 | 
|  | 48 bool AllSamplesPassedQuery::Begin() { | 
|  | 49   BeginQueryHelper(target(), service_id_); | 
|  | 50   return true; | 
|  | 51 } | 
|  | 52 | 
|  | 53 bool AllSamplesPassedQuery::End(uint32 submit_count) { | 
|  | 54   EndQueryHelper(target()); | 
|  | 55   return AddToPendingQueue(submit_count); | 
|  | 56 } | 
|  | 57 | 
|  | 58 bool AllSamplesPassedQuery::Process() { | 
|  | 59   GLuint available = 0; | 
|  | 60   glGetQueryObjectuivARB( | 
|  | 61       service_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available); | 
|  | 62   if (!available) { | 
|  | 63     return true; | 
|  | 64   } | 
|  | 65   GLuint result = 0; | 
|  | 66   glGetQueryObjectuivARB( | 
|  | 67       service_id_, GL_QUERY_RESULT_EXT, &result); | 
|  | 68 | 
|  | 69   return MarkAsCompleted(result); | 
|  | 70 } | 
|  | 71 | 
|  | 72 class CommandsIssuedQuery : public QueryManager::Query { | 
|  | 73  public: | 
|  | 74   CommandsIssuedQuery( | 
|  | 75       QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset); | 
|  | 76   virtual ~CommandsIssuedQuery(); | 
|  | 77 | 
|  | 78   virtual bool Begin() OVERRIDE; | 
|  | 79   virtual bool End(uint32 submit_count) OVERRIDE; | 
|  | 80   virtual bool Process() OVERRIDE; | 
|  | 81   virtual void Destroy(bool have_context) OVERRIDE; | 
|  | 82 | 
|  | 83  private: | 
|  | 84   base::TimeTicks begin_time_; | 
|  | 85 }; | 
|  | 86 | 
|  | 87 CommandsIssuedQuery::CommandsIssuedQuery( | 
|  | 88       QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset) | 
|  | 89     : Query(manager, target, shm_id, shm_offset) { | 
|  | 90 } | 
|  | 91 | 
|  | 92 CommandsIssuedQuery::~CommandsIssuedQuery() { | 
|  | 93 } | 
|  | 94 | 
|  | 95 bool CommandsIssuedQuery::Process() { | 
|  | 96   NOTREACHED(); | 
|  | 97   return true; | 
|  | 98 } | 
|  | 99 | 
|  | 100 bool CommandsIssuedQuery::Begin() { | 
|  | 101   begin_time_ = base::TimeTicks::HighResNow(); | 
|  | 102   return true; | 
|  | 103 } | 
|  | 104 | 
|  | 105 bool CommandsIssuedQuery::End(uint32 submit_count) { | 
|  | 106   base::TimeDelta elapsed = base::TimeTicks::HighResNow() - begin_time_; | 
|  | 107   MarkAsPending(submit_count); | 
|  | 108   return MarkAsCompleted( | 
|  | 109       std::min(elapsed.InMicroseconds(), static_cast<int64>(0xFFFFFFFFL))); | 
|  | 110 } | 
|  | 111 | 
|  | 112 void CommandsIssuedQuery::Destroy(bool /* have_context */) { | 
|  | 113   if (!IsDeleted()) { | 
|  | 114     MarkAsDeleted(); | 
|  | 115   } | 
|  | 116 } | 
|  | 117 | 
|  | 118 QueryManager::QueryManager( | 
|  | 119     CommonDecoder* decoder, | 
|  | 120     bool use_arb_occlusion_query2_for_occlusion_query_boolean) | 
|  | 121     : decoder_(decoder), | 
|  | 122       use_arb_occlusion_query2_for_occlusion_query_boolean_( | 
|  | 123           use_arb_occlusion_query2_for_occlusion_query_boolean), | 
|  | 124       query_count_(0) { | 
| 16 } | 125 } | 
| 17 | 126 | 
| 18 QueryManager::~QueryManager() { | 127 QueryManager::~QueryManager() { | 
| 19   DCHECK(queries_.empty()); | 128   DCHECK(queries_.empty()); | 
| 20 | 129 | 
| 21   // If this triggers, that means something is keeping a reference to | 130   // If this triggers, that means something is keeping a reference to | 
| 22   // a Query belonging to this. | 131   // a Query belonging to this. | 
| 23   CHECK_EQ(query_count_, 0u); | 132   CHECK_EQ(query_count_, 0u); | 
| 24 } | 133 } | 
| 25 | 134 | 
| 26 void QueryManager::Destroy(bool have_context) { | 135 void QueryManager::Destroy(bool have_context) { | 
| 27   pending_queries_.clear(); | 136   pending_queries_.clear(); | 
| 28   while (!queries_.empty()) { | 137   while (!queries_.empty()) { | 
| 29     Query* query = queries_.begin()->second; | 138     Query* query = queries_.begin()->second; | 
| 30     if (have_context) { | 139     query->Destroy(have_context); | 
| 31       if (!query->IsDeleted()) { |  | 
| 32         GLuint service_id = query->service_id(); |  | 
| 33         glDeleteQueriesARB(1, &service_id); |  | 
| 34         query->MarkAsDeleted(); |  | 
| 35       } |  | 
| 36     } |  | 
| 37     queries_.erase(queries_.begin()); | 140     queries_.erase(queries_.begin()); | 
| 38   } | 141   } | 
| 39 } | 142 } | 
| 40 | 143 | 
| 41 QueryManager::Query* QueryManager::CreateQuery( | 144 QueryManager::Query* QueryManager::CreateQuery( | 
| 42     GLuint client_id, | 145     GLenum target, GLuint client_id, int32 shm_id, uint32 shm_offset) { | 
| 43     GLuint service_id) { | 146   Query::Ref query; | 
| 44   Query::Ref query(new Query(this, service_id)); | 147   switch (target) { | 
|  | 148     case GL_COMMANDS_ISSUED_CHROMIUM: | 
|  | 149       query = new CommandsIssuedQuery(this, target, shm_id, shm_offset); | 
|  | 150       break; | 
|  | 151     default: { | 
|  | 152       GLuint service_id = 0; | 
|  | 153       glGenQueriesARB(1, &service_id); | 
|  | 154       DCHECK_NE(0u, service_id); | 
|  | 155       query = new AllSamplesPassedQuery( | 
|  | 156           this, target, shm_id, shm_offset, service_id); | 
|  | 157       break; | 
|  | 158     } | 
|  | 159   } | 
| 45   std::pair<QueryMap::iterator, bool> result = | 160   std::pair<QueryMap::iterator, bool> result = | 
| 46       queries_.insert(std::make_pair(client_id, query)); | 161       queries_.insert(std::make_pair(client_id, query)); | 
| 47   DCHECK(result.second); | 162   DCHECK(result.second); | 
| 48   return query.get(); | 163   return query.get(); | 
| 49 } | 164 } | 
| 50 | 165 | 
| 51 QueryManager::Query* QueryManager::GetQuery( | 166 QueryManager::Query* QueryManager::GetQuery( | 
| 52     GLuint client_id) { | 167     GLuint client_id) { | 
| 53   QueryMap::iterator it = queries_.find(client_id); | 168   QueryMap::iterator it = queries_.find(client_id); | 
| 54   return it != queries_.end() ? it->second : NULL; | 169   return it != queries_.end() ? it->second : NULL; | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 65 } | 180 } | 
| 66 | 181 | 
| 67 void QueryManager::StartTracking(QueryManager::Query* /* query */) { | 182 void QueryManager::StartTracking(QueryManager::Query* /* query */) { | 
| 68   ++query_count_; | 183   ++query_count_; | 
| 69 } | 184 } | 
| 70 | 185 | 
| 71 void QueryManager::StopTracking(QueryManager::Query* /* query */) { | 186 void QueryManager::StopTracking(QueryManager::Query* /* query */) { | 
| 72   --query_count_; | 187   --query_count_; | 
| 73 } | 188 } | 
| 74 | 189 | 
|  | 190 void QueryManager::BeginQueryHelper(GLenum target, GLuint id) { | 
|  | 191   // ARB_occlusion_query2 does not have a GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT | 
|  | 192   // target. | 
|  | 193   if (use_arb_occlusion_query2_for_occlusion_query_boolean_) { | 
|  | 194     target = GL_ANY_SAMPLES_PASSED_EXT; | 
|  | 195   } | 
|  | 196   glBeginQueryARB(target, id); | 
|  | 197 } | 
|  | 198 | 
|  | 199 void QueryManager::EndQueryHelper(GLenum target) { | 
|  | 200   // ARB_occlusion_query2 does not have a GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT | 
|  | 201   // target. | 
|  | 202   if (use_arb_occlusion_query2_for_occlusion_query_boolean_) { | 
|  | 203     target = GL_ANY_SAMPLES_PASSED_EXT; | 
|  | 204   } | 
|  | 205   glEndQueryARB(target); | 
|  | 206 } | 
|  | 207 | 
| 75 QueryManager::Query::Query( | 208 QueryManager::Query::Query( | 
| 76      QueryManager* manager, | 209      QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset) | 
| 77      GLuint service_id) |  | 
| 78     : manager_(manager), | 210     : manager_(manager), | 
| 79       service_id_(service_id), | 211       target_(target), | 
| 80       target_(0), | 212       shm_id_(shm_id), | 
| 81       shm_id_(0), | 213       shm_offset_(shm_offset), | 
| 82       shm_offset_(0), |  | 
| 83       submit_count_(0), | 214       submit_count_(0), | 
| 84       pending_(false) { | 215       pending_(false), | 
|  | 216       deleted_(false) { | 
| 85   DCHECK(manager); | 217   DCHECK(manager); | 
| 86   manager_->StartTracking(this); | 218   manager_->StartTracking(this); | 
| 87 } | 219 } | 
| 88 | 220 | 
| 89 QueryManager::Query::~Query() { | 221 QueryManager::Query::~Query() { | 
| 90   if (manager_) { | 222   if (manager_) { | 
| 91     manager_->StopTracking(this); | 223     manager_->StopTracking(this); | 
| 92     manager_ = NULL; | 224     manager_ = NULL; | 
| 93   } | 225   } | 
| 94 } | 226 } | 
| 95 | 227 | 
| 96 void QueryManager::Query::Initialize( | 228 bool QueryManager::Query::MarkAsCompleted(GLuint result) { | 
| 97     GLenum target, int32 shm_id, uint32 shm_offset) { | 229   DCHECK(pending_); | 
| 98   DCHECK(!IsInitialized()); | 230   QuerySync* sync = manager_->decoder_->GetSharedMemoryAs<QuerySync*>( | 
| 99   target_ = target; | 231           shm_id_, shm_offset_, sizeof(*sync)); | 
| 100   shm_id_ = shm_id; | 232   if (!sync) { | 
| 101   shm_offset_ = shm_offset; | 233     return false; | 
|  | 234   } | 
|  | 235 | 
|  | 236   pending_ = false; | 
|  | 237   sync->result = result; | 
|  | 238   // Need a MemoryBarrier here so that sync->result is written before | 
|  | 239   // sync->process_count. | 
|  | 240   base::subtle::MemoryBarrier(); | 
|  | 241   sync->process_count = submit_count_; | 
|  | 242 | 
|  | 243   return true; | 
| 102 } | 244 } | 
| 103 | 245 | 
| 104 bool QueryManager::GetClientId(GLuint service_id, GLuint* client_id) const { | 246 bool QueryManager::ProcessPendingQueries() { | 
| 105   DCHECK(client_id); | 247   while (!pending_queries_.empty()) { | 
| 106   // This doesn't need to be fast. It's only used during slow queries. | 248     Query* query = pending_queries_.front().get(); | 
| 107   for (QueryMap::const_iterator it = queries_.begin(); | 249     if (!query->Process()) { | 
| 108        it != queries_.end(); ++it) { | 250       return false; | 
| 109     if (it->second->service_id() == service_id) { | 251     } | 
| 110       *client_id = it->first; | 252     if (query->pending()) { | 
| 111       return true; | 253       return true; | 
| 112     } | 254     } | 
| 113   } |  | 
| 114   return false; |  | 
| 115 } |  | 
| 116 |  | 
| 117 bool QueryManager::ProcessPendingQueries(CommonDecoder* decoder) { |  | 
| 118   DCHECK(decoder); |  | 
| 119   while (!pending_queries_.empty()) { |  | 
| 120     Query* query = pending_queries_.front().get(); |  | 
| 121     GLuint available = 0; |  | 
| 122     glGetQueryObjectuivARB( |  | 
| 123         query->service_id(), GL_QUERY_RESULT_AVAILABLE_EXT, &available); |  | 
| 124     if (!available) { |  | 
| 125       return true; |  | 
| 126     } |  | 
| 127     GLuint result = 0; |  | 
| 128     glGetQueryObjectuivARB( |  | 
| 129         query->service_id(), GL_QUERY_RESULT_EXT, &result); |  | 
| 130     QuerySync* sync = decoder->GetSharedMemoryAs<QuerySync*>( |  | 
| 131             query->shm_id(), query->shm_offset(), sizeof(*sync)); |  | 
| 132     if (!sync) { |  | 
| 133       return false; |  | 
| 134     } |  | 
| 135 |  | 
| 136     sync->result = result; |  | 
| 137     // Need a MemoryBarrier here so that sync->result is written before |  | 
| 138     // sync->process_count. |  | 
| 139     base::subtle::MemoryBarrier(); |  | 
| 140     sync->process_count = query->submit_count(); |  | 
| 141 |  | 
| 142     query->MarkAsCompleted(); |  | 
| 143     pending_queries_.pop_front(); | 255     pending_queries_.pop_front(); | 
| 144   } | 256   } | 
| 145 | 257 | 
| 146   return true; | 258   return true; | 
| 147 } | 259 } | 
| 148 | 260 | 
| 149 bool QueryManager::HavePendingQueries() { | 261 bool QueryManager::HavePendingQueries() { | 
| 150   return !pending_queries_.empty(); | 262   return !pending_queries_.empty(); | 
| 151 } | 263 } | 
| 152 | 264 | 
| 153 void QueryManager::AddPendingQuery(Query* query, uint32 submit_count) { | 265 bool QueryManager::AddPendingQuery(Query* query, uint32 submit_count) { | 
| 154   DCHECK(query); | 266   DCHECK(query); | 
| 155   DCHECK(query->IsInitialized()); |  | 
| 156   DCHECK(!query->IsDeleted()); | 267   DCHECK(!query->IsDeleted()); | 
| 157   RemovePendingQuery(query); | 268   if (!RemovePendingQuery(query)) { | 
|  | 269     return false; | 
|  | 270   } | 
| 158   query->MarkAsPending(submit_count); | 271   query->MarkAsPending(submit_count); | 
| 159   pending_queries_.push_back(query); | 272   pending_queries_.push_back(query); | 
|  | 273   return true; | 
| 160 } | 274 } | 
| 161 | 275 | 
| 162 void QueryManager::RemovePendingQuery(Query* query) { | 276 bool QueryManager::RemovePendingQuery(Query* query) { | 
| 163   DCHECK(query); | 277   DCHECK(query); | 
| 164   if (query->pending()) { | 278   if (query->pending()) { | 
| 165     // TODO(gman): Speed this up if this is a common operation. This would only | 279     // TODO(gman): Speed this up if this is a common operation. This would only | 
| 166     // happen if you do being/end begin/end on the same query without waiting | 280     // happen if you do being/end begin/end on the same query without waiting | 
| 167     // for the first one to finish. | 281     // for the first one to finish. | 
| 168     for (QueryQueue::iterator it = pending_queries_.begin(); | 282     for (QueryQueue::iterator it = pending_queries_.begin(); | 
| 169          it != pending_queries_.end(); ++it) { | 283          it != pending_queries_.end(); ++it) { | 
| 170       if (it->get() == query) { | 284       if (it->get() == query) { | 
| 171         pending_queries_.erase(it); | 285         pending_queries_.erase(it); | 
| 172         break; | 286         break; | 
| 173       } | 287       } | 
| 174     } | 288     } | 
| 175     query->MarkAsCompleted(); | 289     if (!query->MarkAsCompleted(0)) { | 
|  | 290       return false; | 
|  | 291     } | 
| 176   } | 292   } | 
|  | 293   return true; | 
|  | 294 } | 
|  | 295 | 
|  | 296 bool QueryManager::BeginQuery(Query* query) { | 
|  | 297   DCHECK(query); | 
|  | 298   if (!RemovePendingQuery(query)) { | 
|  | 299     return false; | 
|  | 300   } | 
|  | 301   return query->Begin(); | 
|  | 302 } | 
|  | 303 | 
|  | 304 bool QueryManager::EndQuery(Query* query, uint32 submit_count) { | 
|  | 305   DCHECK(query); | 
|  | 306   if (!RemovePendingQuery(query)) { | 
|  | 307     return false; | 
|  | 308   } | 
|  | 309   return query->End(submit_count); | 
| 177 } | 310 } | 
| 178 | 311 | 
| 179 }  // namespace gles2 | 312 }  // namespace gles2 | 
| 180 }  // namespace gpu | 313 }  // namespace gpu | 
| 181 | 314 | 
| 182 | 315 | 
| OLD | NEW | 
|---|