| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/command_buffer_proxy.h" | 5 #include "content/renderer/command_buffer_proxy.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/process_util.h" | 8 #include "base/process_util.h" |
| 9 #include "base/shared_memory.h" | 9 #include "base/shared_memory.h" |
| 10 #include "base/task.h" | 10 #include "base/task.h" |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 // Return locally cached ring buffer. | 133 // Return locally cached ring buffer. |
| 134 Buffer buffer; | 134 Buffer buffer; |
| 135 buffer.ptr = ring_buffer_->memory(); | 135 buffer.ptr = ring_buffer_->memory(); |
| 136 buffer.size = num_entries_ * sizeof(gpu::CommandBufferEntry); | 136 buffer.size = num_entries_ * sizeof(gpu::CommandBufferEntry); |
| 137 buffer.shared_memory = ring_buffer_.get(); | 137 buffer.shared_memory = ring_buffer_.get(); |
| 138 return buffer; | 138 return buffer; |
| 139 } | 139 } |
| 140 | 140 |
| 141 gpu::CommandBuffer::State CommandBufferProxy::GetState() { | 141 gpu::CommandBuffer::State CommandBufferProxy::GetState() { |
| 142 // Send will flag state with lost context if IPC fails. | 142 // Send will flag state with lost context if IPC fails. |
| 143 if (last_state_.error == gpu::error::kNoError) | 143 if (last_state_.error == gpu::error::kNoError) { |
| 144 Send(new GpuCommandBufferMsg_GetState(route_id_, &last_state_)); | 144 gpu::CommandBuffer::State state; |
| 145 if (Send(new GpuCommandBufferMsg_GetState(route_id_, &state))) |
| 146 OnUpdateState(state); |
| 147 } |
| 145 | 148 |
| 146 return last_state_; | 149 return last_state_; |
| 147 } | 150 } |
| 148 | 151 |
| 149 void CommandBufferProxy::Flush(int32 put_offset) { | 152 void CommandBufferProxy::Flush(int32 put_offset) { |
| 150 AsyncFlush(put_offset, NULL); | 153 if (last_state_.error != gpu::error::kNoError) |
| 154 return; |
| 155 |
| 156 Send(new GpuCommandBufferMsg_AsyncFlush(route_id_, put_offset)); |
| 151 } | 157 } |
| 152 | 158 |
| 153 gpu::CommandBuffer::State CommandBufferProxy::FlushSync(int32 put_offset) { | 159 gpu::CommandBuffer::State CommandBufferProxy::FlushSync(int32 put_offset, |
| 160 int32 last_known_get) { |
| 154 GPU_TRACE_EVENT0("gpu", "CommandBufferProxy::FlushSync"); | 161 GPU_TRACE_EVENT0("gpu", "CommandBufferProxy::FlushSync"); |
| 155 // Send will flag state with lost context if IPC fails. | 162 if (last_known_get == last_state_.get_offset) { |
| 156 if (last_state_.error == gpu::error::kNoError) { | 163 // Send will flag state with lost context if IPC fails. |
| 157 Send(new GpuCommandBufferMsg_Flush(route_id_, | 164 if (last_state_.error == gpu::error::kNoError) { |
| 158 put_offset, | 165 gpu::CommandBuffer::State state; |
| 159 &last_state_)); | 166 if (Send(new GpuCommandBufferMsg_Flush(route_id_, |
| 167 put_offset, |
| 168 last_known_get, |
| 169 &state))) |
| 170 OnUpdateState(state); |
| 171 } |
| 172 } else { |
| 173 Flush(put_offset); |
| 160 } | 174 } |
| 161 | 175 |
| 162 return last_state_; | 176 return last_state_; |
| 163 } | 177 } |
| 164 | 178 |
| 165 void CommandBufferProxy::SetGetOffset(int32 get_offset) { | 179 void CommandBufferProxy::SetGetOffset(int32 get_offset) { |
| 166 // Not implemented in proxy. | 180 // Not implemented in proxy. |
| 167 NOTREACHED(); | 181 NOTREACHED(); |
| 168 } | 182 } |
| 169 | 183 |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 | 352 |
| 339 #if defined(OS_MACOSX) | 353 #if defined(OS_MACOSX) |
| 340 void CommandBufferProxy::SetWindowSize(const gfx::Size& size) { | 354 void CommandBufferProxy::SetWindowSize(const gfx::Size& size) { |
| 341 if (last_state_.error != gpu::error::kNoError) | 355 if (last_state_.error != gpu::error::kNoError) |
| 342 return; | 356 return; |
| 343 | 357 |
| 344 Send(new GpuCommandBufferMsg_SetWindowSize(route_id_, size)); | 358 Send(new GpuCommandBufferMsg_SetWindowSize(route_id_, size)); |
| 345 } | 359 } |
| 346 #endif | 360 #endif |
| 347 | 361 |
| 348 void CommandBufferProxy::AsyncGetState(Task* completion_task) { | |
| 349 if (last_state_.error != gpu::error::kNoError) | |
| 350 return; | |
| 351 | |
| 352 IPC::Message* message = new GpuCommandBufferMsg_AsyncGetState(route_id_); | |
| 353 | |
| 354 // Do not let a synchronous flush hold up this message. If this handler is | |
| 355 // deferred until after the synchronous flush completes, it will overwrite the | |
| 356 // cached last_state_ with out-of-date data. | |
| 357 message->set_unblock(true); | |
| 358 | |
| 359 if (Send(message)) | |
| 360 pending_async_flush_tasks_.push(linked_ptr<Task>(completion_task)); | |
| 361 } | |
| 362 | |
| 363 void CommandBufferProxy::AsyncFlush(int32 put_offset, Task* completion_task) { | |
| 364 if (last_state_.error != gpu::error::kNoError) | |
| 365 return; | |
| 366 | |
| 367 IPC::Message* message = new GpuCommandBufferMsg_AsyncFlush(route_id_, | |
| 368 put_offset); | |
| 369 | |
| 370 // Do not let a synchronous flush hold up this message. If this handler is | |
| 371 // deferred until after the synchronous flush completes, it will overwrite the | |
| 372 // cached last_state_ with out-of-date data. | |
| 373 message->set_unblock(true); | |
| 374 | |
| 375 if (Send(message)) | |
| 376 pending_async_flush_tasks_.push(linked_ptr<Task>(completion_task)); | |
| 377 } | |
| 378 | |
| 379 bool CommandBufferProxy::Send(IPC::Message* msg) { | 362 bool CommandBufferProxy::Send(IPC::Message* msg) { |
| 380 // Caller should not intentionally send a message if the context is lost. | 363 // Caller should not intentionally send a message if the context is lost. |
| 381 DCHECK(last_state_.error == gpu::error::kNoError); | 364 DCHECK(last_state_.error == gpu::error::kNoError); |
| 382 | 365 |
| 383 if (channel_) { | 366 if (channel_) { |
| 384 if (channel_->Send(msg)) { | 367 if (channel_->Send(msg)) { |
| 385 return true; | 368 return true; |
| 386 } else { | 369 } else { |
| 387 // Flag the command buffer as lost. Defer deleting the channel until | 370 // Flag the command buffer as lost. Defer deleting the channel until |
| 388 // OnChannelError is called after returning to the message loop in case | 371 // OnChannelError is called after returning to the message loop in case |
| 389 // it is referenced elsewhere. | 372 // it is referenced elsewhere. |
| 390 last_state_.error = gpu::error::kLostContext; | 373 last_state_.error = gpu::error::kLostContext; |
| 391 return false; | 374 return false; |
| 392 } | 375 } |
| 393 } | 376 } |
| 394 | 377 |
| 395 // Callee takes ownership of message, regardless of whether Send is | 378 // Callee takes ownership of message, regardless of whether Send is |
| 396 // successful. See IPC::Message::Sender. | 379 // successful. See IPC::Message::Sender. |
| 397 delete msg; | 380 delete msg; |
| 398 return false; | 381 return false; |
| 399 } | 382 } |
| 400 | 383 |
| 401 void CommandBufferProxy::OnUpdateState(const gpu::CommandBuffer::State& state) { | 384 void CommandBufferProxy::OnUpdateState(const gpu::CommandBuffer::State& state) { |
| 402 last_state_ = state; | 385 // Handle wraparound. It works as long as we don't have more than 2B state |
| 403 | 386 // updates in flight across which reordering occurs. |
| 404 linked_ptr<Task> task = pending_async_flush_tasks_.front(); | 387 if (state.generation - last_state_.generation < 0x80000000U) |
| 405 pending_async_flush_tasks_.pop(); | 388 last_state_ = state; |
| 406 | |
| 407 if (task.get()) { | |
| 408 // Although we need need to update last_state_ while potentially waiting | |
| 409 // for a synchronous flush to complete, we do not need to invoke the | |
| 410 // callback synchonously. Also, post it as a non nestable task so it is | |
| 411 // always invoked by the outermost message loop. | |
| 412 MessageLoop::current()->PostNonNestableTask(FROM_HERE, task.release()); | |
| 413 } | |
| 414 } | 389 } |
| OLD | NEW |