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