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