| 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); | |
| 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; // Failed previously. |
| 99 if (lost_context_callback_proxy_) | 96 if (lost_context_callback_proxy_) |
| 100 return true; | 97 return true; |
| 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 |