Home | History | Annotate | Download | only in gles2
      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 mojo {
     15 namespace gles2 {
     16 
     17 namespace {
     18 
     19 bool CreateMapAndDupSharedBuffer(size_t size,
     20                                  void** memory,
     21                                  mojo::ScopedSharedBufferHandle* handle,
     22                                  mojo::ScopedSharedBufferHandle* duped) {
     23   MojoResult result = mojo::CreateSharedBuffer(NULL, size, handle);
     24   if (result != MOJO_RESULT_OK)
     25     return false;
     26   DCHECK(handle->is_valid());
     27 
     28   result = mojo::DuplicateBuffer(handle->get(), NULL, duped);
     29   if (result != MOJO_RESULT_OK)
     30     return false;
     31   DCHECK(duped->is_valid());
     32 
     33   result = mojo::MapBuffer(
     34       handle->get(), 0, size, memory, MOJO_MAP_BUFFER_FLAG_NONE);
     35   if (result != MOJO_RESULT_OK)
     36     return false;
     37   DCHECK(*memory);
     38 
     39   return true;
     40 }
     41 
     42 }  // namespace
     43 
     44 CommandBufferDelegate::~CommandBufferDelegate() {}
     45 
     46 void CommandBufferDelegate::ContextLost() {}
     47 
     48 class CommandBufferClientImpl::SyncClientImpl
     49     : public InterfaceImpl<CommandBufferSyncClient> {
     50  public:
     51   SyncClientImpl() : initialized_successfully_(false) {}
     52 
     53   bool WaitForInitialization() {
     54     if (!WaitForIncomingMethodCall())
     55       return false;
     56     return initialized_successfully_;
     57   }
     58 
     59   CommandBufferStatePtr WaitForProgress() {
     60     if (!WaitForIncomingMethodCall())
     61       return CommandBufferStatePtr();
     62     return command_buffer_state_.Pass();
     63   }
     64 
     65  private:
     66   // CommandBufferSyncClient methods:
     67   virtual void DidInitialize(bool success) OVERRIDE {
     68     initialized_successfully_ = success;
     69   }
     70   virtual void DidMakeProgress(CommandBufferStatePtr state) OVERRIDE {
     71     command_buffer_state_ = state.Pass();
     72   }
     73 
     74   bool initialized_successfully_;
     75   CommandBufferStatePtr command_buffer_state_;
     76 };
     77 
     78 CommandBufferClientImpl::CommandBufferClientImpl(
     79     CommandBufferDelegate* delegate,
     80     const MojoAsyncWaiter* async_waiter,
     81     ScopedMessagePipeHandle command_buffer_handle)
     82     : delegate_(delegate),
     83       shared_state_(NULL),
     84       last_put_offset_(-1),
     85       next_transfer_buffer_id_(0),
     86       async_waiter_(async_waiter) {
     87   command_buffer_.Bind(command_buffer_handle.Pass(), async_waiter);
     88   command_buffer_.set_error_handler(this);
     89   command_buffer_.set_client(this);
     90 }
     91 
     92 CommandBufferClientImpl::~CommandBufferClientImpl() {}
     93 
     94 bool CommandBufferClientImpl::Initialize() {
     95   const size_t kSharedStateSize = sizeof(gpu::CommandBufferSharedState);
     96   void* memory = NULL;
     97   mojo::ScopedSharedBufferHandle duped;
     98   bool result = CreateMapAndDupSharedBuffer(
     99       kSharedStateSize, &memory, &shared_state_handle_, &duped);
    100   if (!result)
    101     return false;
    102 
    103   shared_state_ = static_cast<gpu::CommandBufferSharedState*>(memory);
    104 
    105   shared_state()->Initialize();
    106 
    107   CommandBufferSyncClientPtr sync_client;
    108   sync_client_impl_.reset(
    109       WeakBindToProxy(new SyncClientImpl(), &sync_client, async_waiter_));
    110 
    111   command_buffer_->Initialize(sync_client.Pass(), duped.Pass());
    112 
    113   // Wait for DidInitialize to come on the sync client pipe.
    114   if (!sync_client_impl_->WaitForInitialization()) {
    115     VLOG(1) << "Channel encountered error while creating command buffer";
    116     return false;
    117   }
    118   return true;
    119 }
    120 
    121 gpu::CommandBuffer::State CommandBufferClientImpl::GetLastState() {
    122   return last_state_;
    123 }
    124 
    125 int32 CommandBufferClientImpl::GetLastToken() {
    126   TryUpdateState();
    127   return last_state_.token;
    128 }
    129 
    130 void CommandBufferClientImpl::Flush(int32 put_offset) {
    131   if (last_put_offset_ == put_offset)
    132     return;
    133 
    134   last_put_offset_ = put_offset;
    135   command_buffer_->Flush(put_offset);
    136 }
    137 
    138 void CommandBufferClientImpl::WaitForTokenInRange(int32 start, int32 end) {
    139   TryUpdateState();
    140   while (!InRange(start, end, last_state_.token) &&
    141          last_state_.error == gpu::error::kNoError) {
    142     MakeProgressAndUpdateState();
    143     TryUpdateState();
    144   }
    145 }
    146 
    147 void CommandBufferClientImpl::WaitForGetOffsetInRange(int32 start, int32 end) {
    148   TryUpdateState();
    149   while (!InRange(start, end, last_state_.get_offset) &&
    150          last_state_.error == gpu::error::kNoError) {
    151     MakeProgressAndUpdateState();
    152     TryUpdateState();
    153   }
    154 }
    155 
    156 void CommandBufferClientImpl::SetGetBuffer(int32 shm_id) {
    157   command_buffer_->SetGetBuffer(shm_id);
    158   last_put_offset_ = -1;
    159 }
    160 
    161 scoped_refptr<gpu::Buffer> CommandBufferClientImpl::CreateTransferBuffer(
    162     size_t size,
    163     int32* id) {
    164   if (size >= std::numeric_limits<uint32_t>::max())
    165     return NULL;
    166 
    167   void* memory = NULL;
    168   mojo::ScopedSharedBufferHandle handle;
    169   mojo::ScopedSharedBufferHandle duped;
    170   if (!CreateMapAndDupSharedBuffer(size, &memory, &handle, &duped))
    171     return NULL;
    172 
    173   *id = ++next_transfer_buffer_id_;
    174 
    175   command_buffer_->RegisterTransferBuffer(
    176       *id, duped.Pass(), static_cast<uint32_t>(size));
    177 
    178   scoped_ptr<gpu::BufferBacking> backing(
    179       new MojoBufferBacking(handle.Pass(), memory, size));
    180   scoped_refptr<gpu::Buffer> buffer(new gpu::Buffer(backing.Pass()));
    181   return buffer;
    182 }
    183 
    184 void CommandBufferClientImpl::DestroyTransferBuffer(int32 id) {
    185   command_buffer_->DestroyTransferBuffer(id);
    186 }
    187 
    188 gpu::Capabilities CommandBufferClientImpl::GetCapabilities() {
    189   // TODO(piman)
    190   NOTIMPLEMENTED();
    191   return gpu::Capabilities();
    192 }
    193 
    194 gfx::GpuMemoryBuffer* CommandBufferClientImpl::CreateGpuMemoryBuffer(
    195     size_t width,
    196     size_t height,
    197     unsigned internalformat,
    198     unsigned usage,
    199     int32* id) {
    200   // TODO(piman)
    201   NOTIMPLEMENTED();
    202   return NULL;
    203 }
    204 
    205 void CommandBufferClientImpl::DestroyGpuMemoryBuffer(int32 id) {
    206   // TODO(piman)
    207   NOTIMPLEMENTED();
    208 }
    209 
    210 uint32 CommandBufferClientImpl::InsertSyncPoint() {
    211   // TODO(jamesr): Optimize this.
    212   WaitForGetOffsetInRange(last_put_offset_, last_put_offset_);
    213   return 0;
    214 }
    215 
    216 uint32 CommandBufferClientImpl::InsertFutureSyncPoint() {
    217   // TODO(jamesr): Optimize this.
    218   WaitForGetOffsetInRange(last_put_offset_, last_put_offset_);
    219   return 0;
    220 }
    221 
    222 void CommandBufferClientImpl::RetireSyncPoint(uint32 sync_point) {
    223   // TODO(piman)
    224   NOTIMPLEMENTED();
    225 }
    226 
    227 void CommandBufferClientImpl::SignalSyncPoint(uint32 sync_point,
    228                                               const base::Closure& callback) {
    229   // TODO(piman)
    230   NOTIMPLEMENTED();
    231 }
    232 
    233 void CommandBufferClientImpl::SignalQuery(uint32 query,
    234                                           const base::Closure& callback) {
    235   // TODO(piman)
    236   NOTIMPLEMENTED();
    237 }
    238 
    239 void CommandBufferClientImpl::SetSurfaceVisible(bool visible) {
    240   // TODO(piman)
    241   NOTIMPLEMENTED();
    242 }
    243 
    244 void CommandBufferClientImpl::Echo(const base::Closure& callback) {
    245   command_buffer_->Echo(callback);
    246 }
    247 
    248 uint32 CommandBufferClientImpl::CreateStreamTexture(uint32 texture_id) {
    249   // TODO(piman)
    250   NOTIMPLEMENTED();
    251   return 0;
    252 }
    253 
    254 void CommandBufferClientImpl::DidDestroy() {
    255   LostContext(gpu::error::kUnknown);
    256 }
    257 
    258 void CommandBufferClientImpl::LostContext(int32_t lost_reason) {
    259   last_state_.error = gpu::error::kLostContext;
    260   last_state_.context_lost_reason =
    261       static_cast<gpu::error::ContextLostReason>(lost_reason);
    262   delegate_->ContextLost();
    263 }
    264 
    265 void CommandBufferClientImpl::OnConnectionError() {
    266   LostContext(gpu::error::kUnknown);
    267 }
    268 
    269 void CommandBufferClientImpl::TryUpdateState() {
    270   if (last_state_.error == gpu::error::kNoError)
    271     shared_state()->Read(&last_state_);
    272 }
    273 
    274 void CommandBufferClientImpl::MakeProgressAndUpdateState() {
    275   command_buffer_->MakeProgress(last_state_.get_offset);
    276 
    277   CommandBufferStatePtr state = sync_client_impl_->WaitForProgress();
    278   if (!state) {
    279     VLOG(1) << "Channel encountered error while waiting for command buffer";
    280     // TODO(piman): is it ok for this to re-enter?
    281     DidDestroy();
    282     return;
    283   }
    284 
    285   if (state->generation - last_state_.generation < 0x80000000U)
    286     last_state_ = state.To<State>();
    287 }
    288 
    289 }  // namespace gles2
    290 }  // namespace mojo
    291