OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/compositor/compositor.h" | 5 #include "ui/compositor/compositor.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <deque> | 8 #include <deque> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/debug/trace_event.h" | 12 #include "base/debug/trace_event.h" |
13 #include "base/memory/singleton.h" | |
14 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
15 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
16 #include "base/run_loop.h" | |
17 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
18 #include "base/sys_info.h" | 16 #include "base/sys_info.h" |
19 #include "base/threading/thread.h" | |
20 #include "base/threading/thread_restrictions.h" | |
21 #include "cc/base/latency_info_swap_promise.h" | 17 #include "cc/base/latency_info_swap_promise.h" |
22 #include "cc/base/switches.h" | 18 #include "cc/base/switches.h" |
23 #include "cc/input/input_handler.h" | 19 #include "cc/input/input_handler.h" |
24 #include "cc/layers/layer.h" | 20 #include "cc/layers/layer.h" |
25 #include "cc/output/context_provider.h" | 21 #include "cc/output/context_provider.h" |
26 #include "cc/trees/layer_tree_host.h" | 22 #include "cc/trees/layer_tree_host.h" |
27 #include "third_party/skia/include/core/SkBitmap.h" | 23 #include "third_party/skia/include/core/SkBitmap.h" |
28 #include "ui/compositor/compositor_observer.h" | 24 #include "ui/compositor/compositor_observer.h" |
29 #include "ui/compositor/compositor_switches.h" | 25 #include "ui/compositor/compositor_switches.h" |
30 #include "ui/compositor/compositor_vsync_manager.h" | 26 #include "ui/compositor/compositor_vsync_manager.h" |
31 #include "ui/compositor/dip_util.h" | 27 #include "ui/compositor/dip_util.h" |
32 #include "ui/compositor/layer.h" | 28 #include "ui/compositor/layer.h" |
33 #include "ui/gfx/frame_time.h" | 29 #include "ui/gfx/frame_time.h" |
34 #include "ui/gl/gl_context.h" | 30 #include "ui/gl/gl_context.h" |
35 #include "ui/gl/gl_switches.h" | 31 #include "ui/gl/gl_switches.h" |
36 | 32 |
37 namespace { | 33 namespace { |
38 | 34 |
39 const double kDefaultRefreshRate = 60.0; | 35 const double kDefaultRefreshRate = 60.0; |
40 const double kTestRefreshRate = 200.0; | 36 const double kTestRefreshRate = 200.0; |
41 | 37 |
42 bool g_compositor_initialized = false; | |
43 base::Thread* g_compositor_thread = NULL; | |
44 | |
45 ui::ContextFactory* g_context_factory = NULL; | 38 ui::ContextFactory* g_context_factory = NULL; |
46 | 39 |
47 const int kCompositorLockTimeoutMs = 67; | 40 const int kCompositorLockTimeoutMs = 67; |
48 | 41 |
49 } // namespace | 42 } // namespace |
50 | 43 |
51 namespace ui { | 44 namespace ui { |
52 | 45 |
53 // static | 46 // static |
54 ContextFactory* ContextFactory::GetInstance() { | 47 ContextFactory* ContextFactory::GetInstance() { |
(...skipping 30 matching lines...) Expand all Loading... |
85 | 78 |
86 namespace { | 79 namespace { |
87 | 80 |
88 } // namespace | 81 } // namespace |
89 | 82 |
90 namespace ui { | 83 namespace ui { |
91 | 84 |
92 Compositor::Compositor(gfx::AcceleratedWidget widget) | 85 Compositor::Compositor(gfx::AcceleratedWidget widget) |
93 : root_layer_(NULL), | 86 : root_layer_(NULL), |
94 widget_(widget), | 87 widget_(widget), |
| 88 compositor_thread_loop_(g_context_factory->GetCompositorMessageLoop()), |
95 vsync_manager_(new CompositorVSyncManager()), | 89 vsync_manager_(new CompositorVSyncManager()), |
96 device_scale_factor_(0.0f), | 90 device_scale_factor_(0.0f), |
97 last_started_frame_(0), | 91 last_started_frame_(0), |
98 last_ended_frame_(0), | 92 last_ended_frame_(0), |
99 next_draw_is_resize_(false), | 93 next_draw_is_resize_(false), |
100 disable_schedule_composite_(false), | 94 disable_schedule_composite_(false), |
101 compositor_lock_(NULL), | 95 compositor_lock_(NULL), |
102 defer_draw_scheduling_(false), | 96 defer_draw_scheduling_(false), |
103 waiting_on_compositing_end_(false), | 97 waiting_on_compositing_end_(false), |
104 draw_on_compositing_end_(false), | 98 draw_on_compositing_end_(false), |
105 swap_state_(SWAP_NONE), | 99 swap_state_(SWAP_NONE), |
106 schedule_draw_factory_(this) { | 100 schedule_draw_factory_(this) { |
107 DCHECK(g_compositor_initialized) | |
108 << "Compositor::Initialize must be called before creating a Compositor."; | |
109 | |
110 root_web_layer_ = cc::Layer::Create(); | 101 root_web_layer_ = cc::Layer::Create(); |
111 root_web_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f)); | 102 root_web_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f)); |
112 | 103 |
113 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 104 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
114 | 105 |
115 cc::LayerTreeSettings settings; | 106 cc::LayerTreeSettings settings; |
116 settings.refresh_rate = | 107 settings.refresh_rate = |
117 ContextFactory::GetInstance()->DoesCreateTestContexts() | 108 ContextFactory::GetInstance()->DoesCreateTestContexts() |
118 ? kTestRefreshRate | 109 ? kTestRefreshRate |
119 : kDefaultRefreshRate; | 110 : kDefaultRefreshRate; |
(...skipping 29 matching lines...) Expand all Loading... |
149 settings.initial_debug_state.show_non_occluding_rects = | 140 settings.initial_debug_state.show_non_occluding_rects = |
150 command_line->HasSwitch(cc::switches::kUIShowNonOccludingRects); | 141 command_line->HasSwitch(cc::switches::kUIShowNonOccludingRects); |
151 | 142 |
152 settings.initial_debug_state.SetRecordRenderingStats( | 143 settings.initial_debug_state.SetRecordRenderingStats( |
153 command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking)); | 144 command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking)); |
154 | 145 |
155 settings.impl_side_painting = IsUIImplSidePaintingEnabled(); | 146 settings.impl_side_painting = IsUIImplSidePaintingEnabled(); |
156 settings.use_zero_copy = IsUIZeroCopyEnabled(); | 147 settings.use_zero_copy = IsUIZeroCopyEnabled(); |
157 | 148 |
158 base::TimeTicks before_create = base::TimeTicks::Now(); | 149 base::TimeTicks before_create = base::TimeTicks::Now(); |
159 if (!!g_compositor_thread) { | 150 if (compositor_thread_loop_) { |
160 host_ = cc::LayerTreeHost::CreateThreaded( | 151 host_ = cc::LayerTreeHost::CreateThreaded( |
161 this, | 152 this, |
162 g_context_factory->GetSharedBitmapManager(), | 153 g_context_factory->GetSharedBitmapManager(), |
163 settings, | 154 settings, |
164 g_compositor_thread->message_loop_proxy()); | 155 compositor_thread_loop_); |
165 } else { | 156 } else { |
166 host_ = cc::LayerTreeHost::CreateSingleThreaded( | 157 host_ = cc::LayerTreeHost::CreateSingleThreaded( |
167 this, this, g_context_factory->GetSharedBitmapManager(), settings); | 158 this, this, g_context_factory->GetSharedBitmapManager(), settings); |
168 } | 159 } |
169 UMA_HISTOGRAM_TIMES("GPU.CreateBrowserCompositor", | 160 UMA_HISTOGRAM_TIMES("GPU.CreateBrowserCompositor", |
170 base::TimeTicks::Now() - before_create); | 161 base::TimeTicks::Now() - before_create); |
171 host_->SetRootLayer(root_web_layer_); | 162 host_->SetRootLayer(root_web_layer_); |
172 host_->SetLayerTreeHostClientReady(); | 163 host_->SetLayerTreeHostClientReady(); |
173 } | 164 } |
174 | 165 |
175 Compositor::~Compositor() { | 166 Compositor::~Compositor() { |
176 TRACE_EVENT0("shutdown", "Compositor::destructor"); | 167 TRACE_EVENT0("shutdown", "Compositor::destructor"); |
177 | 168 |
178 DCHECK(g_compositor_initialized); | |
179 | |
180 CancelCompositorLock(); | 169 CancelCompositorLock(); |
181 DCHECK(!compositor_lock_); | 170 DCHECK(!compositor_lock_); |
182 | 171 |
183 if (root_layer_) | 172 if (root_layer_) |
184 root_layer_->SetCompositor(NULL); | 173 root_layer_->SetCompositor(NULL); |
185 | 174 |
186 // Stop all outstanding draws before telling the ContextFactory to tear | 175 // Stop all outstanding draws before telling the ContextFactory to tear |
187 // down any contexts that the |host_| may rely upon. | 176 // down any contexts that the |host_| may rely upon. |
188 host_.reset(); | 177 host_.reset(); |
189 | 178 |
190 ContextFactory::GetInstance()->RemoveCompositor(this); | 179 ContextFactory::GetInstance()->RemoveCompositor(this); |
191 } | 180 } |
192 | 181 |
193 // static | |
194 void Compositor::Initialize() { | |
195 #if defined(OS_CHROMEOS) | |
196 bool use_thread = !CommandLine::ForCurrentProcess()->HasSwitch( | |
197 switches::kUIDisableThreadedCompositing); | |
198 #else | |
199 bool use_thread = false; | |
200 #endif | |
201 if (use_thread) { | |
202 g_compositor_thread = new base::Thread("Browser Compositor"); | |
203 g_compositor_thread->Start(); | |
204 } | |
205 | |
206 DCHECK(!g_compositor_initialized) << "Compositor initialized twice."; | |
207 g_compositor_initialized = true; | |
208 } | |
209 | |
210 // static | |
211 bool Compositor::WasInitializedWithThread() { | |
212 DCHECK(g_compositor_initialized); | |
213 return !!g_compositor_thread; | |
214 } | |
215 | |
216 // static | |
217 scoped_refptr<base::MessageLoopProxy> Compositor::GetCompositorMessageLoop() { | |
218 scoped_refptr<base::MessageLoopProxy> proxy; | |
219 if (g_compositor_thread) | |
220 proxy = g_compositor_thread->message_loop_proxy(); | |
221 return proxy; | |
222 } | |
223 | |
224 // static | |
225 void Compositor::Terminate() { | |
226 if (g_compositor_thread) { | |
227 g_compositor_thread->Stop(); | |
228 delete g_compositor_thread; | |
229 g_compositor_thread = NULL; | |
230 } | |
231 | |
232 DCHECK(g_compositor_initialized) << "Compositor::Initialize() didn't happen."; | |
233 g_compositor_initialized = false; | |
234 } | |
235 | |
236 void Compositor::ScheduleDraw() { | 182 void Compositor::ScheduleDraw() { |
237 if (g_compositor_thread) { | 183 if (compositor_thread_loop_) { |
238 host_->Composite(gfx::FrameTime::Now()); | 184 host_->Composite(gfx::FrameTime::Now()); |
239 } else if (!defer_draw_scheduling_) { | 185 } else if (!defer_draw_scheduling_) { |
240 defer_draw_scheduling_ = true; | 186 defer_draw_scheduling_ = true; |
241 base::MessageLoop::current()->PostTask( | 187 base::MessageLoop::current()->PostTask( |
242 FROM_HERE, | 188 FROM_HERE, |
243 base::Bind(&Compositor::Draw, schedule_draw_factory_.GetWeakPtr())); | 189 base::Bind(&Compositor::Draw, schedule_draw_factory_.GetWeakPtr())); |
244 } | 190 } |
245 } | 191 } |
246 | 192 |
247 void Compositor::SetRootLayer(Layer* root_layer) { | 193 void Compositor::SetRootLayer(Layer* root_layer) { |
248 if (root_layer_ == root_layer) | 194 if (root_layer_ == root_layer) |
249 return; | 195 return; |
250 if (root_layer_) | 196 if (root_layer_) |
251 root_layer_->SetCompositor(NULL); | 197 root_layer_->SetCompositor(NULL); |
252 root_layer_ = root_layer; | 198 root_layer_ = root_layer; |
253 if (root_layer_ && !root_layer_->GetCompositor()) | 199 if (root_layer_ && !root_layer_->GetCompositor()) |
254 root_layer_->SetCompositor(this); | 200 root_layer_->SetCompositor(this); |
255 root_web_layer_->RemoveAllChildren(); | 201 root_web_layer_->RemoveAllChildren(); |
256 if (root_layer_) | 202 if (root_layer_) |
257 root_web_layer_->AddChild(root_layer_->cc_layer()); | 203 root_web_layer_->AddChild(root_layer_->cc_layer()); |
258 } | 204 } |
259 | 205 |
260 void Compositor::SetHostHasTransparentBackground( | 206 void Compositor::SetHostHasTransparentBackground( |
261 bool host_has_transparent_background) { | 207 bool host_has_transparent_background) { |
262 host_->set_has_transparent_background(host_has_transparent_background); | 208 host_->set_has_transparent_background(host_has_transparent_background); |
263 } | 209 } |
264 | 210 |
265 void Compositor::Draw() { | 211 void Compositor::Draw() { |
266 DCHECK(!g_compositor_thread); | 212 DCHECK(!compositor_thread_loop_); |
267 | 213 |
268 defer_draw_scheduling_ = false; | 214 defer_draw_scheduling_ = false; |
269 if (waiting_on_compositing_end_) { | 215 if (waiting_on_compositing_end_) { |
270 draw_on_compositing_end_ = true; | 216 draw_on_compositing_end_ = true; |
271 return; | 217 return; |
272 } | 218 } |
273 waiting_on_compositing_end_ = true; | 219 waiting_on_compositing_end_ = true; |
274 | 220 |
275 TRACE_EVENT_ASYNC_BEGIN0("ui", "Compositor::Draw", last_started_frame_ + 1); | 221 TRACE_EVENT_ASYNC_BEGIN0("ui", "Compositor::Draw", last_started_frame_ + 1); |
276 | 222 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 } | 321 } |
376 | 322 |
377 void Compositor::DidCommitAndDrawFrame() { | 323 void Compositor::DidCommitAndDrawFrame() { |
378 base::TimeTicks start_time = gfx::FrameTime::Now(); | 324 base::TimeTicks start_time = gfx::FrameTime::Now(); |
379 FOR_EACH_OBSERVER(CompositorObserver, | 325 FOR_EACH_OBSERVER(CompositorObserver, |
380 observer_list_, | 326 observer_list_, |
381 OnCompositingStarted(this, start_time)); | 327 OnCompositingStarted(this, start_time)); |
382 } | 328 } |
383 | 329 |
384 void Compositor::DidCompleteSwapBuffers() { | 330 void Compositor::DidCompleteSwapBuffers() { |
385 if (g_compositor_thread) { | 331 if (compositor_thread_loop_) { |
386 NotifyEnd(); | 332 NotifyEnd(); |
387 } else { | 333 } else { |
388 DCHECK_EQ(swap_state_, SWAP_POSTED); | 334 DCHECK_EQ(swap_state_, SWAP_POSTED); |
389 NotifyEnd(); | 335 NotifyEnd(); |
390 swap_state_ = SWAP_COMPLETED; | 336 swap_state_ = SWAP_COMPLETED; |
391 } | 337 } |
392 } | 338 } |
393 | 339 |
394 void Compositor::ScheduleComposite() { | 340 void Compositor::ScheduleComposite() { |
395 if (!disable_schedule_composite_) | 341 if (!disable_schedule_composite_) |
396 ScheduleDraw(); | 342 ScheduleDraw(); |
397 } | 343 } |
398 | 344 |
399 void Compositor::ScheduleAnimation() { | 345 void Compositor::ScheduleAnimation() { |
400 ScheduleComposite(); | 346 ScheduleComposite(); |
401 } | 347 } |
402 | 348 |
403 void Compositor::DidPostSwapBuffers() { | 349 void Compositor::DidPostSwapBuffers() { |
404 DCHECK(!g_compositor_thread); | 350 DCHECK(!compositor_thread_loop_); |
405 DCHECK_EQ(swap_state_, SWAP_NONE); | 351 DCHECK_EQ(swap_state_, SWAP_NONE); |
406 swap_state_ = SWAP_POSTED; | 352 swap_state_ = SWAP_POSTED; |
407 } | 353 } |
408 | 354 |
409 void Compositor::DidAbortSwapBuffers() { | 355 void Compositor::DidAbortSwapBuffers() { |
410 if (!g_compositor_thread) { | 356 if (!compositor_thread_loop_) { |
411 if (swap_state_ == SWAP_POSTED) { | 357 if (swap_state_ == SWAP_POSTED) { |
412 NotifyEnd(); | 358 NotifyEnd(); |
413 swap_state_ = SWAP_COMPLETED; | 359 swap_state_ = SWAP_COMPLETED; |
414 } | 360 } |
415 } | 361 } |
416 | 362 |
417 FOR_EACH_OBSERVER(CompositorObserver, | 363 FOR_EACH_OBSERVER(CompositorObserver, |
418 observer_list_, | 364 observer_list_, |
419 OnCompositingAborted(this)); | 365 OnCompositingAborted(this)); |
420 } | 366 } |
421 | 367 |
422 const cc::LayerTreeDebugState& Compositor::GetLayerTreeDebugState() const { | 368 const cc::LayerTreeDebugState& Compositor::GetLayerTreeDebugState() const { |
423 return host_->debug_state(); | 369 return host_->debug_state(); |
424 } | 370 } |
425 | 371 |
426 void Compositor::SetLayerTreeDebugState( | 372 void Compositor::SetLayerTreeDebugState( |
427 const cc::LayerTreeDebugState& debug_state) { | 373 const cc::LayerTreeDebugState& debug_state) { |
428 host_->SetDebugState(debug_state); | 374 host_->SetDebugState(debug_state); |
429 } | 375 } |
430 | 376 |
431 scoped_refptr<CompositorLock> Compositor::GetCompositorLock() { | 377 scoped_refptr<CompositorLock> Compositor::GetCompositorLock() { |
432 if (!compositor_lock_) { | 378 if (!compositor_lock_) { |
433 compositor_lock_ = new CompositorLock(this); | 379 compositor_lock_ = new CompositorLock(this); |
434 if (g_compositor_thread) | 380 if (compositor_thread_loop_) |
435 host_->SetDeferCommits(true); | 381 host_->SetDeferCommits(true); |
436 FOR_EACH_OBSERVER(CompositorObserver, | 382 FOR_EACH_OBSERVER(CompositorObserver, |
437 observer_list_, | 383 observer_list_, |
438 OnCompositingLockStateChanged(this)); | 384 OnCompositingLockStateChanged(this)); |
439 } | 385 } |
440 return compositor_lock_; | 386 return compositor_lock_; |
441 } | 387 } |
442 | 388 |
443 void Compositor::UnlockCompositor() { | 389 void Compositor::UnlockCompositor() { |
444 DCHECK(compositor_lock_); | 390 DCHECK(compositor_lock_); |
445 compositor_lock_ = NULL; | 391 compositor_lock_ = NULL; |
446 if (g_compositor_thread) | 392 if (compositor_thread_loop_) |
447 host_->SetDeferCommits(false); | 393 host_->SetDeferCommits(false); |
448 FOR_EACH_OBSERVER(CompositorObserver, | 394 FOR_EACH_OBSERVER(CompositorObserver, |
449 observer_list_, | 395 observer_list_, |
450 OnCompositingLockStateChanged(this)); | 396 OnCompositingLockStateChanged(this)); |
451 } | 397 } |
452 | 398 |
453 void Compositor::CancelCompositorLock() { | 399 void Compositor::CancelCompositorLock() { |
454 if (compositor_lock_) | 400 if (compositor_lock_) |
455 compositor_lock_->CancelLock(); | 401 compositor_lock_->CancelLock(); |
456 } | 402 } |
457 | 403 |
458 void Compositor::NotifyEnd() { | 404 void Compositor::NotifyEnd() { |
459 last_ended_frame_++; | 405 last_ended_frame_++; |
460 TRACE_EVENT_ASYNC_END0("ui", "Compositor::Draw", last_ended_frame_); | 406 TRACE_EVENT_ASYNC_END0("ui", "Compositor::Draw", last_ended_frame_); |
461 waiting_on_compositing_end_ = false; | 407 waiting_on_compositing_end_ = false; |
462 if (draw_on_compositing_end_) { | 408 if (draw_on_compositing_end_) { |
463 draw_on_compositing_end_ = false; | 409 draw_on_compositing_end_ = false; |
464 | 410 |
465 // Call ScheduleDraw() instead of Draw() in order to allow other | 411 // Call ScheduleDraw() instead of Draw() in order to allow other |
466 // CompositorObservers to be notified before starting another | 412 // CompositorObservers to be notified before starting another |
467 // draw cycle. | 413 // draw cycle. |
468 ScheduleDraw(); | 414 ScheduleDraw(); |
469 } | 415 } |
470 FOR_EACH_OBSERVER(CompositorObserver, | 416 FOR_EACH_OBSERVER(CompositorObserver, |
471 observer_list_, | 417 observer_list_, |
472 OnCompositingEnded(this)); | 418 OnCompositingEnded(this)); |
473 } | 419 } |
474 | 420 |
475 } // namespace ui | 421 } // namespace ui |
OLD | NEW |