Refactor android test results logging.
[chromium-blink-merge.git] / ppapi / proxy / ppapi_command_buffer_proxy.cc
blobad80a2720d603bf474abe41d0642c9807815cf5b
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"
12 namespace ppapi {
13 namespace proxy {
15 PpapiCommandBufferProxy::PpapiCommandBufferProxy(
16 const ppapi::HostResource& resource,
17 ProxyChannel* channel)
18 : resource_(resource),
19 channel_(channel) {
22 PpapiCommandBufferProxy::~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;
32 void PpapiCommandBufferProxy::ReportChannelError() {
33 if (!channel_error_callback_.is_null()) {
34 channel_error_callback_.Run();
35 channel_error_callback_.Reset();
39 int PpapiCommandBufferProxy::GetRouteID() const {
40 NOTIMPLEMENTED();
41 return 0;
44 bool PpapiCommandBufferProxy::Echo(const base::Closure& callback) {
45 return false;
48 bool PpapiCommandBufferProxy::SetParent(
49 CommandBufferProxy* parent_command_buffer,
50 uint32 parent_texture_id) {
51 // TODO(fsamuel): Need a proper implementation of this to support offscreen
52 // contexts in the guest renderer (WebGL, canvas, etc).
53 NOTIMPLEMENTED();
54 return false;
57 void PpapiCommandBufferProxy::SetChannelErrorCallback(
58 const base::Closure& callback) {
59 channel_error_callback_ = callback;
62 bool PpapiCommandBufferProxy::Initialize() {
63 return Send(new PpapiHostMsg_PPBGraphics3D_InitCommandBuffer(
64 ppapi::API_ID_PPB_GRAPHICS_3D, resource_));
67 gpu::CommandBuffer::State PpapiCommandBufferProxy::GetState() {
68 // Send will flag state with lost context if IPC fails.
69 if (last_state_.error == gpu::error::kNoError) {
70 gpu::CommandBuffer::State state;
71 bool success = false;
72 if (Send(new PpapiHostMsg_PPBGraphics3D_GetState(
73 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &state, &success))) {
74 UpdateState(state, success);
78 return last_state_;
81 gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() {
82 // Note: The locking command buffer wrapper does not take a global lock before
83 // calling this function.
84 return last_state_;
87 void PpapiCommandBufferProxy::Flush(int32 put_offset) {
88 if (last_state_.error != gpu::error::kNoError)
89 return;
91 IPC::Message* message = new PpapiHostMsg_PPBGraphics3D_AsyncFlush(
92 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, put_offset);
94 // Do not let a synchronous flush hold up this message. If this handler is
95 // deferred until after the synchronous flush completes, it will overwrite the
96 // cached last_state_ with out-of-date data.
97 message->set_unblock(true);
98 Send(message);
101 gpu::CommandBuffer::State PpapiCommandBufferProxy::FlushSync(int32 put_offset,
102 int32 last_known_get) {
103 if (last_known_get == last_state_.get_offset) {
104 // Send will flag state with lost context if IPC fails.
105 if (last_state_.error == gpu::error::kNoError) {
106 gpu::CommandBuffer::State state;
107 bool success = false;
108 if (Send(new PpapiHostMsg_PPBGraphics3D_Flush(
109 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, put_offset,
110 last_known_get, &state, &success))) {
111 UpdateState(state, success);
114 } else {
115 Flush(put_offset);
117 return last_state_;
120 void PpapiCommandBufferProxy::SetGetBuffer(int32 transfer_buffer_id) {
121 if (last_state_.error == gpu::error::kNoError) {
122 Send(new PpapiHostMsg_PPBGraphics3D_SetGetBuffer(
123 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, transfer_buffer_id));
127 void PpapiCommandBufferProxy::SetGetOffset(int32 get_offset) {
128 // Not implemented in proxy.
129 NOTREACHED();
132 int32 PpapiCommandBufferProxy::CreateTransferBuffer(
133 size_t size,
134 int32 id_request) {
135 if (last_state_.error == gpu::error::kNoError) {
136 int32 id;
137 if (Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
138 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, &id))) {
139 return id;
142 return -1;
145 int32 PpapiCommandBufferProxy::RegisterTransferBuffer(
146 base::SharedMemory* shared_memory,
147 size_t size,
148 int32 id_request) {
149 // Not implemented in proxy.
150 NOTREACHED();
151 return -1;
154 void PpapiCommandBufferProxy::DestroyTransferBuffer(int32 id) {
155 if (last_state_.error != gpu::error::kNoError)
156 return;
158 // Remove the transfer buffer from the client side4 cache.
159 TransferBufferMap::iterator it = transfer_buffers_.find(id);
161 if (it != transfer_buffers_.end()) {
162 // Delete the shared memory object, closing the handle in this process.
163 delete it->second.shared_memory;
165 transfer_buffers_.erase(it);
168 Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer(
169 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id));
172 gpu::Buffer PpapiCommandBufferProxy::GetTransferBuffer(int32 id) {
173 if (last_state_.error != gpu::error::kNoError)
174 return gpu::Buffer();
176 // Check local cache to see if there is already a client side shared memory
177 // object for this id.
178 TransferBufferMap::iterator it = transfer_buffers_.find(id);
179 if (it != transfer_buffers_.end()) {
180 return it->second;
183 // Assuming we are in the renderer process, the service is responsible for
184 // duplicating the handle. This might not be true for NaCl.
185 ppapi::proxy::SerializedHandle handle(
186 ppapi::proxy::SerializedHandle::SHARED_MEMORY);
187 if (!Send(new PpapiHostMsg_PPBGraphics3D_GetTransferBuffer(
188 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id, &handle))) {
189 return gpu::Buffer();
191 if (!handle.is_shmem())
192 return gpu::Buffer();
194 // Cache the transfer buffer shared memory object client side.
195 scoped_ptr<base::SharedMemory> shared_memory(
196 new base::SharedMemory(handle.shmem(), false));
198 // Map the shared memory on demand.
199 if (!shared_memory->memory()) {
200 if (!shared_memory->Map(handle.size())) {
201 return gpu::Buffer();
205 gpu::Buffer buffer;
206 buffer.ptr = shared_memory->memory();
207 buffer.size = handle.size();
208 buffer.shared_memory = shared_memory.release();
209 transfer_buffers_[id] = buffer;
211 return buffer;
214 void PpapiCommandBufferProxy::SetToken(int32 token) {
215 NOTREACHED();
218 void PpapiCommandBufferProxy::SetParseError(gpu::error::Error error) {
219 NOTREACHED();
222 void PpapiCommandBufferProxy::SetContextLostReason(
223 gpu::error::ContextLostReason reason) {
224 NOTREACHED();
227 bool PpapiCommandBufferProxy::Send(IPC::Message* msg) {
228 DCHECK(last_state_.error == gpu::error::kNoError);
230 if (channel_->Send(msg))
231 return true;
233 last_state_.error = gpu::error::kLostContext;
234 return false;
237 void PpapiCommandBufferProxy::UpdateState(
238 const gpu::CommandBuffer::State& state,
239 bool success) {
240 // Handle wraparound. It works as long as we don't have more than 2B state
241 // updates in flight across which reordering occurs.
242 if (success) {
243 if (state.generation - last_state_.generation < 0x80000000U) {
244 last_state_ = state;
246 } else {
247 last_state_.error = gpu::error::kLostContext;
248 ++last_state_.generation;
252 } // namespace proxy
253 } // namespace ppapi