Home | History | Annotate | Download | only in renderer_host
      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 "content/browser/renderer_host/compositor_impl_android.h"
      6 
      7 #include <android/bitmap.h>
      8 #include <android/native_window_jni.h>
      9 
     10 #include "base/android/jni_android.h"
     11 #include "base/android/scoped_java_ref.h"
     12 #include "base/bind.h"
     13 #include "base/command_line.h"
     14 #include "base/containers/hash_tables.h"
     15 #include "base/lazy_instance.h"
     16 #include "base/logging.h"
     17 #include "base/memory/weak_ptr.h"
     18 #include "base/single_thread_task_runner.h"
     19 #include "base/synchronization/lock.h"
     20 #include "base/threading/thread.h"
     21 #include "base/threading/thread_checker.h"
     22 #include "cc/base/switches.h"
     23 #include "cc/input/input_handler.h"
     24 #include "cc/layers/layer.h"
     25 #include "cc/output/compositor_frame.h"
     26 #include "cc/output/context_provider.h"
     27 #include "cc/output/output_surface.h"
     28 #include "cc/trees/layer_tree_host.h"
     29 #include "content/browser/android/child_process_launcher_android.h"
     30 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
     31 #include "content/browser/gpu/gpu_surface_tracker.h"
     32 #include "content/common/gpu/client/command_buffer_proxy_impl.h"
     33 #include "content/common/gpu/client/context_provider_command_buffer.h"
     34 #include "content/common/gpu/client/gl_helper.h"
     35 #include "content/common/gpu/client/gpu_channel_host.h"
     36 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
     37 #include "content/common/gpu/gpu_process_launch_causes.h"
     38 #include "content/common/host_shared_bitmap_manager.h"
     39 #include "content/public/browser/android/compositor_client.h"
     40 #include "gpu/command_buffer/client/gles2_interface.h"
     41 #include "third_party/khronos/GLES2/gl2.h"
     42 #include "third_party/khronos/GLES2/gl2ext.h"
     43 #include "third_party/skia/include/core/SkMallocPixelRef.h"
     44 #include "ui/base/android/window_android.h"
     45 #include "ui/gfx/android/device_display_info.h"
     46 #include "ui/gfx/frame_time.h"
     47 #include "ui/gl/android/surface_texture.h"
     48 #include "ui/gl/android/surface_texture_tracker.h"
     49 #include "webkit/common/gpu/context_provider_in_process.h"
     50 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
     51 
     52 namespace {
     53 
     54 const unsigned int kMaxSwapBuffers = 2U;
     55 
     56 // Used to override capabilities_.adjust_deadline_for_parent to false
     57 class OutputSurfaceWithoutParent : public cc::OutputSurface {
     58  public:
     59   OutputSurfaceWithoutParent(const scoped_refptr<
     60       content::ContextProviderCommandBuffer>& context_provider,
     61       base::WeakPtr<content::CompositorImpl> compositor_impl)
     62       : cc::OutputSurface(context_provider) {
     63     capabilities_.adjust_deadline_for_parent = false;
     64     compositor_impl_ = compositor_impl;
     65     main_thread_ = base::MessageLoopProxy::current();
     66   }
     67 
     68   virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE {
     69     content::ContextProviderCommandBuffer* provider_command_buffer =
     70         static_cast<content::ContextProviderCommandBuffer*>(
     71             context_provider_.get());
     72     content::CommandBufferProxyImpl* command_buffer_proxy =
     73         provider_command_buffer->GetCommandBufferProxy();
     74     DCHECK(command_buffer_proxy);
     75     command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info);
     76 
     77     OutputSurface::SwapBuffers(frame);
     78   }
     79 
     80   virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE {
     81     if (!OutputSurface::BindToClient(client))
     82       return false;
     83 
     84     main_thread_->PostTask(
     85         FROM_HERE,
     86         base::Bind(&content::CompositorImpl::PopulateGpuCapabilities,
     87                    compositor_impl_,
     88                    context_provider_->ContextCapabilities().gpu));
     89 
     90     return true;
     91   }
     92 
     93   scoped_refptr<base::MessageLoopProxy> main_thread_;
     94   base::WeakPtr<content::CompositorImpl> compositor_impl_;
     95 };
     96 
     97 class SurfaceTextureTrackerImpl : public gfx::SurfaceTextureTracker {
     98  public:
     99   SurfaceTextureTrackerImpl() : next_surface_texture_id_(1) {
    100     thread_checker_.DetachFromThread();
    101   }
    102 
    103   // Overridden from gfx::SurfaceTextureTracker:
    104   virtual scoped_refptr<gfx::SurfaceTexture> AcquireSurfaceTexture(
    105       int primary_id,
    106       int secondary_id) OVERRIDE {
    107     base::AutoLock lock(surface_textures_lock_);
    108     SurfaceTextureMapKey key(primary_id, secondary_id);
    109     SurfaceTextureMap::iterator it = surface_textures_.find(key);
    110     if (it == surface_textures_.end())
    111       return scoped_refptr<gfx::SurfaceTexture>();
    112     scoped_refptr<gfx::SurfaceTexture> surface_texture = it->second;
    113     surface_textures_.erase(it);
    114     return surface_texture;
    115   }
    116 
    117   int AddSurfaceTexture(gfx::SurfaceTexture* surface_texture,
    118                         int child_process_id) {
    119     DCHECK(thread_checker_.CalledOnValidThread());
    120     int surface_texture_id = next_surface_texture_id_++;
    121     if (next_surface_texture_id_ == INT_MAX)
    122       next_surface_texture_id_ = 1;
    123 
    124     base::AutoLock lock(surface_textures_lock_);
    125     SurfaceTextureMapKey key(surface_texture_id, child_process_id);
    126     DCHECK(surface_textures_.find(key) == surface_textures_.end());
    127     surface_textures_[key] = surface_texture;
    128     content::RegisterChildProcessSurfaceTexture(
    129         surface_texture_id,
    130         child_process_id,
    131         surface_texture->j_surface_texture().obj());
    132     return surface_texture_id;
    133   }
    134 
    135   void RemoveAllSurfaceTextures(int child_process_id) {
    136     DCHECK(thread_checker_.CalledOnValidThread());
    137     base::AutoLock lock(surface_textures_lock_);
    138     SurfaceTextureMap::iterator it = surface_textures_.begin();
    139     while (it != surface_textures_.end()) {
    140       if (it->first.second == child_process_id) {
    141         content::UnregisterChildProcessSurfaceTexture(it->first.first,
    142                                                       it->first.second);
    143         surface_textures_.erase(it++);
    144       } else {
    145         ++it;
    146       }
    147     }
    148   }
    149 
    150  private:
    151   typedef std::pair<int, int> SurfaceTextureMapKey;
    152   typedef base::hash_map<SurfaceTextureMapKey,
    153                          scoped_refptr<gfx::SurfaceTexture> >
    154       SurfaceTextureMap;
    155   SurfaceTextureMap surface_textures_;
    156   mutable base::Lock surface_textures_lock_;
    157   int next_surface_texture_id_;
    158   base::ThreadChecker thread_checker_;
    159 };
    160 base::LazyInstance<SurfaceTextureTrackerImpl> g_surface_texture_tracker =
    161     LAZY_INSTANCE_INITIALIZER;
    162 
    163 static bool g_initialized = false;
    164 
    165 } // anonymous namespace
    166 
    167 namespace content {
    168 
    169 // static
    170 Compositor* Compositor::Create(CompositorClient* client,
    171                                gfx::NativeWindow root_window) {
    172   return client ? new CompositorImpl(client, root_window) : NULL;
    173 }
    174 
    175 // static
    176 void Compositor::Initialize() {
    177   DCHECK(!CompositorImpl::IsInitialized());
    178   // SurfaceTextureTracker instance must be set before we create a GPU thread
    179   // that could be using it to initialize GLImage instances.
    180   gfx::SurfaceTextureTracker::InitInstance(g_surface_texture_tracker.Pointer());
    181   g_initialized = true;
    182 }
    183 
    184 // static
    185 bool CompositorImpl::IsInitialized() {
    186   return g_initialized;
    187 }
    188 
    189 // static
    190 int CompositorImpl::CreateSurfaceTexture(int child_process_id) {
    191   // Note: this needs to be 0 as the surface texture implemenation will take
    192   // ownership of the texture and call glDeleteTextures when the GPU service
    193   // attaches the surface texture to a real texture id. glDeleteTextures
    194   // silently ignores 0.
    195   const int kDummyTextureId = 0;
    196   scoped_refptr<gfx::SurfaceTexture> surface_texture =
    197       gfx::SurfaceTexture::Create(kDummyTextureId);
    198   return g_surface_texture_tracker.Pointer()->AddSurfaceTexture(
    199       surface_texture.get(), child_process_id);
    200 }
    201 
    202 // static
    203 void CompositorImpl::DestroyAllSurfaceTextures(int child_process_id) {
    204   g_surface_texture_tracker.Pointer()->RemoveAllSurfaceTextures(
    205       child_process_id);
    206 }
    207 
    208 CompositorImpl::CompositorImpl(CompositorClient* client,
    209                                gfx::NativeWindow root_window)
    210     : root_layer_(cc::Layer::Create()),
    211       has_transparent_background_(false),
    212       device_scale_factor_(1),
    213       window_(NULL),
    214       surface_id_(0),
    215       client_(client),
    216       root_window_(root_window),
    217       did_post_swapbuffers_(false),
    218       ignore_schedule_composite_(false),
    219       needs_composite_(false),
    220       needs_animate_(false),
    221       will_composite_immediately_(false),
    222       composite_on_vsync_trigger_(DO_NOT_COMPOSITE),
    223       pending_swapbuffers_(0U),
    224       weak_factory_(this) {
    225   DCHECK(client);
    226   DCHECK(root_window);
    227   ImageTransportFactoryAndroid::AddObserver(this);
    228   root_window->AttachCompositor(this);
    229 }
    230 
    231 CompositorImpl::~CompositorImpl() {
    232   root_window_->DetachCompositor();
    233   ImageTransportFactoryAndroid::RemoveObserver(this);
    234   // Clean-up any surface references.
    235   SetSurface(NULL);
    236 }
    237 
    238 void CompositorImpl::PostComposite(CompositingTrigger trigger) {
    239   DCHECK(needs_composite_);
    240   DCHECK(trigger == COMPOSITE_IMMEDIATELY || trigger == COMPOSITE_EVENTUALLY);
    241 
    242   if (will_composite_immediately_ ||
    243       (trigger == COMPOSITE_EVENTUALLY && WillComposite())) {
    244     // We will already composite soon enough.
    245     DCHECK(WillComposite());
    246     return;
    247   }
    248 
    249   if (DidCompositeThisFrame()) {
    250     DCHECK(!WillCompositeThisFrame());
    251     if (composite_on_vsync_trigger_ != COMPOSITE_IMMEDIATELY) {
    252       composite_on_vsync_trigger_ = trigger;
    253       root_window_->RequestVSyncUpdate();
    254     }
    255     DCHECK(WillComposite());
    256     return;
    257   }
    258 
    259   base::TimeDelta delay;
    260   if (trigger == COMPOSITE_IMMEDIATELY) {
    261     will_composite_immediately_ = true;
    262     composite_on_vsync_trigger_ = DO_NOT_COMPOSITE;
    263   } else {
    264     DCHECK(!WillComposite());
    265     const base::TimeDelta estimated_composite_time = vsync_period_ / 4;
    266     const base::TimeTicks now = base::TimeTicks::Now();
    267 
    268     if (!last_vsync_.is_null() && (now - last_vsync_) < vsync_period_) {
    269       base::TimeTicks next_composite =
    270           last_vsync_ + vsync_period_ - estimated_composite_time;
    271       if (next_composite < now) {
    272         // It's too late, we will reschedule composite as needed on the next
    273         // vsync.
    274         composite_on_vsync_trigger_ = COMPOSITE_EVENTUALLY;
    275         root_window_->RequestVSyncUpdate();
    276         DCHECK(WillComposite());
    277         return;
    278       }
    279 
    280       delay = next_composite - now;
    281     }
    282   }
    283   TRACE_EVENT2("cc", "CompositorImpl::PostComposite",
    284                "trigger", trigger,
    285                "delay", delay.InMillisecondsF());
    286 
    287   DCHECK(composite_on_vsync_trigger_ == DO_NOT_COMPOSITE);
    288   if (current_composite_task_)
    289     current_composite_task_->Cancel();
    290 
    291   // Unretained because we cancel the task on shutdown.
    292   current_composite_task_.reset(new base::CancelableClosure(
    293       base::Bind(&CompositorImpl::Composite, base::Unretained(this), trigger)));
    294   base::MessageLoop::current()->PostDelayedTask(
    295       FROM_HERE, current_composite_task_->callback(), delay);
    296 }
    297 
    298 void CompositorImpl::Composite(CompositingTrigger trigger) {
    299   BrowserGpuChannelHostFactory* factory =
    300       BrowserGpuChannelHostFactory::instance();
    301   if (!factory->GetGpuChannel() || factory->GetGpuChannel()->IsLost()) {
    302     CauseForGpuLaunch cause =
    303         CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
    304     factory->EstablishGpuChannel(cause,
    305                                  base::Bind(&CompositorImpl::ScheduleComposite,
    306                                             weak_factory_.GetWeakPtr()));
    307     return;
    308   }
    309 
    310   DCHECK(host_);
    311   DCHECK(trigger == COMPOSITE_IMMEDIATELY || trigger == COMPOSITE_EVENTUALLY);
    312   DCHECK(needs_composite_);
    313   DCHECK(!DidCompositeThisFrame());
    314 
    315   if (trigger == COMPOSITE_IMMEDIATELY)
    316     will_composite_immediately_ = false;
    317 
    318   DCHECK_LE(pending_swapbuffers_, kMaxSwapBuffers);
    319   if (pending_swapbuffers_ == kMaxSwapBuffers) {
    320     TRACE_EVENT0("compositor", "CompositorImpl_SwapLimit");
    321     return;
    322   }
    323 
    324   // Reset state before Layout+Composite since that might create more
    325   // requests to Composite that we need to respect.
    326   needs_composite_ = false;
    327 
    328   // Only allow compositing once per vsync.
    329   current_composite_task_->Cancel();
    330   DCHECK(DidCompositeThisFrame() && !WillComposite());
    331 
    332   // Ignore ScheduleComposite() from layer tree changes during layout and
    333   // animation updates that will already be reflected in the current frame
    334   // we are about to draw.
    335   ignore_schedule_composite_ = true;
    336 
    337   const base::TimeTicks frame_time = gfx::FrameTime::Now();
    338   if (needs_animate_) {
    339     needs_animate_ = false;
    340     root_window_->Animate(frame_time);
    341   }
    342   ignore_schedule_composite_ = false;
    343 
    344   did_post_swapbuffers_ = false;
    345   host_->Composite(frame_time);
    346   if (did_post_swapbuffers_)
    347     pending_swapbuffers_++;
    348 
    349   // Need to track vsync to avoid compositing more than once per frame.
    350   root_window_->RequestVSyncUpdate();
    351 }
    352 
    353 UIResourceProvider& CompositorImpl::GetUIResourceProvider() {
    354   return ui_resource_provider_;
    355 }
    356 
    357 ui::SystemUIResourceManager& CompositorImpl::GetSystemUIResourceManager() {
    358   return ui_resource_provider_.GetSystemUIResourceManager();
    359 }
    360 
    361 void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) {
    362   if (subroot_layer_) {
    363     subroot_layer_->RemoveFromParent();
    364     subroot_layer_ = NULL;
    365   }
    366   if (root_layer) {
    367     subroot_layer_ = root_layer;
    368     root_layer_->AddChild(root_layer);
    369   }
    370 }
    371 
    372 void CompositorImpl::SetWindowSurface(ANativeWindow* window) {
    373   GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
    374 
    375   if (window_) {
    376     tracker->RemoveSurface(surface_id_);
    377     ANativeWindow_release(window_);
    378     window_ = NULL;
    379     surface_id_ = 0;
    380     SetVisible(false);
    381   }
    382 
    383   if (window) {
    384     window_ = window;
    385     ANativeWindow_acquire(window);
    386     surface_id_ = tracker->AddSurfaceForNativeWidget(window);
    387     tracker->SetSurfaceHandle(
    388         surface_id_,
    389         gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_DIRECT));
    390     SetVisible(true);
    391   }
    392 }
    393 
    394 void CompositorImpl::SetSurface(jobject surface) {
    395   JNIEnv* env = base::android::AttachCurrentThread();
    396   base::android::ScopedJavaLocalRef<jobject> j_surface(env, surface);
    397 
    398   // First, cleanup any existing surface references.
    399   if (surface_id_)
    400     content::UnregisterViewSurface(surface_id_);
    401   SetWindowSurface(NULL);
    402 
    403   // Now, set the new surface if we have one.
    404   ANativeWindow* window = NULL;
    405   if (surface) {
    406     // Note: This ensures that any local references used by
    407     // ANativeWindow_fromSurface are released immediately. This is needed as a
    408     // workaround for https://code.google.com/p/android/issues/detail?id=68174
    409     base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env);
    410     window = ANativeWindow_fromSurface(env, surface);
    411   }
    412   if (window) {
    413     SetWindowSurface(window);
    414     ANativeWindow_release(window);
    415     content::RegisterViewSurface(surface_id_, j_surface.obj());
    416   }
    417 }
    418 
    419 void CompositorImpl::SetVisible(bool visible) {
    420   if (!visible) {
    421     DCHECK(host_);
    422     // Look for any layers that were attached to the root for readback
    423     // and are waiting for Composite() to happen.
    424     bool readback_pending = false;
    425     for (size_t i = 0; i < root_layer_->children().size(); ++i) {
    426       if (root_layer_->children()[i]->HasCopyRequest()) {
    427         readback_pending = true;
    428         break;
    429       }
    430     }
    431     if (readback_pending) {
    432       ignore_schedule_composite_ = true;
    433       host_->Composite(base::TimeTicks::Now());
    434       ignore_schedule_composite_ = false;
    435     }
    436     if (WillComposite())
    437       CancelComposite();
    438     ui_resource_provider_.SetLayerTreeHost(NULL);
    439     host_.reset();
    440   } else if (!host_) {
    441     DCHECK(!WillComposite());
    442     needs_composite_ = false;
    443     pending_swapbuffers_ = 0;
    444     cc::LayerTreeSettings settings;
    445     settings.refresh_rate = 60.0;
    446     settings.impl_side_painting = false;
    447     settings.allow_antialiasing = false;
    448     settings.calculate_top_controls_position = false;
    449     settings.top_controls_height = 0.f;
    450     settings.highp_threshold_min = 2048;
    451 
    452     base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
    453     settings.initial_debug_state.SetRecordRenderingStats(
    454         command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking));
    455     settings.initial_debug_state.show_fps_counter =
    456         command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
    457     // TODO(enne): Update this this compositor to use the scheduler.
    458     settings.single_thread_proxy_scheduler = false;
    459 
    460     host_ = cc::LayerTreeHost::CreateSingleThreaded(
    461         this,
    462         this,
    463         HostSharedBitmapManager::current(),
    464         settings,
    465         base::MessageLoopProxy::current());
    466     host_->SetRootLayer(root_layer_);
    467 
    468     host_->SetVisible(true);
    469     host_->SetLayerTreeHostClientReady();
    470     host_->SetViewportSize(size_);
    471     host_->set_has_transparent_background(has_transparent_background_);
    472     host_->SetDeviceScaleFactor(device_scale_factor_);
    473     ui_resource_provider_.SetLayerTreeHost(host_.get());
    474   }
    475 }
    476 
    477 void CompositorImpl::setDeviceScaleFactor(float factor) {
    478   device_scale_factor_ = factor;
    479   if (host_)
    480     host_->SetDeviceScaleFactor(factor);
    481 }
    482 
    483 void CompositorImpl::SetWindowBounds(const gfx::Size& size) {
    484   if (size_ == size)
    485     return;
    486 
    487   size_ = size;
    488   if (host_)
    489     host_->SetViewportSize(size);
    490   root_layer_->SetBounds(size);
    491 }
    492 
    493 void CompositorImpl::SetHasTransparentBackground(bool flag) {
    494   has_transparent_background_ = flag;
    495   if (host_)
    496     host_->set_has_transparent_background(flag);
    497 }
    498 
    499 void CompositorImpl::SetNeedsComposite() {
    500   if (!host_.get())
    501     return;
    502   DCHECK(!needs_composite_ || WillComposite());
    503 
    504   needs_composite_ = true;
    505   PostComposite(COMPOSITE_IMMEDIATELY);
    506 }
    507 
    508 static scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
    509 CreateGpuProcessViewContext(
    510     const scoped_refptr<GpuChannelHost>& gpu_channel_host,
    511     const blink::WebGraphicsContext3D::Attributes attributes,
    512     int surface_id) {
    513   DCHECK(gpu_channel_host);
    514 
    515   GURL url("chrome://gpu/Compositor::createContext3D");
    516   static const size_t kBytesPerPixel = 4;
    517   gfx::DeviceDisplayInfo display_info;
    518   size_t full_screen_texture_size_in_bytes =
    519       display_info.GetDisplayHeight() *
    520       display_info.GetDisplayWidth() *
    521       kBytesPerPixel;
    522   WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
    523   limits.command_buffer_size = 64 * 1024;
    524   limits.start_transfer_buffer_size = 64 * 1024;
    525   limits.min_transfer_buffer_size = 64 * 1024;
    526   limits.max_transfer_buffer_size = std::min(
    527       3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
    528   limits.mapped_memory_reclaim_limit = 2 * 1024 * 1024;
    529   bool lose_context_when_out_of_memory = true;
    530   return make_scoped_ptr(
    531       new WebGraphicsContext3DCommandBufferImpl(surface_id,
    532                                                 url,
    533                                                 gpu_channel_host.get(),
    534                                                 attributes,
    535                                                 lose_context_when_out_of_memory,
    536                                                 limits,
    537                                                 NULL));
    538 }
    539 
    540 void CompositorImpl::Layout() {
    541   ignore_schedule_composite_ = true;
    542   client_->Layout();
    543   ignore_schedule_composite_ = false;
    544 }
    545 
    546 void CompositorImpl::RequestNewOutputSurface(bool fallback) {
    547   BrowserGpuChannelHostFactory* factory =
    548       BrowserGpuChannelHostFactory::instance();
    549   if (!factory->GetGpuChannel() || factory->GetGpuChannel()->IsLost()) {
    550     CauseForGpuLaunch cause =
    551         CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
    552     factory->EstablishGpuChannel(
    553         cause,
    554         base::Bind(&CompositorImpl::CreateOutputSurface,
    555                    weak_factory_.GetWeakPtr(),
    556                    fallback));
    557     return;
    558   }
    559 
    560   CreateOutputSurface(fallback);
    561 }
    562 
    563 void CompositorImpl::CreateOutputSurface(bool fallback) {
    564   blink::WebGraphicsContext3D::Attributes attrs;
    565   attrs.shareResources = true;
    566   attrs.noAutomaticFlushes = true;
    567   pending_swapbuffers_ = 0;
    568 
    569   DCHECK(window_);
    570   DCHECK(surface_id_);
    571 
    572   scoped_refptr<ContextProviderCommandBuffer> context_provider;
    573   BrowserGpuChannelHostFactory* factory =
    574       BrowserGpuChannelHostFactory::instance();
    575   scoped_refptr<GpuChannelHost> gpu_channel_host = factory->GetGpuChannel();
    576   if (gpu_channel_host && !gpu_channel_host->IsLost()) {
    577     context_provider = ContextProviderCommandBuffer::Create(
    578         CreateGpuProcessViewContext(gpu_channel_host, attrs, surface_id_),
    579         "BrowserCompositor");
    580   }
    581   if (!context_provider.get()) {
    582     LOG(ERROR) << "Failed to create 3D context for compositor.";
    583     host_->SetOutputSurface(scoped_ptr<cc::OutputSurface>());
    584     return;
    585   }
    586 
    587   host_->SetOutputSurface(
    588       scoped_ptr<cc::OutputSurface>(new OutputSurfaceWithoutParent(
    589           context_provider, weak_factory_.GetWeakPtr())));
    590 }
    591 
    592 void CompositorImpl::PopulateGpuCapabilities(
    593     gpu::Capabilities gpu_capabilities) {
    594   ui_resource_provider_.SetSupportsETC1NonPowerOfTwo(
    595       gpu_capabilities.texture_format_etc1_npot);
    596 }
    597 
    598 void CompositorImpl::OnLostResources() {
    599   client_->DidLoseResources();
    600 }
    601 
    602 void CompositorImpl::ScheduleComposite() {
    603   DCHECK(!needs_composite_ || WillComposite());
    604   if (ignore_schedule_composite_)
    605     return;
    606 
    607   needs_composite_ = true;
    608   // We currently expect layer tree invalidations at most once per frame
    609   // during normal operation and therefore try to composite immediately
    610   // to minimize latency.
    611   PostComposite(COMPOSITE_IMMEDIATELY);
    612 }
    613 
    614 void CompositorImpl::ScheduleAnimation() {
    615   DCHECK(!needs_composite_ || WillComposite());
    616   needs_animate_ = true;
    617 
    618   if (needs_composite_)
    619     return;
    620 
    621   TRACE_EVENT0("cc", "CompositorImpl::ScheduleAnimation");
    622   needs_composite_ = true;
    623   PostComposite(COMPOSITE_EVENTUALLY);
    624 }
    625 
    626 void CompositorImpl::DidPostSwapBuffers() {
    627   TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers");
    628   did_post_swapbuffers_ = true;
    629 }
    630 
    631 void CompositorImpl::DidCompleteSwapBuffers() {
    632   TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers");
    633   DCHECK_GT(pending_swapbuffers_, 0U);
    634   if (pending_swapbuffers_-- == kMaxSwapBuffers && needs_composite_)
    635     PostComposite(COMPOSITE_IMMEDIATELY);
    636   client_->OnSwapBuffersCompleted(pending_swapbuffers_);
    637 }
    638 
    639 void CompositorImpl::DidAbortSwapBuffers() {
    640   TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers");
    641   // This really gets called only once from
    642   // SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() when the
    643   // context was lost.
    644   ScheduleComposite();
    645   client_->OnSwapBuffersCompleted(0);
    646 }
    647 
    648 void CompositorImpl::DidCommit() {
    649   root_window_->OnCompositingDidCommit();
    650 }
    651 
    652 void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) {
    653   root_layer_->AddChild(layer);
    654 }
    655 
    656 void CompositorImpl::RequestCopyOfOutputOnRootLayer(
    657     scoped_ptr<cc::CopyOutputRequest> request) {
    658   root_layer_->RequestCopyOfOutput(request.Pass());
    659 }
    660 
    661 void CompositorImpl::OnVSync(base::TimeTicks frame_time,
    662                              base::TimeDelta vsync_period) {
    663   vsync_period_ = vsync_period;
    664   last_vsync_ = frame_time;
    665 
    666   if (WillCompositeThisFrame()) {
    667     // We somehow missed the last vsync interval, so reschedule for deadline.
    668     // We cannot schedule immediately, or will get us out-of-phase with new
    669     // renderer frames.
    670     CancelComposite();
    671     composite_on_vsync_trigger_ = COMPOSITE_EVENTUALLY;
    672   } else {
    673     current_composite_task_.reset();
    674   }
    675 
    676   DCHECK(!DidCompositeThisFrame() && !WillCompositeThisFrame());
    677   if (composite_on_vsync_trigger_ != DO_NOT_COMPOSITE) {
    678     CompositingTrigger trigger = composite_on_vsync_trigger_;
    679     composite_on_vsync_trigger_ = DO_NOT_COMPOSITE;
    680     PostComposite(trigger);
    681   }
    682 }
    683 
    684 void CompositorImpl::SetNeedsAnimate() {
    685   if (!host_)
    686     return;
    687 
    688   host_->SetNeedsAnimate();
    689 }
    690 
    691 }  // namespace content
    692