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