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. 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 #include "ppapi/shared_impl/proxy_lock.h" 12 13 namespace ppapi { 14 namespace proxy { 15 16 PpapiCommandBufferProxy::PpapiCommandBufferProxy( 17 const ppapi::HostResource& resource, 18 ProxyChannel* channel) 19 : resource_(resource), 20 channel_(channel) { 21 } 22 23 PpapiCommandBufferProxy::~PpapiCommandBufferProxy() { 24 // gpu::Buffers are no longer referenced, allowing shared memory objects to be 25 // deleted, closing the handle in this process. 26 } 27 28 bool PpapiCommandBufferProxy::Initialize() { 29 return true; 30 } 31 32 gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() { 33 ppapi::ProxyLock::AssertAcquiredDebugOnly(); 34 return last_state_; 35 } 36 37 int32 PpapiCommandBufferProxy::GetLastToken() { 38 ppapi::ProxyLock::AssertAcquiredDebugOnly(); 39 return last_state_.token; 40 } 41 42 void PpapiCommandBufferProxy::Flush(int32 put_offset) { 43 if (last_state_.error != gpu::error::kNoError) 44 return; 45 46 IPC::Message* message = new PpapiHostMsg_PPBGraphics3D_AsyncFlush( 47 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, put_offset); 48 49 // Do not let a synchronous flush hold up this message. If this handler is 50 // deferred until after the synchronous flush completes, it will overwrite the 51 // cached last_state_ with out-of-date data. 52 message->set_unblock(true); 53 Send(message); 54 } 55 56 void PpapiCommandBufferProxy::WaitForTokenInRange(int32 start, int32 end) { 57 if (last_state_.error != gpu::error::kNoError) 58 return; 59 60 bool success; 61 gpu::CommandBuffer::State state; 62 if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange( 63 ppapi::API_ID_PPB_GRAPHICS_3D, 64 resource_, 65 start, 66 end, 67 &state, 68 &success))) 69 UpdateState(state, success); 70 } 71 72 void PpapiCommandBufferProxy::WaitForGetOffsetInRange(int32 start, int32 end) { 73 if (last_state_.error != gpu::error::kNoError) 74 return; 75 76 bool success; 77 gpu::CommandBuffer::State state; 78 if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange( 79 ppapi::API_ID_PPB_GRAPHICS_3D, 80 resource_, 81 start, 82 end, 83 &state, 84 &success))) 85 UpdateState(state, success); 86 } 87 88 void PpapiCommandBufferProxy::SetGetBuffer(int32 transfer_buffer_id) { 89 if (last_state_.error == gpu::error::kNoError) { 90 Send(new PpapiHostMsg_PPBGraphics3D_SetGetBuffer( 91 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, transfer_buffer_id)); 92 } 93 } 94 95 scoped_refptr<gpu::Buffer> PpapiCommandBufferProxy::CreateTransferBuffer( 96 size_t size, 97 int32* id) { 98 *id = -1; 99 100 if (last_state_.error != gpu::error::kNoError) 101 return NULL; 102 103 // Assuming we are in the renderer process, the service is responsible for 104 // duplicating the handle. This might not be true for NaCl. 105 ppapi::proxy::SerializedHandle handle( 106 ppapi::proxy::SerializedHandle::SHARED_MEMORY); 107 if (!Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer( 108 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, id, &handle))) { 109 return NULL; 110 } 111 112 if (*id <= 0 || !handle.is_shmem()) 113 return NULL; 114 115 scoped_ptr<base::SharedMemory> shared_memory( 116 new base::SharedMemory(handle.shmem(), false)); 117 118 // Map the shared memory on demand. 119 if (!shared_memory->memory()) { 120 if (!shared_memory->Map(handle.size())) { 121 *id = -1; 122 return NULL; 123 } 124 } 125 126 return gpu::MakeBufferFromSharedMemory(shared_memory.Pass(), handle.size()); 127 } 128 129 void PpapiCommandBufferProxy::DestroyTransferBuffer(int32 id) { 130 if (last_state_.error != gpu::error::kNoError) 131 return; 132 133 Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer( 134 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id)); 135 } 136 137 void PpapiCommandBufferProxy::Echo(const base::Closure& callback) { 138 NOTREACHED(); 139 } 140 141 uint32 PpapiCommandBufferProxy::CreateStreamTexture(uint32 texture_id) { 142 NOTREACHED(); 143 return 0; 144 } 145 146 uint32 PpapiCommandBufferProxy::InsertSyncPoint() { 147 uint32 sync_point = 0; 148 if (last_state_.error == gpu::error::kNoError) { 149 Send(new PpapiHostMsg_PPBGraphics3D_InsertSyncPoint( 150 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &sync_point)); 151 } 152 return sync_point; 153 } 154 155 void PpapiCommandBufferProxy::SignalSyncPoint(uint32 sync_point, 156 const base::Closure& callback) { 157 NOTREACHED(); 158 } 159 160 void PpapiCommandBufferProxy::SignalQuery(uint32 query, 161 const base::Closure& callback) { 162 NOTREACHED(); 163 } 164 165 void PpapiCommandBufferProxy::SetSurfaceVisible(bool visible) { 166 NOTREACHED(); 167 } 168 169 gpu::Capabilities PpapiCommandBufferProxy::GetCapabilities() { 170 // TODO(boliu): Need to implement this to use cc in Pepper. Tracked in 171 // crbug.com/325391. 172 return gpu::Capabilities(); 173 } 174 175 gfx::GpuMemoryBuffer* PpapiCommandBufferProxy::CreateGpuMemoryBuffer( 176 size_t width, 177 size_t height, 178 unsigned internalformat, 179 unsigned usage, 180 int32* id) { 181 NOTREACHED(); 182 return NULL; 183 } 184 185 void PpapiCommandBufferProxy::DestroyGpuMemoryBuffer(int32 id) { 186 NOTREACHED(); 187 } 188 189 bool PpapiCommandBufferProxy::Send(IPC::Message* msg) { 190 DCHECK(last_state_.error == gpu::error::kNoError); 191 192 if (channel_->Send(msg)) 193 return true; 194 195 last_state_.error = gpu::error::kLostContext; 196 return false; 197 } 198 199 void PpapiCommandBufferProxy::UpdateState( 200 const gpu::CommandBuffer::State& state, 201 bool success) { 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 (success) { 205 if (state.generation - last_state_.generation < 0x80000000U) { 206 last_state_ = state; 207 } 208 } else { 209 last_state_.error = gpu::error::kLostContext; 210 ++last_state_.generation; 211 } 212 } 213 214 } // namespace proxy 215 } // namespace ppapi 216