summaryrefslogtreecommitdiffstats
path: root/chromium/gpu/command_buffer/service/query_manager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/gpu/command_buffer/service/query_manager.cc')
-rw-r--r--chromium/gpu/command_buffer/service/query_manager.cc156
1 files changed, 110 insertions, 46 deletions
diff --git a/chromium/gpu/command_buffer/service/query_manager.cc b/chromium/gpu/command_buffer/service/query_manager.cc
index db508e0a7f7..ffb54cca514 100644
--- a/chromium/gpu/command_buffer/service/query_manager.cc
+++ b/chromium/gpu/command_buffer/service/query_manager.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/shared_memory.h"
+#include "base/numerics/safe_math.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "gpu/command_buffer/common/gles2_cmd_format.h"
@@ -15,6 +16,7 @@
#include "gpu/command_buffer/service/error_state.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "ui/gl/gl_fence.h"
namespace gpu {
namespace gles2 {
@@ -24,9 +26,8 @@ namespace {
class AsyncPixelTransferCompletionObserverImpl
: public AsyncPixelTransferCompletionObserver {
public:
- AsyncPixelTransferCompletionObserverImpl(uint32 submit_count)
- : submit_count_(submit_count),
- cancelled_(false) {}
+ AsyncPixelTransferCompletionObserverImpl(base::subtle::Atomic32 submit_count)
+ : submit_count_(submit_count), cancelled_(false) {}
void Cancel() {
base::AutoLock locked(lock_);
@@ -36,23 +37,17 @@ class AsyncPixelTransferCompletionObserverImpl
virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE {
base::AutoLock locked(lock_);
if (!cancelled_) {
- DCHECK(mem_params.shared_memory);
- DCHECK(mem_params.shared_memory->memory());
- void* data = static_cast<int8*>(mem_params.shared_memory->memory()) +
- mem_params.shm_data_offset;
+ DCHECK(mem_params.buffer());
+ void* data = mem_params.GetDataAddress();
QuerySync* sync = static_cast<QuerySync*>(data);
-
- // Need a MemoryBarrier here to ensure that upload completed before
- // submit_count was written to sync->process_count.
- base::subtle::MemoryBarrier();
- sync->process_count = submit_count_;
+ base::subtle::Release_Store(&sync->process_count, submit_count_);
}
}
private:
virtual ~AsyncPixelTransferCompletionObserverImpl() {}
- uint32 submit_count_;
+ base::subtle::Atomic32 submit_count_;
base::Lock lock_;
bool cancelled_;
@@ -68,7 +63,7 @@ class AsyncPixelTransfersCompletedQuery
QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset);
virtual bool Begin() OVERRIDE;
- virtual bool End(uint32 submit_count) OVERRIDE;
+ virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE;
virtual bool Process() OVERRIDE;
virtual void Destroy(bool have_context) OVERRIDE;
@@ -87,19 +82,16 @@ bool AsyncPixelTransfersCompletedQuery::Begin() {
return true;
}
-bool AsyncPixelTransfersCompletedQuery::End(uint32 submit_count) {
- AsyncMemoryParams mem_params;
+bool AsyncPixelTransfersCompletedQuery::End(
+ base::subtle::Atomic32 submit_count) {
// Get the real shared memory since it might need to be duped to prevent
// use-after-free of the memory.
- Buffer buffer = manager()->decoder()->GetSharedMemoryBuffer(shm_id());
- if (!buffer.shared_memory)
+ scoped_refptr<Buffer> buffer =
+ manager()->decoder()->GetSharedMemoryBuffer(shm_id());
+ if (!buffer)
return false;
- mem_params.shared_memory = buffer.shared_memory;
- mem_params.shm_size = buffer.size;
- mem_params.shm_data_offset = shm_offset();
- mem_params.shm_data_size = sizeof(QuerySync);
- uint32 end = mem_params.shm_data_offset + mem_params.shm_data_size;
- if (end > mem_params.shm_size || end < mem_params.shm_data_offset)
+ AsyncMemoryParams mem_params(buffer, shm_offset(), sizeof(QuerySync));
+ if (!mem_params.GetDataAddress())
return false;
observer_ = new AsyncPixelTransferCompletionObserverImpl(submit_count);
@@ -122,7 +114,7 @@ bool AsyncPixelTransfersCompletedQuery::Process() {
// Check if completion callback has been run. sync->process_count atomicity
// is guaranteed as this is already used to notify client of a completed
// query.
- if (sync->process_count != submit_count())
+ if (base::subtle::Acquire_Load(&sync->process_count) != submit_count())
return true;
UnmarkAsPending();
@@ -148,7 +140,7 @@ class AllSamplesPassedQuery : public QueryManager::Query {
QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset,
GLuint service_id);
virtual bool Begin() OVERRIDE;
- virtual bool End(uint32 submit_count) OVERRIDE;
+ virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE;
virtual bool Process() OVERRIDE;
virtual void Destroy(bool have_context) OVERRIDE;
@@ -172,7 +164,7 @@ bool AllSamplesPassedQuery::Begin() {
return true;
}
-bool AllSamplesPassedQuery::End(uint32 submit_count) {
+bool AllSamplesPassedQuery::End(base::subtle::Atomic32 submit_count) {
EndQueryHelper(target());
return AddToPendingQueue(submit_count);
}
@@ -207,7 +199,7 @@ class CommandsIssuedQuery : public QueryManager::Query {
QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset);
virtual bool Begin() OVERRIDE;
- virtual bool End(uint32 submit_count) OVERRIDE;
+ virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE;
virtual bool Process() OVERRIDE;
virtual void Destroy(bool have_context) OVERRIDE;
@@ -228,7 +220,7 @@ bool CommandsIssuedQuery::Begin() {
return true;
}
-bool CommandsIssuedQuery::End(uint32 submit_count) {
+bool CommandsIssuedQuery::End(base::subtle::Atomic32 submit_count) {
base::TimeDelta elapsed = base::TimeTicks::HighResNow() - begin_time_;
MarkAsPending(submit_count);
return MarkAsCompleted(elapsed.InMicroseconds());
@@ -254,7 +246,7 @@ class CommandLatencyQuery : public QueryManager::Query {
QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset);
virtual bool Begin() OVERRIDE;
- virtual bool End(uint32 submit_count) OVERRIDE;
+ virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE;
virtual bool Process() OVERRIDE;
virtual void Destroy(bool have_context) OVERRIDE;
@@ -271,7 +263,7 @@ bool CommandLatencyQuery::Begin() {
return true;
}
-bool CommandLatencyQuery::End(uint32 submit_count) {
+bool CommandLatencyQuery::End(base::subtle::Atomic32 submit_count) {
base::TimeDelta now = base::TimeTicks::HighResNow() - base::TimeTicks();
MarkAsPending(submit_count);
return MarkAsCompleted(now.InMicroseconds());
@@ -300,25 +292,31 @@ class AsyncReadPixelsCompletedQuery
QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset);
virtual bool Begin() OVERRIDE;
- virtual bool End(uint32 submit_count) OVERRIDE;
+ virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE;
virtual bool Process() OVERRIDE;
virtual void Destroy(bool have_context) OVERRIDE;
protected:
void Complete();
virtual ~AsyncReadPixelsCompletedQuery();
+
+ private:
+ bool completed_;
+ bool complete_result_;
};
AsyncReadPixelsCompletedQuery::AsyncReadPixelsCompletedQuery(
QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset)
- : Query(manager, target, shm_id, shm_offset) {
+ : Query(manager, target, shm_id, shm_offset),
+ completed_(false),
+ complete_result_(false) {
}
bool AsyncReadPixelsCompletedQuery::Begin() {
return true;
}
-bool AsyncReadPixelsCompletedQuery::End(uint32 submit_count) {
+bool AsyncReadPixelsCompletedQuery::End(base::subtle::Atomic32 submit_count) {
if (!AddToPendingQueue(submit_count)) {
return false;
}
@@ -326,15 +324,16 @@ bool AsyncReadPixelsCompletedQuery::End(uint32 submit_count) {
base::Bind(&AsyncReadPixelsCompletedQuery::Complete,
AsWeakPtr()));
- return true;
+ return Process();
}
void AsyncReadPixelsCompletedQuery::Complete() {
- MarkAsCompleted(1);
+ completed_ = true;
+ complete_result_ = MarkAsCompleted(1);
}
bool AsyncReadPixelsCompletedQuery::Process() {
- return true;
+ return !completed_ || complete_result_;
}
void AsyncReadPixelsCompletedQuery::Destroy(bool /* have_context */) {
@@ -353,7 +352,7 @@ class GetErrorQuery : public QueryManager::Query {
QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset);
virtual bool Begin() OVERRIDE;
- virtual bool End(uint32 submit_count) OVERRIDE;
+ virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE;
virtual bool Process() OVERRIDE;
virtual void Destroy(bool have_context) OVERRIDE;
@@ -372,7 +371,7 @@ bool GetErrorQuery::Begin() {
return true;
}
-bool GetErrorQuery::End(uint32 submit_count) {
+bool GetErrorQuery::End(base::subtle::Atomic32 submit_count) {
MarkAsPending(submit_count);
return MarkAsCompleted(manager()->decoder()->GetErrorState()->GetGLError());
}
@@ -391,6 +390,55 @@ void GetErrorQuery::Destroy(bool /* have_context */) {
GetErrorQuery::~GetErrorQuery() {
}
+class CommandsCompletedQuery : public QueryManager::Query {
+ public:
+ CommandsCompletedQuery(QueryManager* manager,
+ GLenum target,
+ int32 shm_id,
+ uint32 shm_offset);
+
+ // Overridden from QueryManager::Query:
+ virtual bool Begin() OVERRIDE;
+ virtual bool End(base::subtle::Atomic32 submit_count) OVERRIDE;
+ virtual bool Process() OVERRIDE;
+ virtual void Destroy(bool have_context) OVERRIDE;
+
+ protected:
+ virtual ~CommandsCompletedQuery();
+
+ private:
+ scoped_ptr<gfx::GLFence> fence_;
+};
+
+CommandsCompletedQuery::CommandsCompletedQuery(QueryManager* manager,
+ GLenum target,
+ int32 shm_id,
+ uint32 shm_offset)
+ : Query(manager, target, shm_id, shm_offset) {}
+
+bool CommandsCompletedQuery::Begin() { return true; }
+
+bool CommandsCompletedQuery::End(base::subtle::Atomic32 submit_count) {
+ fence_.reset(gfx::GLFence::Create());
+ DCHECK(fence_);
+ return AddToPendingQueue(submit_count);
+}
+
+bool CommandsCompletedQuery::Process() {
+ if (fence_ && !fence_->HasCompleted())
+ return true;
+ return MarkAsCompleted(0);
+}
+
+void CommandsCompletedQuery::Destroy(bool have_context) {
+ if (have_context && !IsDeleted()) {
+ fence_.reset();
+ MarkAsDeleted();
+ }
+}
+
+CommandsCompletedQuery::~CommandsCompletedQuery() {}
+
QueryManager::QueryManager(
GLES2Decoder* decoder,
FeatureInfo* feature_info)
@@ -446,6 +494,9 @@ QueryManager::Query* QueryManager::CreateQuery(
case GL_GET_ERROR_QUERY_CHROMIUM:
query = new GetErrorQuery(this, target, shm_id, shm_offset);
break;
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ query = new CommandsCompletedQuery(this, target, shm_id, shm_offset);
+ break;
default: {
GLuint service_id = 0;
glGenQueriesARB(1, &service_id);
@@ -461,6 +512,18 @@ QueryManager::Query* QueryManager::CreateQuery(
return query.get();
}
+void QueryManager::GenQueries(GLsizei n, const GLuint* queries) {
+ DCHECK_GE(n, 0);
+ for (GLsizei i = 0; i < n; ++i) {
+ generated_query_ids_.insert(queries[i]);
+ }
+}
+
+bool QueryManager::IsValidQuery(GLuint id) {
+ GeneratedQueryIds::iterator it = generated_query_ids_.find(id);
+ return it != generated_query_ids_.end();
+}
+
QueryManager::Query* QueryManager::GetQuery(
GLuint client_id) {
QueryMap::iterator it = queries_.find(client_id);
@@ -475,6 +538,7 @@ void QueryManager::RemoveQuery(GLuint client_id) {
query->MarkAsDeleted();
queries_.erase(it);
}
+ generated_query_ids_.erase(client_id);
}
void QueryManager::StartTracking(QueryManager::Query* /* query */) {
@@ -566,10 +630,7 @@ bool QueryManager::Query::MarkAsCompleted(uint64 result) {
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_;
+ base::subtle::Release_Store(&sync->process_count, submit_count_);
return true;
}
@@ -614,7 +675,8 @@ bool QueryManager::HavePendingTransferQueries() {
return !pending_transfer_queries_.empty();
}
-bool QueryManager::AddPendingQuery(Query* query, uint32 submit_count) {
+bool QueryManager::AddPendingQuery(Query* query,
+ base::subtle::Atomic32 submit_count) {
DCHECK(query);
DCHECK(!query->IsDeleted());
if (!RemovePendingQuery(query)) {
@@ -625,7 +687,9 @@ bool QueryManager::AddPendingQuery(Query* query, uint32 submit_count) {
return true;
}
-bool QueryManager::AddPendingTransferQuery(Query* query, uint32 submit_count) {
+bool QueryManager::AddPendingTransferQuery(
+ Query* query,
+ base::subtle::Atomic32 submit_count) {
DCHECK(query);
DCHECK(!query->IsDeleted());
if (!RemovePendingQuery(query)) {
@@ -671,7 +735,7 @@ bool QueryManager::BeginQuery(Query* query) {
return query->Begin();
}
-bool QueryManager::EndQuery(Query* query, uint32 submit_count) {
+bool QueryManager::EndQuery(Query* query, base::subtle::Atomic32 submit_count) {
DCHECK(query);
if (!RemovePendingQuery(query)) {
return false;