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