diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-08 19:02:53 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-08 19:02:53 +0000 |
commit | 882ba1e272371308cfecfb5436eb5dec0ee0cea5 (patch) | |
tree | 4bc2e0a9ad3f557a693252c9057831fac3cdd130 /gpu/command_buffer/service/query_manager.cc | |
parent | da20ec411725ebed3aaffab88095b2201a9511fe (diff) | |
download | chromium_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.cc | 177 |
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 + + |