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