Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / common / gpu / client / context_provider_command_buffer.cc
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 "content/common/gpu/client/context_provider_command_buffer.h"
6
7 #include <set>
8 #include <vector>
9
10 #include "base/callback_helpers.h"
11 #include "base/strings/stringprintf.h"
12 #include "cc/output/managed_memory_policy.h"
13 #include "gpu/command_buffer/client/gles2_implementation.h"
14 #include "webkit/common/gpu/grcontext_for_webgraphicscontext3d.h"
15
16 namespace content {
17
18 class ContextProviderCommandBuffer::LostContextCallbackProxy
19     : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
20  public:
21   explicit LostContextCallbackProxy(ContextProviderCommandBuffer* provider)
22       : provider_(provider) {
23     provider_->context3d_->setContextLostCallback(this);
24   }
25
26   virtual ~LostContextCallbackProxy() {
27     provider_->context3d_->setContextLostCallback(NULL);
28   }
29
30   virtual void onContextLost() {
31     provider_->OnLostContext();
32   }
33
34  private:
35   ContextProviderCommandBuffer* provider_;
36 };
37
38 scoped_refptr<ContextProviderCommandBuffer>
39 ContextProviderCommandBuffer::Create(
40     scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context3d,
41     const std::string& debug_name) {
42   if (!context3d)
43     return NULL;
44
45   return new ContextProviderCommandBuffer(context3d.Pass(), debug_name);
46 }
47
48 ContextProviderCommandBuffer::ContextProviderCommandBuffer(
49     scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context3d,
50     const std::string& debug_name)
51     : context3d_(context3d.Pass()),
52       debug_name_(debug_name),
53       destroyed_(false) {
54   DCHECK(main_thread_checker_.CalledOnValidThread());
55   DCHECK(context3d_);
56   context_thread_checker_.DetachFromThread();
57 }
58
59 ContextProviderCommandBuffer::~ContextProviderCommandBuffer() {
60   DCHECK(main_thread_checker_.CalledOnValidThread() ||
61          context_thread_checker_.CalledOnValidThread());
62
63   base::AutoLock lock(main_thread_lock_);
64
65   // Destroy references to the context3d_ before leaking it.
66   if (context3d_->GetCommandBufferProxy()) {
67     context3d_->GetCommandBufferProxy()->SetMemoryAllocationChangedCallback(
68         CommandBufferProxyImpl::MemoryAllocationChangedCallback());
69   }
70   lost_context_callback_proxy_.reset();
71 }
72
73
74 CommandBufferProxyImpl* ContextProviderCommandBuffer::GetCommandBufferProxy() {
75   return context3d_->GetCommandBufferProxy();
76 }
77
78 WebGraphicsContext3DCommandBufferImpl*
79 ContextProviderCommandBuffer::WebContext3D() {
80   DCHECK(context3d_);
81   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
82   DCHECK(context_thread_checker_.CalledOnValidThread());
83
84   return context3d_.get();
85 }
86
87 bool ContextProviderCommandBuffer::BindToCurrentThread() {
88   // This is called on the thread the context will be used.
89   DCHECK(context_thread_checker_.CalledOnValidThread());
90
91   if (lost_context_callback_proxy_)
92     return true;
93
94   if (!context3d_->InitializeOnCurrentThread())
95     return false;
96
97   InitializeCapabilities();
98
99   std::string unique_context_name =
100       base::StringPrintf("%s-%p", debug_name_.c_str(), context3d_.get());
101   context3d_->pushGroupMarkerEXT(unique_context_name.c_str());
102
103   lost_context_callback_proxy_.reset(new LostContextCallbackProxy(this));
104   context3d_->GetCommandBufferProxy()->SetMemoryAllocationChangedCallback(
105       base::Bind(&ContextProviderCommandBuffer::OnMemoryAllocationChanged,
106                  base::Unretained(this)));
107   return true;
108 }
109
110 gpu::gles2::GLES2Interface* ContextProviderCommandBuffer::ContextGL() {
111   DCHECK(context3d_);
112   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
113   DCHECK(context_thread_checker_.CalledOnValidThread());
114
115   return context3d_->GetImplementation();
116 }
117
118 gpu::ContextSupport* ContextProviderCommandBuffer::ContextSupport() {
119   return context3d_->GetContextSupport();
120 }
121
122 class GrContext* ContextProviderCommandBuffer::GrContext() {
123   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
124   DCHECK(context_thread_checker_.CalledOnValidThread());
125
126   if (gr_context_)
127     return gr_context_->get();
128
129   gr_context_.reset(
130       new webkit::gpu::GrContextForWebGraphicsContext3D(context3d_.get()));
131   return gr_context_->get();
132 }
133
134 cc::ContextProvider::Capabilities
135 ContextProviderCommandBuffer::ContextCapabilities() {
136   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
137   DCHECK(context_thread_checker_.CalledOnValidThread());
138
139   return capabilities_;
140 }
141
142 bool ContextProviderCommandBuffer::IsContextLost() {
143   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
144   DCHECK(context_thread_checker_.CalledOnValidThread());
145
146   return context3d_->isContextLost();
147 }
148
149 void ContextProviderCommandBuffer::VerifyContexts() {
150   DCHECK(lost_context_callback_proxy_);  // Is bound to thread.
151   DCHECK(context_thread_checker_.CalledOnValidThread());
152
153   if (context3d_->isContextLost())
154     OnLostContext();
155 }
156
157 void ContextProviderCommandBuffer::DeleteCachedResources() {
158   DCHECK(context_thread_checker_.CalledOnValidThread());
159
160   if (gr_context_)
161     gr_context_->FreeGpuResources();
162 }
163
164 void ContextProviderCommandBuffer::OnLostContext() {
165   DCHECK(context_thread_checker_.CalledOnValidThread());
166   {
167     base::AutoLock lock(main_thread_lock_);
168     if (destroyed_)
169       return;
170     destroyed_ = true;
171   }
172   if (!lost_context_callback_.is_null())
173     base::ResetAndReturn(&lost_context_callback_).Run();
174   if (gr_context_)
175     gr_context_->OnLostContext();
176 }
177
178 void ContextProviderCommandBuffer::OnMemoryAllocationChanged(
179     const gpu::MemoryAllocation& allocation) {
180   DCHECK(context_thread_checker_.CalledOnValidThread());
181
182   if (memory_policy_changed_callback_.is_null())
183     return;
184
185   memory_policy_changed_callback_.Run(cc::ManagedMemoryPolicy(allocation));
186 }
187
188 void ContextProviderCommandBuffer::InitializeCapabilities() {
189   Capabilities caps;
190   caps.gpu = context3d_->GetImplementation()->capabilities();
191
192   size_t mapped_memory_limit = context3d_->GetMappedMemoryLimit();
193   caps.max_transfer_buffer_usage_bytes =
194       mapped_memory_limit == WebGraphicsContext3DCommandBufferImpl::kNoLimit
195       ? std::numeric_limits<size_t>::max() : mapped_memory_limit;
196
197   capabilities_ = caps;
198 }
199
200 bool ContextProviderCommandBuffer::DestroyedOnMainThread() {
201   DCHECK(main_thread_checker_.CalledOnValidThread());
202
203   base::AutoLock lock(main_thread_lock_);
204   return destroyed_;
205 }
206
207 void ContextProviderCommandBuffer::SetLostContextCallback(
208     const LostContextCallback& lost_context_callback) {
209   DCHECK(context_thread_checker_.CalledOnValidThread());
210   DCHECK(lost_context_callback_.is_null() ||
211          lost_context_callback.is_null());
212   lost_context_callback_ = lost_context_callback;
213 }
214
215 void ContextProviderCommandBuffer::SetMemoryPolicyChangedCallback(
216     const MemoryPolicyChangedCallback& memory_policy_changed_callback) {
217   DCHECK(context_thread_checker_.CalledOnValidThread());
218   DCHECK(memory_policy_changed_callback_.is_null() ||
219          memory_policy_changed_callback.is_null());
220   memory_policy_changed_callback_ = memory_policy_changed_callback;
221 }
222
223 }  // namespace content