Home | History | Annotate | Download | only in browser
      1 // Copyright 2014 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 "android_webview/browser/shared_renderer_state.h"
      6 
      7 #include "android_webview/browser/browser_view_renderer_client.h"
      8 #include "base/bind.h"
      9 #include "base/lazy_instance.h"
     10 #include "base/location.h"
     11 
     12 namespace android_webview {
     13 
     14 namespace internal {
     15 
     16 class RequestDrawGLTracker {
     17  public:
     18   RequestDrawGLTracker();
     19   bool ShouldRequestOnNoneUiThread(SharedRendererState* state);
     20   bool ShouldRequestOnUiThread(SharedRendererState* state);
     21   void ResetPending();
     22   void SetQueuedFunctorOnUi(SharedRendererState* state);
     23 
     24  private:
     25   base::Lock lock_;
     26   SharedRendererState* pending_ui_;
     27   SharedRendererState* pending_non_ui_;
     28 };
     29 
     30 RequestDrawGLTracker::RequestDrawGLTracker()
     31     : pending_ui_(NULL), pending_non_ui_(NULL) {
     32 }
     33 
     34 bool RequestDrawGLTracker::ShouldRequestOnNoneUiThread(
     35     SharedRendererState* state) {
     36   base::AutoLock lock(lock_);
     37   if (pending_ui_ || pending_non_ui_)
     38     return false;
     39   pending_non_ui_ = state;
     40   return true;
     41 }
     42 
     43 bool RequestDrawGLTracker::ShouldRequestOnUiThread(SharedRendererState* state) {
     44   base::AutoLock lock(lock_);
     45   if (pending_non_ui_) {
     46     pending_non_ui_->ResetRequestDrawGLCallback();
     47     pending_non_ui_ = NULL;
     48   }
     49   // At this time, we could have already called RequestDrawGL on the UI thread,
     50   // but the corresponding GL mode process hasn't happened yet. In this case,
     51   // don't schedule another requestDrawGL on the UI thread.
     52   if (pending_ui_)
     53     return false;
     54   pending_ui_ = state;
     55   return true;
     56 }
     57 
     58 void RequestDrawGLTracker::ResetPending() {
     59   base::AutoLock lock(lock_);
     60   pending_non_ui_ = NULL;
     61   pending_ui_ = NULL;
     62 }
     63 
     64 void RequestDrawGLTracker::SetQueuedFunctorOnUi(SharedRendererState* state) {
     65   base::AutoLock lock(lock_);
     66   DCHECK(state);
     67   DCHECK(pending_ui_ == state || pending_non_ui_ == state);
     68   pending_ui_ = state;
     69   pending_non_ui_ = NULL;
     70 }
     71 
     72 }  // namespace internal
     73 
     74 namespace {
     75 
     76 base::LazyInstance<internal::RequestDrawGLTracker> g_request_draw_gl_tracker =
     77     LAZY_INSTANCE_INITIALIZER;
     78 
     79 }
     80 
     81 SharedRendererState::SharedRendererState(
     82     scoped_refptr<base::MessageLoopProxy> ui_loop,
     83     BrowserViewRendererClient* client)
     84     : ui_loop_(ui_loop),
     85       client_on_ui_(client),
     86       force_commit_(false),
     87       inside_hardware_release_(false),
     88       needs_force_invalidate_on_next_draw_gl_(false),
     89       weak_factory_on_ui_thread_(this) {
     90   DCHECK(ui_loop_->BelongsToCurrentThread());
     91   DCHECK(client_on_ui_);
     92   ui_thread_weak_ptr_ = weak_factory_on_ui_thread_.GetWeakPtr();
     93   ResetRequestDrawGLCallback();
     94 }
     95 
     96 SharedRendererState::~SharedRendererState() {
     97   DCHECK(ui_loop_->BelongsToCurrentThread());
     98 }
     99 
    100 void SharedRendererState::ClientRequestDrawGL() {
    101   if (ui_loop_->BelongsToCurrentThread()) {
    102     if (!g_request_draw_gl_tracker.Get().ShouldRequestOnUiThread(this))
    103       return;
    104     ClientRequestDrawGLOnUIThread();
    105   } else {
    106     if (!g_request_draw_gl_tracker.Get().ShouldRequestOnNoneUiThread(this))
    107       return;
    108     base::Closure callback;
    109     {
    110       base::AutoLock lock(lock_);
    111       callback = request_draw_gl_closure_;
    112     }
    113     ui_loop_->PostTask(FROM_HERE, callback);
    114   }
    115 }
    116 
    117 void SharedRendererState::DidDrawGLProcess() {
    118   g_request_draw_gl_tracker.Get().ResetPending();
    119 }
    120 
    121 void SharedRendererState::ResetRequestDrawGLCallback() {
    122   DCHECK(ui_loop_->BelongsToCurrentThread());
    123   base::AutoLock lock(lock_);
    124   request_draw_gl_cancelable_closure_.Reset(
    125       base::Bind(&SharedRendererState::ClientRequestDrawGLOnUIThread,
    126                  base::Unretained(this)));
    127   request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback();
    128 }
    129 
    130 void SharedRendererState::ClientRequestDrawGLOnUIThread() {
    131   DCHECK(ui_loop_->BelongsToCurrentThread());
    132   ResetRequestDrawGLCallback();
    133   g_request_draw_gl_tracker.Get().SetQueuedFunctorOnUi(this);
    134   if (!client_on_ui_->RequestDrawGL(NULL, false)) {
    135     g_request_draw_gl_tracker.Get().ResetPending();
    136     LOG(ERROR) << "Failed to request GL process. Deadlock likely";
    137   }
    138 }
    139 
    140 void SharedRendererState::UpdateParentDrawConstraintsOnUIThread() {
    141   DCHECK(ui_loop_->BelongsToCurrentThread());
    142   client_on_ui_->UpdateParentDrawConstraints();
    143 }
    144 
    145 void SharedRendererState::SetScrollOffset(gfx::Vector2d scroll_offset) {
    146   base::AutoLock lock(lock_);
    147   scroll_offset_ = scroll_offset;
    148 }
    149 
    150 gfx::Vector2d SharedRendererState::GetScrollOffset() {
    151   base::AutoLock lock(lock_);
    152   return scroll_offset_;
    153 }
    154 
    155 bool SharedRendererState::HasCompositorFrame() const {
    156   base::AutoLock lock(lock_);
    157   return compositor_frame_.get();
    158 }
    159 
    160 void SharedRendererState::SetCompositorFrame(
    161     scoped_ptr<cc::CompositorFrame> frame, bool force_commit) {
    162   base::AutoLock lock(lock_);
    163   DCHECK(!compositor_frame_.get());
    164   compositor_frame_ = frame.Pass();
    165   force_commit_ = force_commit;
    166 }
    167 
    168 scoped_ptr<cc::CompositorFrame> SharedRendererState::PassCompositorFrame() {
    169   base::AutoLock lock(lock_);
    170   return compositor_frame_.Pass();
    171 }
    172 
    173 bool SharedRendererState::ForceCommit() const {
    174   base::AutoLock lock(lock_);
    175   return force_commit_;
    176 }
    177 
    178 bool SharedRendererState::UpdateDrawConstraints(
    179     const ParentCompositorDrawConstraints& parent_draw_constraints) {
    180   base::AutoLock lock(lock_);
    181   if (needs_force_invalidate_on_next_draw_gl_ ||
    182       !parent_draw_constraints_.Equals(parent_draw_constraints)) {
    183     parent_draw_constraints_ = parent_draw_constraints;
    184     return true;
    185   }
    186 
    187   return false;
    188 }
    189 
    190 void SharedRendererState::PostExternalDrawConstraintsToChildCompositor(
    191     const ParentCompositorDrawConstraints& parent_draw_constraints) {
    192   if (UpdateDrawConstraints(parent_draw_constraints)) {
    193     // No need to hold the lock_ during the post task.
    194     ui_loop_->PostTask(
    195         FROM_HERE,
    196         base::Bind(&SharedRendererState::UpdateParentDrawConstraintsOnUIThread,
    197                    ui_thread_weak_ptr_));
    198   }
    199 }
    200 
    201 void SharedRendererState::DidSkipCommitFrame() {
    202   ui_loop_->PostTask(
    203       FROM_HERE,
    204       base::Bind(&SharedRendererState::DidSkipCommitFrameOnUIThread,
    205                  ui_thread_weak_ptr_));
    206 }
    207 
    208 void SharedRendererState::DidSkipCommitFrameOnUIThread() {
    209   DCHECK(ui_loop_->BelongsToCurrentThread());
    210   client_on_ui_->DidSkipCommitFrame();
    211 }
    212 
    213 const ParentCompositorDrawConstraints
    214 SharedRendererState::ParentDrawConstraints() const {
    215   base::AutoLock lock(lock_);
    216   return parent_draw_constraints_;
    217 }
    218 
    219 void SharedRendererState::SetForceInvalidateOnNextDrawGL(
    220     bool needs_force_invalidate_on_next_draw_gl) {
    221   base::AutoLock lock(lock_);
    222   needs_force_invalidate_on_next_draw_gl_ =
    223       needs_force_invalidate_on_next_draw_gl;
    224 }
    225 
    226 bool SharedRendererState::NeedsForceInvalidateOnNextDrawGL() const {
    227   base::AutoLock lock(lock_);
    228   return needs_force_invalidate_on_next_draw_gl_;
    229 }
    230 
    231 void SharedRendererState::SetInsideHardwareRelease(bool inside) {
    232   base::AutoLock lock(lock_);
    233   inside_hardware_release_ = inside;
    234 }
    235 
    236 bool SharedRendererState::IsInsideHardwareRelease() const {
    237   base::AutoLock lock(lock_);
    238   return inside_hardware_release_;
    239 }
    240 
    241 void SharedRendererState::InsertReturnedResources(
    242     const cc::ReturnedResourceArray& resources) {
    243   base::AutoLock lock(lock_);
    244   returned_resources_.insert(
    245       returned_resources_.end(), resources.begin(), resources.end());
    246 }
    247 
    248 void SharedRendererState::SwapReturnedResources(
    249     cc::ReturnedResourceArray* resources) {
    250   DCHECK(resources->empty());
    251   base::AutoLock lock(lock_);
    252   resources->swap(returned_resources_);
    253 }
    254 
    255 bool SharedRendererState::ReturnedResourcesEmpty() const {
    256   base::AutoLock lock(lock_);
    257   return returned_resources_.empty();
    258 }
    259 
    260 InsideHardwareReleaseReset::InsideHardwareReleaseReset(
    261     SharedRendererState* shared_renderer_state)
    262     : shared_renderer_state_(shared_renderer_state) {
    263   DCHECK(!shared_renderer_state_->IsInsideHardwareRelease());
    264   shared_renderer_state_->SetInsideHardwareRelease(true);
    265 }
    266 
    267 InsideHardwareReleaseReset::~InsideHardwareReleaseReset() {
    268   shared_renderer_state_->SetInsideHardwareRelease(false);
    269 }
    270 
    271 }  // namespace android_webview
    272