| 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 |