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   blink::WebGraphicsContext3D::Attributes attributes;
     53   attributes.depth = false;
     54   attributes.stencil = true;
     55   attributes.antialias = false;
     56   attributes.shareResources = true;
     57   attributes.noAutomaticFlushes = true;
     58 
     59   return Create(
     60       WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext(
     61           attributes), "Offscreen");
     62 }
     63 
     64 ContextProviderInProcess::ContextProviderInProcess(
     65     scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context3d,
     66     const std::string& debug_name)
     67     : context3d_(context3d.Pass()),
     68       destroyed_(false),
     69       debug_name_(debug_name) {
     70   DCHECK(main_thread_checker_.CalledOnValidThread());
     71   DCHECK(context3d_);
     72   context_thread_checker_.DetachFromThread();
     73 }
     74 
     75 ContextProviderInProcess::~ContextProviderInProcess() {
     76   DCHECK(main_thread_checker_.CalledOnValidThread() ||
     77          context_thread_checker_.CalledOnValidThread());
     78 }
     79 
     80 bool ContextProviderInProcess::BindToCurrentThread() {
     81   DCHECK(context3d_);
     82 
     83   // This is called on the thread the context will be used.
     84   DCHECK(context_thread_checker_.CalledOnValidThread());
     85 
     86   if (lost_context_callback_proxy_)
     87     return true;
     88 
     89   if (!context3d_->makeContextCurrent())
     90     return false;
     91 
     92   InitializeCapabilities();
     93 
     94   std::string unique_context_name =
     95       base::StringPrintf("%s-%p", debug_name_.c_str(), context3d_.get());
     96   context3d_->pushGroupMarkerEXT(unique_context_name.c_str());
     97 
     98   lost_context_callback_proxy_.reset(new LostContextCallbackProxy(this));
     99   return true;
    100 }
    101 
    102 void ContextProviderInProcess::InitializeCapabilities() {
    103   capabilities_ = Capabilities(context3d_->GetImplementation()->capabilities());
    104 }
    105 
    106 cc::ContextProvider::Capabilities
    107 ContextProviderInProcess::ContextCapabilities() {
    108   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
    109   DCHECK(context_thread_checker_.CalledOnValidThread());
    110   return capabilities_;
    111 }
    112 
    113 blink::WebGraphicsContext3D* ContextProviderInProcess::Context3d() {
    114   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
    115   DCHECK(context_thread_checker_.CalledOnValidThread());
    116 
    117   return context3d_.get();
    118 }
    119 
    120 ::gpu::gles2::GLES2Interface* ContextProviderInProcess::ContextGL() {
    121   DCHECK(context3d_);
    122   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
    123   DCHECK(context_thread_checker_.CalledOnValidThread());
    124 
    125   return context3d_->GetGLInterface();
    126 }
    127 
    128 ::gpu::ContextSupport* ContextProviderInProcess::ContextSupport() {
    129   DCHECK(context3d_);
    130   if (!lost_context_callback_proxy_)
    131     return NULL;  // Not bound to anything.
    132 
    133   DCHECK(context_thread_checker_.CalledOnValidThread());
    134 
    135   return context3d_->GetContextSupport();
    136 }
    137 
    138 class GrContext* ContextProviderInProcess::GrContext() {
    139   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
    140   DCHECK(context_thread_checker_.CalledOnValidThread());
    141 
    142   if (gr_context_)
    143     return gr_context_->get();
    144 
    145   gr_context_.reset(
    146       new webkit::gpu::GrContextForWebGraphicsContext3D(context3d_.get()));
    147   return gr_context_->get();
    148 }
    149 
    150 void ContextProviderInProcess::MakeGrContextCurrent() {
    151   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
    152   DCHECK(context_thread_checker_.CalledOnValidThread());
    153   DCHECK(gr_context_);
    154 
    155   context3d_->makeContextCurrent();
    156 }
    157 
    158 bool ContextProviderInProcess::IsContextLost() {
    159   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
    160   DCHECK(context_thread_checker_.CalledOnValidThread());
    161 
    162   return context3d_->isContextLost();
    163 }
    164 
    165 void ContextProviderInProcess::VerifyContexts() {
    166   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
    167   DCHECK(context_thread_checker_.CalledOnValidThread());
    168 
    169   if (context3d_->isContextLost())
    170     OnLostContext();
    171 }
    172 
    173 void ContextProviderInProcess::OnLostContext() {
    174   DCHECK(context_thread_checker_.CalledOnValidThread());
    175   {
    176     base::AutoLock lock(destroyed_lock_);
    177     if (destroyed_)
    178       return;
    179     destroyed_ = true;
    180   }
    181   if (!lost_context_callback_.is_null())
    182     base::ResetAndReturn(&lost_context_callback_).Run();
    183 }
    184 
    185 bool ContextProviderInProcess::DestroyedOnMainThread() {
    186   DCHECK(main_thread_checker_.CalledOnValidThread());
    187 
    188   base::AutoLock lock(destroyed_lock_);
    189   return destroyed_;
    190 }
    191 
    192 void ContextProviderInProcess::SetLostContextCallback(
    193     const LostContextCallback& lost_context_callback) {
    194   DCHECK(context_thread_checker_.CalledOnValidThread());
    195   DCHECK(lost_context_callback_.is_null() ||
    196          lost_context_callback.is_null());
    197   lost_context_callback_ = lost_context_callback;
    198 }
    199 
    200 void ContextProviderInProcess::SetMemoryPolicyChangedCallback(
    201     const MemoryPolicyChangedCallback& memory_policy_changed_callback) {
    202   // There's no memory manager for the in-process implementation.
    203 }
    204 
    205 }  // namespace gpu
    206 }  // namespace webkit
    207