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::GetLastState() {
     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 int32 CommandBufferService::GetLastToken() {
     54   return GetLastState().token;
     55 }
     56 
     57 void CommandBufferService::UpdateState() {
     58   if (shared_state_) {
     59     CommandBufferService::State state = GetLastState();
     60     shared_state_->Write(state);
     61   }
     62 }
     63 
     64 void CommandBufferService::WaitForTokenInRange(int32 start, int32 end) {
     65   DCHECK(error_ != error::kNoError || InRange(start, end, token_));
     66 }
     67 
     68 void CommandBufferService::WaitForGetOffsetInRange(int32 start, int32 end) {
     69   DCHECK(error_ != error::kNoError || InRange(start, end, get_offset_));
     70 }
     71 
     72 void CommandBufferService::Flush(int32 put_offset) {
     73   if (put_offset < 0 || put_offset > num_entries_) {
     74     error_ = gpu::error::kOutOfBounds;
     75     return;
     76   }
     77 
     78   put_offset_ = put_offset;
     79 
     80   if (!put_offset_change_callback_.is_null())
     81     put_offset_change_callback_.Run();
     82 }
     83 
     84 void CommandBufferService::SetGetBuffer(int32 transfer_buffer_id) {
     85   DCHECK_EQ(-1, ring_buffer_id_);
     86   DCHECK_EQ(put_offset_, get_offset_);  // Only if it's empty.
     87   // If the buffer is invalid we handle it gracefully.
     88   // This means ring_buffer_ can be NULL.
     89   ring_buffer_ = GetTransferBuffer(transfer_buffer_id);
     90   ring_buffer_id_ = transfer_buffer_id;
     91   int32 size = ring_buffer_.get() ? ring_buffer_->size() : 0;
     92   num_entries_ = size / sizeof(CommandBufferEntry);
     93   put_offset_ = 0;
     94   SetGetOffset(0);
     95   if (!get_buffer_change_callback_.is_null()) {
     96     get_buffer_change_callback_.Run(ring_buffer_id_);
     97   }
     98 
     99   UpdateState();
    100 }
    101 
    102 void CommandBufferService::SetSharedStateBuffer(
    103     scoped_ptr<BufferBacking> shared_state_buffer) {
    104   shared_state_buffer_ = shared_state_buffer.Pass();
    105   DCHECK(shared_state_buffer_->GetSize() >= sizeof(*shared_state_));
    106 
    107   shared_state_ =
    108       static_cast<CommandBufferSharedState*>(shared_state_buffer_->GetMemory());
    109 
    110   UpdateState();
    111 }
    112 
    113 void CommandBufferService::SetGetOffset(int32 get_offset) {
    114   DCHECK(get_offset >= 0 && get_offset < num_entries_);
    115   get_offset_ = get_offset;
    116 }
    117 
    118 scoped_refptr<Buffer> CommandBufferService::CreateTransferBuffer(size_t size,
    119                                                                  int32* id) {
    120   *id = -1;
    121 
    122   scoped_ptr<SharedMemory> shared_memory(new SharedMemory());
    123   if (!shared_memory->CreateAndMapAnonymous(size))
    124     return NULL;
    125 
    126   static int32 next_id = 1;
    127   *id = next_id++;
    128 
    129   if (!RegisterTransferBuffer(
    130           *id, MakeBackingFromSharedMemory(shared_memory.Pass(), size))) {
    131     *id = -1;
    132     return NULL;
    133   }
    134 
    135   return GetTransferBuffer(*id);
    136 }
    137 
    138 void CommandBufferService::DestroyTransferBuffer(int32 id) {
    139   transfer_buffer_manager_->DestroyTransferBuffer(id);
    140   if (id == ring_buffer_id_) {
    141     ring_buffer_id_ = -1;
    142     ring_buffer_ = NULL;
    143     num_entries_ = 0;
    144     get_offset_ = 0;
    145     put_offset_ = 0;
    146   }
    147 }
    148 
    149 scoped_refptr<Buffer> CommandBufferService::GetTransferBuffer(int32 id) {
    150   return transfer_buffer_manager_->GetTransferBuffer(id);
    151 }
    152 
    153 bool CommandBufferService::RegisterTransferBuffer(
    154     int32 id,
    155     scoped_ptr<BufferBacking> buffer) {
    156   return transfer_buffer_manager_->RegisterTransferBuffer(id, buffer.Pass());
    157 }
    158 
    159 void CommandBufferService::SetToken(int32 token) {
    160   token_ = token;
    161   UpdateState();
    162 }
    163 
    164 void CommandBufferService::SetParseError(error::Error error) {
    165   if (error_ == error::kNoError) {
    166     error_ = error;
    167     if (!parse_error_callback_.is_null())
    168       parse_error_callback_.Run();
    169   }
    170 }
    171 
    172 void CommandBufferService::SetContextLostReason(
    173     error::ContextLostReason reason) {
    174   context_lost_reason_ = reason;
    175 }
    176 
    177 void CommandBufferService::SetPutOffsetChangeCallback(
    178     const base::Closure& callback) {
    179   put_offset_change_callback_ = callback;
    180 }
    181 
    182 void CommandBufferService::SetGetBufferChangeCallback(
    183     const GetBufferChangedCallback& callback) {
    184   get_buffer_change_callback_ = callback;
    185 }
    186 
    187 void CommandBufferService::SetParseErrorCallback(
    188     const base::Closure& callback) {
    189   parse_error_callback_ = callback;
    190 }
    191 
    192 }  // namespace gpu
    193