| Index: mojo/gles2/command_buffer_client_impl.cc
|
| diff --git a/mojo/gles2/command_buffer_client_impl.cc b/mojo/gles2/command_buffer_client_impl.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..37dc30cd6dbe5a24e60af3de8d0bad520883b518
|
| --- /dev/null
|
| +++ b/mojo/gles2/command_buffer_client_impl.cc
|
| @@ -0,0 +1,336 @@
|
| +// Copyright 2014 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 "mojo/gles2/command_buffer_client_impl.h"
|
| +
|
| +#include <limits>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/process/process_handle.h"
|
| +#include "mojo/services/gles2/command_buffer_type_conversions.h"
|
| +#include "mojo/services/gles2/mojo_buffer_backing.h"
|
| +
|
| +namespace gles2 {
|
| +
|
| +namespace {
|
| +
|
| +bool CreateMapAndDupSharedBuffer(size_t size,
|
| + void** memory,
|
| + mojo::ScopedSharedBufferHandle* handle,
|
| + mojo::ScopedSharedBufferHandle* duped) {
|
| + MojoResult result = mojo::CreateSharedBuffer(NULL, size, handle);
|
| + if (result != MOJO_RESULT_OK)
|
| + return false;
|
| + DCHECK(handle->is_valid());
|
| +
|
| + result = mojo::DuplicateBuffer(handle->get(), NULL, duped);
|
| + if (result != MOJO_RESULT_OK)
|
| + return false;
|
| + DCHECK(duped->is_valid());
|
| +
|
| + result = mojo::MapBuffer(
|
| + handle->get(), 0, size, memory, MOJO_MAP_BUFFER_FLAG_NONE);
|
| + if (result != MOJO_RESULT_OK)
|
| + return false;
|
| + DCHECK(*memory);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +CommandBufferDelegate::~CommandBufferDelegate() {}
|
| +
|
| +void CommandBufferDelegate::ContextLost() {}
|
| +
|
| +class CommandBufferClientImpl::SyncClientImpl
|
| + : public mojo::CommandBufferSyncClient {
|
| + public:
|
| + SyncClientImpl(mojo::CommandBufferSyncClientPtr* ptr,
|
| + const MojoAsyncWaiter* async_waiter)
|
| + : initialized_successfully_(false), binding_(this, ptr, async_waiter) {}
|
| +
|
| + bool WaitForInitialization() {
|
| + if (!binding_.WaitForIncomingMethodCall())
|
| + return false;
|
| + return initialized_successfully_;
|
| + }
|
| +
|
| + mojo::CommandBufferStatePtr WaitForProgress() {
|
| + if (!binding_.WaitForIncomingMethodCall())
|
| + return mojo::CommandBufferStatePtr();
|
| + return command_buffer_state_.Pass();
|
| + }
|
| +
|
| + gpu::Capabilities GetCapabilities() {
|
| + return capabilities_.To<gpu::Capabilities>();
|
| + }
|
| +
|
| + private:
|
| + // CommandBufferSyncClient methods:
|
| + void DidInitialize(bool success,
|
| + mojo::GpuCapabilitiesPtr capabilities) override {
|
| + initialized_successfully_ = success;
|
| + capabilities_ = capabilities.Pass();
|
| + }
|
| + void DidMakeProgress(mojo::CommandBufferStatePtr state) override {
|
| + command_buffer_state_ = state.Pass();
|
| + }
|
| +
|
| + bool initialized_successfully_;
|
| + mojo::GpuCapabilitiesPtr capabilities_;
|
| + mojo::CommandBufferStatePtr command_buffer_state_;
|
| + mojo::Binding<mojo::CommandBufferSyncClient> binding_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SyncClientImpl);
|
| +};
|
| +
|
| +class CommandBufferClientImpl::SyncPointClientImpl
|
| + : public mojo::CommandBufferSyncPointClient {
|
| + public:
|
| + SyncPointClientImpl(mojo::CommandBufferSyncPointClientPtr* ptr,
|
| + const MojoAsyncWaiter* async_waiter)
|
| + : sync_point_(0u), binding_(this, ptr, async_waiter) {}
|
| +
|
| + uint32_t WaitForInsertSyncPoint() {
|
| + if (!binding_.WaitForIncomingMethodCall())
|
| + return 0u;
|
| + uint32_t result = sync_point_;
|
| + sync_point_ = 0u;
|
| + return result;
|
| + }
|
| +
|
| + private:
|
| + void DidInsertSyncPoint(uint32_t sync_point) override {
|
| + sync_point_ = sync_point;
|
| + }
|
| +
|
| + uint32_t sync_point_;
|
| +
|
| + mojo::Binding<mojo::CommandBufferSyncPointClient> binding_;
|
| +};
|
| +
|
| +CommandBufferClientImpl::CommandBufferClientImpl(
|
| + CommandBufferDelegate* delegate,
|
| + const MojoAsyncWaiter* async_waiter,
|
| + mojo::ScopedMessagePipeHandle command_buffer_handle)
|
| + : delegate_(delegate),
|
| + observer_binding_(this),
|
| + shared_state_(NULL),
|
| + last_put_offset_(-1),
|
| + next_transfer_buffer_id_(0),
|
| + async_waiter_(async_waiter) {
|
| + command_buffer_.Bind(command_buffer_handle.Pass(), async_waiter);
|
| + command_buffer_.set_error_handler(this);
|
| +}
|
| +
|
| +CommandBufferClientImpl::~CommandBufferClientImpl() {}
|
| +
|
| +bool CommandBufferClientImpl::Initialize() {
|
| + const size_t kSharedStateSize = sizeof(gpu::CommandBufferSharedState);
|
| + void* memory = NULL;
|
| + mojo::ScopedSharedBufferHandle duped;
|
| + bool result = CreateMapAndDupSharedBuffer(
|
| + kSharedStateSize, &memory, &shared_state_handle_, &duped);
|
| + if (!result)
|
| + return false;
|
| +
|
| + shared_state_ = static_cast<gpu::CommandBufferSharedState*>(memory);
|
| +
|
| + shared_state()->Initialize();
|
| +
|
| + mojo::CommandBufferSyncClientPtr sync_client;
|
| + sync_client_impl_.reset(new SyncClientImpl(&sync_client, async_waiter_));
|
| +
|
| + mojo::CommandBufferSyncPointClientPtr sync_point_client;
|
| + sync_point_client_impl_.reset(
|
| + new SyncPointClientImpl(&sync_point_client, async_waiter_));
|
| +
|
| + mojo::CommandBufferLostContextObserverPtr observer_ptr;
|
| + observer_binding_.Bind(GetProxy(&observer_ptr), async_waiter_);
|
| + command_buffer_->Initialize(sync_client.Pass(),
|
| + sync_point_client.Pass(),
|
| + observer_ptr.Pass(),
|
| + duped.Pass());
|
| +
|
| + // Wait for DidInitialize to come on the sync client pipe.
|
| + if (!sync_client_impl_->WaitForInitialization()) {
|
| + VLOG(1) << "Channel encountered error while creating command buffer";
|
| + return false;
|
| + }
|
| + capabilities_ = sync_client_impl_->GetCapabilities();
|
| + return true;
|
| +}
|
| +
|
| +gpu::CommandBuffer::State CommandBufferClientImpl::GetLastState() {
|
| + return last_state_;
|
| +}
|
| +
|
| +int32 CommandBufferClientImpl::GetLastToken() {
|
| + TryUpdateState();
|
| + return last_state_.token;
|
| +}
|
| +
|
| +void CommandBufferClientImpl::Flush(int32 put_offset) {
|
| + if (last_put_offset_ == put_offset)
|
| + return;
|
| +
|
| + last_put_offset_ = put_offset;
|
| + command_buffer_->Flush(put_offset);
|
| +}
|
| +
|
| +void CommandBufferClientImpl::OrderingBarrier(int32_t put_offset) {
|
| + // TODO(jamesr): Implement this more efficiently.
|
| + Flush(put_offset);
|
| +}
|
| +
|
| +void CommandBufferClientImpl::WaitForTokenInRange(int32 start, int32 end) {
|
| + TryUpdateState();
|
| + while (!InRange(start, end, last_state_.token) &&
|
| + last_state_.error == gpu::error::kNoError) {
|
| + MakeProgressAndUpdateState();
|
| + TryUpdateState();
|
| + }
|
| +}
|
| +
|
| +void CommandBufferClientImpl::WaitForGetOffsetInRange(int32 start, int32 end) {
|
| + TryUpdateState();
|
| + while (!InRange(start, end, last_state_.get_offset) &&
|
| + last_state_.error == gpu::error::kNoError) {
|
| + MakeProgressAndUpdateState();
|
| + TryUpdateState();
|
| + }
|
| +}
|
| +
|
| +void CommandBufferClientImpl::SetGetBuffer(int32 shm_id) {
|
| + command_buffer_->SetGetBuffer(shm_id);
|
| + last_put_offset_ = -1;
|
| +}
|
| +
|
| +scoped_refptr<gpu::Buffer> CommandBufferClientImpl::CreateTransferBuffer(
|
| + size_t size,
|
| + int32* id) {
|
| + if (size >= std::numeric_limits<uint32_t>::max())
|
| + return NULL;
|
| +
|
| + void* memory = NULL;
|
| + mojo::ScopedSharedBufferHandle handle;
|
| + mojo::ScopedSharedBufferHandle duped;
|
| + if (!CreateMapAndDupSharedBuffer(size, &memory, &handle, &duped))
|
| + return NULL;
|
| +
|
| + *id = ++next_transfer_buffer_id_;
|
| +
|
| + command_buffer_->RegisterTransferBuffer(
|
| + *id, duped.Pass(), static_cast<uint32_t>(size));
|
| +
|
| + scoped_ptr<gpu::BufferBacking> backing(
|
| + new MojoBufferBacking(handle.Pass(), memory, size));
|
| + scoped_refptr<gpu::Buffer> buffer(new gpu::Buffer(backing.Pass()));
|
| + return buffer;
|
| +}
|
| +
|
| +void CommandBufferClientImpl::DestroyTransferBuffer(int32 id) {
|
| + command_buffer_->DestroyTransferBuffer(id);
|
| +}
|
| +
|
| +gpu::Capabilities CommandBufferClientImpl::GetCapabilities() {
|
| + return capabilities_;
|
| +}
|
| +
|
| +int32_t CommandBufferClientImpl::CreateImage(ClientBuffer buffer,
|
| + size_t width,
|
| + size_t height,
|
| + unsigned internalformat) {
|
| + // TODO(piman)
|
| + NOTIMPLEMENTED();
|
| + return -1;
|
| +}
|
| +
|
| +void CommandBufferClientImpl::DestroyImage(int32 id) {
|
| + // TODO(piman)
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +int32_t CommandBufferClientImpl::CreateGpuMemoryBufferImage(
|
| + size_t width,
|
| + size_t height,
|
| + unsigned internalformat,
|
| + unsigned usage) {
|
| + // TODO(piman)
|
| + NOTIMPLEMENTED();
|
| + return -1;
|
| +}
|
| +
|
| +uint32_t CommandBufferClientImpl::InsertSyncPoint() {
|
| + command_buffer_->InsertSyncPoint(true);
|
| + return sync_point_client_impl_->WaitForInsertSyncPoint();
|
| +}
|
| +
|
| +uint32_t CommandBufferClientImpl::InsertFutureSyncPoint() {
|
| + command_buffer_->InsertSyncPoint(false);
|
| + return sync_point_client_impl_->WaitForInsertSyncPoint();
|
| +}
|
| +
|
| +void CommandBufferClientImpl::RetireSyncPoint(uint32_t sync_point) {
|
| + command_buffer_->RetireSyncPoint(sync_point);
|
| +}
|
| +
|
| +void CommandBufferClientImpl::SignalSyncPoint(uint32_t sync_point,
|
| + const base::Closure& callback) {
|
| + // TODO(piman)
|
| +}
|
| +
|
| +void CommandBufferClientImpl::SignalQuery(uint32_t query,
|
| + const base::Closure& callback) {
|
| + // TODO(piman)
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +void CommandBufferClientImpl::SetSurfaceVisible(bool visible) {
|
| + // TODO(piman)
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +uint32_t CommandBufferClientImpl::CreateStreamTexture(uint32_t texture_id) {
|
| + // TODO(piman)
|
| + NOTIMPLEMENTED();
|
| + return 0;
|
| +}
|
| +
|
| +void CommandBufferClientImpl::DidLoseContext(int32_t lost_reason) {
|
| + last_state_.error = gpu::error::kLostContext;
|
| + last_state_.context_lost_reason =
|
| + static_cast<gpu::error::ContextLostReason>(lost_reason);
|
| + delegate_->ContextLost();
|
| +}
|
| +
|
| +void CommandBufferClientImpl::OnConnectionError() {
|
| + DidLoseContext(gpu::error::kUnknown);
|
| +}
|
| +
|
| +void CommandBufferClientImpl::TryUpdateState() {
|
| + if (last_state_.error == gpu::error::kNoError)
|
| + shared_state()->Read(&last_state_);
|
| +}
|
| +
|
| +void CommandBufferClientImpl::MakeProgressAndUpdateState() {
|
| + command_buffer_->MakeProgress(last_state_.get_offset);
|
| +
|
| + mojo::CommandBufferStatePtr state = sync_client_impl_->WaitForProgress();
|
| + if (!state) {
|
| + VLOG(1) << "Channel encountered error while waiting for command buffer";
|
| + // TODO(piman): is it ok for this to re-enter?
|
| + DidLoseContext(gpu::error::kUnknown);
|
| + return;
|
| + }
|
| +
|
| + if (state->generation - last_state_.generation < 0x80000000U)
|
| + last_state_ = state.To<State>();
|
| +}
|
| +
|
| +void CommandBufferClientImpl::SetLock(base::Lock* lock) {
|
| +}
|
| +
|
| +} // namespace gles2
|
|
|