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. | 79 if (lost_context_callback_proxy_) { |
80 // TODO(danakj): Delete this. | 80 // Clear the lock to avoid DCHECKs that the lock is being held during |
81 if (context3d_->GetCommandBufferProxy()) | 81 // shutdown. |
82 context3d_->GetCommandBufferProxy()->SetLock(nullptr); | 82 context3d_->GetCommandBufferProxy()->SetLock(nullptr); |
83 | |
84 if (lost_context_callback_proxy_) { | |
85 // Disconnect lost callbacks during destruction. | 83 // Disconnect lost callbacks during destruction. |
86 lost_context_callback_proxy_.reset(); | 84 lost_context_callback_proxy_.reset(); |
87 } | 85 } |
88 } | 86 } |
89 | 87 |
90 gpu::CommandBufferProxyImpl* | 88 gpu::CommandBufferProxyImpl* |
91 ContextProviderCommandBuffer::GetCommandBufferProxy() { | 89 ContextProviderCommandBuffer::GetCommandBufferProxy() { |
92 return context3d_->GetCommandBufferProxy(); | 90 return context3d_->GetCommandBufferProxy(); |
93 } | 91 } |
94 | 92 |
95 bool ContextProviderCommandBuffer::BindToCurrentThread() { | 93 bool ContextProviderCommandBuffer::BindToCurrentThread() { |
96 // This is called on the thread the context will be used. | 94 // This is called on the thread the context will be used. |
97 DCHECK(context_thread_checker_.CalledOnValidThread()); | 95 DCHECK(context_thread_checker_.CalledOnValidThread()); |
98 | 96 |
| 97 if (!context3d_) |
| 98 return false; // Already failed. |
99 if (lost_context_callback_proxy_) | 99 if (lost_context_callback_proxy_) |
100 return true; | 100 return true; // Already succeeded. |
101 | 101 |
102 // It's possible to be running BindToCurrentThread on two contexts | 102 // 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 | 103 // 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 | 104 // 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 | 105 // shared_providers_ (which they will share) after querying the group, until |
106 // this context has been added to the list. | 106 // this context has been added to the list. |
107 { | 107 { |
108 ContextProviderCommandBuffer* shared_context_provider = nullptr; | 108 ContextProviderCommandBuffer* shared_context_provider = nullptr; |
109 gpu::CommandBufferProxyImpl* shared_command_buffer = nullptr; | 109 gpu::CommandBufferProxyImpl* shared_command_buffer = nullptr; |
110 scoped_refptr<gpu::gles2::ShareGroup> share_group; | 110 scoped_refptr<gpu::gles2::ShareGroup> share_group; |
111 | 111 |
112 base::AutoLock hold(shared_providers_->lock); | 112 base::AutoLock hold(shared_providers_->lock); |
113 | 113 |
114 if (!shared_providers_->list.empty()) { | 114 if (!shared_providers_->list.empty()) { |
115 shared_context_provider = shared_providers_->list.front(); | 115 shared_context_provider = shared_providers_->list.front(); |
116 shared_command_buffer = | 116 shared_command_buffer = |
117 shared_context_provider->context3d_->GetCommandBufferProxy(); | 117 shared_context_provider->context3d_->GetCommandBufferProxy(); |
118 share_group = shared_context_provider->context3d_->GetImplementation() | 118 share_group = shared_context_provider->context3d_->GetImplementation() |
119 ->share_group(); | 119 ->share_group(); |
120 } | 120 } |
121 | 121 |
122 if (!context3d_->InitializeOnCurrentThread( | 122 if (!context3d_->InitializeOnCurrentThread( |
123 memory_limits_, shared_command_buffer, std::move(share_group), | 123 memory_limits_, shared_command_buffer, std::move(share_group), |
124 attributes_, context_type_)) | 124 attributes_, context_type_)) { |
| 125 context3d_ = nullptr; |
125 return false; | 126 return false; |
| 127 } |
126 | 128 |
127 // If any context in the share group has been lost, then abort and don't | 129 // 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 | 130 // continue since we need to go back to the caller of the constructor to |
129 // find the correct share group. | 131 // find the correct share group. |
130 // This may happen in between the share group being chosen at the | 132 // This may happen in between the share group being chosen at the |
131 // constructor, and getting to run this BindToCurrentThread method which | 133 // constructor, and getting to run this BindToCurrentThread method which |
132 // can be on some other thread. | 134 // can be on some other thread. |
133 // We intentionally call this *after* creating the command buffer via the | 135 // We intentionally call this *after* creating the command buffer via the |
134 // GpuChannelHost. Once that has happened, the service knows we are in the | 136 // 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 | 137 // 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 | 138 // 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 | 139 // 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 | 140 // between these two states and our context here would be left in an orphan |
139 // share group. | 141 // share group. |
140 if (share_group && share_group->IsLost()) | 142 if (share_group && share_group->IsLost()) { |
| 143 context3d_ = nullptr; |
141 return false; | 144 return false; |
| 145 } |
142 | 146 |
143 shared_providers_->list.push_back(this); | 147 shared_providers_->list.push_back(this); |
144 } | 148 } |
145 | 149 |
146 lost_context_callback_proxy_.reset(new LostContextCallbackProxy(this)); | 150 lost_context_callback_proxy_.reset(new LostContextCallbackProxy(this)); |
147 | 151 |
148 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 152 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
149 switches::kEnableGpuClientTracing)) { | 153 switches::kEnableGpuClientTracing)) { |
150 // This wraps the real GLES2Implementation and we should always use this | 154 // This wraps the real GLES2Implementation and we should always use this |
151 // instead when it's present. | 155 // instead when it's present. |
(...skipping 18 matching lines...) Expand all Loading... |
170 DCHECK(context3d_); | 174 DCHECK(context3d_); |
171 DCHECK(lost_context_callback_proxy_); // Is bound to thread. | 175 DCHECK(lost_context_callback_proxy_); // Is bound to thread. |
172 DCHECK(context_thread_checker_.CalledOnValidThread()); | 176 DCHECK(context_thread_checker_.CalledOnValidThread()); |
173 | 177 |
174 if (trace_impl_) | 178 if (trace_impl_) |
175 return trace_impl_.get(); | 179 return trace_impl_.get(); |
176 return context3d_->GetImplementation(); | 180 return context3d_->GetImplementation(); |
177 } | 181 } |
178 | 182 |
179 gpu::ContextSupport* ContextProviderCommandBuffer::ContextSupport() { | 183 gpu::ContextSupport* ContextProviderCommandBuffer::ContextSupport() { |
180 return context3d_->GetContextSupport(); | 184 return context3d_->GetImplementation(); |
181 } | 185 } |
182 | 186 |
183 class GrContext* ContextProviderCommandBuffer::GrContext() { | 187 class GrContext* ContextProviderCommandBuffer::GrContext() { |
184 DCHECK(lost_context_callback_proxy_); // Is bound to thread. | 188 DCHECK(lost_context_callback_proxy_); // Is bound to thread. |
185 DCHECK(context_thread_checker_.CalledOnValidThread()); | 189 DCHECK(context_thread_checker_.CalledOnValidThread()); |
186 | 190 |
187 if (gr_context_) | 191 if (gr_context_) |
188 return gr_context_->get(); | 192 return gr_context_->get(); |
189 | 193 |
190 gr_context_.reset(new skia_bindings::GrContextForGLES2Interface(ContextGL())); | 194 gr_context_.reset(new skia_bindings::GrContextForGLES2Interface(ContextGL())); |
191 | 195 |
192 // If GlContext is already lost, also abandon the new GrContext. | 196 // If GlContext is already lost, also abandon the new GrContext. |
193 if (gr_context_->get() && | 197 if (gr_context_->get() && |
194 ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR) | 198 ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR) |
195 gr_context_->get()->abandonContext(); | 199 gr_context_->get()->abandonContext(); |
196 | 200 |
197 return gr_context_->get(); | 201 return gr_context_->get(); |
198 } | 202 } |
199 | 203 |
200 void ContextProviderCommandBuffer::InvalidateGrContext(uint32_t state) { | 204 void ContextProviderCommandBuffer::InvalidateGrContext(uint32_t state) { |
201 if (gr_context_) { | 205 if (gr_context_) { |
202 DCHECK(lost_context_callback_proxy_); // Is bound to thread. | 206 DCHECK(lost_context_callback_proxy_); // Is bound to thread. |
203 DCHECK(context_thread_checker_.CalledOnValidThread()); | 207 DCHECK(context_thread_checker_.CalledOnValidThread()); |
204 gr_context_->ResetContext(state); | 208 gr_context_->ResetContext(state); |
205 } | 209 } |
206 } | 210 } |
207 | 211 |
208 void ContextProviderCommandBuffer::SetupLock() { | 212 void ContextProviderCommandBuffer::SetupLock() { |
209 DCHECK(context3d_); | 213 DCHECK(lost_context_callback_proxy_); // Is bound to thread. |
| 214 DCHECK(context_thread_checker_.CalledOnValidThread()); |
210 context3d_->GetCommandBufferProxy()->SetLock(&context_lock_); | 215 context3d_->GetCommandBufferProxy()->SetLock(&context_lock_); |
211 } | 216 } |
212 | 217 |
213 base::Lock* ContextProviderCommandBuffer::GetLock() { | 218 base::Lock* ContextProviderCommandBuffer::GetLock() { |
214 return &context_lock_; | 219 return &context_lock_; |
215 } | 220 } |
216 | 221 |
217 gpu::Capabilities ContextProviderCommandBuffer::ContextCapabilities() { | 222 gpu::Capabilities ContextProviderCommandBuffer::ContextCapabilities() { |
218 DCHECK(lost_context_callback_proxy_); // Is bound to thread. | 223 DCHECK(lost_context_callback_proxy_); // Is bound to thread. |
219 DCHECK(context_thread_checker_.CalledOnValidThread()); | 224 DCHECK(context_thread_checker_.CalledOnValidThread()); |
(...skipping 23 matching lines...) Expand all Loading... |
243 | 248 |
244 void ContextProviderCommandBuffer::SetLostContextCallback( | 249 void ContextProviderCommandBuffer::SetLostContextCallback( |
245 const LostContextCallback& lost_context_callback) { | 250 const LostContextCallback& lost_context_callback) { |
246 DCHECK(context_thread_checker_.CalledOnValidThread()); | 251 DCHECK(context_thread_checker_.CalledOnValidThread()); |
247 DCHECK(lost_context_callback_.is_null() || | 252 DCHECK(lost_context_callback_.is_null() || |
248 lost_context_callback.is_null()); | 253 lost_context_callback.is_null()); |
249 lost_context_callback_ = lost_context_callback; | 254 lost_context_callback_ = lost_context_callback; |
250 } | 255 } |
251 | 256 |
252 } // namespace content | 257 } // namespace content |
OLD | NEW |