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 17namespace webkit { 18namespace gpu { 19 20class 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 41scoped_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 50scoped_refptr<ContextProviderInProcess> 51ContextProviderInProcess::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 66ContextProviderInProcess::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 77ContextProviderInProcess::~ContextProviderInProcess() { 78 DCHECK(main_thread_checker_.CalledOnValidThread() || 79 context_thread_checker_.CalledOnValidThread()); 80} 81 82blink::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 89bool 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_->InitializeOnCurrentThread()) 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 111void ContextProviderInProcess::InitializeCapabilities() { 112 capabilities_.gpu = context3d_->GetImplementation()->capabilities(); 113 114 size_t mapped_memory_limit = context3d_->GetMappedMemoryLimit(); 115 capabilities_.max_transfer_buffer_usage_bytes = 116 mapped_memory_limit == 117 WebGraphicsContext3DInProcessCommandBufferImpl::kNoLimit 118 ? std::numeric_limits<size_t>::max() 119 : mapped_memory_limit; 120} 121 122cc::ContextProvider::Capabilities 123ContextProviderInProcess::ContextCapabilities() { 124 DCHECK(lost_context_callback_proxy_); // Is bound to thread. 125 DCHECK(context_thread_checker_.CalledOnValidThread()); 126 return capabilities_; 127} 128 129::gpu::gles2::GLES2Interface* ContextProviderInProcess::ContextGL() { 130 DCHECK(context3d_); 131 DCHECK(lost_context_callback_proxy_); // Is bound to thread. 132 DCHECK(context_thread_checker_.CalledOnValidThread()); 133 134 return context3d_->GetGLInterface(); 135} 136 137::gpu::ContextSupport* ContextProviderInProcess::ContextSupport() { 138 DCHECK(context3d_); 139 if (!lost_context_callback_proxy_) 140 return NULL; // Not bound to anything. 141 142 DCHECK(context_thread_checker_.CalledOnValidThread()); 143 144 return context3d_->GetContextSupport(); 145} 146 147class GrContext* ContextProviderInProcess::GrContext() { 148 DCHECK(lost_context_callback_proxy_); // Is bound to thread. 149 DCHECK(context_thread_checker_.CalledOnValidThread()); 150 151 if (gr_context_) 152 return gr_context_->get(); 153 154 gr_context_.reset( 155 new webkit::gpu::GrContextForWebGraphicsContext3D(context3d_.get())); 156 return gr_context_->get(); 157} 158 159bool ContextProviderInProcess::IsContextLost() { 160 DCHECK(lost_context_callback_proxy_); // Is bound to thread. 161 DCHECK(context_thread_checker_.CalledOnValidThread()); 162 163 return context3d_->isContextLost(); 164} 165 166void ContextProviderInProcess::VerifyContexts() { 167 DCHECK(lost_context_callback_proxy_); // Is bound to thread. 168 DCHECK(context_thread_checker_.CalledOnValidThread()); 169 170 if (context3d_->isContextLost()) 171 OnLostContext(); 172} 173 174void ContextProviderInProcess::DeleteCachedResources() { 175 DCHECK(context_thread_checker_.CalledOnValidThread()); 176 177 if (gr_context_) 178 gr_context_->FreeGpuResources(); 179} 180 181void ContextProviderInProcess::OnLostContext() { 182 DCHECK(context_thread_checker_.CalledOnValidThread()); 183 { 184 base::AutoLock lock(destroyed_lock_); 185 if (destroyed_) 186 return; 187 destroyed_ = true; 188 } 189 if (!lost_context_callback_.is_null()) 190 base::ResetAndReturn(&lost_context_callback_).Run(); 191 if (gr_context_) 192 gr_context_->OnLostContext(); 193} 194 195bool ContextProviderInProcess::DestroyedOnMainThread() { 196 DCHECK(main_thread_checker_.CalledOnValidThread()); 197 198 base::AutoLock lock(destroyed_lock_); 199 return destroyed_; 200} 201 202void ContextProviderInProcess::SetLostContextCallback( 203 const LostContextCallback& lost_context_callback) { 204 DCHECK(context_thread_checker_.CalledOnValidThread()); 205 DCHECK(lost_context_callback_.is_null() || 206 lost_context_callback.is_null()); 207 lost_context_callback_ = lost_context_callback; 208} 209 210void ContextProviderInProcess::SetMemoryPolicyChangedCallback( 211 const MemoryPolicyChangedCallback& memory_policy_changed_callback) { 212 // There's no memory manager for the in-process implementation. 213} 214 215} // namespace gpu 216} // namespace webkit 217