15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/command_buffer_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/logging.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/common/cmd_buffer_common.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/common/command_buffer_shared.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/transfer_buffer_manager.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::base::SharedMemory;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gpu {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferService::CommandBufferService(
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransferBufferManagerInterface* transfer_buffer_manager)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : ring_buffer_id_(-1),
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shared_state_(NULL),
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      num_entries_(0),
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      get_offset_(0),
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      put_offset_(0),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transfer_buffer_manager_(transfer_buffer_manager),
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      token_(0),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      generation_(0),
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_(error::kNoError),
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_lost_reason_(error::kUnknown) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferService::~CommandBufferService() {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferService::Initialize() {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferService::State CommandBufferService::GetState() {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State state;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state.num_entries = num_entries_;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state.get_offset = get_offset_;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state.put_offset = put_offset_;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state.token = token_;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state.error = error_;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state.context_lost_reason = context_lost_reason_;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state.generation = ++generation_;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return state;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferService::State CommandBufferService::GetLastState() {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetState();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 CommandBufferService::GetLastToken() {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetState().token;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::UpdateState() {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shared_state_) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandBufferService::State state = GetState();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shared_state_->Write(state);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferService::State CommandBufferService::FlushSync(
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 put_offset, int32 last_known_get) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (put_offset < 0 || put_offset > num_entries_) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = gpu::error::kOutOfBounds;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetState();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  put_offset_ = put_offset;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!put_offset_change_callback_.is_null())
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    put_offset_change_callback_.Run();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetState();
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::Flush(int32 put_offset) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (put_offset < 0 || put_offset > num_entries_) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = gpu::error::kOutOfBounds;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  put_offset_ = put_offset;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!put_offset_change_callback_.is_null())
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    put_offset_change_callback_.Run();
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetGetBuffer(int32 transfer_buffer_id) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(-1, ring_buffer_id_);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(put_offset_, get_offset_);  // Only if it's empty.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ring_buffer_ = GetTransferBuffer(transfer_buffer_id);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ring_buffer_.ptr);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ring_buffer_id_ = transfer_buffer_id;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  num_entries_ = ring_buffer_.size / sizeof(CommandBufferEntry);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  put_offset_ = 0;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetGetOffset(0);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!get_buffer_change_callback_.is_null()) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    get_buffer_change_callback_.Run(ring_buffer_id_);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateState();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CommandBufferService::SetSharedStateBuffer(
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::SharedMemory> shared_state_shm) {
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  shared_state_shm_.reset(shared_state_shm.release());
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!shared_state_shm_->Map(sizeof(*shared_state_)))
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  shared_state_ =
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<CommandBufferSharedState*>(shared_state_shm_->memory());
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateState();
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetGetOffset(int32 get_offset) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(get_offset >= 0 && get_offset < num_entries_);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  get_offset_ = get_offset;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Buffer CommandBufferService::CreateTransferBuffer(size_t size,
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  int32* id) {
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *id = -1;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SharedMemory buffer;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!buffer.CreateAnonymous(size))
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Buffer();
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static int32 next_id = 1;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *id = next_id++;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
140a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!RegisterTransferBuffer(*id, &buffer, size)) {
141a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    *id = -1;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Buffer();
143a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetTransferBuffer(*id);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CommandBufferService::DestroyTransferBuffer(int32 id) {
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transfer_buffer_manager_->DestroyTransferBuffer(id);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (id == ring_buffer_id_) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ring_buffer_id_ = -1;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ring_buffer_ = Buffer();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_entries_ = 0;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    get_offset_ = 0;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    put_offset_ = 0;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Buffer CommandBufferService::GetTransferBuffer(int32 id) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return transfer_buffer_manager_->GetTransferBuffer(id);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CommandBufferService::RegisterTransferBuffer(
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int32 id,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::SharedMemory* shared_memory,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t size) {
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return transfer_buffer_manager_->RegisterTransferBuffer(id,
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                          shared_memory,
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                          size);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetToken(int32 token) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  token_ = token;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateState();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetParseError(error::Error error) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error_ == error::kNoError) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = error;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!parse_error_callback_.is_null())
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parse_error_callback_.Run();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetContextLostReason(
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error::ContextLostReason reason) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_lost_reason_ = reason;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetPutOffsetChangeCallback(
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& callback) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  put_offset_change_callback_ = callback;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetGetBufferChangeCallback(
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GetBufferChangedCallback& callback) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  get_buffer_change_callback_ = callback;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetParseErrorCallback(
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& callback) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parse_error_callback_ = callback;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gpu
206