Plugin Power Saver: Force SW rendering for peripheral plugins.
[chromium-blink-merge.git] / ppapi / proxy / ppapi_command_buffer_proxy.cc
blobfd84d01d7b8b411b45531368645396d65ed87a96
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"
13 namespace ppapi {
14 namespace proxy {
16 PpapiCommandBufferProxy::PpapiCommandBufferProxy(
17 const ppapi::HostResource& resource,
18 ProxyChannel* channel,
19 const gpu::Capabilities& capabilities,
20 const SerializedHandle& shared_state)
21 : capabilities_(capabilities),
22 resource_(resource),
23 channel_(channel) {
24 shared_state_shm_.reset(
25 new base::SharedMemory(shared_state.shmem(), false));
26 shared_state_shm_->Map(shared_state.size());
29 PpapiCommandBufferProxy::~PpapiCommandBufferProxy() {
30 // gpu::Buffers are no longer referenced, allowing shared memory objects to be
31 // deleted, closing the handle in this process.
34 bool PpapiCommandBufferProxy::Initialize() {
35 return true;
38 gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() {
39 ppapi::ProxyLock::AssertAcquiredDebugOnly();
40 return last_state_;
43 int32 PpapiCommandBufferProxy::GetLastToken() {
44 ppapi::ProxyLock::AssertAcquiredDebugOnly();
45 TryUpdateState();
46 return last_state_.token;
49 void PpapiCommandBufferProxy::Flush(int32 put_offset) {
50 if (last_state_.error != gpu::error::kNoError)
51 return;
53 IPC::Message* message = new PpapiHostMsg_PPBGraphics3D_AsyncFlush(
54 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, put_offset);
56 // Do not let a synchronous flush hold up this message. If this handler is
57 // deferred until after the synchronous flush completes, it will overwrite the
58 // cached last_state_ with out-of-date data.
59 message->set_unblock(true);
60 Send(message);
63 void PpapiCommandBufferProxy::WaitForTokenInRange(int32 start, int32 end) {
64 TryUpdateState();
65 if (!InRange(start, end, last_state_.token) &&
66 last_state_.error == gpu::error::kNoError) {
67 bool success = false;
68 gpu::CommandBuffer::State state;
69 if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange(
70 ppapi::API_ID_PPB_GRAPHICS_3D,
71 resource_,
72 start,
73 end,
74 &state,
75 &success)))
76 UpdateState(state, success);
78 DCHECK(InRange(start, end, last_state_.token) ||
79 last_state_.error != gpu::error::kNoError);
82 void PpapiCommandBufferProxy::WaitForGetOffsetInRange(int32 start, int32 end) {
83 TryUpdateState();
84 if (!InRange(start, end, last_state_.get_offset) &&
85 last_state_.error == gpu::error::kNoError) {
86 bool success = false;
87 gpu::CommandBuffer::State state;
88 if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange(
89 ppapi::API_ID_PPB_GRAPHICS_3D,
90 resource_,
91 start,
92 end,
93 &state,
94 &success)))
95 UpdateState(state, success);
97 DCHECK(InRange(start, end, last_state_.get_offset) ||
98 last_state_.error != gpu::error::kNoError);
101 void PpapiCommandBufferProxy::SetGetBuffer(int32 transfer_buffer_id) {
102 if (last_state_.error == gpu::error::kNoError) {
103 Send(new PpapiHostMsg_PPBGraphics3D_SetGetBuffer(
104 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, transfer_buffer_id));
108 scoped_refptr<gpu::Buffer> PpapiCommandBufferProxy::CreateTransferBuffer(
109 size_t size,
110 int32* id) {
111 *id = -1;
113 if (last_state_.error != gpu::error::kNoError)
114 return NULL;
116 // Assuming we are in the renderer process, the service is responsible for
117 // duplicating the handle. This might not be true for NaCl.
118 ppapi::proxy::SerializedHandle handle(
119 ppapi::proxy::SerializedHandle::SHARED_MEMORY);
120 if (!Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
121 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, id, &handle))) {
122 return NULL;
125 if (*id <= 0 || !handle.is_shmem())
126 return NULL;
128 scoped_ptr<base::SharedMemory> shared_memory(
129 new base::SharedMemory(handle.shmem(), false));
131 // Map the shared memory on demand.
132 if (!shared_memory->memory()) {
133 if (!shared_memory->Map(handle.size())) {
134 *id = -1;
135 return NULL;
139 return gpu::MakeBufferFromSharedMemory(shared_memory.Pass(), handle.size());
142 void PpapiCommandBufferProxy::DestroyTransferBuffer(int32 id) {
143 if (last_state_.error != gpu::error::kNoError)
144 return;
146 Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer(
147 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id));
150 uint32 PpapiCommandBufferProxy::CreateStreamTexture(uint32 texture_id) {
151 NOTREACHED();
152 return 0;
155 uint32 PpapiCommandBufferProxy::InsertSyncPoint() {
156 uint32 sync_point = 0;
157 if (last_state_.error == gpu::error::kNoError) {
158 Send(new PpapiHostMsg_PPBGraphics3D_InsertSyncPoint(
159 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &sync_point));
161 return sync_point;
164 uint32 PpapiCommandBufferProxy::InsertFutureSyncPoint() {
165 uint32 sync_point = 0;
166 if (last_state_.error == gpu::error::kNoError) {
167 Send(new PpapiHostMsg_PPBGraphics3D_InsertFutureSyncPoint(
168 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &sync_point));
170 return sync_point;
173 void PpapiCommandBufferProxy::RetireSyncPoint(uint32 sync_point) {
174 if (last_state_.error == gpu::error::kNoError) {
175 Send(new PpapiHostMsg_PPBGraphics3D_RetireSyncPoint(
176 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, sync_point));
180 void PpapiCommandBufferProxy::SignalSyncPoint(uint32 sync_point,
181 const base::Closure& callback) {
182 NOTREACHED();
185 void PpapiCommandBufferProxy::SignalQuery(uint32 query,
186 const base::Closure& callback) {
187 NOTREACHED();
190 void PpapiCommandBufferProxy::SetSurfaceVisible(bool visible) {
191 NOTREACHED();
194 gpu::Capabilities PpapiCommandBufferProxy::GetCapabilities() {
195 return capabilities_;
198 int32 PpapiCommandBufferProxy::CreateImage(ClientBuffer buffer,
199 size_t width,
200 size_t height,
201 unsigned internalformat) {
202 NOTREACHED();
203 return -1;
206 void PpapiCommandBufferProxy::DestroyImage(int32 id) {
207 NOTREACHED();
210 int32 PpapiCommandBufferProxy::CreateGpuMemoryBufferImage(
211 size_t width,
212 size_t height,
213 unsigned internalformat,
214 unsigned usage) {
215 NOTREACHED();
216 return -1;
219 bool PpapiCommandBufferProxy::Send(IPC::Message* msg) {
220 DCHECK(last_state_.error == gpu::error::kNoError);
222 // We need hold the Pepper proxy lock for sync IPC, because GPU command buffer
223 // may use a sync IPC with another lock held. It may cause deadlock.
224 // http://crbug.com/418651
225 if (channel_->SendAndStayLocked(msg))
226 return true;
228 last_state_.error = gpu::error::kLostContext;
229 return false;
232 void PpapiCommandBufferProxy::UpdateState(
233 const gpu::CommandBuffer::State& state,
234 bool success) {
235 // Handle wraparound. It works as long as we don't have more than 2B state
236 // updates in flight across which reordering occurs.
237 if (success) {
238 if (state.generation - last_state_.generation < 0x80000000U) {
239 last_state_ = state;
241 } else {
242 last_state_.error = gpu::error::kLostContext;
243 ++last_state_.generation;
247 void PpapiCommandBufferProxy::TryUpdateState() {
248 if (last_state_.error == gpu::error::kNoError)
249 shared_state()->Read(&last_state_);
252 gpu::CommandBufferSharedState* PpapiCommandBufferProxy::shared_state() const {
253 return reinterpret_cast<gpu::CommandBufferSharedState*>(
254 shared_state_shm_->memory());
257 } // namespace proxy
258 } // namespace ppapi