OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/gpu/client/context_provider_command_buffer.h" | 5 #include "content/common/gpu/client/context_provider_command_buffer.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <set> | 10 #include <set> |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
69 context_thread_checker_.CalledOnValidThread()); | 69 context_thread_checker_.CalledOnValidThread()); |
70 | 70 |
71 { | 71 { |
72 base::AutoLock hold(shared_providers_->lock); | 72 base::AutoLock hold(shared_providers_->lock); |
73 auto it = std::find(shared_providers_->list.begin(), | 73 auto it = std::find(shared_providers_->list.begin(), |
74 shared_providers_->list.end(), this); | 74 shared_providers_->list.end(), this); |
75 if (it != shared_providers_->list.end()) | 75 if (it != shared_providers_->list.end()) |
76 shared_providers_->list.erase(it); | 76 shared_providers_->list.erase(it); |
77 } | 77 } |
78 | 78 |
79 // Destroy references to the context3d_ before leaking it. | |
80 // TODO(danakj): Delete this. | |
81 if (context3d_->GetCommandBufferProxy()) | |
82 context3d_->GetCommandBufferProxy()->SetLock(nullptr); | |
piman
2016/05/02 20:45:17
See buildbots. If we don't reset the lock on the C
danakj
2016/05/02 21:11:36
Ah okay.. how about I set the lock to null, but av
| |
83 | |
84 if (lost_context_callback_proxy_) { | 79 if (lost_context_callback_proxy_) { |
85 // Disconnect lost callbacks during destruction. | 80 // Disconnect lost callbacks during destruction. |
86 lost_context_callback_proxy_.reset(); | 81 lost_context_callback_proxy_.reset(); |
87 } | 82 } |
88 } | 83 } |
89 | 84 |
90 gpu::CommandBufferProxyImpl* | 85 gpu::CommandBufferProxyImpl* |
91 ContextProviderCommandBuffer::GetCommandBufferProxy() { | 86 ContextProviderCommandBuffer::GetCommandBufferProxy() { |
92 return context3d_->GetCommandBufferProxy(); | 87 return context3d_->GetCommandBufferProxy(); |
93 } | 88 } |
94 | 89 |
95 bool ContextProviderCommandBuffer::BindToCurrentThread() { | 90 bool ContextProviderCommandBuffer::BindToCurrentThread() { |
96 // This is called on the thread the context will be used. | 91 // This is called on the thread the context will be used. |
97 DCHECK(context_thread_checker_.CalledOnValidThread()); | 92 DCHECK(context_thread_checker_.CalledOnValidThread()); |
98 | 93 |
94 if (!context3d_) | |
95 return false; // Already failed. | |
99 if (lost_context_callback_proxy_) | 96 if (lost_context_callback_proxy_) |
100 return true; | 97 return true; // Already succeeded. |
101 | 98 |
102 // It's possible to be running BindToCurrentThread on two contexts | 99 // It's possible to be running BindToCurrentThread on two contexts |
103 // on different threads at the same time, but which will be in the same share | 100 // on different threads at the same time, but which will be in the same share |
104 // group. To ensure they end up in the same group, hold the lock on the | 101 // group. To ensure they end up in the same group, hold the lock on the |
105 // shared_providers_ (which they will share) after querying the group, until | 102 // shared_providers_ (which they will share) after querying the group, until |
106 // this context has been added to the list. | 103 // this context has been added to the list. |
107 { | 104 { |
108 ContextProviderCommandBuffer* shared_context_provider = nullptr; | 105 ContextProviderCommandBuffer* shared_context_provider = nullptr; |
109 gpu::CommandBufferProxyImpl* shared_command_buffer = nullptr; | 106 gpu::CommandBufferProxyImpl* shared_command_buffer = nullptr; |
110 scoped_refptr<gpu::gles2::ShareGroup> share_group; | 107 scoped_refptr<gpu::gles2::ShareGroup> share_group; |
111 | 108 |
112 base::AutoLock hold(shared_providers_->lock); | 109 base::AutoLock hold(shared_providers_->lock); |
113 | 110 |
114 if (!shared_providers_->list.empty()) { | 111 if (!shared_providers_->list.empty()) { |
115 shared_context_provider = shared_providers_->list.front(); | 112 shared_context_provider = shared_providers_->list.front(); |
116 shared_command_buffer = | 113 shared_command_buffer = |
117 shared_context_provider->context3d_->GetCommandBufferProxy(); | 114 shared_context_provider->context3d_->GetCommandBufferProxy(); |
118 share_group = shared_context_provider->context3d_->GetImplementation() | 115 share_group = shared_context_provider->context3d_->GetImplementation() |
119 ->share_group(); | 116 ->share_group(); |
120 } | 117 } |
121 | 118 |
122 if (!context3d_->InitializeOnCurrentThread( | 119 if (!context3d_->InitializeOnCurrentThread( |
123 memory_limits_, shared_command_buffer, std::move(share_group), | 120 memory_limits_, shared_command_buffer, std::move(share_group), |
124 attributes_, context_type_)) | 121 attributes_, context_type_)) { |
122 context3d_ = nullptr; | |
125 return false; | 123 return false; |
124 } | |
126 | 125 |
127 // If any context in the share group has been lost, then abort and don't | 126 // If any context in the share group has been lost, then abort and don't |
128 // continue since we need to go back to the caller of the constructor to | 127 // continue since we need to go back to the caller of the constructor to |
129 // find the correct share group. | 128 // find the correct share group. |
130 // This may happen in between the share group being chosen at the | 129 // This may happen in between the share group being chosen at the |
131 // constructor, and getting to run this BindToCurrentThread method which | 130 // constructor, and getting to run this BindToCurrentThread method which |
132 // can be on some other thread. | 131 // can be on some other thread. |
133 // We intentionally call this *after* creating the command buffer via the | 132 // We intentionally call this *after* creating the command buffer via the |
134 // GpuChannelHost. Once that has happened, the service knows we are in the | 133 // GpuChannelHost. Once that has happened, the service knows we are in the |
135 // share group and if a shared context is lost, our context will be informed | 134 // share group and if a shared context is lost, our context will be informed |
136 // also, and the lost context callback will occur for the owner of the | 135 // also, and the lost context callback will occur for the owner of the |
137 // context provider. If we check sooner, the shared context may be lost in | 136 // context provider. If we check sooner, the shared context may be lost in |
138 // between these two states and our context here would be left in an orphan | 137 // between these two states and our context here would be left in an orphan |
139 // share group. | 138 // share group. |
140 if (share_group && share_group->IsLost()) | 139 if (share_group && share_group->IsLost()) { |
140 context3d_ = nullptr; | |
141 return false; | 141 return false; |
142 } | |
142 | 143 |
143 shared_providers_->list.push_back(this); | 144 shared_providers_->list.push_back(this); |
144 } | 145 } |
145 | 146 |
146 lost_context_callback_proxy_.reset(new LostContextCallbackProxy(this)); | 147 lost_context_callback_proxy_.reset(new LostContextCallbackProxy(this)); |
147 | 148 |
148 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 149 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
149 switches::kEnableGpuClientTracing)) { | 150 switches::kEnableGpuClientTracing)) { |
150 // This wraps the real GLES2Implementation and we should always use this | 151 // This wraps the real GLES2Implementation and we should always use this |
151 // instead when it's present. | 152 // instead when it's present. |
(...skipping 18 matching lines...) Expand all Loading... | |
170 DCHECK(context3d_); | 171 DCHECK(context3d_); |
171 DCHECK(lost_context_callback_proxy_); // Is bound to thread. | 172 DCHECK(lost_context_callback_proxy_); // Is bound to thread. |
172 DCHECK(context_thread_checker_.CalledOnValidThread()); | 173 DCHECK(context_thread_checker_.CalledOnValidThread()); |
173 | 174 |
174 if (trace_impl_) | 175 if (trace_impl_) |
175 return trace_impl_.get(); | 176 return trace_impl_.get(); |
176 return context3d_->GetImplementation(); | 177 return context3d_->GetImplementation(); |
177 } | 178 } |
178 | 179 |
179 gpu::ContextSupport* ContextProviderCommandBuffer::ContextSupport() { | 180 gpu::ContextSupport* ContextProviderCommandBuffer::ContextSupport() { |
180 return context3d_->GetContextSupport(); | 181 return context3d_->GetImplementation(); |
181 } | 182 } |
182 | 183 |
183 class GrContext* ContextProviderCommandBuffer::GrContext() { | 184 class GrContext* ContextProviderCommandBuffer::GrContext() { |
184 DCHECK(lost_context_callback_proxy_); // Is bound to thread. | 185 DCHECK(lost_context_callback_proxy_); // Is bound to thread. |
185 DCHECK(context_thread_checker_.CalledOnValidThread()); | 186 DCHECK(context_thread_checker_.CalledOnValidThread()); |
186 | 187 |
187 if (gr_context_) | 188 if (gr_context_) |
188 return gr_context_->get(); | 189 return gr_context_->get(); |
189 | 190 |
190 gr_context_.reset(new skia_bindings::GrContextForGLES2Interface(ContextGL())); | 191 gr_context_.reset(new skia_bindings::GrContextForGLES2Interface(ContextGL())); |
191 | 192 |
192 // If GlContext is already lost, also abandon the new GrContext. | 193 // If GlContext is already lost, also abandon the new GrContext. |
193 if (gr_context_->get() && | 194 if (gr_context_->get() && |
194 ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR) | 195 ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR) |
195 gr_context_->get()->abandonContext(); | 196 gr_context_->get()->abandonContext(); |
196 | 197 |
197 return gr_context_->get(); | 198 return gr_context_->get(); |
198 } | 199 } |
199 | 200 |
200 void ContextProviderCommandBuffer::InvalidateGrContext(uint32_t state) { | 201 void ContextProviderCommandBuffer::InvalidateGrContext(uint32_t state) { |
201 if (gr_context_) { | 202 if (gr_context_) { |
202 DCHECK(lost_context_callback_proxy_); // Is bound to thread. | 203 DCHECK(lost_context_callback_proxy_); // Is bound to thread. |
203 DCHECK(context_thread_checker_.CalledOnValidThread()); | 204 DCHECK(context_thread_checker_.CalledOnValidThread()); |
204 gr_context_->ResetContext(state); | 205 gr_context_->ResetContext(state); |
205 } | 206 } |
206 } | 207 } |
207 | 208 |
208 void ContextProviderCommandBuffer::SetupLock() { | 209 void ContextProviderCommandBuffer::SetupLock() { |
209 DCHECK(context3d_); | 210 DCHECK(lost_context_callback_proxy_); // Is bound to thread. |
211 DCHECK(context_thread_checker_.CalledOnValidThread()); | |
210 context3d_->GetCommandBufferProxy()->SetLock(&context_lock_); | 212 context3d_->GetCommandBufferProxy()->SetLock(&context_lock_); |
211 } | 213 } |
212 | 214 |
213 base::Lock* ContextProviderCommandBuffer::GetLock() { | 215 base::Lock* ContextProviderCommandBuffer::GetLock() { |
214 return &context_lock_; | 216 return &context_lock_; |
215 } | 217 } |
216 | 218 |
217 gpu::Capabilities ContextProviderCommandBuffer::ContextCapabilities() { | 219 gpu::Capabilities ContextProviderCommandBuffer::ContextCapabilities() { |
218 DCHECK(lost_context_callback_proxy_); // Is bound to thread. | 220 DCHECK(lost_context_callback_proxy_); // Is bound to thread. |
219 DCHECK(context_thread_checker_.CalledOnValidThread()); | 221 DCHECK(context_thread_checker_.CalledOnValidThread()); |
(...skipping 23 matching lines...) Expand all Loading... | |
243 | 245 |
244 void ContextProviderCommandBuffer::SetLostContextCallback( | 246 void ContextProviderCommandBuffer::SetLostContextCallback( |
245 const LostContextCallback& lost_context_callback) { | 247 const LostContextCallback& lost_context_callback) { |
246 DCHECK(context_thread_checker_.CalledOnValidThread()); | 248 DCHECK(context_thread_checker_.CalledOnValidThread()); |
247 DCHECK(lost_context_callback_.is_null() || | 249 DCHECK(lost_context_callback_.is_null() || |
248 lost_context_callback.is_null()); | 250 lost_context_callback.is_null()); |
249 lost_context_callback_ = lost_context_callback; | 251 lost_context_callback_ = lost_context_callback; |
250 } | 252 } |
251 | 253 |
252 } // namespace content | 254 } // namespace content |
OLD | NEW |