OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 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 "mojo/gles2/command_buffer_client_impl.h" |
| 6 |
| 7 #include <limits> |
| 8 |
| 9 #include "base/logging.h" |
| 10 #include "base/process/process_handle.h" |
| 11 #include "mojo/services/gles2/command_buffer_type_conversions.h" |
| 12 #include "mojo/services/gles2/mojo_buffer_backing.h" |
| 13 |
| 14 namespace gles2 { |
| 15 |
| 16 namespace { |
| 17 |
| 18 bool CreateMapAndDupSharedBuffer(size_t size, |
| 19 void** memory, |
| 20 mojo::ScopedSharedBufferHandle* handle, |
| 21 mojo::ScopedSharedBufferHandle* duped) { |
| 22 MojoResult result = mojo::CreateSharedBuffer(NULL, size, handle); |
| 23 if (result != MOJO_RESULT_OK) |
| 24 return false; |
| 25 DCHECK(handle->is_valid()); |
| 26 |
| 27 result = mojo::DuplicateBuffer(handle->get(), NULL, duped); |
| 28 if (result != MOJO_RESULT_OK) |
| 29 return false; |
| 30 DCHECK(duped->is_valid()); |
| 31 |
| 32 result = mojo::MapBuffer( |
| 33 handle->get(), 0, size, memory, MOJO_MAP_BUFFER_FLAG_NONE); |
| 34 if (result != MOJO_RESULT_OK) |
| 35 return false; |
| 36 DCHECK(*memory); |
| 37 |
| 38 return true; |
| 39 } |
| 40 |
| 41 } // namespace |
| 42 |
| 43 CommandBufferDelegate::~CommandBufferDelegate() {} |
| 44 |
| 45 void CommandBufferDelegate::ContextLost() {} |
| 46 |
| 47 class CommandBufferClientImpl::SyncClientImpl |
| 48 : public mojo::CommandBufferSyncClient { |
| 49 public: |
| 50 SyncClientImpl(mojo::CommandBufferSyncClientPtr* ptr, |
| 51 const MojoAsyncWaiter* async_waiter) |
| 52 : initialized_successfully_(false), binding_(this, ptr, async_waiter) {} |
| 53 |
| 54 bool WaitForInitialization() { |
| 55 if (!binding_.WaitForIncomingMethodCall()) |
| 56 return false; |
| 57 return initialized_successfully_; |
| 58 } |
| 59 |
| 60 mojo::CommandBufferStatePtr WaitForProgress() { |
| 61 if (!binding_.WaitForIncomingMethodCall()) |
| 62 return mojo::CommandBufferStatePtr(); |
| 63 return command_buffer_state_.Pass(); |
| 64 } |
| 65 |
| 66 gpu::Capabilities GetCapabilities() { |
| 67 return capabilities_.To<gpu::Capabilities>(); |
| 68 } |
| 69 |
| 70 private: |
| 71 // CommandBufferSyncClient methods: |
| 72 void DidInitialize(bool success, |
| 73 mojo::GpuCapabilitiesPtr capabilities) override { |
| 74 initialized_successfully_ = success; |
| 75 capabilities_ = capabilities.Pass(); |
| 76 } |
| 77 void DidMakeProgress(mojo::CommandBufferStatePtr state) override { |
| 78 command_buffer_state_ = state.Pass(); |
| 79 } |
| 80 |
| 81 bool initialized_successfully_; |
| 82 mojo::GpuCapabilitiesPtr capabilities_; |
| 83 mojo::CommandBufferStatePtr command_buffer_state_; |
| 84 mojo::Binding<mojo::CommandBufferSyncClient> binding_; |
| 85 |
| 86 DISALLOW_COPY_AND_ASSIGN(SyncClientImpl); |
| 87 }; |
| 88 |
| 89 class CommandBufferClientImpl::SyncPointClientImpl |
| 90 : public mojo::CommandBufferSyncPointClient { |
| 91 public: |
| 92 SyncPointClientImpl(mojo::CommandBufferSyncPointClientPtr* ptr, |
| 93 const MojoAsyncWaiter* async_waiter) |
| 94 : sync_point_(0u), binding_(this, ptr, async_waiter) {} |
| 95 |
| 96 uint32_t WaitForInsertSyncPoint() { |
| 97 if (!binding_.WaitForIncomingMethodCall()) |
| 98 return 0u; |
| 99 uint32_t result = sync_point_; |
| 100 sync_point_ = 0u; |
| 101 return result; |
| 102 } |
| 103 |
| 104 private: |
| 105 void DidInsertSyncPoint(uint32_t sync_point) override { |
| 106 sync_point_ = sync_point; |
| 107 } |
| 108 |
| 109 uint32_t sync_point_; |
| 110 |
| 111 mojo::Binding<mojo::CommandBufferSyncPointClient> binding_; |
| 112 }; |
| 113 |
| 114 CommandBufferClientImpl::CommandBufferClientImpl( |
| 115 CommandBufferDelegate* delegate, |
| 116 const MojoAsyncWaiter* async_waiter, |
| 117 mojo::ScopedMessagePipeHandle command_buffer_handle) |
| 118 : delegate_(delegate), |
| 119 observer_binding_(this), |
| 120 shared_state_(NULL), |
| 121 last_put_offset_(-1), |
| 122 next_transfer_buffer_id_(0), |
| 123 async_waiter_(async_waiter) { |
| 124 command_buffer_.Bind(command_buffer_handle.Pass(), async_waiter); |
| 125 command_buffer_.set_error_handler(this); |
| 126 } |
| 127 |
| 128 CommandBufferClientImpl::~CommandBufferClientImpl() {} |
| 129 |
| 130 bool CommandBufferClientImpl::Initialize() { |
| 131 const size_t kSharedStateSize = sizeof(gpu::CommandBufferSharedState); |
| 132 void* memory = NULL; |
| 133 mojo::ScopedSharedBufferHandle duped; |
| 134 bool result = CreateMapAndDupSharedBuffer( |
| 135 kSharedStateSize, &memory, &shared_state_handle_, &duped); |
| 136 if (!result) |
| 137 return false; |
| 138 |
| 139 shared_state_ = static_cast<gpu::CommandBufferSharedState*>(memory); |
| 140 |
| 141 shared_state()->Initialize(); |
| 142 |
| 143 mojo::CommandBufferSyncClientPtr sync_client; |
| 144 sync_client_impl_.reset(new SyncClientImpl(&sync_client, async_waiter_)); |
| 145 |
| 146 mojo::CommandBufferSyncPointClientPtr sync_point_client; |
| 147 sync_point_client_impl_.reset( |
| 148 new SyncPointClientImpl(&sync_point_client, async_waiter_)); |
| 149 |
| 150 mojo::CommandBufferLostContextObserverPtr observer_ptr; |
| 151 observer_binding_.Bind(GetProxy(&observer_ptr), async_waiter_); |
| 152 command_buffer_->Initialize(sync_client.Pass(), |
| 153 sync_point_client.Pass(), |
| 154 observer_ptr.Pass(), |
| 155 duped.Pass()); |
| 156 |
| 157 // Wait for DidInitialize to come on the sync client pipe. |
| 158 if (!sync_client_impl_->WaitForInitialization()) { |
| 159 VLOG(1) << "Channel encountered error while creating command buffer"; |
| 160 return false; |
| 161 } |
| 162 capabilities_ = sync_client_impl_->GetCapabilities(); |
| 163 return true; |
| 164 } |
| 165 |
| 166 gpu::CommandBuffer::State CommandBufferClientImpl::GetLastState() { |
| 167 return last_state_; |
| 168 } |
| 169 |
| 170 int32 CommandBufferClientImpl::GetLastToken() { |
| 171 TryUpdateState(); |
| 172 return last_state_.token; |
| 173 } |
| 174 |
| 175 void CommandBufferClientImpl::Flush(int32 put_offset) { |
| 176 if (last_put_offset_ == put_offset) |
| 177 return; |
| 178 |
| 179 last_put_offset_ = put_offset; |
| 180 command_buffer_->Flush(put_offset); |
| 181 } |
| 182 |
| 183 void CommandBufferClientImpl::OrderingBarrier(int32_t put_offset) { |
| 184 // TODO(jamesr): Implement this more efficiently. |
| 185 Flush(put_offset); |
| 186 } |
| 187 |
| 188 void CommandBufferClientImpl::WaitForTokenInRange(int32 start, int32 end) { |
| 189 TryUpdateState(); |
| 190 while (!InRange(start, end, last_state_.token) && |
| 191 last_state_.error == gpu::error::kNoError) { |
| 192 MakeProgressAndUpdateState(); |
| 193 TryUpdateState(); |
| 194 } |
| 195 } |
| 196 |
| 197 void CommandBufferClientImpl::WaitForGetOffsetInRange(int32 start, int32 end) { |
| 198 TryUpdateState(); |
| 199 while (!InRange(start, end, last_state_.get_offset) && |
| 200 last_state_.error == gpu::error::kNoError) { |
| 201 MakeProgressAndUpdateState(); |
| 202 TryUpdateState(); |
| 203 } |
| 204 } |
| 205 |
| 206 void CommandBufferClientImpl::SetGetBuffer(int32 shm_id) { |
| 207 command_buffer_->SetGetBuffer(shm_id); |
| 208 last_put_offset_ = -1; |
| 209 } |
| 210 |
| 211 scoped_refptr<gpu::Buffer> CommandBufferClientImpl::CreateTransferBuffer( |
| 212 size_t size, |
| 213 int32* id) { |
| 214 if (size >= std::numeric_limits<uint32_t>::max()) |
| 215 return NULL; |
| 216 |
| 217 void* memory = NULL; |
| 218 mojo::ScopedSharedBufferHandle handle; |
| 219 mojo::ScopedSharedBufferHandle duped; |
| 220 if (!CreateMapAndDupSharedBuffer(size, &memory, &handle, &duped)) |
| 221 return NULL; |
| 222 |
| 223 *id = ++next_transfer_buffer_id_; |
| 224 |
| 225 command_buffer_->RegisterTransferBuffer( |
| 226 *id, duped.Pass(), static_cast<uint32_t>(size)); |
| 227 |
| 228 scoped_ptr<gpu::BufferBacking> backing( |
| 229 new MojoBufferBacking(handle.Pass(), memory, size)); |
| 230 scoped_refptr<gpu::Buffer> buffer(new gpu::Buffer(backing.Pass())); |
| 231 return buffer; |
| 232 } |
| 233 |
| 234 void CommandBufferClientImpl::DestroyTransferBuffer(int32 id) { |
| 235 command_buffer_->DestroyTransferBuffer(id); |
| 236 } |
| 237 |
| 238 gpu::Capabilities CommandBufferClientImpl::GetCapabilities() { |
| 239 return capabilities_; |
| 240 } |
| 241 |
| 242 int32_t CommandBufferClientImpl::CreateImage(ClientBuffer buffer, |
| 243 size_t width, |
| 244 size_t height, |
| 245 unsigned internalformat) { |
| 246 // TODO(piman) |
| 247 NOTIMPLEMENTED(); |
| 248 return -1; |
| 249 } |
| 250 |
| 251 void CommandBufferClientImpl::DestroyImage(int32 id) { |
| 252 // TODO(piman) |
| 253 NOTIMPLEMENTED(); |
| 254 } |
| 255 |
| 256 int32_t CommandBufferClientImpl::CreateGpuMemoryBufferImage( |
| 257 size_t width, |
| 258 size_t height, |
| 259 unsigned internalformat, |
| 260 unsigned usage) { |
| 261 // TODO(piman) |
| 262 NOTIMPLEMENTED(); |
| 263 return -1; |
| 264 } |
| 265 |
| 266 uint32_t CommandBufferClientImpl::InsertSyncPoint() { |
| 267 command_buffer_->InsertSyncPoint(true); |
| 268 return sync_point_client_impl_->WaitForInsertSyncPoint(); |
| 269 } |
| 270 |
| 271 uint32_t CommandBufferClientImpl::InsertFutureSyncPoint() { |
| 272 command_buffer_->InsertSyncPoint(false); |
| 273 return sync_point_client_impl_->WaitForInsertSyncPoint(); |
| 274 } |
| 275 |
| 276 void CommandBufferClientImpl::RetireSyncPoint(uint32_t sync_point) { |
| 277 command_buffer_->RetireSyncPoint(sync_point); |
| 278 } |
| 279 |
| 280 void CommandBufferClientImpl::SignalSyncPoint(uint32_t sync_point, |
| 281 const base::Closure& callback) { |
| 282 // TODO(piman) |
| 283 } |
| 284 |
| 285 void CommandBufferClientImpl::SignalQuery(uint32_t query, |
| 286 const base::Closure& callback) { |
| 287 // TODO(piman) |
| 288 NOTIMPLEMENTED(); |
| 289 } |
| 290 |
| 291 void CommandBufferClientImpl::SetSurfaceVisible(bool visible) { |
| 292 // TODO(piman) |
| 293 NOTIMPLEMENTED(); |
| 294 } |
| 295 |
| 296 uint32_t CommandBufferClientImpl::CreateStreamTexture(uint32_t texture_id) { |
| 297 // TODO(piman) |
| 298 NOTIMPLEMENTED(); |
| 299 return 0; |
| 300 } |
| 301 |
| 302 void CommandBufferClientImpl::DidLoseContext(int32_t lost_reason) { |
| 303 last_state_.error = gpu::error::kLostContext; |
| 304 last_state_.context_lost_reason = |
| 305 static_cast<gpu::error::ContextLostReason>(lost_reason); |
| 306 delegate_->ContextLost(); |
| 307 } |
| 308 |
| 309 void CommandBufferClientImpl::OnConnectionError() { |
| 310 DidLoseContext(gpu::error::kUnknown); |
| 311 } |
| 312 |
| 313 void CommandBufferClientImpl::TryUpdateState() { |
| 314 if (last_state_.error == gpu::error::kNoError) |
| 315 shared_state()->Read(&last_state_); |
| 316 } |
| 317 |
| 318 void CommandBufferClientImpl::MakeProgressAndUpdateState() { |
| 319 command_buffer_->MakeProgress(last_state_.get_offset); |
| 320 |
| 321 mojo::CommandBufferStatePtr state = sync_client_impl_->WaitForProgress(); |
| 322 if (!state) { |
| 323 VLOG(1) << "Channel encountered error while waiting for command buffer"; |
| 324 // TODO(piman): is it ok for this to re-enter? |
| 325 DidLoseContext(gpu::error::kUnknown); |
| 326 return; |
| 327 } |
| 328 |
| 329 if (state->generation - last_state_.generation < 0x80000000U) |
| 330 last_state_ = state.To<State>(); |
| 331 } |
| 332 |
| 333 void CommandBufferClientImpl::SetLock(base::Lock* lock) { |
| 334 } |
| 335 |
| 336 } // namespace gles2 |
OLD | NEW |