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