#include "base/logging.h"
#include "base/process/process_handle.h"
-#include "mojo/public/bindings/allocation_scope.h"
-#include "mojo/public/bindings/sync_dispatcher.h"
#include "mojo/services/gles2/command_buffer_type_conversions.h"
+#include "mojo/services/gles2/mojo_buffer_backing.h"
namespace mojo {
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() {}
-void CommandBufferDelegate::DrawAnimationFrame() {}
+
+class CommandBufferClientImpl::SyncClientImpl
+ : public InterfaceImpl<CommandBufferSyncClient> {
+ public:
+ SyncClientImpl() : initialized_successfully_(false) {}
+
+ bool WaitForInitialization() {
+ if (!WaitForIncomingMethodCall())
+ return false;
+ return initialized_successfully_;
+ }
+
+ CommandBufferStatePtr WaitForProgress() {
+ if (!WaitForIncomingMethodCall())
+ return CommandBufferStatePtr();
+ return command_buffer_state_.Pass();
+ }
+
+ private:
+ // CommandBufferSyncClient methods:
+ virtual void DidInitialize(bool success) OVERRIDE {
+ initialized_successfully_ = success;
+ }
+ virtual void DidMakeProgress(CommandBufferStatePtr state) OVERRIDE {
+ command_buffer_state_ = state.Pass();
+ }
+
+ bool initialized_successfully_;
+ CommandBufferStatePtr command_buffer_state_;
+};
CommandBufferClientImpl::CommandBufferClientImpl(
CommandBufferDelegate* delegate,
- MojoAsyncWaiter* async_waiter,
- ScopedCommandBufferHandle command_buffer_handle)
+ const MojoAsyncWaiter* async_waiter,
+ ScopedMessagePipeHandle command_buffer_handle)
: delegate_(delegate),
- command_buffer_(command_buffer_handle.Pass(), this, this, async_waiter),
+ shared_state_(NULL),
last_put_offset_(-1),
next_transfer_buffer_id_(0),
- initialize_result_(false) {}
+ async_waiter_(async_waiter) {
+ command_buffer_.Bind(command_buffer_handle.Pass(), async_waiter);
+ command_buffer_.set_error_handler(this);
+ command_buffer_.set_client(this);
+}
CommandBufferClientImpl::~CommandBufferClientImpl() {}
bool CommandBufferClientImpl::Initialize() {
- shared_state_shm_.reset(new base::SharedMemory);
- if (!shared_state_shm_->CreateAndMapAnonymous(
- sizeof(gpu::CommandBufferSharedState)))
+ 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;
- base::SharedMemoryHandle handle;
- shared_state_shm_->ShareToProcess(base::GetCurrentProcessHandle(), &handle);
- if (!base::SharedMemory::IsHandleValid(handle))
- return false;
+ shared_state_ = static_cast<gpu::CommandBufferSharedState*>(memory);
shared_state()->Initialize();
- InterfacePipe<CommandBufferSyncClient, NoInterface> sync_pipe;
- sync_dispatcher_.reset(new SyncDispatcher<CommandBufferSyncClient>(
- sync_pipe.handle_to_peer.Pass(), this));
- AllocationScope scope;
- command_buffer_->Initialize(sync_pipe.handle_to_self.Pass(), handle);
+ CommandBufferSyncClientPtr sync_client;
+ sync_client_impl_.reset(
+ WeakBindToProxy(new SyncClientImpl(), &sync_client, async_waiter_));
+
+ command_buffer_->Initialize(sync_client.Pass(), duped.Pass());
+
// Wait for DidInitialize to come on the sync client pipe.
- if (!sync_dispatcher_->WaitAndDispatchOneMessage()) {
+ if (!sync_client_impl_->WaitForInitialization()) {
VLOG(1) << "Channel encountered error while creating command buffer";
return false;
}
- return initialize_result_;
-}
-
-gpu::CommandBuffer::State CommandBufferClientImpl::GetState() {
- MakeProgressAndUpdateState();
- return last_state_;
+ return true;
}
gpu::CommandBuffer::State CommandBufferClientImpl::GetLastState() {
command_buffer_->Flush(put_offset);
}
-gpu::CommandBuffer::State CommandBufferClientImpl::FlushSync(
- int32 put_offset,
- int32 last_known_get) {
- Flush(put_offset);
+void CommandBufferClientImpl::WaitForTokenInRange(int32 start, int32 end) {
TryUpdateState();
- if (last_known_get == last_state_.get_offset)
+ while (!InRange(start, end, last_state_.token) &&
+ last_state_.error == gpu::error::kNoError) {
MakeProgressAndUpdateState();
+ TryUpdateState();
+ }
+}
- return last_state_;
+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) {
last_put_offset_ = -1;
}
-void CommandBufferClientImpl::SetGetOffset(int32 get_offset) {
- // Not implemented in proxy.
- NOTREACHED();
-}
-
-gpu::Buffer CommandBufferClientImpl::CreateTransferBuffer(size_t size,
- int32* id) {
- gpu::Buffer buffer;
+scoped_refptr<gpu::Buffer> CommandBufferClientImpl::CreateTransferBuffer(
+ size_t size,
+ int32* id) {
if (size >= std::numeric_limits<uint32_t>::max())
- return buffer;
-
- scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
- if (!shared_memory->CreateAndMapAnonymous(size))
- return buffer;
+ return NULL;
- base::SharedMemoryHandle handle;
- shared_memory->ShareToProcess(base::GetCurrentProcessHandle(), &handle);
- if (!base::SharedMemory::IsHandleValid(handle))
- return buffer;
+ void* memory = NULL;
+ mojo::ScopedSharedBufferHandle handle;
+ mojo::ScopedSharedBufferHandle duped;
+ if (!CreateMapAndDupSharedBuffer(size, &memory, &handle, &duped))
+ return NULL;
*id = ++next_transfer_buffer_id_;
- DCHECK(transfer_buffers_.find(*id) == transfer_buffers_.end());
- AllocationScope scope;
command_buffer_->RegisterTransferBuffer(
- *id, handle, static_cast<uint32_t>(size));
-
- buffer.ptr = shared_memory->memory();
- buffer.size = size;
- buffer.shared_memory = shared_memory.release();
- transfer_buffers_[*id] = buffer;
+ *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) {
- TransferBufferMap::iterator it = transfer_buffers_.find(id);
- if (it != transfer_buffers_.end()) {
- delete it->second.shared_memory;
- transfer_buffers_.erase(it);
- }
command_buffer_->DestroyTransferBuffer(id);
}
-gpu::Buffer CommandBufferClientImpl::GetTransferBuffer(int32 id) {
- TransferBufferMap::iterator it = transfer_buffers_.find(id);
- if (it != transfer_buffers_.end()) {
- return it->second;
- } else {
- return gpu::Buffer();
- }
-}
-
-void CommandBufferClientImpl::SetToken(int32 token) {
- // Not implemented in proxy.
- NOTREACHED();
-}
-
-void CommandBufferClientImpl::SetParseError(gpu::error::Error error) {
- // Not implemented in proxy.
- NOTREACHED();
-}
-
-void CommandBufferClientImpl::SetContextLostReason(
- gpu::error::ContextLostReason reason) {
- // Not implemented in proxy.
- NOTREACHED();
-}
-
gpu::Capabilities CommandBufferClientImpl::GetCapabilities() {
// TODO(piman)
NOTIMPLEMENTED();
size_t width,
size_t height,
unsigned internalformat,
+ unsigned usage,
int32* id) {
// TODO(piman)
NOTIMPLEMENTED();
}
uint32 CommandBufferClientImpl::InsertSyncPoint() {
+ // TODO(jamesr): Optimize this.
+ WaitForGetOffsetInRange(last_put_offset_, last_put_offset_);
+ return 0;
+}
+
+uint32 CommandBufferClientImpl::InsertFutureSyncPoint() {
+ // TODO(jamesr): Optimize this.
+ WaitForGetOffsetInRange(last_put_offset_, last_put_offset_);
+ return 0;
+}
+
+void CommandBufferClientImpl::RetireSyncPoint(uint32 sync_point) {
// TODO(piman)
NOTIMPLEMENTED();
- return 0;
}
void CommandBufferClientImpl::SignalSyncPoint(uint32 sync_point,
NOTIMPLEMENTED();
}
-void CommandBufferClientImpl::SendManagedMemoryStats(
- const gpu::ManagedMemoryStats& stats) {
- // TODO(piman)
- NOTIMPLEMENTED();
-}
-
void CommandBufferClientImpl::Echo(const base::Closure& callback) {
- echo_closures_.push(callback);
- command_buffer_->Echo();
+ command_buffer_->Echo(callback);
}
uint32 CommandBufferClientImpl::CreateStreamTexture(uint32 texture_id) {
return 0;
}
-void CommandBufferClientImpl::RequestAnimationFrames() {
- command_buffer_->RequestAnimationFrames();
-}
-
-void CommandBufferClientImpl::CancelAnimationFrames() {
- command_buffer_->CancelAnimationFrames();
-}
-
-void CommandBufferClientImpl::DidInitialize(bool success) {
- initialize_result_ = success;
-}
-
-void CommandBufferClientImpl::DidMakeProgress(const CommandBufferState& state) {
- if (state.generation() - last_state_.generation < 0x80000000U)
- last_state_ = state;
-}
-
void CommandBufferClientImpl::DidDestroy() {
LostContext(gpu::error::kUnknown);
}
-void CommandBufferClientImpl::EchoAck() {
- base::Closure closure = echo_closures_.front();
- echo_closures_.pop();
- closure.Run();
-}
-
void CommandBufferClientImpl::LostContext(int32_t lost_reason) {
last_state_.error = gpu::error::kLostContext;
last_state_.context_lost_reason =
delegate_->ContextLost();
}
-void CommandBufferClientImpl::OnError() { LostContext(gpu::error::kUnknown); }
+void CommandBufferClientImpl::OnConnectionError() {
+ LostContext(gpu::error::kUnknown);
+}
void CommandBufferClientImpl::TryUpdateState() {
if (last_state_.error == gpu::error::kNoError)
void CommandBufferClientImpl::MakeProgressAndUpdateState() {
command_buffer_->MakeProgress(last_state_.get_offset);
- if (!sync_dispatcher_->WaitAndDispatchOneMessage()) {
+
+ 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?
DidDestroy();
return;
}
-}
-void CommandBufferClientImpl::DrawAnimationFrame() {
- delegate_->DrawAnimationFrame();
+ if (state->generation - last_state_.generation < 0x80000000U)
+ last_state_ = state.To<State>();
}
} // namespace gles2