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 // Delete all the locally cached shared memory objects, closing the handle
26 for (TransferBufferMap::iterator it
= transfer_buffers_
.begin();
27 it
!= transfer_buffers_
.end(); ++it
) {
28 delete it
->second
.shared_memory
;
29 it
->second
.shared_memory
= NULL
;
33 bool PpapiCommandBufferProxy::Initialize() {
37 gpu::CommandBuffer::State
PpapiCommandBufferProxy::GetState() {
38 // Send will flag state with lost context if IPC fails.
39 if (last_state_
.error
== gpu::error::kNoError
) {
40 gpu::CommandBuffer::State state
;
42 if (Send(new PpapiHostMsg_PPBGraphics3D_GetState(
43 ppapi::API_ID_PPB_GRAPHICS_3D
, resource_
, &state
, &success
))) {
44 UpdateState(state
, success
);
51 gpu::CommandBuffer::State
PpapiCommandBufferProxy::GetLastState() {
52 ppapi::ProxyLock::AssertAcquiredDebugOnly();
56 int32
PpapiCommandBufferProxy::GetLastToken() {
57 ppapi::ProxyLock::AssertAcquiredDebugOnly();
58 return last_state_
.token
;
61 void PpapiCommandBufferProxy::Flush(int32 put_offset
) {
62 if (last_state_
.error
!= gpu::error::kNoError
)
65 IPC::Message
* message
= new PpapiHostMsg_PPBGraphics3D_AsyncFlush(
66 ppapi::API_ID_PPB_GRAPHICS_3D
, resource_
, put_offset
);
68 // Do not let a synchronous flush hold up this message. If this handler is
69 // deferred until after the synchronous flush completes, it will overwrite the
70 // cached last_state_ with out-of-date data.
71 message
->set_unblock(true);
75 gpu::CommandBuffer::State
PpapiCommandBufferProxy::FlushSync(int32 put_offset
,
76 int32 last_known_get
) {
77 if (last_known_get
== last_state_
.get_offset
) {
78 // Send will flag state with lost context if IPC fails.
79 if (last_state_
.error
== gpu::error::kNoError
) {
80 gpu::CommandBuffer::State state
;
82 if (Send(new PpapiHostMsg_PPBGraphics3D_Flush(
83 ppapi::API_ID_PPB_GRAPHICS_3D
, resource_
, put_offset
,
84 last_known_get
, &state
, &success
))) {
85 UpdateState(state
, success
);
94 void PpapiCommandBufferProxy::SetGetBuffer(int32 transfer_buffer_id
) {
95 if (last_state_
.error
== gpu::error::kNoError
) {
96 Send(new PpapiHostMsg_PPBGraphics3D_SetGetBuffer(
97 ppapi::API_ID_PPB_GRAPHICS_3D
, resource_
, transfer_buffer_id
));
101 void PpapiCommandBufferProxy::SetGetOffset(int32 get_offset
) {
102 // Not implemented in proxy.
106 gpu::Buffer
PpapiCommandBufferProxy::CreateTransferBuffer(size_t size
,
110 if (last_state_
.error
!= gpu::error::kNoError
)
111 return gpu::Buffer();
113 if (!Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
114 ppapi::API_ID_PPB_GRAPHICS_3D
, resource_
, size
, id
))) {
115 return gpu::Buffer();
119 return gpu::Buffer();
121 return GetTransferBuffer(*id
);
124 void PpapiCommandBufferProxy::DestroyTransferBuffer(int32 id
) {
125 if (last_state_
.error
!= gpu::error::kNoError
)
128 // Remove the transfer buffer from the client side4 cache.
129 TransferBufferMap::iterator it
= transfer_buffers_
.find(id
);
131 if (it
!= transfer_buffers_
.end()) {
132 // Delete the shared memory object, closing the handle in this process.
133 delete it
->second
.shared_memory
;
135 transfer_buffers_
.erase(it
);
138 Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer(
139 ppapi::API_ID_PPB_GRAPHICS_3D
, resource_
, id
));
142 void PpapiCommandBufferProxy::Echo(const base::Closure
& callback
) {
146 uint32
PpapiCommandBufferProxy::CreateStreamTexture(uint32 texture_id
) {
151 gpu::Buffer
PpapiCommandBufferProxy::GetTransferBuffer(int32 id
) {
152 if (last_state_
.error
!= gpu::error::kNoError
)
153 return gpu::Buffer();
155 // Check local cache to see if there is already a client side shared memory
156 // object for this id.
157 TransferBufferMap::iterator it
= transfer_buffers_
.find(id
);
158 if (it
!= transfer_buffers_
.end()) {
162 // Assuming we are in the renderer process, the service is responsible for
163 // duplicating the handle. This might not be true for NaCl.
164 ppapi::proxy::SerializedHandle
handle(
165 ppapi::proxy::SerializedHandle::SHARED_MEMORY
);
166 if (!Send(new PpapiHostMsg_PPBGraphics3D_GetTransferBuffer(
167 ppapi::API_ID_PPB_GRAPHICS_3D
, resource_
, id
, &handle
))) {
168 return gpu::Buffer();
170 if (!handle
.is_shmem())
171 return gpu::Buffer();
173 // Cache the transfer buffer shared memory object client side.
174 scoped_ptr
<base::SharedMemory
> shared_memory(
175 new base::SharedMemory(handle
.shmem(), false));
177 // Map the shared memory on demand.
178 if (!shared_memory
->memory()) {
179 if (!shared_memory
->Map(handle
.size())) {
180 return gpu::Buffer();
185 buffer
.ptr
= shared_memory
->memory();
186 buffer
.size
= handle
.size();
187 buffer
.shared_memory
= shared_memory
.release();
188 transfer_buffers_
[id
] = buffer
;
193 void PpapiCommandBufferProxy::SetToken(int32 token
) {
197 void PpapiCommandBufferProxy::SetParseError(gpu::error::Error error
) {
201 void PpapiCommandBufferProxy::SetContextLostReason(
202 gpu::error::ContextLostReason reason
) {
206 uint32
PpapiCommandBufferProxy::InsertSyncPoint() {
207 uint32 sync_point
= 0;
208 if (last_state_
.error
== gpu::error::kNoError
) {
209 Send(new PpapiHostMsg_PPBGraphics3D_InsertSyncPoint(
210 ppapi::API_ID_PPB_GRAPHICS_3D
, resource_
, &sync_point
));
215 void PpapiCommandBufferProxy::SignalSyncPoint(uint32 sync_point
,
216 const base::Closure
& callback
) {
220 void PpapiCommandBufferProxy::SignalQuery(uint32 query
,
221 const base::Closure
& callback
) {
225 void PpapiCommandBufferProxy::SetSurfaceVisible(bool visible
) {
229 void PpapiCommandBufferProxy::SendManagedMemoryStats(
230 const gpu::ManagedMemoryStats
& stats
) {
234 gpu::Capabilities
PpapiCommandBufferProxy::GetCapabilities() {
235 // TODO(boliu): Need to implement this to use cc in Pepper. Tracked in
237 return gpu::Capabilities();
240 gfx::GpuMemoryBuffer
* PpapiCommandBufferProxy::CreateGpuMemoryBuffer(
243 unsigned internalformat
,
249 void PpapiCommandBufferProxy::DestroyGpuMemoryBuffer(int32 id
) {
253 bool PpapiCommandBufferProxy::GenerateMailboxNames(
254 unsigned num
, std::vector
<gpu::Mailbox
>* names
) {
255 // TODO(piman): implement this so we can expose mailboxes to pepper
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
;