Index: gpu/command_buffer/service/query_manager.cc |
diff --git a/gpu/command_buffer/service/query_manager.cc b/gpu/command_buffer/service/query_manager.cc |
index baad7f66f9c440743cf42ffcde90df828c1cae9f..c8f06a3e35ebb6551d5e8041e2373ffe9da04ede 100644 |
--- a/gpu/command_buffer/service/query_manager.cc |
+++ b/gpu/command_buffer/service/query_manager.cc |
@@ -5,14 +5,123 @@ |
#include "gpu/command_buffer/service/query_manager.h" |
#include "base/atomicops.h" |
#include "base/logging.h" |
+#include "base/time.h" |
#include "gpu/command_buffer/common/gles2_cmd_format.h" |
#include "gpu/command_buffer/service/common_decoder.h" |
namespace gpu { |
namespace gles2 { |
-QueryManager::QueryManager() |
- : query_count_(0) { |
+class AllSamplesPassedQuery : public QueryManager::Query { |
+ public: |
+ AllSamplesPassedQuery( |
+ QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset, |
+ GLuint service_id); |
+ virtual ~AllSamplesPassedQuery(); |
+ virtual bool Begin() OVERRIDE; |
+ virtual bool End(uint32 submit_count) OVERRIDE; |
+ virtual bool Process() OVERRIDE; |
+ virtual void Destroy(bool have_context) OVERRIDE; |
+ |
+ private: |
+ // Service side query id. |
+ GLuint service_id_; |
+}; |
+ |
+AllSamplesPassedQuery::AllSamplesPassedQuery( |
+ QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset, |
+ GLuint service_id) |
+ : Query(manager, target, shm_id, shm_offset), |
+ service_id_(service_id) { |
+} |
+ |
+AllSamplesPassedQuery::~AllSamplesPassedQuery() { |
+} |
+ |
+void AllSamplesPassedQuery::Destroy(bool have_context) { |
+ if (have_context && !IsDeleted()) { |
+ glDeleteQueriesARB(1, &service_id_); |
+ MarkAsDeleted(); |
+ } |
+} |
+ |
+bool AllSamplesPassedQuery::Begin() { |
+ BeginQueryHelper(target(), service_id_); |
+ return true; |
+} |
+ |
+bool AllSamplesPassedQuery::End(uint32 submit_count) { |
+ EndQueryHelper(target()); |
+ return AddToPendingQueue(submit_count); |
+} |
+ |
+bool AllSamplesPassedQuery::Process() { |
+ GLuint available = 0; |
+ glGetQueryObjectuivARB( |
+ service_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available); |
+ if (!available) { |
+ return true; |
+ } |
+ GLuint result = 0; |
+ glGetQueryObjectuivARB( |
+ service_id_, GL_QUERY_RESULT_EXT, &result); |
+ |
+ return MarkAsCompleted(result); |
+} |
+ |
+class CommandsIssuedQuery : public QueryManager::Query { |
+ public: |
+ CommandsIssuedQuery( |
+ QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset); |
+ virtual ~CommandsIssuedQuery(); |
+ |
+ virtual bool Begin() OVERRIDE; |
+ virtual bool End(uint32 submit_count) OVERRIDE; |
+ virtual bool Process() OVERRIDE; |
+ virtual void Destroy(bool have_context) OVERRIDE; |
+ |
+ private: |
+ base::TimeTicks begin_time_; |
+}; |
+ |
+CommandsIssuedQuery::CommandsIssuedQuery( |
+ QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset) |
+ : Query(manager, target, shm_id, shm_offset) { |
+} |
+ |
+CommandsIssuedQuery::~CommandsIssuedQuery() { |
+} |
+ |
+bool CommandsIssuedQuery::Process() { |
+ NOTREACHED(); |
+ return true; |
+} |
+ |
+bool CommandsIssuedQuery::Begin() { |
+ begin_time_ = base::TimeTicks::HighResNow(); |
+ return true; |
+} |
+ |
+bool CommandsIssuedQuery::End(uint32 submit_count) { |
+ base::TimeDelta elapsed = base::TimeTicks::HighResNow() - begin_time_; |
+ MarkAsPending(submit_count); |
+ return MarkAsCompleted( |
+ std::min(elapsed.InMicroseconds(), static_cast<int64>(0xFFFFFFFFL))); |
+} |
+ |
+void CommandsIssuedQuery::Destroy(bool /* have_context */) { |
+ if (!IsDeleted()) { |
+ MarkAsDeleted(); |
+ } |
+} |
+ |
+QueryManager::QueryManager( |
+ CommonDecoder* decoder, |
+ bool use_arb_occlusion_query2_for_occlusion_query_boolean) |
+ : decoder_(decoder), |
+ use_arb_occlusion_query2_for_occlusion_query_boolean_( |
+ use_arb_occlusion_query2_for_occlusion_query_boolean), |
+ query_count_(0) { |
} |
QueryManager::~QueryManager() { |
@@ -27,21 +136,27 @@ void QueryManager::Destroy(bool have_context) { |
pending_queries_.clear(); |
while (!queries_.empty()) { |
Query* query = queries_.begin()->second; |
- if (have_context) { |
- if (!query->IsDeleted()) { |
- GLuint service_id = query->service_id(); |
- glDeleteQueriesARB(1, &service_id); |
- query->MarkAsDeleted(); |
- } |
- } |
+ query->Destroy(have_context); |
queries_.erase(queries_.begin()); |
} |
} |
QueryManager::Query* QueryManager::CreateQuery( |
- GLuint client_id, |
- GLuint service_id) { |
- Query::Ref query(new Query(this, service_id)); |
+ GLenum target, GLuint client_id, int32 shm_id, uint32 shm_offset) { |
+ Query::Ref query; |
+ switch (target) { |
+ case GL_COMMANDS_ISSUED_CHROMIUM: |
+ query = new CommandsIssuedQuery(this, target, shm_id, shm_offset); |
+ break; |
+ default: { |
+ GLuint service_id = 0; |
+ glGenQueriesARB(1, &service_id); |
+ DCHECK_NE(0u, service_id); |
+ query = new AllSamplesPassedQuery( |
+ this, target, shm_id, shm_offset, service_id); |
+ break; |
+ } |
+ } |
std::pair<QueryMap::iterator, bool> result = |
queries_.insert(std::make_pair(client_id, query)); |
DCHECK(result.second); |
@@ -72,16 +187,33 @@ void QueryManager::StopTracking(QueryManager::Query* /* query */) { |
--query_count_; |
} |
+void QueryManager::BeginQueryHelper(GLenum target, GLuint id) { |
+ // ARB_occlusion_query2 does not have a GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT |
+ // target. |
+ if (use_arb_occlusion_query2_for_occlusion_query_boolean_) { |
+ target = GL_ANY_SAMPLES_PASSED_EXT; |
+ } |
+ glBeginQueryARB(target, id); |
+} |
+ |
+void QueryManager::EndQueryHelper(GLenum target) { |
+ // ARB_occlusion_query2 does not have a GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT |
+ // target. |
+ if (use_arb_occlusion_query2_for_occlusion_query_boolean_) { |
+ target = GL_ANY_SAMPLES_PASSED_EXT; |
+ } |
+ glEndQueryARB(target); |
+} |
+ |
QueryManager::Query::Query( |
- QueryManager* manager, |
- GLuint service_id) |
+ QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset) |
: manager_(manager), |
- service_id_(service_id), |
- target_(0), |
- shm_id_(0), |
- shm_offset_(0), |
+ target_(target), |
+ shm_id_(shm_id), |
+ shm_offset_(shm_offset), |
submit_count_(0), |
- pending_(false) { |
+ pending_(false), |
+ deleted_(false) { |
DCHECK(manager); |
manager_->StartTracking(this); |
} |
@@ -93,53 +225,33 @@ QueryManager::Query::~Query() { |
} |
} |
-void QueryManager::Query::Initialize( |
- GLenum target, int32 shm_id, uint32 shm_offset) { |
- DCHECK(!IsInitialized()); |
- target_ = target; |
- shm_id_ = shm_id; |
- shm_offset_ = shm_offset; |
-} |
- |
-bool QueryManager::GetClientId(GLuint service_id, GLuint* client_id) const { |
- DCHECK(client_id); |
- // This doesn't need to be fast. It's only used during slow queries. |
- for (QueryMap::const_iterator it = queries_.begin(); |
- it != queries_.end(); ++it) { |
- if (it->second->service_id() == service_id) { |
- *client_id = it->first; |
- return true; |
- } |
+bool QueryManager::Query::MarkAsCompleted(GLuint result) { |
+ DCHECK(pending_); |
+ QuerySync* sync = manager_->decoder_->GetSharedMemoryAs<QuerySync*>( |
+ shm_id_, shm_offset_, sizeof(*sync)); |
+ if (!sync) { |
+ return false; |
} |
- return false; |
+ |
+ pending_ = false; |
+ sync->result = result; |
+ // Need a MemoryBarrier here so that sync->result is written before |
+ // sync->process_count. |
+ base::subtle::MemoryBarrier(); |
+ sync->process_count = submit_count_; |
+ |
+ return true; |
} |
-bool QueryManager::ProcessPendingQueries(CommonDecoder* decoder) { |
- DCHECK(decoder); |
+bool QueryManager::ProcessPendingQueries() { |
while (!pending_queries_.empty()) { |
Query* query = pending_queries_.front().get(); |
- GLuint available = 0; |
- glGetQueryObjectuivARB( |
- query->service_id(), GL_QUERY_RESULT_AVAILABLE_EXT, &available); |
- if (!available) { |
- return true; |
- } |
- GLuint result = 0; |
- glGetQueryObjectuivARB( |
- query->service_id(), GL_QUERY_RESULT_EXT, &result); |
- QuerySync* sync = decoder->GetSharedMemoryAs<QuerySync*>( |
- query->shm_id(), query->shm_offset(), sizeof(*sync)); |
- if (!sync) { |
+ if (!query->Process()) { |
return false; |
} |
- |
- sync->result = result; |
- // Need a MemoryBarrier here so that sync->result is written before |
- // sync->process_count. |
- base::subtle::MemoryBarrier(); |
- sync->process_count = query->submit_count(); |
- |
- query->MarkAsCompleted(); |
+ if (query->pending()) { |
+ return true; |
+ } |
pending_queries_.pop_front(); |
} |
@@ -150,16 +262,18 @@ bool QueryManager::HavePendingQueries() { |
return !pending_queries_.empty(); |
} |
-void QueryManager::AddPendingQuery(Query* query, uint32 submit_count) { |
+bool QueryManager::AddPendingQuery(Query* query, uint32 submit_count) { |
DCHECK(query); |
- DCHECK(query->IsInitialized()); |
DCHECK(!query->IsDeleted()); |
- RemovePendingQuery(query); |
+ if (!RemovePendingQuery(query)) { |
+ return false; |
+ } |
query->MarkAsPending(submit_count); |
pending_queries_.push_back(query); |
+ return true; |
} |
-void QueryManager::RemovePendingQuery(Query* query) { |
+bool QueryManager::RemovePendingQuery(Query* query) { |
DCHECK(query); |
if (query->pending()) { |
// TODO(gman): Speed this up if this is a common operation. This would only |
@@ -172,8 +286,27 @@ void QueryManager::RemovePendingQuery(Query* query) { |
break; |
} |
} |
- query->MarkAsCompleted(); |
+ if (!query->MarkAsCompleted(0)) { |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
+bool QueryManager::BeginQuery(Query* query) { |
+ DCHECK(query); |
+ if (!RemovePendingQuery(query)) { |
+ return false; |
+ } |
+ return query->Begin(); |
+} |
+ |
+bool QueryManager::EndQuery(Query* query, uint32 submit_count) { |
+ DCHECK(query); |
+ if (!RemovePendingQuery(query)) { |
+ return false; |
} |
+ return query->End(submit_count); |
} |
} // namespace gles2 |