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 3 // found in the LICENSE file. 4 5 #include "ui/compositor/compositor.h" 6 7 #include <algorithm> 8 #include <deque> 9 10 #include "base/bind.h" 11 #include "base/command_line.h" 12 #include "base/memory/singleton.h" 13 #include "base/message_loop/message_loop.h" 14 #include "base/run_loop.h" 15 #include "base/strings/string_util.h" 16 #include "base/threading/thread.h" 17 #include "base/threading/thread_restrictions.h" 18 #include "cc/base/switches.h" 19 #include "cc/input/input_handler.h" 20 #include "cc/layers/layer.h" 21 #include "cc/output/context_provider.h" 22 #include "cc/output/output_surface.h" 23 #include "cc/trees/layer_tree_host.h" 24 #include "third_party/skia/include/core/SkBitmap.h" 25 #include "ui/compositor/compositor_observer.h" 26 #include "ui/compositor/compositor_switches.h" 27 #include "ui/compositor/context_provider_from_context_factory.h" 28 #include "ui/compositor/dip_util.h" 29 #include "ui/compositor/layer.h" 30 #include "ui/compositor/reflector.h" 31 #include "ui/compositor/test_web_graphics_context_3d.h" 32 #include "ui/gl/gl_context.h" 33 #include "ui/gl/gl_implementation.h" 34 #include "ui/gl/gl_surface.h" 35 #include "ui/gl/gl_switches.h" 36 #include "webkit/common/gpu/grcontext_for_webgraphicscontext3d.h" 37 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" 38 39 #if defined(OS_CHROMEOS) 40 #include "base/chromeos/chromeos_version.h" 41 #endif 42 43 namespace { 44 45 const double kDefaultRefreshRate = 60.0; 46 const double kTestRefreshRate = 200.0; 47 48 enum SwapType { 49 DRAW_SWAP, 50 READPIXELS_SWAP, 51 }; 52 53 bool g_compositor_initialized = false; 54 base::Thread* g_compositor_thread = NULL; 55 56 ui::ContextFactory* g_implicit_factory = NULL; 57 ui::ContextFactory* g_context_factory = NULL; 58 59 const int kCompositorLockTimeoutMs = 67; 60 61 class PendingSwap { 62 public: 63 PendingSwap(SwapType type, ui::PostedSwapQueue* posted_swaps); 64 ~PendingSwap(); 65 66 SwapType type() const { return type_; } 67 bool posted() const { return posted_; } 68 69 private: 70 friend class ui::PostedSwapQueue; 71 72 SwapType type_; 73 bool posted_; 74 ui::PostedSwapQueue* posted_swaps_; 75 76 DISALLOW_COPY_AND_ASSIGN(PendingSwap); 77 }; 78 79 } // namespace 80 81 namespace ui { 82 83 // static 84 ContextFactory* ContextFactory::GetInstance() { 85 DCHECK(g_context_factory); 86 return g_context_factory; 87 } 88 89 // static 90 void ContextFactory::SetInstance(ContextFactory* instance) { 91 g_context_factory = instance; 92 } 93 94 DefaultContextFactory::DefaultContextFactory() { 95 } 96 97 DefaultContextFactory::~DefaultContextFactory() { 98 } 99 100 bool DefaultContextFactory::Initialize() { 101 if (!gfx::GLSurface::InitializeOneOff() || 102 gfx::GetGLImplementation() == gfx::kGLImplementationNone) { 103 LOG(ERROR) << "Could not load the GL bindings"; 104 return false; 105 } 106 return true; 107 } 108 109 scoped_ptr<cc::OutputSurface> DefaultContextFactory::CreateOutputSurface( 110 Compositor* compositor) { 111 return make_scoped_ptr(new cc::OutputSurface( 112 CreateContextCommon(compositor, false))); 113 } 114 115 scoped_ptr<WebKit::WebGraphicsContext3D> 116 DefaultContextFactory::CreateOffscreenContext() { 117 return CreateContextCommon(NULL, true); 118 } 119 120 scoped_refptr<Reflector> DefaultContextFactory::CreateReflector( 121 Compositor* mirroed_compositor, 122 Layer* mirroring_layer) { 123 return NULL; 124 } 125 126 void DefaultContextFactory::RemoveReflector( 127 scoped_refptr<Reflector> reflector) { 128 } 129 130 scoped_refptr<cc::ContextProvider> 131 DefaultContextFactory::OffscreenContextProviderForMainThread() { 132 if (!offscreen_contexts_main_thread_.get() || 133 !offscreen_contexts_main_thread_->DestroyedOnMainThread()) { 134 offscreen_contexts_main_thread_ = 135 webkit::gpu::ContextProviderInProcess::CreateOffscreen(); 136 if (offscreen_contexts_main_thread_.get() && 137 !offscreen_contexts_main_thread_->BindToCurrentThread()) 138 offscreen_contexts_main_thread_ = NULL; 139 } 140 return offscreen_contexts_main_thread_; 141 } 142 143 scoped_refptr<cc::ContextProvider> 144 DefaultContextFactory::OffscreenContextProviderForCompositorThread() { 145 if (!offscreen_contexts_compositor_thread_.get() || 146 !offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) { 147 offscreen_contexts_compositor_thread_ = 148 webkit::gpu::ContextProviderInProcess::CreateOffscreen(); 149 } 150 return offscreen_contexts_compositor_thread_; 151 } 152 153 void DefaultContextFactory::RemoveCompositor(Compositor* compositor) { 154 } 155 156 bool DefaultContextFactory::DoesCreateTestContexts() { return false; } 157 158 scoped_ptr<WebKit::WebGraphicsContext3D> 159 DefaultContextFactory::CreateContextCommon(Compositor* compositor, 160 bool offscreen) { 161 DCHECK(offscreen || compositor); 162 WebKit::WebGraphicsContext3D::Attributes attrs; 163 attrs.depth = false; 164 attrs.stencil = false; 165 attrs.antialias = false; 166 attrs.shareResources = true; 167 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl; 168 if (offscreen) { 169 return WebGraphicsContext3DInProcessCommandBufferImpl:: 170 CreateOffscreenContext(attrs); 171 } 172 return WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext( 173 attrs, compositor->widget()); 174 } 175 176 TestContextFactory::TestContextFactory() {} 177 178 TestContextFactory::~TestContextFactory() {} 179 180 scoped_ptr<cc::OutputSurface> TestContextFactory::CreateOutputSurface( 181 Compositor* compositor) { 182 return make_scoped_ptr(new cc::OutputSurface(CreateOffscreenContext())); 183 } 184 185 scoped_ptr<WebKit::WebGraphicsContext3D> 186 TestContextFactory::CreateOffscreenContext() { 187 scoped_ptr<ui::TestWebGraphicsContext3D> context( 188 new ui::TestWebGraphicsContext3D); 189 context->Initialize(); 190 return context.PassAs<WebKit::WebGraphicsContext3D>(); 191 } 192 193 scoped_refptr<Reflector> TestContextFactory::CreateReflector( 194 Compositor* mirrored_compositor, 195 Layer* mirroring_layer) { 196 return new Reflector(); 197 } 198 199 void TestContextFactory::RemoveReflector(scoped_refptr<Reflector> reflector) { 200 } 201 202 scoped_refptr<cc::ContextProvider> 203 TestContextFactory::OffscreenContextProviderForMainThread() { 204 if (!offscreen_contexts_main_thread_.get() || 205 offscreen_contexts_main_thread_->DestroyedOnMainThread()) { 206 offscreen_contexts_main_thread_ = 207 ContextProviderFromContextFactory::CreateForOffscreen(this); 208 CHECK(offscreen_contexts_main_thread_->BindToCurrentThread()); 209 } 210 return offscreen_contexts_main_thread_; 211 } 212 213 scoped_refptr<cc::ContextProvider> 214 TestContextFactory::OffscreenContextProviderForCompositorThread() { 215 if (!offscreen_contexts_compositor_thread_.get() || 216 offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) { 217 offscreen_contexts_compositor_thread_ = 218 ContextProviderFromContextFactory::CreateForOffscreen(this); 219 } 220 return offscreen_contexts_compositor_thread_; 221 } 222 223 void TestContextFactory::RemoveCompositor(Compositor* compositor) { 224 } 225 226 bool TestContextFactory::DoesCreateTestContexts() { return true; } 227 228 Texture::Texture(bool flipped, const gfx::Size& size, float device_scale_factor) 229 : size_(size), 230 flipped_(flipped), 231 device_scale_factor_(device_scale_factor) { 232 } 233 234 Texture::~Texture() { 235 } 236 237 std::string Texture::Produce() { 238 return EmptyString(); 239 } 240 241 CompositorLock::CompositorLock(Compositor* compositor) 242 : compositor_(compositor) { 243 base::MessageLoop::current()->PostDelayedTask( 244 FROM_HERE, 245 base::Bind(&CompositorLock::CancelLock, AsWeakPtr()), 246 base::TimeDelta::FromMilliseconds(kCompositorLockTimeoutMs)); 247 } 248 249 CompositorLock::~CompositorLock() { 250 CancelLock(); 251 } 252 253 void CompositorLock::CancelLock() { 254 if (!compositor_) 255 return; 256 compositor_->UnlockCompositor(); 257 compositor_ = NULL; 258 } 259 260 // static 261 void DrawWaiterForTest::Wait(Compositor* compositor) { 262 DrawWaiterForTest waiter; 263 waiter.wait_for_commit_ = false; 264 waiter.WaitImpl(compositor); 265 } 266 267 // static 268 void DrawWaiterForTest::WaitForCommit(Compositor* compositor) { 269 DrawWaiterForTest waiter; 270 waiter.wait_for_commit_ = true; 271 waiter.WaitImpl(compositor); 272 } 273 274 DrawWaiterForTest::DrawWaiterForTest() { 275 } 276 277 DrawWaiterForTest::~DrawWaiterForTest() { 278 } 279 280 void DrawWaiterForTest::WaitImpl(Compositor* compositor) { 281 compositor->AddObserver(this); 282 wait_run_loop_.reset(new base::RunLoop()); 283 wait_run_loop_->Run(); 284 compositor->RemoveObserver(this); 285 } 286 287 void DrawWaiterForTest::OnCompositingDidCommit(Compositor* compositor) { 288 if (wait_for_commit_) 289 wait_run_loop_->Quit(); 290 } 291 292 void DrawWaiterForTest::OnCompositingStarted(Compositor* compositor, 293 base::TimeTicks start_time) { 294 } 295 296 void DrawWaiterForTest::OnCompositingEnded(Compositor* compositor) { 297 if (!wait_for_commit_) 298 wait_run_loop_->Quit(); 299 } 300 301 void DrawWaiterForTest::OnCompositingAborted(Compositor* compositor) { 302 } 303 304 void DrawWaiterForTest::OnCompositingLockStateChanged(Compositor* compositor) { 305 } 306 307 void DrawWaiterForTest::OnUpdateVSyncParameters(Compositor* compositor, 308 base::TimeTicks timebase, 309 base::TimeDelta interval) { 310 } 311 312 class PostedSwapQueue { 313 public: 314 PostedSwapQueue() : pending_swap_(NULL) { 315 } 316 317 ~PostedSwapQueue() { 318 DCHECK(!pending_swap_); 319 } 320 321 SwapType NextPostedSwap() const { 322 return queue_.front(); 323 } 324 325 bool AreSwapsPosted() const { 326 return !queue_.empty(); 327 } 328 329 int NumSwapsPosted(SwapType type) const { 330 int count = 0; 331 for (std::deque<SwapType>::const_iterator it = queue_.begin(); 332 it != queue_.end(); ++it) { 333 if (*it == type) 334 count++; 335 } 336 return count; 337 } 338 339 void PostSwap() { 340 DCHECK(pending_swap_); 341 queue_.push_back(pending_swap_->type()); 342 pending_swap_->posted_ = true; 343 } 344 345 void EndSwap() { 346 queue_.pop_front(); 347 } 348 349 private: 350 friend class ::PendingSwap; 351 352 PendingSwap* pending_swap_; 353 std::deque<SwapType> queue_; 354 355 DISALLOW_COPY_AND_ASSIGN(PostedSwapQueue); 356 }; 357 358 } // namespace ui 359 360 namespace { 361 362 PendingSwap::PendingSwap(SwapType type, ui::PostedSwapQueue* posted_swaps) 363 : type_(type), posted_(false), posted_swaps_(posted_swaps) { 364 // Only one pending swap in flight. 365 DCHECK_EQ(static_cast<PendingSwap*>(NULL), posted_swaps_->pending_swap_); 366 posted_swaps_->pending_swap_ = this; 367 } 368 369 PendingSwap::~PendingSwap() { 370 DCHECK_EQ(this, posted_swaps_->pending_swap_); 371 posted_swaps_->pending_swap_ = NULL; 372 } 373 374 } // namespace 375 376 namespace ui { 377 378 Compositor::Compositor(CompositorDelegate* delegate, 379 gfx::AcceleratedWidget widget) 380 : delegate_(delegate), 381 root_layer_(NULL), 382 widget_(widget), 383 posted_swaps_(new PostedSwapQueue()), 384 device_scale_factor_(0.0f), 385 last_started_frame_(0), 386 last_ended_frame_(0), 387 next_draw_is_resize_(false), 388 disable_schedule_composite_(false), 389 compositor_lock_(NULL) { 390 DCHECK(g_compositor_initialized) 391 << "Compositor::Initialize must be called before creating a Compositor."; 392 393 root_web_layer_ = cc::Layer::Create(); 394 root_web_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f)); 395 396 CommandLine* command_line = CommandLine::ForCurrentProcess(); 397 398 cc::LayerTreeSettings settings; 399 settings.refresh_rate = 400 ContextFactory::GetInstance()->DoesCreateTestContexts() 401 ? kTestRefreshRate 402 : kDefaultRefreshRate; 403 settings.partial_swap_enabled = 404 !command_line->HasSwitch(cc::switches::kUIDisablePartialSwap); 405 settings.per_tile_painting_enabled = 406 command_line->HasSwitch(cc::switches::kUIEnablePerTilePainting); 407 408 // These flags should be mirrored by renderer versions in content/renderer/. 409 settings.initial_debug_state.show_debug_borders = 410 command_line->HasSwitch(cc::switches::kUIShowCompositedLayerBorders); 411 settings.initial_debug_state.show_fps_counter = 412 command_line->HasSwitch(cc::switches::kUIShowFPSCounter); 413 settings.initial_debug_state.show_paint_rects = 414 command_line->HasSwitch(switches::kUIShowPaintRects); 415 settings.initial_debug_state.show_property_changed_rects = 416 command_line->HasSwitch(cc::switches::kUIShowPropertyChangedRects); 417 settings.initial_debug_state.show_surface_damage_rects = 418 command_line->HasSwitch(cc::switches::kUIShowSurfaceDamageRects); 419 settings.initial_debug_state.show_screen_space_rects = 420 command_line->HasSwitch(cc::switches::kUIShowScreenSpaceRects); 421 settings.initial_debug_state.show_replica_screen_space_rects = 422 command_line->HasSwitch(cc::switches::kUIShowReplicaScreenSpaceRects); 423 settings.initial_debug_state.show_occluding_rects = 424 command_line->HasSwitch(cc::switches::kUIShowOccludingRects); 425 settings.initial_debug_state.show_non_occluding_rects = 426 command_line->HasSwitch(cc::switches::kUIShowNonOccludingRects); 427 428 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner = 429 g_compositor_thread ? g_compositor_thread->message_loop_proxy() : NULL; 430 431 host_ = cc::LayerTreeHost::Create(this, settings, compositor_task_runner); 432 host_->SetRootLayer(root_web_layer_); 433 host_->SetLayerTreeHostClientReady(); 434 } 435 436 Compositor::~Compositor() { 437 DCHECK(g_compositor_initialized); 438 439 CancelCompositorLock(); 440 DCHECK(!compositor_lock_); 441 442 // Don't call |CompositorDelegate::ScheduleDraw| from this point. 443 delegate_ = NULL; 444 if (root_layer_) 445 root_layer_->SetCompositor(NULL); 446 447 // Stop all outstanding draws before telling the ContextFactory to tear 448 // down any contexts that the |host_| may rely upon. 449 host_.reset(); 450 451 ContextFactory::GetInstance()->RemoveCompositor(this); 452 } 453 454 // static 455 void Compositor::InitializeContextFactoryForTests(bool allow_test_contexts) { 456 DCHECK(!g_context_factory) << "ContextFactory already initialized."; 457 DCHECK(!g_implicit_factory) << 458 "ContextFactory for tests already initialized."; 459 460 bool use_test_contexts = true; 461 462 // Always use test contexts unless the disable command line flag is used. 463 CommandLine* command_line = CommandLine::ForCurrentProcess(); 464 if (command_line->HasSwitch(switches::kDisableTestCompositor)) 465 use_test_contexts = false; 466 467 #if defined(OS_CHROMEOS) 468 // If the test is running on the chromeos envrionment (such as 469 // device or vm bots), always use real contexts. 470 if (base::chromeos::IsRunningOnChromeOS()) 471 use_test_contexts = false; 472 #endif 473 474 if (!allow_test_contexts) 475 use_test_contexts = false; 476 477 if (use_test_contexts) { 478 g_implicit_factory = new ui::TestContextFactory; 479 } else { 480 DVLOG(1) << "Using DefaultContextFactory"; 481 scoped_ptr<ui::DefaultContextFactory> instance( 482 new ui::DefaultContextFactory()); 483 if (instance->Initialize()) 484 g_implicit_factory = instance.release(); 485 } 486 g_context_factory = g_implicit_factory; 487 } 488 489 // static 490 void Compositor::Initialize() { 491 #if defined(OS_CHROMEOS) 492 bool use_thread = !CommandLine::ForCurrentProcess()->HasSwitch( 493 switches::kUIDisableThreadedCompositing); 494 #else 495 bool use_thread = 496 CommandLine::ForCurrentProcess()->HasSwitch( 497 switches::kUIEnableThreadedCompositing) && 498 !CommandLine::ForCurrentProcess()->HasSwitch( 499 switches::kUIDisableThreadedCompositing); 500 #endif 501 if (use_thread) { 502 g_compositor_thread = new base::Thread("Browser Compositor"); 503 #if defined(OS_POSIX) 504 // Workaround for crbug.com/293736 505 // On Posix, MessagePumpDefault uses system time, so delayed tasks (for 506 // compositor scheduling) work incorrectly across system time changes (e.g. 507 // tlsdate). So instead, use an IO loop, which uses libevent, that uses 508 // monotonic time (immune to these problems). 509 base::Thread::Options options; 510 options.message_loop_type = base::MessageLoop::TYPE_IO; 511 g_compositor_thread->StartWithOptions(options); 512 #else 513 g_compositor_thread->Start(); 514 #endif 515 } 516 517 DCHECK(!g_compositor_initialized) << "Compositor initialized twice."; 518 g_compositor_initialized = true; 519 } 520 521 // static 522 bool Compositor::WasInitializedWithThread() { 523 return !!g_compositor_thread; 524 } 525 526 // static 527 scoped_refptr<base::MessageLoopProxy> Compositor::GetCompositorMessageLoop() { 528 scoped_refptr<base::MessageLoopProxy> proxy; 529 if (g_compositor_thread) 530 proxy = g_compositor_thread->message_loop_proxy(); 531 return proxy; 532 } 533 534 // static 535 void Compositor::Terminate() { 536 if (g_context_factory) { 537 if (g_implicit_factory) { 538 delete g_implicit_factory; 539 g_implicit_factory = NULL; 540 } 541 g_context_factory = NULL; 542 } 543 544 if (g_compositor_thread) { 545 DCHECK(!g_context_factory) 546 << "The ContextFactory should not outlive the compositor thread."; 547 g_compositor_thread->Stop(); 548 delete g_compositor_thread; 549 g_compositor_thread = NULL; 550 } 551 552 DCHECK(g_compositor_initialized) << "Compositor::Initialize() didn't happen."; 553 g_compositor_initialized = false; 554 } 555 556 void Compositor::ScheduleDraw() { 557 if (g_compositor_thread) 558 host_->Composite(base::TimeTicks::Now()); 559 else if (delegate_) 560 delegate_->ScheduleDraw(); 561 } 562 563 void Compositor::SetRootLayer(Layer* root_layer) { 564 if (root_layer_ == root_layer) 565 return; 566 if (root_layer_) 567 root_layer_->SetCompositor(NULL); 568 root_layer_ = root_layer; 569 if (root_layer_ && !root_layer_->GetCompositor()) 570 root_layer_->SetCompositor(this); 571 root_web_layer_->RemoveAllChildren(); 572 if (root_layer_) 573 root_web_layer_->AddChild(root_layer_->cc_layer()); 574 } 575 576 void Compositor::SetHostHasTransparentBackground( 577 bool host_has_transparent_background) { 578 host_->set_has_transparent_background(host_has_transparent_background); 579 } 580 581 void Compositor::Draw() { 582 DCHECK(!g_compositor_thread); 583 584 if (!root_layer_) 585 return; 586 587 last_started_frame_++; 588 PendingSwap pending_swap(DRAW_SWAP, posted_swaps_.get()); 589 if (!IsLocked()) { 590 // TODO(nduca): Temporary while compositor calls 591 // compositeImmediately() directly. 592 Layout(); 593 host_->Composite(base::TimeTicks::Now()); 594 595 #if defined(OS_WIN) 596 // While we resize, we are usually a few frames behind. By blocking 597 // the UI thread here we minize the area that is mis-painted, specially 598 // in the non-client area. See RenderWidgetHostViewAura::SetBounds for 599 // more details and bug 177115. 600 if (next_draw_is_resize_ && (last_ended_frame_ > 1)) { 601 next_draw_is_resize_ = false; 602 host_->FinishAllRendering(); 603 } 604 #endif 605 606 } 607 if (!pending_swap.posted()) 608 NotifyEnd(); 609 } 610 611 void Compositor::ScheduleFullRedraw() { 612 host_->SetNeedsRedraw(); 613 } 614 615 void Compositor::ScheduleRedrawRect(const gfx::Rect& damage_rect) { 616 host_->SetNeedsRedrawRect(damage_rect); 617 } 618 619 void Compositor::SetLatencyInfo(const ui::LatencyInfo& latency_info) { 620 host_->SetLatencyInfo(latency_info); 621 } 622 623 bool Compositor::ReadPixels(SkBitmap* bitmap, 624 const gfx::Rect& bounds_in_pixel) { 625 if (bounds_in_pixel.right() > size().width() || 626 bounds_in_pixel.bottom() > size().height()) 627 return false; 628 bitmap->setConfig(SkBitmap::kARGB_8888_Config, 629 bounds_in_pixel.width(), bounds_in_pixel.height()); 630 bitmap->allocPixels(); 631 SkAutoLockPixels lock_image(*bitmap); 632 unsigned char* pixels = static_cast<unsigned char*>(bitmap->getPixels()); 633 CancelCompositorLock(); 634 PendingSwap pending_swap(READPIXELS_SWAP, posted_swaps_.get()); 635 return host_->CompositeAndReadback(pixels, bounds_in_pixel); 636 } 637 638 void Compositor::SetScaleAndSize(float scale, const gfx::Size& size_in_pixel) { 639 DCHECK_GT(scale, 0); 640 if (!size_in_pixel.IsEmpty()) { 641 size_ = size_in_pixel; 642 host_->SetViewportSize(size_in_pixel); 643 root_web_layer_->SetBounds(size_in_pixel); 644 645 next_draw_is_resize_ = true; 646 } 647 if (device_scale_factor_ != scale) { 648 device_scale_factor_ = scale; 649 if (root_layer_) 650 root_layer_->OnDeviceScaleFactorChanged(scale); 651 } 652 } 653 654 void Compositor::SetBackgroundColor(SkColor color) { 655 host_->set_background_color(color); 656 ScheduleDraw(); 657 } 658 659 void Compositor::AddObserver(CompositorObserver* observer) { 660 observer_list_.AddObserver(observer); 661 } 662 663 void Compositor::RemoveObserver(CompositorObserver* observer) { 664 observer_list_.RemoveObserver(observer); 665 } 666 667 bool Compositor::HasObserver(CompositorObserver* observer) { 668 return observer_list_.HasObserver(observer); 669 } 670 671 void Compositor::OnSwapBuffersPosted() { 672 DCHECK(!g_compositor_thread); 673 posted_swaps_->PostSwap(); 674 } 675 676 void Compositor::OnSwapBuffersComplete() { 677 DCHECK(!g_compositor_thread); 678 DCHECK(posted_swaps_->AreSwapsPosted()); 679 DCHECK_GE(1, posted_swaps_->NumSwapsPosted(DRAW_SWAP)); 680 if (posted_swaps_->NextPostedSwap() == DRAW_SWAP) 681 NotifyEnd(); 682 posted_swaps_->EndSwap(); 683 } 684 685 void Compositor::OnSwapBuffersAborted() { 686 if (!g_compositor_thread) { 687 DCHECK_GE(1, posted_swaps_->NumSwapsPosted(DRAW_SWAP)); 688 689 // We've just lost the context, so unwind all posted_swaps. 690 while (posted_swaps_->AreSwapsPosted()) { 691 if (posted_swaps_->NextPostedSwap() == DRAW_SWAP) 692 NotifyEnd(); 693 posted_swaps_->EndSwap(); 694 } 695 } 696 697 FOR_EACH_OBSERVER(CompositorObserver, 698 observer_list_, 699 OnCompositingAborted(this)); 700 } 701 702 void Compositor::OnUpdateVSyncParameters(base::TimeTicks timebase, 703 base::TimeDelta interval) { 704 FOR_EACH_OBSERVER(CompositorObserver, 705 observer_list_, 706 OnUpdateVSyncParameters(this, timebase, interval)); 707 } 708 709 void Compositor::Layout() { 710 // We're sending damage that will be addressed during this composite 711 // cycle, so we don't need to schedule another composite to address it. 712 disable_schedule_composite_ = true; 713 if (root_layer_) 714 root_layer_->SendDamagedRects(); 715 disable_schedule_composite_ = false; 716 } 717 718 scoped_ptr<cc::OutputSurface> Compositor::CreateOutputSurface(bool fallback) { 719 return ContextFactory::GetInstance()->CreateOutputSurface(this); 720 } 721 722 void Compositor::DidCommit() { 723 DCHECK(!IsLocked()); 724 FOR_EACH_OBSERVER(CompositorObserver, 725 observer_list_, 726 OnCompositingDidCommit(this)); 727 } 728 729 void Compositor::DidCommitAndDrawFrame() { 730 base::TimeTicks start_time = base::TimeTicks::Now(); 731 FOR_EACH_OBSERVER(CompositorObserver, 732 observer_list_, 733 OnCompositingStarted(this, start_time)); 734 } 735 736 void Compositor::DidCompleteSwapBuffers() { 737 DCHECK(g_compositor_thread); 738 NotifyEnd(); 739 } 740 741 void Compositor::ScheduleComposite() { 742 if (!disable_schedule_composite_) 743 ScheduleDraw(); 744 } 745 746 scoped_refptr<cc::ContextProvider> 747 Compositor::OffscreenContextProviderForMainThread() { 748 return ContextFactory::GetInstance()->OffscreenContextProviderForMainThread(); 749 } 750 751 scoped_refptr<cc::ContextProvider> 752 Compositor::OffscreenContextProviderForCompositorThread() { 753 return ContextFactory::GetInstance()-> 754 OffscreenContextProviderForCompositorThread(); 755 } 756 757 const cc::LayerTreeDebugState& Compositor::GetLayerTreeDebugState() const { 758 return host_->debug_state(); 759 } 760 761 void Compositor::SetLayerTreeDebugState( 762 const cc::LayerTreeDebugState& debug_state) { 763 host_->SetDebugState(debug_state); 764 } 765 766 scoped_refptr<CompositorLock> Compositor::GetCompositorLock() { 767 if (!compositor_lock_) { 768 compositor_lock_ = new CompositorLock(this); 769 if (g_compositor_thread) 770 host_->SetDeferCommits(true); 771 FOR_EACH_OBSERVER(CompositorObserver, 772 observer_list_, 773 OnCompositingLockStateChanged(this)); 774 } 775 return compositor_lock_; 776 } 777 778 void Compositor::UnlockCompositor() { 779 DCHECK(compositor_lock_); 780 compositor_lock_ = NULL; 781 if (g_compositor_thread) 782 host_->SetDeferCommits(false); 783 FOR_EACH_OBSERVER(CompositorObserver, 784 observer_list_, 785 OnCompositingLockStateChanged(this)); 786 } 787 788 void Compositor::CancelCompositorLock() { 789 if (compositor_lock_) 790 compositor_lock_->CancelLock(); 791 } 792 793 void Compositor::NotifyEnd() { 794 last_ended_frame_++; 795 FOR_EACH_OBSERVER(CompositorObserver, 796 observer_list_, 797 OnCompositingEnded(this)); 798 } 799 800 } // namespace ui 801