Home | History | Annotate | Download | only in service
      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 "gpu/command_buffer/service/command_buffer_service.h"
      6 
      7 #include <limits>
      8 
      9 #include "base/logging.h"
     10 #include "base/debug/trace_event.h"
     11 #include "gpu/command_buffer/common/cmd_buffer_common.h"
     12 #include "gpu/command_buffer/common/command_buffer_shared.h"
     13 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
     14 
     15 using ::base::SharedMemory;
     16 
     17 namespace gpu {
     18 
     19 CommandBufferService::CommandBufferService(
     20     TransferBufferManagerInterface* transfer_buffer_manager)
     21     : ring_buffer_id_(-1),
     22       shared_state_(NULL),
     23       num_entries_(0),
     24       get_offset_(0),
     25       put_offset_(0),
     26       transfer_buffer_manager_(transfer_buffer_manager),
     27       token_(0),
     28       generation_(0),
     29       error_(error::kNoError),
     30       context_lost_reason_(error::kUnknown) {
     31 }
     32 
     33 CommandBufferService::~CommandBufferService() {
     34 }
     35 
     36 bool CommandBufferService::Initialize() {
     37   return true;
     38 }
     39 
     40 CommandBufferService::State CommandBufferService::GetState() {
     41   State state;
     42   state.num_entries = num_entries_;
     43   state.get_offset = get_offset_;
     44   state.put_offset = put_offset_;
     45   state.token = token_;
     46   state.error = error_;
     47   state.context_lost_reason = context_lost_reason_;
     48   state.generation = ++generation_;
     49 
     50   return state;
     51 }
     52 
     53 CommandBufferService::State CommandBufferService::GetLastState() {
     54   return GetState();
     55 }
     56 
     57 int32 CommandBufferService::GetLastToken() {
     58   return GetState().token;
     59 }
     60 
     61 void CommandBufferService::UpdateState() {
     62   if (shared_state_) {
     63     CommandBufferService::State state = GetState();
     64     shared_state_->Write(state);
     65   }
     66 }
     67 
     68 CommandBufferService::State CommandBufferService::FlushSync(
     69     int32 put_offset, int32 last_known_get) {
     70   if (put_offset < 0 || put_offset > num_entries_) {
     71     error_ = gpu::error::kOutOfBounds;
     72     return GetState();
     73   }
     74 
     75   put_offset_ = put_offset;
     76 
     77   if (!put_offset_change_callback_.is_null())
     78     put_offset_change_callback_.Run();
     79 
     80   return GetState();
     81 }
     82 
     83 void CommandBufferService::Flush(int32 put_offset) {
     84   if (put_offset < 0 || put_offset > num_entries_) {
     85     error_ = gpu::error::kOutOfBounds;
     86     return;
     87   }
     88 
     89   put_offset_ = put_offset;
     90 
     91   if (!put_offset_change_callback_.is_null())
     92     put_offset_change_callback_.Run();
     93 }
     94 
     95 void CommandBufferService::SetGetBuffer(int32 transfer_buffer_id) {
     96   DCHECK_EQ(-1, ring_buffer_id_);
     97   DCHECK_EQ(put_offset_, get_offset_);  // Only if it's empty.
     98   ring_buffer_ = GetTransferBuffer(transfer_buffer_id);
     99   DCHECK(ring_buffer_.ptr);
    100   ring_buffer_id_ = transfer_buffer_id;
    101   num_entries_ = ring_buffer_.size / sizeof(CommandBufferEntry);
    102   put_offset_ = 0;
    103   SetGetOffset(0);
    104   if (!get_buffer_change_callback_.is_null()) {
    105     get_buffer_change_callback_.Run(ring_buffer_id_);
    106   }
    107 
    108   UpdateState();
    109 }
    110 
    111 bool CommandBufferService::SetSharedStateBuffer(
    112     scoped_ptr<base::SharedMemory> shared_state_shm) {
    113   shared_state_shm_.reset(shared_state_shm.release());
    114   if (!shared_state_shm_->Map(sizeof(*shared_state_)))
    115     return false;
    116 
    117   shared_state_ =
    118       static_cast<CommandBufferSharedState*>(shared_state_shm_->memory());
    119 
    120   UpdateState();
    121   return true;
    122 }
    123 
    124 void CommandBufferService::SetGetOffset(int32 get_offset) {
    125   DCHECK(get_offset >= 0 && get_offset < num_entries_);
    126   get_offset_ = get_offset;
    127 }
    128 
    129 Buffer CommandBufferService::CreateTransferBuffer(size_t size,
    130                                                   int32* id) {
    131   *id = -1;
    132 
    133   SharedMemory buffer;
    134   if (!buffer.CreateAnonymous(size))
    135     return Buffer();
    136 
    137   static int32 next_id = 1;
    138   *id = next_id++;
    139 
    140   if (!RegisterTransferBuffer(*id, &buffer, size)) {
    141     *id = -1;
    142     return Buffer();
    143   }
    144 
    145   return GetTransferBuffer(*id);
    146 }
    147 
    148 void CommandBufferService::DestroyTransferBuffer(int32 id) {
    149   transfer_buffer_manager_->DestroyTransferBuffer(id);
    150   if (id == ring_buffer_id_) {
    151     ring_buffer_id_ = -1;
    152     ring_buffer_ = Buffer();
    153     num_entries_ = 0;
    154     get_offset_ = 0;
    155     put_offset_ = 0;
    156   }
    157 }
    158 
    159 Buffer CommandBufferService::GetTransferBuffer(int32 id) {
    160   return transfer_buffer_manager_->GetTransferBuffer(id);
    161 }
    162 
    163 bool CommandBufferService::RegisterTransferBuffer(
    164     int32 id,
    165     base::SharedMemory* shared_memory,
    166     size_t size) {
    167   return transfer_buffer_manager_->RegisterTransferBuffer(id,
    168                                                           shared_memory,
    169                                                           size);
    170 }
    171 
    172 void CommandBufferService::SetToken(int32 token) {
    173   token_ = token;
    174   UpdateState();
    175 }
    176 
    177 void CommandBufferService::SetParseError(error::Error error) {
    178   if (error_ == error::kNoError) {
    179     error_ = error;
    180     if (!parse_error_callback_.is_null())
    181       parse_error_callback_.Run();
    182   }
    183 }
    184 
    185 void CommandBufferService::SetContextLostReason(
    186     error::ContextLostReason reason) {
    187   context_lost_reason_ = reason;
    188 }
    189 
    190 void CommandBufferService::SetPutOffsetChangeCallback(
    191     const base::Closure& callback) {
    192   put_offset_change_callback_ = callback;
    193 }
    194 
    195 void CommandBufferService::SetGetBufferChangeCallback(
    196     const GetBufferChangedCallback& callback) {
    197   get_buffer_change_callback_ = callback;
    198 }
    199 
    200 void CommandBufferService::SetParseErrorCallback(
    201     const base::Closure& callback) {
    202   parse_error_callback_ = callback;
    203 }
    204 
    205 }  // namespace gpu
    206