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