Home | History | Annotate | Download | only in in_process
      1 // Copyright 2013 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/android/in_process/synchronous_compositor_impl.h"
      6 
      7 #include "base/lazy_instance.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "cc/input/input_handler.h"
     10 #include "content/browser/android/in_process/synchronous_compositor_factory_impl.h"
     11 #include "content/browser/android/in_process/synchronous_input_event_filter.h"
     12 #include "content/browser/renderer_host/render_widget_host_view_android.h"
     13 #include "content/common/input/did_overscroll_params.h"
     14 #include "content/public/browser/android/synchronous_compositor_client.h"
     15 #include "content/public/browser/browser_thread.h"
     16 #include "content/public/browser/render_process_host.h"
     17 #include "content/public/browser/render_view_host.h"
     18 #include "ui/gl/gl_surface.h"
     19 
     20 namespace content {
     21 
     22 namespace {
     23 
     24 int GetInProcessRendererId() {
     25   content::RenderProcessHost::iterator it =
     26       content::RenderProcessHost::AllHostsIterator();
     27   if (it.IsAtEnd()) {
     28     // There should always be one RPH in single process mode.
     29     NOTREACHED();
     30     return 0;
     31   }
     32 
     33   int id = it.GetCurrentValue()->GetID();
     34   it.Advance();
     35   DCHECK(it.IsAtEnd());  // Not multiprocess compatible.
     36   return id;
     37 }
     38 
     39 base::LazyInstance<SynchronousCompositorFactoryImpl>::Leaky g_factory =
     40     LAZY_INSTANCE_INITIALIZER;
     41 
     42 }  // namespace
     43 
     44 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SynchronousCompositorImpl);
     45 
     46 // static
     47 SynchronousCompositorImpl* SynchronousCompositorImpl::FromID(int process_id,
     48                                                              int routing_id) {
     49   if (g_factory == NULL)
     50     return NULL;
     51   RenderViewHost* rvh = RenderViewHost::FromID(process_id, routing_id);
     52   if (!rvh)
     53     return NULL;
     54   WebContents* contents = WebContents::FromRenderViewHost(rvh);
     55   if (!contents)
     56     return NULL;
     57   return FromWebContents(contents);
     58 }
     59 
     60 SynchronousCompositorImpl* SynchronousCompositorImpl::FromRoutingID(
     61     int routing_id) {
     62   return FromID(GetInProcessRendererId(), routing_id);
     63 }
     64 
     65 SynchronousCompositorImpl::SynchronousCompositorImpl(WebContents* contents)
     66     : compositor_client_(NULL),
     67       output_surface_(NULL),
     68       contents_(contents),
     69       input_handler_(NULL),
     70       weak_ptr_factory_(this) {
     71   DCHECK(contents);
     72 }
     73 
     74 SynchronousCompositorImpl::~SynchronousCompositorImpl() {
     75   if (compositor_client_)
     76     compositor_client_->DidDestroyCompositor(this);
     77   SetInputHandler(NULL);
     78 }
     79 
     80 void SynchronousCompositorImpl::SetClient(
     81     SynchronousCompositorClient* compositor_client) {
     82   DCHECK(CalledOnValidThread());
     83   compositor_client_ = compositor_client;
     84 }
     85 
     86 // static
     87 void SynchronousCompositor::SetGpuService(
     88     scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
     89   g_factory.Get().SetDeferredGpuService(service);
     90 }
     91 
     92 // static
     93 void SynchronousCompositor::SetRecordFullDocument(bool record_full_document) {
     94   g_factory.Get().SetRecordFullDocument(record_full_document);
     95 }
     96 
     97 bool SynchronousCompositorImpl::InitializeHwDraw() {
     98   DCHECK(CalledOnValidThread());
     99   DCHECK(output_surface_);
    100 
    101   scoped_refptr<cc::ContextProvider> onscreen_context =
    102       g_factory.Get().CreateOnscreenContextProviderForCompositorThread();
    103 
    104   bool success = output_surface_->InitializeHwDraw(onscreen_context);
    105 
    106   if (success)
    107     g_factory.Get().CompositorInitializedHardwareDraw();
    108   return success;
    109 }
    110 
    111 void SynchronousCompositorImpl::ReleaseHwDraw() {
    112   DCHECK(CalledOnValidThread());
    113   DCHECK(output_surface_);
    114   output_surface_->ReleaseHwDraw();
    115   g_factory.Get().CompositorReleasedHardwareDraw();
    116 }
    117 
    118 gpu::GLInProcessContext* SynchronousCompositorImpl::GetShareContext() {
    119   DCHECK(CalledOnValidThread());
    120   return g_factory.Get().GetShareContext();
    121 }
    122 
    123 scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw(
    124     gfx::Size surface_size,
    125     const gfx::Transform& transform,
    126     gfx::Rect viewport,
    127     gfx::Rect clip,
    128     gfx::Rect viewport_rect_for_tile_priority,
    129     const gfx::Transform& transform_for_tile_priority) {
    130   DCHECK(CalledOnValidThread());
    131   DCHECK(output_surface_);
    132 
    133   scoped_ptr<cc::CompositorFrame> frame =
    134       output_surface_->DemandDrawHw(surface_size,
    135                                     transform,
    136                                     viewport,
    137                                     clip,
    138                                     viewport_rect_for_tile_priority,
    139                                     transform_for_tile_priority);
    140   if (frame.get())
    141     UpdateFrameMetaData(frame->metadata);
    142   return frame.Pass();
    143 }
    144 
    145 void SynchronousCompositorImpl::ReturnResources(
    146     const cc::CompositorFrameAck& frame_ack) {
    147   DCHECK(CalledOnValidThread());
    148   output_surface_->ReturnResources(frame_ack);
    149 }
    150 
    151 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
    152   DCHECK(CalledOnValidThread());
    153   DCHECK(output_surface_);
    154 
    155   scoped_ptr<cc::CompositorFrame> frame = output_surface_->DemandDrawSw(canvas);
    156   if (frame.get())
    157     UpdateFrameMetaData(frame->metadata);
    158   return !!frame.get();
    159 }
    160 
    161 void SynchronousCompositorImpl::UpdateFrameMetaData(
    162     const cc::CompositorFrameMetadata& frame_metadata) {
    163   RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
    164       contents_->GetRenderWidgetHostView());
    165   if (rwhv)
    166     rwhv->SynchronousFrameMetadata(frame_metadata);
    167 }
    168 
    169 void SynchronousCompositorImpl::SetMemoryPolicy(
    170     const SynchronousCompositorMemoryPolicy& policy) {
    171   DCHECK(CalledOnValidThread());
    172   DCHECK(output_surface_);
    173 
    174   output_surface_->SetMemoryPolicy(policy);
    175 }
    176 
    177 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
    178   if (input_handler_)
    179     input_handler_->OnRootLayerDelegatedScrollOffsetChanged();
    180 }
    181 
    182 void SynchronousCompositorImpl::DidBindOutputSurface(
    183       SynchronousCompositorOutputSurface* output_surface) {
    184   DCHECK(CalledOnValidThread());
    185   output_surface_ = output_surface;
    186   if (compositor_client_)
    187     compositor_client_->DidInitializeCompositor(this);
    188 }
    189 
    190 void SynchronousCompositorImpl::DidDestroySynchronousOutputSurface(
    191        SynchronousCompositorOutputSurface* output_surface) {
    192   DCHECK(CalledOnValidThread());
    193 
    194   // Allow for transient hand-over when two output surfaces may refer to
    195   // a single delegate.
    196   if (output_surface_ == output_surface) {
    197     output_surface_ = NULL;
    198     if (compositor_client_)
    199       compositor_client_->DidDestroyCompositor(this);
    200     compositor_client_ = NULL;
    201   }
    202 }
    203 
    204 void SynchronousCompositorImpl::SetInputHandler(
    205     cc::InputHandler* input_handler) {
    206   DCHECK(CalledOnValidThread());
    207 
    208   if (input_handler_)
    209     input_handler_->SetRootLayerScrollOffsetDelegate(NULL);
    210 
    211   input_handler_ = input_handler;
    212 
    213   if (input_handler_)
    214     input_handler_->SetRootLayerScrollOffsetDelegate(this);
    215 }
    216 
    217 void SynchronousCompositorImpl::DidOverscroll(
    218     const DidOverscrollParams& params) {
    219   if (compositor_client_) {
    220     compositor_client_->DidOverscroll(params.accumulated_overscroll,
    221                                       params.latest_overscroll_delta,
    222                                       params.current_fling_velocity);
    223   }
    224 }
    225 
    226 void SynchronousCompositorImpl::DidStopFlinging() {
    227   RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
    228       contents_->GetRenderWidgetHostView());
    229   if (rwhv)
    230     rwhv->DidStopFlinging();
    231 }
    232 
    233 void SynchronousCompositorImpl::SetContinuousInvalidate(bool enable) {
    234   DCHECK(CalledOnValidThread());
    235   if (compositor_client_)
    236     compositor_client_->SetContinuousInvalidate(enable);
    237 }
    238 
    239 InputEventAckState SynchronousCompositorImpl::HandleInputEvent(
    240     const blink::WebInputEvent& input_event) {
    241   DCHECK(CalledOnValidThread());
    242   return g_factory.Get().synchronous_input_event_filter()->HandleInputEvent(
    243       contents_->GetRoutingID(), input_event);
    244 }
    245 
    246 void SynchronousCompositorImpl::DidActivatePendingTree() {
    247   if (compositor_client_)
    248     compositor_client_->DidUpdateContent();
    249 }
    250 
    251 gfx::Vector2dF SynchronousCompositorImpl::GetTotalScrollOffset() {
    252   DCHECK(CalledOnValidThread());
    253   if (compositor_client_)
    254     return compositor_client_->GetTotalRootLayerScrollOffset();
    255   return gfx::Vector2dF();
    256 }
    257 
    258 bool SynchronousCompositorImpl::IsExternalFlingActive() const {
    259   DCHECK(CalledOnValidThread());
    260   if (compositor_client_)
    261     return compositor_client_->IsExternalFlingActive();
    262   return false;
    263 }
    264 
    265 void SynchronousCompositorImpl::UpdateRootLayerState(
    266     const gfx::Vector2dF& total_scroll_offset,
    267     const gfx::Vector2dF& max_scroll_offset,
    268     const gfx::SizeF& scrollable_size,
    269     float page_scale_factor,
    270     float min_page_scale_factor,
    271     float max_page_scale_factor) {
    272   DCHECK(CalledOnValidThread());
    273   if (!compositor_client_)
    274     return;
    275 
    276   compositor_client_->UpdateRootLayerState(total_scroll_offset,
    277                                            max_scroll_offset,
    278                                            scrollable_size,
    279                                            page_scale_factor,
    280                                            min_page_scale_factor,
    281                                            max_page_scale_factor);
    282 }
    283 
    284 // Not using base::NonThreadSafe as we want to enforce a more exacting threading
    285 // requirement: SynchronousCompositorImpl() must only be used on the UI thread.
    286 bool SynchronousCompositorImpl::CalledOnValidThread() const {
    287   return BrowserThread::CurrentlyOn(BrowserThread::UI);
    288 }
    289 
    290 // static
    291 void SynchronousCompositor::SetClientForWebContents(
    292     WebContents* contents,
    293     SynchronousCompositorClient* client) {
    294   DCHECK(contents);
    295   if (client) {
    296     g_factory.Get();  // Ensure it's initialized.
    297     SynchronousCompositorImpl::CreateForWebContents(contents);
    298   }
    299   if (SynchronousCompositorImpl* instance =
    300       SynchronousCompositorImpl::FromWebContents(contents)) {
    301     instance->SetClient(client);
    302   }
    303 }
    304 
    305 }  // namespace content
    306