blob: a457bc4f826a022a54e367c94a0a9ee83190de00 [file] [log] [blame]
[email protected]aaa11b32012-03-08 12:30:131// 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.
4
5#include "ppapi/proxy/ppapi_command_buffer_proxy.h"
6
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
12namespace ppapi {
13namespace proxy {
14
15PpapiCommandBufferProxy::PpapiCommandBufferProxy(
16 const ppapi::HostResource& resource,
17 ProxyChannel* channel)
18 : resource_(resource),
19 channel_(channel) {
20}
21
22PpapiCommandBufferProxy::~PpapiCommandBufferProxy() {
23 // Delete all the locally cached shared memory objects, closing the handle
24 // in this process.
25 for (TransferBufferMap::iterator it = transfer_buffers_.begin();
26 it != transfer_buffers_.end(); ++it) {
27 delete it->second.shared_memory;
28 it->second.shared_memory = NULL;
29 }
30}
31
32bool PpapiCommandBufferProxy::Initialize() {
33 return Send(new PpapiHostMsg_PPBGraphics3D_InitCommandBuffer(
34 ppapi::API_ID_PPB_GRAPHICS_3D, resource_));
35}
36
37gpu::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;
41 if (Send(new PpapiHostMsg_PPBGraphics3D_GetState(
42 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &state))) {
43 UpdateState(state);
44 }
45 }
46
47 return last_state_;
48}
49
50gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() {
51 return last_state_;
52}
53
54void PpapiCommandBufferProxy::Flush(int32 put_offset) {
55 if (last_state_.error != gpu::error::kNoError)
56 return;
57
58 IPC::Message* message = new PpapiHostMsg_PPBGraphics3D_AsyncFlush(
59 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, put_offset);
60
61 // Do not let a synchronous flush hold up this message. If this handler is
62 // deferred until after the synchronous flush completes, it will overwrite the
63 // cached last_state_ with out-of-date data.
64 message->set_unblock(true);
65 Send(message);
66}
67
68gpu::CommandBuffer::State PpapiCommandBufferProxy::FlushSync(int32 put_offset,
69 int32 last_known_get) {
70 if (last_known_get == last_state_.get_offset) {
71 // Send will flag state with lost context if IPC fails.
72 if (last_state_.error == gpu::error::kNoError) {
73 gpu::CommandBuffer::State state;
74 if (Send(new PpapiHostMsg_PPBGraphics3D_Flush(
75 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, put_offset,
76 last_known_get, &state))) {
77 UpdateState(state);
78 }
79 }
80 } else {
81 Flush(put_offset);
82 }
83 return last_state_;
84}
85
86void PpapiCommandBufferProxy::SetGetBuffer(int32 transfer_buffer_id) {
87 if (last_state_.error == gpu::error::kNoError) {
88 Send(new PpapiHostMsg_PPBGraphics3D_SetGetBuffer(
89 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, transfer_buffer_id));
90 }
91}
92
93void PpapiCommandBufferProxy::SetGetOffset(int32 get_offset) {
94 // Not implemented in proxy.
95 NOTREACHED();
96}
97
98int32 PpapiCommandBufferProxy::CreateTransferBuffer(
99 size_t size,
100 int32 id_request) {
101 if (last_state_.error == gpu::error::kNoError) {
102 int32 id;
103 if (Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
104 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, &id))) {
105 return id;
106 }
107 }
108 return -1;
109}
110
111int32 PpapiCommandBufferProxy::RegisterTransferBuffer(
112 base::SharedMemory* shared_memory,
113 size_t size,
114 int32 id_request) {
115 // Not implemented in proxy.
116 NOTREACHED();
117 return -1;
118}
119
120void PpapiCommandBufferProxy::DestroyTransferBuffer(int32 id) {
121 if (last_state_.error != gpu::error::kNoError)
122 return;
123
124 // Remove the transfer buffer from the client side4 cache.
125 TransferBufferMap::iterator it = transfer_buffers_.find(id);
126 DCHECK(it != transfer_buffers_.end());
127
128 // Delete the shared memory object, closing the handle in this process.
129 delete it->second.shared_memory;
130
131 transfer_buffers_.erase(it);
132
133 Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer(
134 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id));
135}
136
137gpu::Buffer PpapiCommandBufferProxy::GetTransferBuffer(int32 id) {
138 if (last_state_.error != gpu::error::kNoError)
139 return gpu::Buffer();
140
141 // Check local cache to see if there is already a client side shared memory
142 // object for this id.
143 TransferBufferMap::iterator it = transfer_buffers_.find(id);
144 if (it != transfer_buffers_.end()) {
145 return it->second;
146 }
147
148 // Assuming we are in the renderer process, the service is responsible for
149 // duplicating the handle. This might not be true for NaCl.
150 base::SharedMemoryHandle handle;
151 uint32 size;
152 if (!Send(new PpapiHostMsg_PPBGraphics3D_GetTransferBuffer(
153 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id, &handle, &size))) {
154 return gpu::Buffer();
155 }
156
157 // Cache the transfer buffer shared memory object client side.
158 scoped_ptr<base::SharedMemory> shared_memory(
159 new base::SharedMemory(handle, false));
160
161 // Map the shared memory on demand.
162 if (!shared_memory->memory()) {
163 if (!shared_memory->Map(size)) {
164 return gpu::Buffer();
165 }
166 }
167
168 gpu::Buffer buffer;
169 buffer.ptr = shared_memory->memory();
170 buffer.size = size;
171 buffer.shared_memory = shared_memory.release();
172 transfer_buffers_[id] = buffer;
173
174 return buffer;
175}
176
177void PpapiCommandBufferProxy::SetToken(int32 token) {
178 NOTREACHED();
179}
180
181void PpapiCommandBufferProxy::SetParseError(gpu::error::Error error) {
182 NOTREACHED();
183}
184
185void PpapiCommandBufferProxy::SetContextLostReason(
186 gpu::error::ContextLostReason reason) {
187 NOTREACHED();
188}
189
190bool PpapiCommandBufferProxy::Send(IPC::Message* msg) {
191 DCHECK(last_state_.error == gpu::error::kNoError);
192
193 if (channel_->Send(msg))
194 return true;
195
196 last_state_.error = gpu::error::kLostContext;
197 return false;
198}
199
200void PpapiCommandBufferProxy::UpdateState(
201 const gpu::CommandBuffer::State& state) {
202 // Handle wraparound. It works as long as we don't have more than 2B state
203 // updates in flight across which reordering occurs.
204 if (state.generation - last_state_.generation < 0x80000000U)
205 last_state_ = state;
206}
207
208} // namespace proxy
209} // namespace ppapi
210