Refactor WebsiteSettings to operate on a SecurityInfo
[chromium-blink-merge.git] / ppapi / proxy / ppapi_command_buffer_proxy.cc
blobc430c784d167347e85536a6ca85d8b373fab2c3d
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 "base/numerics/safe_conversions.h"
8 #include "ppapi/proxy/ppapi_messages.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 PluginDispatcher* dispatcher,
19 const gpu::Capabilities& capabilities,
20 const SerializedHandle& shared_state,
21 uint64_t command_buffer_id)
22 : command_buffer_id_(command_buffer_id),
23 capabilities_(capabilities),
24 resource_(resource),
25 dispatcher_(dispatcher) {
26 shared_state_shm_.reset(
27 new base::SharedMemory(shared_state.shmem(), false));
28 shared_state_shm_->Map(shared_state.size());
29 InstanceData* data = dispatcher->GetInstanceData(resource.instance());
30 flush_info_ = &data->flush_info_;
33 PpapiCommandBufferProxy::~PpapiCommandBufferProxy() {
34 // gpu::Buffers are no longer referenced, allowing shared memory objects to be
35 // deleted, closing the handle in this process.
38 bool PpapiCommandBufferProxy::Initialize() {
39 return true;
42 gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() {
43 ppapi::ProxyLock::AssertAcquiredDebugOnly();
44 return last_state_;
47 int32 PpapiCommandBufferProxy::GetLastToken() {
48 ppapi::ProxyLock::AssertAcquiredDebugOnly();
49 TryUpdateState();
50 return last_state_.token;
53 void PpapiCommandBufferProxy::Flush(int32 put_offset) {
54 if (last_state_.error != gpu::error::kNoError)
55 return;
57 OrderingBarrier(put_offset);
58 FlushInternal();
61 void PpapiCommandBufferProxy::OrderingBarrier(int32 put_offset) {
62 if (last_state_.error != gpu::error::kNoError)
63 return;
65 if (flush_info_->flush_pending && flush_info_->resource != resource_)
66 FlushInternal();
68 flush_info_->flush_pending = true;
69 flush_info_->resource = resource_;
70 flush_info_->put_offset = put_offset;
73 void PpapiCommandBufferProxy::WaitForTokenInRange(int32 start, int32 end) {
74 TryUpdateState();
75 if (!InRange(start, end, last_state_.token) &&
76 last_state_.error == gpu::error::kNoError) {
77 bool success = false;
78 gpu::CommandBuffer::State state;
79 if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange(
80 ppapi::API_ID_PPB_GRAPHICS_3D,
81 resource_,
82 start,
83 end,
84 &state,
85 &success)))
86 UpdateState(state, success);
88 DCHECK(InRange(start, end, last_state_.token) ||
89 last_state_.error != gpu::error::kNoError);
92 void PpapiCommandBufferProxy::WaitForGetOffsetInRange(int32 start, int32 end) {
93 TryUpdateState();
94 if (!InRange(start, end, last_state_.get_offset) &&
95 last_state_.error == gpu::error::kNoError) {
96 bool success = false;
97 gpu::CommandBuffer::State state;
98 if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange(
99 ppapi::API_ID_PPB_GRAPHICS_3D,
100 resource_,
101 start,
102 end,
103 &state,
104 &success)))
105 UpdateState(state, success);
107 DCHECK(InRange(start, end, last_state_.get_offset) ||
108 last_state_.error != gpu::error::kNoError);
111 void PpapiCommandBufferProxy::SetGetBuffer(int32 transfer_buffer_id) {
112 if (last_state_.error == gpu::error::kNoError) {
113 Send(new PpapiHostMsg_PPBGraphics3D_SetGetBuffer(
114 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, transfer_buffer_id));
118 scoped_refptr<gpu::Buffer> PpapiCommandBufferProxy::CreateTransferBuffer(
119 size_t size,
120 int32* id) {
121 *id = -1;
123 if (last_state_.error != gpu::error::kNoError)
124 return NULL;
126 // Assuming we are in the renderer process, the service is responsible for
127 // duplicating the handle. This might not be true for NaCl.
128 ppapi::proxy::SerializedHandle handle(
129 ppapi::proxy::SerializedHandle::SHARED_MEMORY);
130 if (!Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
131 ppapi::API_ID_PPB_GRAPHICS_3D, resource_,
132 base::checked_cast<uint32_t>(size), id, &handle))) {
133 if (last_state_.error == gpu::error::kNoError)
134 last_state_.error = gpu::error::kLostContext;
135 return NULL;
138 if (*id <= 0 || !handle.is_shmem()) {
139 if (last_state_.error == gpu::error::kNoError)
140 last_state_.error = gpu::error::kOutOfBounds;
141 return NULL;
144 scoped_ptr<base::SharedMemory> shared_memory(
145 new base::SharedMemory(handle.shmem(), false));
147 // Map the shared memory on demand.
148 if (!shared_memory->memory()) {
149 if (!shared_memory->Map(handle.size())) {
150 if (last_state_.error == gpu::error::kNoError)
151 last_state_.error = gpu::error::kOutOfBounds;
152 *id = -1;
153 return NULL;
157 return gpu::MakeBufferFromSharedMemory(shared_memory.Pass(), handle.size());
160 void PpapiCommandBufferProxy::DestroyTransferBuffer(int32 id) {
161 if (last_state_.error != gpu::error::kNoError)
162 return;
164 Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer(
165 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id));
168 uint32 PpapiCommandBufferProxy::CreateStreamTexture(uint32 texture_id) {
169 NOTREACHED();
170 return 0;
173 void PpapiCommandBufferProxy::SetLock(base::Lock*) {
174 NOTIMPLEMENTED();
177 bool PpapiCommandBufferProxy::IsGpuChannelLost() {
178 NOTIMPLEMENTED();
179 return false;
182 gpu::CommandBufferNamespace PpapiCommandBufferProxy::GetNamespaceID() const {
183 return gpu::CommandBufferNamespace::GPU_IO;
186 uint64_t PpapiCommandBufferProxy::GetCommandBufferID() const {
187 return command_buffer_id_;
190 uint32 PpapiCommandBufferProxy::InsertSyncPoint() {
191 uint32 sync_point = 0;
192 if (last_state_.error == gpu::error::kNoError) {
193 Send(new PpapiHostMsg_PPBGraphics3D_InsertSyncPoint(
194 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &sync_point));
196 return sync_point;
199 uint32 PpapiCommandBufferProxy::InsertFutureSyncPoint() {
200 uint32 sync_point = 0;
201 if (last_state_.error == gpu::error::kNoError) {
202 Send(new PpapiHostMsg_PPBGraphics3D_InsertFutureSyncPoint(
203 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &sync_point));
205 return sync_point;
208 void PpapiCommandBufferProxy::RetireSyncPoint(uint32 sync_point) {
209 if (last_state_.error == gpu::error::kNoError) {
210 Send(new PpapiHostMsg_PPBGraphics3D_RetireSyncPoint(
211 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, sync_point));
215 void PpapiCommandBufferProxy::SignalSyncPoint(uint32 sync_point,
216 const base::Closure& callback) {
217 NOTREACHED();
220 void PpapiCommandBufferProxy::SignalQuery(uint32 query,
221 const base::Closure& callback) {
222 NOTREACHED();
225 void PpapiCommandBufferProxy::SetSurfaceVisible(bool visible) {
226 NOTREACHED();
229 gpu::Capabilities PpapiCommandBufferProxy::GetCapabilities() {
230 return capabilities_;
233 int32 PpapiCommandBufferProxy::CreateImage(ClientBuffer buffer,
234 size_t width,
235 size_t height,
236 unsigned internalformat) {
237 NOTREACHED();
238 return -1;
241 void PpapiCommandBufferProxy::DestroyImage(int32 id) {
242 NOTREACHED();
245 int32 PpapiCommandBufferProxy::CreateGpuMemoryBufferImage(
246 size_t width,
247 size_t height,
248 unsigned internalformat,
249 unsigned usage) {
250 NOTREACHED();
251 return -1;
254 bool PpapiCommandBufferProxy::Send(IPC::Message* msg) {
255 DCHECK(last_state_.error == gpu::error::kNoError);
257 // We need to hold the Pepper proxy lock for sync IPC, because the GPU command
258 // buffer may use a sync IPC with another lock held which could lead to lock
259 // and deadlock if we dropped the proxy lock here.
260 // http://crbug.com/418651
261 if (dispatcher_->SendAndStayLocked(msg))
262 return true;
264 last_state_.error = gpu::error::kLostContext;
265 return false;
268 void PpapiCommandBufferProxy::UpdateState(
269 const gpu::CommandBuffer::State& state,
270 bool success) {
271 // Handle wraparound. It works as long as we don't have more than 2B state
272 // updates in flight across which reordering occurs.
273 if (success) {
274 if (state.generation - last_state_.generation < 0x80000000U) {
275 last_state_ = state;
277 } else {
278 last_state_.error = gpu::error::kLostContext;
279 ++last_state_.generation;
283 void PpapiCommandBufferProxy::TryUpdateState() {
284 if (last_state_.error == gpu::error::kNoError)
285 shared_state()->Read(&last_state_);
288 gpu::CommandBufferSharedState* PpapiCommandBufferProxy::shared_state() const {
289 return reinterpret_cast<gpu::CommandBufferSharedState*>(
290 shared_state_shm_->memory());
293 void PpapiCommandBufferProxy::FlushInternal() {
294 DCHECK(last_state_.error == gpu::error::kNoError);
296 DCHECK(flush_info_->flush_pending);
298 IPC::Message* message = new PpapiHostMsg_PPBGraphics3D_AsyncFlush(
299 ppapi::API_ID_PPB_GRAPHICS_3D, flush_info_->resource,
300 flush_info_->put_offset);
302 // Do not let a synchronous flush hold up this message. If this handler is
303 // deferred until after the synchronous flush completes, it will overwrite the
304 // cached last_state_ with out-of-date data.
305 message->set_unblock(true);
306 Send(message);
308 flush_info_->flush_pending = false;
309 flush_info_->resource.SetHostResource(0, 0);
312 } // namespace proxy
313 } // namespace ppapi