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