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 scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw(
    119     gfx::Size surface_size,
    120     const gfx::Transform& transform,
    121     gfx::Rect viewport,
    122     gfx::Rect clip,
    123     gfx::Rect viewport_rect_for_tile_priority,
    124     const gfx::Transform& transform_for_tile_priority) {
    125   DCHECK(CalledOnValidThread());
    126   DCHECK(output_surface_);
    127 
    128   scoped_ptr<cc::CompositorFrame> frame =
    129       output_surface_->DemandDrawHw(surface_size,
    130                                     transform,
    131                                     viewport,
    132                                     clip,
    133                                     viewport_rect_for_tile_priority,
    134                                     transform_for_tile_priority);
    135   if (frame.get())
    136     UpdateFrameMetaData(frame->metadata);
    137 
    138   return frame.Pass();
    139 }
    140 
    141 void SynchronousCompositorImpl::ReturnResources(
    142     const cc::CompositorFrameAck& frame_ack) {
    143   DCHECK(CalledOnValidThread());
    144   output_surface_->ReturnResources(frame_ack);
    145 }
    146 
    147 bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
    148   DCHECK(CalledOnValidThread());
    149   DCHECK(output_surface_);
    150 
    151   scoped_ptr<cc::CompositorFrame> frame = output_surface_->DemandDrawSw(canvas);
    152   if (frame.get())
    153     UpdateFrameMetaData(frame->metadata);
    154   return !!frame.get();
    155 }
    156 
    157 void SynchronousCompositorImpl::UpdateFrameMetaData(
    158     const cc::CompositorFrameMetadata& frame_metadata) {
    159   RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
    160       contents_->GetRenderWidgetHostView());
    161   if (rwhv)
    162     rwhv->SynchronousFrameMetadata(frame_metadata);
    163   DeliverMessages();
    164 }
    165 
    166 void SynchronousCompositorImpl::SetMemoryPolicy(
    167     const SynchronousCompositorMemoryPolicy& policy) {
    168   DCHECK(CalledOnValidThread());
    169   DCHECK(output_surface_);
    170 
    171   output_surface_->SetMemoryPolicy(policy);
    172 }
    173 
    174 void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
    175   if (input_handler_)
    176     input_handler_->OnRootLayerDelegatedScrollOffsetChanged();
    177 }
    178 
    179 void SynchronousCompositorImpl::DidBindOutputSurface(
    180       SynchronousCompositorOutputSurface* output_surface) {
    181   DCHECK(CalledOnValidThread());
    182   output_surface_ = output_surface;
    183   if (compositor_client_)
    184     compositor_client_->DidInitializeCompositor(this);
    185 }
    186 
    187 void SynchronousCompositorImpl::DidDestroySynchronousOutputSurface(
    188        SynchronousCompositorOutputSurface* output_surface) {
    189   DCHECK(CalledOnValidThread());
    190 
    191   // Allow for transient hand-over when two output surfaces may refer to
    192   // a single delegate.
    193   if (output_surface_ == output_surface) {
    194     output_surface_ = NULL;
    195     if (compositor_client_)
    196       compositor_client_->DidDestroyCompositor(this);
    197     compositor_client_ = NULL;
    198   }
    199 }
    200 
    201 void SynchronousCompositorImpl::SetInputHandler(
    202     cc::InputHandler* input_handler) {
    203   DCHECK(CalledOnValidThread());
    204 
    205   if (input_handler_)
    206     input_handler_->SetRootLayerScrollOffsetDelegate(NULL);
    207 
    208   input_handler_ = input_handler;
    209 
    210   if (input_handler_)
    211     input_handler_->SetRootLayerScrollOffsetDelegate(this);
    212 }
    213 
    214 void SynchronousCompositorImpl::DidOverscroll(
    215     const DidOverscrollParams& params) {
    216   if (compositor_client_) {
    217     compositor_client_->DidOverscroll(params.accumulated_overscroll,
    218                                       params.latest_overscroll_delta,
    219                                       params.current_fling_velocity);
    220   }
    221 }
    222 
    223 void SynchronousCompositorImpl::DidStopFlinging() {
    224   RenderWidgetHostViewAndroid* rwhv = static_cast<RenderWidgetHostViewAndroid*>(
    225       contents_->GetRenderWidgetHostView());
    226   if (rwhv)
    227     rwhv->DidStopFlinging();
    228 }
    229 
    230 void SynchronousCompositorImpl::SetContinuousInvalidate(bool enable) {
    231   DCHECK(CalledOnValidThread());
    232   if (compositor_client_)
    233     compositor_client_->SetContinuousInvalidate(enable);
    234 }
    235 
    236 InputEventAckState SynchronousCompositorImpl::HandleInputEvent(
    237     const blink::WebInputEvent& input_event) {
    238   DCHECK(CalledOnValidThread());
    239   return g_factory.Get().synchronous_input_event_filter()->HandleInputEvent(
    240       contents_->GetRoutingID(), input_event);
    241 }
    242 
    243 void SynchronousCompositorImpl::DeliverMessages() {
    244   ScopedVector<IPC::Message> messages;
    245   output_surface_->GetMessagesToDeliver(&messages);
    246   RenderProcessHost* rph = contents_->GetRenderProcessHost();
    247   for (ScopedVector<IPC::Message>::const_iterator i = messages.begin();
    248        i != messages.end();
    249        ++i) {
    250     rph->OnMessageReceived(**i);
    251   }
    252 }
    253 
    254 void SynchronousCompositorImpl::DidActivatePendingTree() {
    255   if (compositor_client_)
    256     compositor_client_->DidUpdateContent();
    257 }
    258 
    259 gfx::Vector2dF SynchronousCompositorImpl::GetTotalScrollOffset() {
    260   DCHECK(CalledOnValidThread());
    261   if (compositor_client_)
    262     return compositor_client_->GetTotalRootLayerScrollOffset();
    263   return gfx::Vector2dF();
    264 }
    265 
    266 bool SynchronousCompositorImpl::IsExternalFlingActive() const {
    267   DCHECK(CalledOnValidThread());
    268   if (compositor_client_)
    269     return compositor_client_->IsExternalFlingActive();
    270   return false;
    271 }
    272 
    273 void SynchronousCompositorImpl::UpdateRootLayerState(
    274     const gfx::Vector2dF& total_scroll_offset,
    275     const gfx::Vector2dF& max_scroll_offset,
    276     const gfx::SizeF& scrollable_size,
    277     float page_scale_factor,
    278     float min_page_scale_factor,
    279     float max_page_scale_factor) {
    280   DCHECK(CalledOnValidThread());
    281   if (!compositor_client_)
    282     return;
    283 
    284   compositor_client_->UpdateRootLayerState(total_scroll_offset,
    285                                            max_scroll_offset,
    286                                            scrollable_size,
    287                                            page_scale_factor,
    288                                            min_page_scale_factor,
    289                                            max_page_scale_factor);
    290 }
    291 
    292 // Not using base::NonThreadSafe as we want to enforce a more exacting threading
    293 // requirement: SynchronousCompositorImpl() must only be used on the UI thread.
    294 bool SynchronousCompositorImpl::CalledOnValidThread() const {
    295   return BrowserThread::CurrentlyOn(BrowserThread::UI);
    296 }
    297 
    298 // static
    299 void SynchronousCompositor::SetClientForWebContents(
    300     WebContents* contents,
    301     SynchronousCompositorClient* client) {
    302   DCHECK(contents);
    303   if (client) {
    304     g_factory.Get();  // Ensure it's initialized.
    305     SynchronousCompositorImpl::CreateForWebContents(contents);
    306   }
    307   if (SynchronousCompositorImpl* instance =
    308       SynchronousCompositorImpl::FromWebContents(contents)) {
    309     instance->SetClient(client);
    310   }
    311 }
    312 
    313 }  // namespace content
    314