| 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 |