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 DidRequestOnUiThread();
     22   void ResetPending();
     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   if (pending_ui_)
     50     return false;
     51   pending_ui_ = state;
     52   return true;
     53 }
     54 
     55 void RequestDrawGLTracker::ResetPending() {
     56   base::AutoLock lock(lock_);
     57   pending_non_ui_ = NULL;
     58   pending_ui_ = NULL;
     59 }
     60 
     61 }  // namespace internal
     62 
     63 namespace {
     64 
     65 base::LazyInstance<internal::RequestDrawGLTracker> g_request_draw_gl_tracker =
     66     LAZY_INSTANCE_INITIALIZER;
     67 
     68 }
     69 
     70 DrawGLInput::DrawGLInput() : width(0), height(0) {
     71 }
     72 
     73 DrawGLInput::~DrawGLInput() {
     74 }
     75 
     76 SharedRendererState::SharedRendererState(
     77     scoped_refptr<base::MessageLoopProxy> ui_loop,
     78     BrowserViewRendererClient* client)
     79     : ui_loop_(ui_loop),
     80       client_on_ui_(client),
     81       weak_factory_on_ui_thread_(this),
     82       ui_thread_weak_ptr_(weak_factory_on_ui_thread_.GetWeakPtr()),
     83       inside_hardware_release_(false),
     84       needs_force_invalidate_on_next_draw_gl_(false),
     85       share_context_(NULL) {
     86   DCHECK(ui_loop_->BelongsToCurrentThread());
     87   DCHECK(client_on_ui_);
     88   ResetRequestDrawGLCallback();
     89 }
     90 
     91 SharedRendererState::~SharedRendererState() {
     92   DCHECK(ui_loop_->BelongsToCurrentThread());
     93 }
     94 
     95 void SharedRendererState::ClientRequestDrawGL() {
     96   if (ui_loop_->BelongsToCurrentThread()) {
     97     if (!g_request_draw_gl_tracker.Get().ShouldRequestOnUiThread(this))
     98       return;
     99     ClientRequestDrawGLOnUIThread();
    100   } else {
    101     if (!g_request_draw_gl_tracker.Get().ShouldRequestOnNoneUiThread(this))
    102       return;
    103     base::Closure callback;
    104     {
    105       base::AutoLock lock(lock_);
    106       callback = request_draw_gl_closure_;
    107     }
    108     ui_loop_->PostTask(FROM_HERE, callback);
    109   }
    110 }
    111 
    112 void SharedRendererState::DidDrawGLProcess() {
    113   g_request_draw_gl_tracker.Get().ResetPending();
    114 }
    115 
    116 void SharedRendererState::ResetRequestDrawGLCallback() {
    117   DCHECK(ui_loop_->BelongsToCurrentThread());
    118   base::AutoLock lock(lock_);
    119   request_draw_gl_cancelable_closure_.Reset(
    120       base::Bind(&SharedRendererState::ClientRequestDrawGLOnUIThread,
    121                  base::Unretained(this)));
    122   request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback();
    123 }
    124 
    125 void SharedRendererState::ClientRequestDrawGLOnUIThread() {
    126   DCHECK(ui_loop_->BelongsToCurrentThread());
    127   ResetRequestDrawGLCallback();
    128   if (!client_on_ui_->RequestDrawGL(NULL, false)) {
    129     g_request_draw_gl_tracker.Get().ResetPending();
    130     LOG(ERROR) << "Failed to request GL process. Deadlock likely";
    131   }
    132 }
    133 
    134 void SharedRendererState::UpdateParentDrawConstraintsOnUIThread() {
    135   DCHECK(ui_loop_->BelongsToCurrentThread());
    136   client_on_ui_->UpdateParentDrawConstraints();
    137 }
    138 
    139 void SharedRendererState::SetDrawGLInput(scoped_ptr<DrawGLInput> input) {
    140   base::AutoLock lock(lock_);
    141   DCHECK(!draw_gl_input_.get());
    142   draw_gl_input_ = input.Pass();
    143 }
    144 
    145 scoped_ptr<DrawGLInput> SharedRendererState::PassDrawGLInput() {
    146   base::AutoLock lock(lock_);
    147   return draw_gl_input_.Pass();
    148 }
    149 
    150 bool SharedRendererState::UpdateDrawConstraints(
    151     const ParentCompositorDrawConstraints& parent_draw_constraints) {
    152   base::AutoLock lock(lock_);
    153   if (needs_force_invalidate_on_next_draw_gl_ ||
    154       !parent_draw_constraints_.Equals(parent_draw_constraints)) {
    155     parent_draw_constraints_ = parent_draw_constraints;
    156     return true;
    157   }
    158 
    159   return false;
    160 }
    161 
    162 void SharedRendererState::PostExternalDrawConstraintsToChildCompositor(
    163     const ParentCompositorDrawConstraints& parent_draw_constraints) {
    164   if (UpdateDrawConstraints(parent_draw_constraints)) {
    165     // No need to hold the lock_ during the post task.
    166     ui_loop_->PostTask(
    167         FROM_HERE,
    168         base::Bind(&SharedRendererState::UpdateParentDrawConstraintsOnUIThread,
    169                    ui_thread_weak_ptr_));
    170   }
    171 }
    172 
    173 const ParentCompositorDrawConstraints
    174 SharedRendererState::ParentDrawConstraints() const {
    175   base::AutoLock lock(lock_);
    176   return parent_draw_constraints_;
    177 }
    178 
    179 void SharedRendererState::SetForceInvalidateOnNextDrawGL(
    180     bool needs_force_invalidate_on_next_draw_gl) {
    181   base::AutoLock lock(lock_);
    182   needs_force_invalidate_on_next_draw_gl_ =
    183       needs_force_invalidate_on_next_draw_gl;
    184 }
    185 
    186 bool SharedRendererState::NeedsForceInvalidateOnNextDrawGL() const {
    187   base::AutoLock lock(lock_);
    188   return needs_force_invalidate_on_next_draw_gl_;
    189 }
    190 
    191 void SharedRendererState::SetInsideHardwareRelease(bool inside) {
    192   base::AutoLock lock(lock_);
    193   inside_hardware_release_ = inside;
    194 }
    195 
    196 bool SharedRendererState::IsInsideHardwareRelease() const {
    197   base::AutoLock lock(lock_);
    198   return inside_hardware_release_;
    199 }
    200 
    201 void SharedRendererState::SetSharedContext(gpu::GLInProcessContext* context) {
    202   base::AutoLock lock(lock_);
    203   DCHECK(!share_context_ || !context);
    204   share_context_ = context;
    205 }
    206 
    207 gpu::GLInProcessContext* SharedRendererState::GetSharedContext() const {
    208   base::AutoLock lock(lock_);
    209   DCHECK(share_context_);
    210   return share_context_;
    211 }
    212 
    213 void SharedRendererState::InsertReturnedResources(
    214     const cc::ReturnedResourceArray& resources) {
    215   base::AutoLock lock(lock_);
    216   returned_resources_.insert(
    217       returned_resources_.end(), resources.begin(), resources.end());
    218 }
    219 
    220 void SharedRendererState::SwapReturnedResources(
    221     cc::ReturnedResourceArray* resources) {
    222   DCHECK(resources->empty());
    223   base::AutoLock lock(lock_);
    224   resources->swap(returned_resources_);
    225 }
    226 
    227 bool SharedRendererState::ReturnedResourcesEmpty() const {
    228   base::AutoLock lock(lock_);
    229   return returned_resources_.empty();
    230 }
    231 
    232 InsideHardwareReleaseReset::InsideHardwareReleaseReset(
    233     SharedRendererState* shared_renderer_state)
    234     : shared_renderer_state_(shared_renderer_state) {
    235   DCHECK(!shared_renderer_state_->IsInsideHardwareRelease());
    236   shared_renderer_state_->SetInsideHardwareRelease(true);
    237 }
    238 
    239 InsideHardwareReleaseReset::~InsideHardwareReleaseReset() {
    240   shared_renderer_state_->SetInsideHardwareRelease(false);
    241 }
    242 
    243 }  // namespace android_webview
    244