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