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