15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/client/command_buffer_proxy_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/memory/shared_memory.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/child_process_messages.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/client/gpu_channel_host.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/common/gpu/client/gpu_video_decode_accelerator_host.h"
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/common/gpu/gpu_memory_allocation.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_messages.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/view_messages.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/common/cmd_buffer_common.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/common/command_buffer_shared.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferProxyImpl::CommandBufferProxyImpl(
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuChannelHost* channel,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int route_id)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : channel_(channel),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      route_id_(route_id),
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flush_count_(0),
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_put_offset_(-1),
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_signal_id_(0) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferProxyImpl::~CommandBufferProxyImpl() {
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FOR_EACH_OBSERVER(DeletionObserver,
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    deletion_observers_,
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    OnWillDeleteImpl());
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete all the locally cached shared memory objects, closing the handle
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in this process.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TransferBufferMap::iterator it = transfer_buffers_.begin();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != transfer_buffers_.end();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete it->second.shared_memory;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->second.shared_memory = NULL;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferProxyImpl::OnMessageReceived(const IPC::Message& message) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(CommandBufferProxyImpl, message)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Destroyed, OnDestroyed);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_EchoAck, OnEchoAck);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ConsoleMsg, OnConsoleMessage);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetMemoryAllocation,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnSetMemoryAllocation);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SignalSyncPointAck,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnSignalSyncPointAck);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(handled);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::OnChannelError() {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnDestroyed(gpu::error::kUnknown);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::OnDestroyed(gpu::error::ContextLostReason reason) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prevent any further messages from being sent.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_ = NULL;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When the client sees that the context is lost, they should delete this
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CommandBufferProxyImpl and create a new one.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_state_.error = gpu::error::kLostContext;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_state_.context_lost_reason = reason;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!channel_error_callback_.is_null()) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_error_callback_.Run();
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Avoid calling the error callback more than once.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_error_callback_.Reset();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::OnEchoAck() {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!echo_tasks_.empty());
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure callback = echo_tasks_.front();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  echo_tasks_.pop();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::OnConsoleMessage(
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GPUCommandBufferConsoleMessage& message) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!console_message_callback_.is_null()) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    console_message_callback_.Run(message.message, message.id);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::SetMemoryAllocationChangedCallback(
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Callback<void(const GpuMemoryAllocationForRenderer&)>&
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memory_allocation_changed_callback_ = callback;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new GpuCommandBufferMsg_SetClientHasMemoryAllocationChangedCallback(
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      route_id_, !memory_allocation_changed_callback_.is_null()));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CommandBufferProxyImpl::AddDeletionObserver(DeletionObserver* observer) {
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  deletion_observers_.AddObserver(observer);
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CommandBufferProxyImpl::RemoveDeletionObserver(
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DeletionObserver* observer) {
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  deletion_observers_.RemoveObserver(observer);
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::OnSetMemoryAllocation(
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GpuMemoryAllocationForRenderer& allocation) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!memory_allocation_changed_callback_.is_null())
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memory_allocation_changed_callback_.Run(allocation);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::OnSignalSyncPointAck(uint32 id) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignalTaskMap::iterator it = signal_tasks_.find(id);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it != signal_tasks_.end());
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure callback = it->second;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal_tasks_.erase(it);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::SetChannelErrorCallback(
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& callback) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_error_callback_ = callback;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferProxyImpl::Initialize() {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  shared_state_shm_.reset(channel_->factory()->AllocateSharedMemory(
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sizeof(*shared_state())).release());
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!shared_state_shm_)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!shared_state_shm_->Map(sizeof(*shared_state())))
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  shared_state()->Initialize();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This handle is owned by the GPU process and must be passed to it or it
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // will leak. In otherwords, do not early out on error between here and the
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // sending of the Initialize IPC below.
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::SharedMemoryHandle handle =
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      channel_->ShareToGpuProcess(shared_state_shm_->handle());
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!base::SharedMemory::IsHandleValid(handle))
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool result;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!Send(new GpuCommandBufferMsg_Initialize(route_id_, handle, &result))) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Could not send GpuCommandBufferMsg_Initialize.";
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result) {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Failed to initialize command buffer service.";
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gpu::CommandBuffer::State CommandBufferProxyImpl::GetState() {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send will flag state with lost context if IPC fails.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error == gpu::error::kNoError) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gpu::CommandBuffer::State state;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (Send(new GpuCommandBufferMsg_GetState(route_id_, &state)))
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnUpdateState(state);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TryUpdateState();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return last_state_;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gpu::CommandBuffer::State CommandBufferProxyImpl::GetLastState() {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return last_state_;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 CommandBufferProxyImpl::GetLastToken() {
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TryUpdateState();
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return last_state_.token;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::Flush(int32 put_offset) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT1("gpu",
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "CommandBufferProxyImpl::Flush",
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               "put_offset",
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               put_offset);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_put_offset_ == put_offset)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_put_offset_ = put_offset;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new GpuCommandBufferMsg_AsyncFlush(route_id_,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          put_offset,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          ++flush_count_));
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CommandBufferProxyImpl::SetLatencyInfo(
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ui::LatencyInfo& latency_info) {
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Send(new GpuCommandBufferMsg_SetLatencyInfo(route_id_, latency_info));
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gpu::CommandBuffer::State CommandBufferProxyImpl::FlushSync(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 put_offset,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 last_known_get) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT1("gpu", "CommandBufferProxyImpl::FlushSync", "put_offset",
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               put_offset);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Flush(put_offset);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TryUpdateState();
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_known_get == last_state_.get_offset) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send will flag state with lost context if IPC fails.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (last_state_.error == gpu::error::kNoError) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gpu::CommandBuffer::State state;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (Send(new GpuCommandBufferMsg_GetStateFast(route_id_,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    &state)))
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OnUpdateState(state);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TryUpdateState();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return last_state_;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::SetGetBuffer(int32 shm_id) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new GpuCommandBufferMsg_SetGetBuffer(route_id_, shm_id));
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_put_offset_ = -1;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::SetGetOffset(int32 get_offset) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Not implemented in proxy.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gpu::Buffer CommandBufferProxyImpl::CreateTransferBuffer(size_t size,
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                         int32* id) {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *id = -1;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gpu::Buffer();
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 new_id = channel_->ReserveTransferBufferId();
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(transfer_buffers_.find(new_id) == transfer_buffers_.end());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::SharedMemory> shared_memory(
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      channel_->factory()->AllocateSharedMemory(size));
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!shared_memory)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gpu::Buffer();
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!shared_memory->memory());
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!shared_memory->Map(size))
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gpu::Buffer();
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This handle is owned by the GPU process and must be passed to it or it
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // will leak. In otherwords, do not early out on error between here and the
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // sending of the RegisterTransferBuffer IPC below.
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::SharedMemoryHandle handle =
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      channel_->ShareToGpuProcess(shared_memory->handle());
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!base::SharedMemory::IsHandleValid(handle))
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gpu::Buffer();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new GpuCommandBufferMsg_RegisterTransferBuffer(route_id_,
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                           new_id,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           handle,
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                           size))) {
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gpu::Buffer();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *id = new_id;
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gpu::Buffer buffer;
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  buffer.ptr = shared_memory->memory();
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  buffer.size = size;
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  buffer.shared_memory = shared_memory.release();
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transfer_buffers_[new_id] = buffer;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return buffer;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::DestroyTransferBuffer(int32 id) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the transfer buffer from the client side cache.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransferBufferMap::iterator it = transfer_buffers_.find(id);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != transfer_buffers_.end()) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete it->second.shared_memory;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transfer_buffers_.erase(it);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new GpuCommandBufferMsg_DestroyTransferBuffer(route_id_, id));
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gpu::Buffer CommandBufferProxyImpl::GetTransferBuffer(int32 id) {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gpu::Buffer();
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check local cache to see if there is already a client side shared memory
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // object for this id.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransferBufferMap::iterator it = transfer_buffers_.find(id);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != transfer_buffers_.end()) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return it->second;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assuming we are in the renderer process, the service is responsible for
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // duplicating the handle. This might not be true for NaCl.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SharedMemoryHandle handle = base::SharedMemoryHandle();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 size;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new GpuCommandBufferMsg_GetTransferBuffer(route_id_,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      id,
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      &handle,
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      &size))) {
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gpu::Buffer();
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cache the transfer buffer shared memory object client side.
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::SharedMemory> shared_memory(
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::SharedMemory(handle, false));
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Map the shared memory on demand.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!shared_memory->memory()) {
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!shared_memory->Map(size))
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return gpu::Buffer();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gpu::Buffer buffer;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer.ptr = shared_memory->memory();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer.size = size;
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  buffer.shared_memory = shared_memory.release();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transfer_buffers_[id] = buffer;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return buffer;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::SetToken(int32 token) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Not implemented in proxy.
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::SetParseError(
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gpu::error::Error error) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Not implemented in proxy.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::SetContextLostReason(
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gpu::error::ContextLostReason reason) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Not implemented in proxy.
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CommandBufferProxyImpl::GetRouteID() const {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return route_id_;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferProxyImpl::Echo(const base::Closure& callback) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error != gpu::error::kNoError) {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new GpuCommandBufferMsg_Echo(route_id_,
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    GpuCommandBufferMsg_EchoAck(route_id_)))) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  echo_tasks_.push(callback);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferProxyImpl::SetSurfaceVisible(bool visible) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Send(new GpuCommandBufferMsg_SetSurfaceVisible(route_id_, visible));
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferProxyImpl::DiscardBackbuffer() {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Send(new GpuCommandBufferMsg_DiscardBackbuffer(route_id_));
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferProxyImpl::EnsureBackbuffer() {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Send(new GpuCommandBufferMsg_EnsureBackbuffer(route_id_));
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 CommandBufferProxyImpl::InsertSyncPoint() {
41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 0;
41290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 sync_point = 0;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new GpuCommandBufferMsg_InsertSyncPoint(route_id_, &sync_point));
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sync_point;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferProxyImpl::SignalSyncPoint(uint32 sync_point,
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const base::Closure& callback) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error != gpu::error::kNoError) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 signal_id = next_signal_id_++;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new GpuCommandBufferMsg_SignalSyncPoint(route_id_,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    sync_point,
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    signal_id))) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal_tasks_.insert(std::make_pair(signal_id, callback));
432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return true;
434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool CommandBufferProxyImpl::SignalQuery(unsigned query,
437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                         const base::Closure& callback) {
438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (last_state_.error != gpu::error::kNoError) {
439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Signal identifiers are hidden, so nobody outside of this class will see
443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // them. (And thus, they cannot save them.) The IDs themselves only last
444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // until the callback is invoked, which will happen as soon as the GPU
445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // catches upwith the command buffer.
446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // A malicious caller trying to create a collision by making next_signal_id
447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // would have to make calls at an astounding rate (300B/s) and even if they
448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // could do that, all they would do is to prevent some callbacks from getting
449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // called, leading to stalled threads and/or memory leaks.
450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  uint32 signal_id = next_signal_id_++;
451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!Send(new GpuCommandBufferMsg_SignalQuery(route_id_,
452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                query,
453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                signal_id))) {
454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  signal_tasks_.insert(std::make_pair(signal_id, callback));
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferProxyImpl::GenerateMailboxNames(
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned num,
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<gpu::Mailbox>* names) {
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return channel_->GenerateMailboxNames(num, names);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool CommandBufferProxyImpl::ProduceFrontBuffer(const gpu::Mailbox& mailbox) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return Send(new GpuCommandBufferMsg_ProduceFrontBuffer(route_id_, mailbox));
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<media::VideoDecodeAccelerator>
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferProxyImpl::CreateVideoDecoder(
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::VideoCodecProfile profile,
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::VideoDecodeAccelerator::Client* client) {
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int decoder_route_id;
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<media::VideoDecodeAccelerator> vda;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Send(new GpuCommandBufferMsg_CreateVideoDecoder(route_id_, profile,
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       &decoder_route_id))) {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Send(GpuCommandBufferMsg_CreateVideoDecoder) failed";
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return vda.Pass();
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (decoder_route_id < 0) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Failed to Initialize GPU decoder on profile: " << profile;
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return vda.Pass();
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GpuVideoDecodeAcceleratorHost* decoder_host =
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new GpuVideoDecodeAcceleratorHost(channel_, decoder_route_id, client,
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        this);
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  vda.reset(decoder_host);
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return vda.Pass();
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gpu::error::Error CommandBufferProxyImpl::GetLastError() {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return last_state_.error;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferProxyImpl::Send(IPC::Message* msg) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Caller should not intentionally send a message if the context is lost.
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(last_state_.error == gpu::error::kNoError);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (channel_) {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (channel_->Send(msg)) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Flag the command buffer as lost. Defer deleting the channel until
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // OnChannelError is called after returning to the message loop in case
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // it is referenced elsewhere.
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_state_.error = gpu::error::kLostContext;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callee takes ownership of message, regardless of whether Send is
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // successful. See IPC::Sender.
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete msg;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::OnUpdateState(
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gpu::CommandBuffer::State& state) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle wraparound. It works as long as we don't have more than 2B state
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // updates in flight across which reordering occurs.
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state.generation - last_state_.generation < 0x80000000U)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_state_ = state;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::SetOnConsoleMessageCallback(
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GpuConsoleMessageCallback& callback) {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  console_message_callback_ = callback;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::TryUpdateState() {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error == gpu::error::kNoError)
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    shared_state()->Read(&last_state_);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferProxyImpl::SendManagedMemoryStats(
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GpuManagedMemoryStats& stats) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_state_.error != gpu::error::kNoError)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new GpuCommandBufferMsg_SendClientManagedMemoryStats(route_id_,
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                            stats));
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
557