1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi/proxy/ppapi_command_buffer_proxy.h"
7 #include "ppapi/proxy/ppapi_messages.h"
8 #include "ppapi/proxy/proxy_channel.h"
9 #include "ppapi/shared_impl/api_id.h"
10 #include "ppapi/shared_impl/host_resource.h"
11 #include "ppapi/shared_impl/proxy_lock.h"
16 PpapiCommandBufferProxy::PpapiCommandBufferProxy(
17 const ppapi::HostResource& resource,
18 ProxyChannel* channel)
19 : resource_(resource),
23 PpapiCommandBufferProxy::~PpapiCommandBufferProxy() {
24 // gpu::Buffers are no longer referenced, allowing shared memory objects to be
25 // deleted, closing the handle in this process.
28 bool PpapiCommandBufferProxy::Initialize() {
32 gpu::CommandBuffer::State PpapiCommandBufferProxy::GetState() {
33 // Send will flag state with lost context if IPC fails.
34 if (last_state_.error == gpu::error::kNoError) {
35 gpu::CommandBuffer::State state;
37 if (Send(new PpapiHostMsg_PPBGraphics3D_GetState(
38 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &state, &success))) {
39 UpdateState(state, success);
46 gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() {
47 ppapi::ProxyLock::AssertAcquiredDebugOnly();
51 int32 PpapiCommandBufferProxy::GetLastToken() {
52 ppapi::ProxyLock::AssertAcquiredDebugOnly();
53 return last_state_.token;
56 void PpapiCommandBufferProxy::Flush(int32 put_offset) {
57 if (last_state_.error != gpu::error::kNoError)
60 IPC::Message* message = new PpapiHostMsg_PPBGraphics3D_AsyncFlush(
61 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, put_offset);
63 // Do not let a synchronous flush hold up this message. If this handler is
64 // deferred until after the synchronous flush completes, it will overwrite the
65 // cached last_state_ with out-of-date data.
66 message->set_unblock(true);
70 void PpapiCommandBufferProxy::WaitForTokenInRange(int32 start, int32 end) {
71 if (last_state_.error != gpu::error::kNoError)
75 gpu::CommandBuffer::State state;
76 if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange(
77 ppapi::API_ID_PPB_GRAPHICS_3D,
83 UpdateState(state, success);
86 void PpapiCommandBufferProxy::WaitForGetOffsetInRange(int32 start, int32 end) {
87 if (last_state_.error != gpu::error::kNoError)
91 gpu::CommandBuffer::State state;
92 if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange(
93 ppapi::API_ID_PPB_GRAPHICS_3D,
99 UpdateState(state, success);
102 void PpapiCommandBufferProxy::SetGetBuffer(int32 transfer_buffer_id) {
103 if (last_state_.error == gpu::error::kNoError) {
104 Send(new PpapiHostMsg_PPBGraphics3D_SetGetBuffer(
105 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, transfer_buffer_id));
109 void PpapiCommandBufferProxy::SetGetOffset(int32 get_offset) {
110 // Not implemented in proxy.
114 scoped_refptr<gpu::Buffer> PpapiCommandBufferProxy::CreateTransferBuffer(
119 if (last_state_.error != gpu::error::kNoError)
122 if (!Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
123 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, id))) {
130 scoped_refptr<gpu::Buffer> buffer = GetTransferBuffer(*id);
137 void PpapiCommandBufferProxy::DestroyTransferBuffer(int32 id) {
138 if (last_state_.error != gpu::error::kNoError)
141 // Remove the transfer buffer from the client side4 cache.
142 TransferBufferMap::iterator it = transfer_buffers_.find(id);
144 // Remove reference to buffer, allowing the shared memory object to be
145 // deleted, closing the handle in the process.
146 if (it != transfer_buffers_.end())
147 transfer_buffers_.erase(it);
149 Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer(
150 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id));
153 void PpapiCommandBufferProxy::Echo(const base::Closure& callback) {
157 uint32 PpapiCommandBufferProxy::CreateStreamTexture(uint32 texture_id) {
162 scoped_refptr<gpu::Buffer> PpapiCommandBufferProxy::GetTransferBuffer(
164 if (last_state_.error != gpu::error::kNoError)
167 // Check local cache to see if there is already a client side shared memory
168 // object for this id.
169 TransferBufferMap::iterator it = transfer_buffers_.find(id);
170 if (it != transfer_buffers_.end()) {
174 // Assuming we are in the renderer process, the service is responsible for
175 // duplicating the handle. This might not be true for NaCl.
176 ppapi::proxy::SerializedHandle handle(
177 ppapi::proxy::SerializedHandle::SHARED_MEMORY);
178 if (!Send(new PpapiHostMsg_PPBGraphics3D_GetTransferBuffer(
179 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id, &handle))) {
182 if (!handle.is_shmem())
185 // Cache the transfer buffer shared memory object client side.
186 scoped_ptr<base::SharedMemory> shared_memory(
187 new base::SharedMemory(handle.shmem(), false));
189 // Map the shared memory on demand.
190 if (!shared_memory->memory()) {
191 if (!shared_memory->Map(handle.size())) {
196 scoped_refptr<gpu::Buffer> buffer =
197 new gpu::Buffer(shared_memory.Pass(), handle.size());
198 transfer_buffers_[id] = buffer;
202 void PpapiCommandBufferProxy::SetToken(int32 token) {
206 void PpapiCommandBufferProxy::SetParseError(gpu::error::Error error) {
210 void PpapiCommandBufferProxy::SetContextLostReason(
211 gpu::error::ContextLostReason reason) {
215 uint32 PpapiCommandBufferProxy::InsertSyncPoint() {
216 uint32 sync_point = 0;
217 if (last_state_.error == gpu::error::kNoError) {
218 Send(new PpapiHostMsg_PPBGraphics3D_InsertSyncPoint(
219 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &sync_point));
224 void PpapiCommandBufferProxy::SignalSyncPoint(uint32 sync_point,
225 const base::Closure& callback) {
229 void PpapiCommandBufferProxy::SignalQuery(uint32 query,
230 const base::Closure& callback) {
234 void PpapiCommandBufferProxy::SetSurfaceVisible(bool visible) {
238 void PpapiCommandBufferProxy::SendManagedMemoryStats(
239 const gpu::ManagedMemoryStats& stats) {
243 gpu::Capabilities PpapiCommandBufferProxy::GetCapabilities() {
244 // TODO(boliu): Need to implement this to use cc in Pepper. Tracked in
246 return gpu::Capabilities();
249 gfx::GpuMemoryBuffer* PpapiCommandBufferProxy::CreateGpuMemoryBuffer(
252 unsigned internalformat,
258 void PpapiCommandBufferProxy::DestroyGpuMemoryBuffer(int32 id) {
262 bool PpapiCommandBufferProxy::Send(IPC::Message* msg) {
263 DCHECK(last_state_.error == gpu::error::kNoError);
265 if (channel_->Send(msg))
268 last_state_.error = gpu::error::kLostContext;
272 void PpapiCommandBufferProxy::UpdateState(
273 const gpu::CommandBuffer::State& state,
275 // Handle wraparound. It works as long as we don't have more than 2B state
276 // updates in flight across which reordering occurs.
278 if (state.generation - last_state_.generation < 0x80000000U) {
282 last_state_.error = gpu::error::kLostContext;
283 ++last_state_.generation;