summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service/query_manager.cc
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-08 19:02:53 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-08 19:02:53 +0000
commit882ba1e272371308cfecfb5436eb5dec0ee0cea5 (patch)
tree4bc2e0a9ad3f557a693252c9057831fac3cdd130 /gpu/command_buffer/service/query_manager.cc
parentda20ec411725ebed3aaffab88095b2201a9511fe (diff)
downloadchromium_src-882ba1e272371308cfecfb5436eb5dec0ee0cea5.zip
chromium_src-882ba1e272371308cfecfb5436eb5dec0ee0cea5.tar.gz
chromium_src-882ba1e272371308cfecfb5436eb5dec0ee0cea5.tar.bz2
Add support for GL_EXT_occlusion_query_boolean
TEST=unit tests BUG=88601 Review URL: http://codereview.chromium.org/9555011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@125649 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer/service/query_manager.cc')
-rw-r--r--gpu/command_buffer/service/query_manager.cc177
1 files changed, 177 insertions, 0 deletions
diff --git a/gpu/command_buffer/service/query_manager.cc b/gpu/command_buffer/service/query_manager.cc
new file mode 100644
index 0000000..08cecea
--- /dev/null
+++ b/gpu/command_buffer/service/query_manager.cc
@@ -0,0 +1,177 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/service/query_manager.h"
+#include "base/atomicops.h"
+#include "base/logging.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) {
+}
+
+QueryManager::~QueryManager() {
+ DCHECK(queries_.empty());
+
+ // If this triggers, that means something is keeping a reference to
+ // a Query belonging to this.
+ CHECK_EQ(query_count_, 0u);
+}
+
+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();
+ }
+ }
+ queries_.erase(queries_.begin());
+ }
+}
+
+QueryManager::Query* QueryManager::CreateQuery(
+ GLuint client_id,
+ GLuint service_id) {
+ Query::Ref query(new Query(this, service_id));
+ std::pair<QueryMap::iterator, bool> result =
+ queries_.insert(std::make_pair(client_id, query));
+ DCHECK(result.second);
+ return query.get();
+}
+
+QueryManager::Query* QueryManager::GetQuery(
+ GLuint client_id) {
+ QueryMap::iterator it = queries_.find(client_id);
+ return it != queries_.end() ? it->second : NULL;
+}
+
+void QueryManager::RemoveQuery(GLuint client_id) {
+ QueryMap::iterator it = queries_.find(client_id);
+ if (it != queries_.end()) {
+ Query* query = it->second;
+ RemovePendingQuery(query);
+ query->MarkAsDeleted();
+ queries_.erase(it);
+ }
+}
+
+void QueryManager::StartTracking(QueryManager::Query* /* query */) {
+ ++query_count_;
+}
+
+void QueryManager::StopTracking(QueryManager::Query* /* query */) {
+ --query_count_;
+}
+
+QueryManager::Query::Query(
+ QueryManager* manager,
+ GLuint service_id)
+ : manager_(manager),
+ service_id_(service_id),
+ target_(0),
+ shm_id_(0),
+ shm_offset_(0),
+ pending_(false) {
+ DCHECK(manager);
+ manager_->StartTracking(this);
+}
+
+QueryManager::Query::~Query() {
+ if (manager_) {
+ manager_->StopTracking(this);
+ manager_ = NULL;
+ }
+}
+
+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;
+ }
+ }
+ return false;
+}
+
+bool QueryManager::ProcessPendingQueries(CommonDecoder* decoder) {
+ DCHECK(decoder);
+ 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) {
+ 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();
+ pending_queries_.pop_front();
+ }
+
+ return true;
+}
+
+void QueryManager::AddPendingQuery(Query* query, uint32 submit_count) {
+ DCHECK(query);
+ DCHECK(query->IsInitialized());
+ DCHECK(!query->IsDeleted());
+ RemovePendingQuery(query);
+ query->MarkAsPending(submit_count);
+ pending_queries_.push_back(query);
+}
+
+void QueryManager::RemovePendingQuery(Query* query) {
+ DCHECK(query);
+ if (query->pending()) {
+ // TODO(gman): Speed this up if this is a common operation. This would only
+ // happen if you do being/end begin/end on the same query without waiting
+ // for the first one to finish.
+ for (QueryQueue::iterator it = pending_queries_.begin();
+ it != pending_queries_.end(); ++it) {
+ if (it->get() == query) {
+ pending_queries_.erase(it);
+ break;
+ }
+ }
+ query->MarkAsCompleted();
+ }
+}
+
+} // namespace gles2
+} // namespace gpu
+
+