Home | History | Annotate | Download | only in gpu
      1 // Copyright (c) 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 "webkit/common/gpu/context_provider_in_process.h"
      6 
      7 #include <set>
      8 
      9 #include "base/bind.h"
     10 #include "base/callback_helpers.h"
     11 #include "base/strings/string_split.h"
     12 #include "base/strings/stringprintf.h"
     13 #include "cc/output/managed_memory_policy.h"
     14 #include "gpu/command_buffer/client/gles2_implementation.h"
     15 #include "webkit/common/gpu/grcontext_for_webgraphicscontext3d.h"
     16 
     17 namespace webkit {
     18 namespace gpu {
     19 
     20 class ContextProviderInProcess::LostContextCallbackProxy
     21     : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
     22  public:
     23   explicit LostContextCallbackProxy(ContextProviderInProcess* provider)
     24       : provider_(provider) {
     25     provider_->context3d_->setContextLostCallback(this);
     26   }
     27 
     28   virtual ~LostContextCallbackProxy() {
     29     provider_->context3d_->setContextLostCallback(NULL);
     30   }
     31 
     32   virtual void onContextLost() {
     33     provider_->OnLostContext();
     34   }
     35 
     36  private:
     37   ContextProviderInProcess* provider_;
     38 };
     39 
     40 // static
     41 scoped_refptr<ContextProviderInProcess> ContextProviderInProcess::Create(
     42     scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context3d,
     43     const std::string& debug_name) {
     44   if (!context3d)
     45     return NULL;
     46   return new ContextProviderInProcess(context3d.Pass(), debug_name);
     47 }
     48 
     49 // static
     50 scoped_refptr<ContextProviderInProcess>
     51 ContextProviderInProcess::CreateOffscreen(
     52     bool lose_context_when_out_of_memory) {
     53   blink::WebGraphicsContext3D::Attributes attributes;
     54   attributes.depth = false;
     55   attributes.stencil = true;
     56   attributes.antialias = false;
     57   attributes.shareResources = true;
     58   attributes.noAutomaticFlushes = true;
     59 
     60   return Create(
     61       WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext(
     62           attributes, lose_context_when_out_of_memory),
     63       "Offscreen");
     64 }
     65 
     66 ContextProviderInProcess::ContextProviderInProcess(
     67     scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context3d,
     68     const std::string& debug_name)
     69     : context3d_(context3d.Pass()),
     70       destroyed_(false),
     71       debug_name_(debug_name) {
     72   DCHECK(main_thread_checker_.CalledOnValidThread());
     73   DCHECK(context3d_);
     74   context_thread_checker_.DetachFromThread();
     75 }
     76 
     77 ContextProviderInProcess::~ContextProviderInProcess() {
     78   DCHECK(main_thread_checker_.CalledOnValidThread() ||
     79          context_thread_checker_.CalledOnValidThread());
     80 }
     81 
     82 blink::WebGraphicsContext3D* ContextProviderInProcess::WebContext3D() {
     83   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
     84   DCHECK(context_thread_checker_.CalledOnValidThread());
     85 
     86   return context3d_.get();
     87 }
     88 
     89 bool ContextProviderInProcess::BindToCurrentThread() {
     90   DCHECK(context3d_);
     91 
     92   // This is called on the thread the context will be used.
     93   DCHECK(context_thread_checker_.CalledOnValidThread());
     94 
     95   if (lost_context_callback_proxy_)
     96     return true;
     97 
     98   if (!context3d_->makeContextCurrent())
     99     return false;
    100 
    101   InitializeCapabilities();
    102 
    103   std::string unique_context_name =
    104       base::StringPrintf("%s-%p", debug_name_.c_str(), context3d_.get());
    105   context3d_->pushGroupMarkerEXT(unique_context_name.c_str());
    106 
    107   lost_context_callback_proxy_.reset(new LostContextCallbackProxy(this));
    108   return true;
    109 }
    110 
    111 void ContextProviderInProcess::InitializeCapabilities() {
    112   capabilities_.gpu = context3d_->GetImplementation()->capabilities();
    113 }
    114 
    115 cc::ContextProvider::Capabilities
    116 ContextProviderInProcess::ContextCapabilities() {
    117   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
    118   DCHECK(context_thread_checker_.CalledOnValidThread());
    119   return capabilities_;
    120 }
    121 
    122 ::gpu::gles2::GLES2Interface* ContextProviderInProcess::ContextGL() {
    123   DCHECK(context3d_);
    124   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
    125   DCHECK(context_thread_checker_.CalledOnValidThread());
    126 
    127   return context3d_->GetGLInterface();
    128 }
    129 
    130 ::gpu::ContextSupport* ContextProviderInProcess::ContextSupport() {
    131   DCHECK(context3d_);
    132   if (!lost_context_callback_proxy_)
    133     return NULL;  // Not bound to anything.
    134 
    135   DCHECK(context_thread_checker_.CalledOnValidThread());
    136 
    137   return context3d_->GetContextSupport();
    138 }
    139 
    140 class GrContext* ContextProviderInProcess::GrContext() {
    141   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
    142   DCHECK(context_thread_checker_.CalledOnValidThread());
    143 
    144   if (gr_context_)
    145     return gr_context_->get();
    146 
    147   gr_context_.reset(
    148       new webkit::gpu::GrContextForWebGraphicsContext3D(context3d_.get()));
    149   return gr_context_->get();
    150 }
    151 
    152 bool ContextProviderInProcess::IsContextLost() {
    153   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
    154   DCHECK(context_thread_checker_.CalledOnValidThread());
    155 
    156   return context3d_->isContextLost();
    157 }
    158 
    159 void ContextProviderInProcess::VerifyContexts() {
    160   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
    161   DCHECK(context_thread_checker_.CalledOnValidThread());
    162 
    163   if (context3d_->isContextLost())
    164     OnLostContext();
    165 }
    166 
    167 void ContextProviderInProcess::DeleteCachedResources() {
    168   DCHECK(context_thread_checker_.CalledOnValidThread());
    169 
    170   if (gr_context_)
    171     gr_context_->FreeGpuResources();
    172 }
    173 
    174 void ContextProviderInProcess::OnLostContext() {
    175   DCHECK(context_thread_checker_.CalledOnValidThread());
    176   {
    177     base::AutoLock lock(destroyed_lock_);
    178     if (destroyed_)
    179       return;
    180     destroyed_ = true;
    181   }
    182   if (!lost_context_callback_.is_null())
    183     base::ResetAndReturn(&lost_context_callback_).Run();
    184   if (gr_context_)
    185     gr_context_->OnLostContext();
    186 }
    187 
    188 bool ContextProviderInProcess::DestroyedOnMainThread() {
    189   DCHECK(main_thread_checker_.CalledOnValidThread());
    190 
    191   base::AutoLock lock(destroyed_lock_);
    192   return destroyed_;
    193 }
    194 
    195 void ContextProviderInProcess::SetLostContextCallback(
    196     const LostContextCallback& lost_context_callback) {
    197   DCHECK(context_thread_checker_.CalledOnValidThread());
    198   DCHECK(lost_context_callback_.is_null() ||
    199          lost_context_callback.is_null());
    200   lost_context_callback_ = lost_context_callback;
    201 }
    202 
    203 void ContextProviderInProcess::SetMemoryPolicyChangedCallback(
    204     const MemoryPolicyChangedCallback& memory_policy_changed_callback) {
    205   // There's no memory manager for the in-process implementation.
    206 }
    207 
    208 }  // namespace gpu
    209 }  // namespace webkit
    210