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.
5 #include "content/common/gpu/client/context_provider_command_buffer.h"
10 #include "base/callback_helpers.h"
11 #include "base/strings/stringprintf.h"
12 #include "cc/output/managed_memory_policy.h"
13 #include "content/common/gpu/client/grcontext_for_webgraphicscontext3d.h"
14 #include "gpu/command_buffer/client/gles2_implementation.h"
15 #include "third_party/skia/include/gpu/GrContext.h"
19 class ContextProviderCommandBuffer::LostContextCallbackProxy
20 : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback
{
22 explicit LostContextCallbackProxy(ContextProviderCommandBuffer
* provider
)
23 : provider_(provider
) {
24 provider_
->context3d_
->setContextLostCallback(this);
27 virtual ~LostContextCallbackProxy() {
28 provider_
->context3d_
->setContextLostCallback(NULL
);
31 virtual void onContextLost() {
32 provider_
->OnLostContext();
36 ContextProviderCommandBuffer
* provider_
;
39 scoped_refptr
<ContextProviderCommandBuffer
>
40 ContextProviderCommandBuffer::Create(
41 scoped_ptr
<WebGraphicsContext3DCommandBufferImpl
> context3d
,
42 CommandBufferContextType type
) {
46 return new ContextProviderCommandBuffer(context3d
.Pass(), type
);
49 ContextProviderCommandBuffer::ContextProviderCommandBuffer(
50 scoped_ptr
<WebGraphicsContext3DCommandBufferImpl
> context3d
,
51 CommandBufferContextType type
)
52 : context3d_(context3d
.Pass()),
54 debug_name_(CommandBufferContextTypeToString(type
)),
56 DCHECK(main_thread_checker_
.CalledOnValidThread());
58 context_thread_checker_
.DetachFromThread();
61 ContextProviderCommandBuffer::~ContextProviderCommandBuffer() {
62 DCHECK(main_thread_checker_
.CalledOnValidThread() ||
63 context_thread_checker_
.CalledOnValidThread());
65 base::AutoLock
lock(main_thread_lock_
);
67 // Destroy references to the context3d_ before leaking it.
68 if (context3d_
->GetCommandBufferProxy()) {
69 context3d_
->GetCommandBufferProxy()->SetLock(nullptr);
70 context3d_
->GetCommandBufferProxy()->SetMemoryAllocationChangedCallback(
71 CommandBufferProxyImpl::MemoryAllocationChangedCallback());
73 lost_context_callback_proxy_
.reset();
77 CommandBufferProxyImpl
* ContextProviderCommandBuffer::GetCommandBufferProxy() {
78 return context3d_
->GetCommandBufferProxy();
81 WebGraphicsContext3DCommandBufferImpl
*
82 ContextProviderCommandBuffer::WebContext3D() {
84 DCHECK(lost_context_callback_proxy_
); // Is bound to thread.
85 DCHECK(context_thread_checker_
.CalledOnValidThread());
87 return context3d_
.get();
90 bool ContextProviderCommandBuffer::BindToCurrentThread() {
91 // This is called on the thread the context will be used.
92 DCHECK(context_thread_checker_
.CalledOnValidThread());
94 if (lost_context_callback_proxy_
)
97 context3d_
->SetContextType(context_type_
);
98 if (!context3d_
->InitializeOnCurrentThread())
101 InitializeCapabilities();
103 std::string unique_context_name
=
104 base::StringPrintf("%s-%p", debug_name_
.c_str(), context3d_
.get());
105 context3d_
->traceBeginCHROMIUM("gpu_toplevel", unique_context_name
.c_str());
107 lost_context_callback_proxy_
.reset(new LostContextCallbackProxy(this));
108 context3d_
->GetCommandBufferProxy()->SetMemoryAllocationChangedCallback(
109 base::Bind(&ContextProviderCommandBuffer::OnMemoryAllocationChanged
,
110 base::Unretained(this)));
114 void ContextProviderCommandBuffer::DetachFromThread() {
115 context_thread_checker_
.DetachFromThread();
118 gpu::gles2::GLES2Interface
* ContextProviderCommandBuffer::ContextGL() {
120 DCHECK(lost_context_callback_proxy_
); // Is bound to thread.
121 DCHECK(context_thread_checker_
.CalledOnValidThread());
123 return context3d_
->GetImplementation();
126 gpu::ContextSupport
* ContextProviderCommandBuffer::ContextSupport() {
127 return context3d_
->GetContextSupport();
130 class GrContext
* ContextProviderCommandBuffer::GrContext() {
131 DCHECK(lost_context_callback_proxy_
); // Is bound to thread.
132 DCHECK(context_thread_checker_
.CalledOnValidThread());
135 return gr_context_
->get();
137 gr_context_
.reset(new GrContextForWebGraphicsContext3D(context3d_
.get()));
139 // If GlContext is already lost, also abandon the new GrContext.
140 if (gr_context_
->get() &&
141 ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR
)
142 gr_context_
->get()->abandonContext();
144 return gr_context_
->get();
147 void ContextProviderCommandBuffer::InvalidateGrContext(uint32_t state
) {
149 DCHECK(lost_context_callback_proxy_
); // Is bound to thread.
150 DCHECK(context_thread_checker_
.CalledOnValidThread());
151 gr_context_
->get()->resetContext(state
);
155 void ContextProviderCommandBuffer::SetupLock() {
157 context3d_
->GetCommandBufferProxy()->SetLock(&context_lock_
);
160 base::Lock
* ContextProviderCommandBuffer::GetLock() {
161 return &context_lock_
;
164 cc::ContextProvider::Capabilities
165 ContextProviderCommandBuffer::ContextCapabilities() {
166 DCHECK(lost_context_callback_proxy_
); // Is bound to thread.
167 DCHECK(context_thread_checker_
.CalledOnValidThread());
169 return capabilities_
;
172 void ContextProviderCommandBuffer::VerifyContexts() {
173 DCHECK(lost_context_callback_proxy_
); // Is bound to thread.
174 DCHECK(context_thread_checker_
.CalledOnValidThread());
176 if (ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR
)
180 void ContextProviderCommandBuffer::DeleteCachedResources() {
181 DCHECK(context_thread_checker_
.CalledOnValidThread());
184 gr_context_
->FreeGpuResources();
187 void ContextProviderCommandBuffer::OnLostContext() {
188 DCHECK(context_thread_checker_
.CalledOnValidThread());
190 base::AutoLock
lock(main_thread_lock_
);
195 if (!lost_context_callback_
.is_null())
196 base::ResetAndReturn(&lost_context_callback_
).Run();
198 gr_context_
->OnLostContext();
201 void ContextProviderCommandBuffer::OnMemoryAllocationChanged(
202 const gpu::MemoryAllocation
& allocation
) {
203 DCHECK(context_thread_checker_
.CalledOnValidThread());
205 if (memory_policy_changed_callback_
.is_null())
208 memory_policy_changed_callback_
.Run(cc::ManagedMemoryPolicy(allocation
));
211 void ContextProviderCommandBuffer::InitializeCapabilities() {
213 caps
.gpu
= context3d_
->GetImplementation()->capabilities();
215 size_t mapped_memory_limit
= context3d_
->GetMappedMemoryLimit();
216 caps
.max_transfer_buffer_usage_bytes
=
217 mapped_memory_limit
== WebGraphicsContext3DCommandBufferImpl::kNoLimit
218 ? std::numeric_limits
<size_t>::max() : mapped_memory_limit
;
220 capabilities_
= caps
;
223 bool ContextProviderCommandBuffer::DestroyedOnMainThread() {
224 DCHECK(main_thread_checker_
.CalledOnValidThread());
226 base::AutoLock
lock(main_thread_lock_
);
230 void ContextProviderCommandBuffer::SetLostContextCallback(
231 const LostContextCallback
& lost_context_callback
) {
232 DCHECK(context_thread_checker_
.CalledOnValidThread());
233 DCHECK(lost_context_callback_
.is_null() ||
234 lost_context_callback
.is_null());
235 lost_context_callback_
= lost_context_callback
;
238 void ContextProviderCommandBuffer::SetMemoryPolicyChangedCallback(
239 const MemoryPolicyChangedCallback
& memory_policy_changed_callback
) {
240 DCHECK(context_thread_checker_
.CalledOnValidThread());
241 DCHECK(memory_policy_changed_callback_
.is_null() ||
242 memory_policy_changed_callback
.is_null());
243 memory_policy_changed_callback_
= memory_policy_changed_callback
;
246 } // namespace content