command_buffer_impl.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
1// Copyright 2013 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/services/gles2/command_buffer_impl.h" 6 7#include "base/bind.h" 8#include "base/memory/shared_memory.h" 9 10#include "gpu/command_buffer/common/constants.h" 11#include "gpu/command_buffer/service/command_buffer_service.h" 12#include "gpu/command_buffer/service/context_group.h" 13#include "gpu/command_buffer/service/gles2_cmd_decoder.h" 14#include "gpu/command_buffer/service/gpu_control_service.h" 15#include "gpu/command_buffer/service/gpu_scheduler.h" 16#include "gpu/command_buffer/service/image_manager.h" 17#include "gpu/command_buffer/service/mailbox_manager.h" 18#include "gpu/command_buffer/service/memory_tracking.h" 19#include "mojo/public/cpp/bindings/allocation_scope.h" 20#include "mojo/services/gles2/command_buffer_type_conversions.h" 21#include "mojo/services/gles2/mojo_buffer_backing.h" 22#include "ui/gl/gl_context.h" 23#include "ui/gl/gl_surface.h" 24 25namespace mojo { 26namespace services { 27 28namespace { 29 30class MemoryTrackerStub : public gpu::gles2::MemoryTracker { 31 public: 32 MemoryTrackerStub() {} 33 34 virtual void TrackMemoryAllocatedChange(size_t old_size, 35 size_t new_size, 36 gpu::gles2::MemoryTracker::Pool pool) 37 OVERRIDE {} 38 39 virtual bool EnsureGPUMemoryAvailable(size_t size_needed) OVERRIDE { 40 return true; 41 }; 42 43 private: 44 virtual ~MemoryTrackerStub() {} 45 46 DISALLOW_COPY_AND_ASSIGN(MemoryTrackerStub); 47}; 48 49} // anonymous namespace 50 51CommandBufferImpl::CommandBufferImpl(ScopedCommandBufferClientHandle client, 52 gfx::AcceleratedWidget widget, 53 const gfx::Size& size) 54 : client_(client.Pass(), this), widget_(widget), size_(size) {} 55 56CommandBufferImpl::~CommandBufferImpl() { client_->DidDestroy(); } 57 58void CommandBufferImpl::Initialize( 59 ScopedCommandBufferSyncClientHandle sync_client, 60 mojo::ScopedSharedBufferHandle shared_state) { 61 sync_client_.reset(sync_client.Pass(), NULL); 62 sync_client_->DidInitialize(DoInitialize(shared_state.Pass())); 63} 64 65bool CommandBufferImpl::DoInitialize( 66 mojo::ScopedSharedBufferHandle shared_state) { 67 // TODO(piman): offscreen surface. 68 scoped_refptr<gfx::GLSurface> surface = 69 gfx::GLSurface::CreateViewGLSurface(widget_); 70 if (!surface.get()) 71 return false; 72 73 // TODO(piman): context sharing, virtual contexts, gpu preference. 74 scoped_refptr<gfx::GLContext> context = gfx::GLContext::CreateGLContext( 75 NULL, surface.get(), gfx::PreferIntegratedGpu); 76 if (!context.get()) 77 return false; 78 79 if (!context->MakeCurrent(surface.get())) 80 return false; 81 82 // TODO(piman): ShaderTranslatorCache is currently per-ContextGroup but 83 // only needs to be per-thread. 84 scoped_refptr<gpu::gles2::ContextGroup> context_group = 85 new gpu::gles2::ContextGroup(NULL, 86 NULL, 87 new MemoryTrackerStub, 88 new gpu::gles2::ShaderTranslatorCache, 89 NULL, 90 true); 91 92 command_buffer_.reset( 93 new gpu::CommandBufferService(context_group->transfer_buffer_manager())); 94 bool result = command_buffer_->Initialize(); 95 DCHECK(result); 96 97 decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group.get())); 98 scheduler_.reset(new gpu::GpuScheduler( 99 command_buffer_.get(), decoder_.get(), decoder_.get())); 100 decoder_->set_engine(scheduler_.get()); 101 102 gpu::gles2::DisallowedFeatures disallowed_features; 103 104 // TODO(piman): attributes. 105 std::vector<int32> attrib_vector; 106 if (!decoder_->Initialize(surface, 107 context, 108 false /* offscreen */, 109 size_, 110 disallowed_features, 111 attrib_vector)) 112 return false; 113 114 gpu_control_.reset( 115 new gpu::GpuControlService(context_group->image_manager(), 116 NULL, 117 context_group->mailbox_manager(), 118 NULL, 119 decoder_->GetCapabilities())); 120 121 command_buffer_->SetPutOffsetChangeCallback(base::Bind( 122 &gpu::GpuScheduler::PutChanged, base::Unretained(scheduler_.get()))); 123 command_buffer_->SetGetBufferChangeCallback(base::Bind( 124 &gpu::GpuScheduler::SetGetBuffer, base::Unretained(scheduler_.get()))); 125 command_buffer_->SetParseErrorCallback( 126 base::Bind(&CommandBufferImpl::OnParseError, base::Unretained(this))); 127 128 // TODO(piman): other callbacks 129 130 const size_t kSize = sizeof(gpu::CommandBufferSharedState); 131 scoped_ptr<gpu::BufferBacking> backing( 132 gles2::MojoBufferBacking::Create(shared_state.Pass(), kSize)); 133 if (!backing.get()) 134 return false; 135 136 command_buffer_->SetSharedStateBuffer(backing.Pass()); 137 return true; 138} 139 140void CommandBufferImpl::SetGetBuffer(int32_t buffer) { 141 command_buffer_->SetGetBuffer(buffer); 142} 143 144void CommandBufferImpl::Flush(int32_t put_offset) { 145 command_buffer_->Flush(put_offset); 146} 147 148void CommandBufferImpl::MakeProgress(int32_t last_get_offset) { 149 // TODO(piman): handle out-of-order. 150 AllocationScope scope; 151 sync_client_->DidMakeProgress(command_buffer_->GetLastState()); 152} 153 154void CommandBufferImpl::RegisterTransferBuffer( 155 int32_t id, 156 mojo::ScopedSharedBufferHandle transfer_buffer, 157 uint32_t size) { 158 // Take ownership of the memory and map it into this process. 159 // This validates the size. 160 scoped_ptr<gpu::BufferBacking> backing( 161 gles2::MojoBufferBacking::Create(transfer_buffer.Pass(), size)); 162 if (!backing.get()) { 163 DVLOG(0) << "Failed to map shared memory."; 164 return; 165 } 166 command_buffer_->RegisterTransferBuffer(id, backing.Pass()); 167} 168 169void CommandBufferImpl::DestroyTransferBuffer(int32_t id) { 170 command_buffer_->DestroyTransferBuffer(id); 171} 172 173void CommandBufferImpl::Echo(const Callback<void()>& callback) { 174 callback.Run(); 175} 176 177void CommandBufferImpl::RequestAnimationFrames() { 178 timer_.Start(FROM_HERE, 179 base::TimeDelta::FromMilliseconds(16), 180 this, 181 &CommandBufferImpl::DrawAnimationFrame); 182} 183 184void CommandBufferImpl::CancelAnimationFrames() { timer_.Stop(); } 185 186void CommandBufferImpl::OnParseError() { 187 gpu::CommandBuffer::State state = command_buffer_->GetLastState(); 188 client_->LostContext(state.context_lost_reason); 189} 190 191void CommandBufferImpl::DrawAnimationFrame() { client_->DrawAnimationFrame(); } 192 193} // namespace services 194} // namespace mojo 195