Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1412)

Side by Side Diff: content/browser/renderer_host/context_provider_factory_impl_android.cc

Issue 2190033002: content: Add ContextProviderFactory to create a render ContextProvider. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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/browser/renderer_host/context_provider_factory_impl_android.h"
6
7 #include "base/auto_reset.h"
8 #include "base/command_line.h"
9 #include "base/lazy_instance.h"
10 #include "base/memory/singleton.h"
11 #include "cc/output/context_provider.h"
12 #include "cc/output/vulkan_in_process_context_provider.h"
13 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
14 #include "content/browser/gpu/compositor_util.h"
15 #include "content/common/gpu/client/context_provider_command_buffer.h"
16 #include "content/public/common/content_switches.h"
17 #include "gpu/command_buffer/client/gles2_interface.h"
18 #include "gpu/ipc/client/gpu_channel_host.h"
19
20 namespace content {
21
22 base::LazyInstance<scoped_refptr<cc::VulkanInProcessContextProvider>>
23 g_shared_vulkan_context_provider_android = LAZY_INSTANCE_INITIALIZER;
24
25 // static
26 ContextProviderFactory* ContextProviderFactory::GetInstance() {
27 return ContextProviderFactoryImpl::GetInstance();
28 }
29
30 ContextProviderFactory::ContextProviders::ContextProviders() = default;
31
32 ContextProviderFactory::ContextProviders::~ContextProviders() = default;
33
34 // static
35 ContextProviderFactoryImpl* ContextProviderFactoryImpl::GetInstance() {
36 return base::Singleton<ContextProviderFactoryImpl>::get();
37 }
38
39 ContextProviderFactoryImpl::ContextProviderFactoryImpl()
40 : in_handle_pending_requests_(false), weak_factory_(this) {}
41
42 ContextProviderFactoryImpl::~ContextProviderFactoryImpl() {}
43
44 void ContextProviderFactoryImpl::RequestRenderContextProvider(
45 ContextProviderCallback result_callback) {
46 render_context_request_callbacks_.push_back(result_callback);
47
48 HandlePendingRequests();
49 }
50
51 void ContextProviderFactoryImpl::RequestGpuChannel(
52 GpuChannelRequestCallback gpu_channel_request_callback) {
53 gpu_channel_request_callback_ = gpu_channel_request_callback;
54
55 HandlePendingRequests();
56 }
57
58 scoped_refptr<cc::VulkanInProcessContextProvider>
59 ContextProviderFactoryImpl::GetSharedVulkanContextProviderAndroid() {
60 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
61 switches::kEnableVulkan)) {
62 scoped_refptr<cc::VulkanInProcessContextProvider>* context_provider =
63 g_shared_vulkan_context_provider_android.Pointer();
64 if (!*context_provider)
65 *context_provider = cc::VulkanInProcessContextProvider::Create();
66 return *context_provider;
67 }
68 return nullptr;
69 }
70
71 void ContextProviderFactoryImpl::HandlePendingRequests() {
72 // Failure to initialize the context could result in new requests. Handle
73 // them after going through the current list.
74 if (in_handle_pending_requests_)
75 return;
76
77 {
78 base::AutoReset<bool> auto_reset_in_handle_requests(
79 &in_handle_pending_requests_, true);
80
81 scoped_refptr<cc::VulkanInProcessContextProvider> vulkan_context_provider =
82 GetSharedVulkanContextProviderAndroid();
83
84 scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(
85 vulkan_context_provider ? nullptr : EnsureGpuChannelEstablished());
86
87 if (!vulkan_context_provider && !gpu_channel_host)
88 return;
89
90 if (!render_context_request_callbacks_.empty()) {
91 std::list<ContextProviderCallback> context_requests =
92 render_context_request_callbacks_;
93 render_context_request_callbacks_.clear();
94
95 for (ContextProviderCallback& context_request : context_requests) {
96 ContextProviders context_providers;
97
98 if (vulkan_context_provider)
99 context_providers.vulkan_context_provider = vulkan_context_provider;
100 else
101 CreateRenderCompositorContexts(context_providers, gpu_channel_host);
102
103 context_request.Run(context_providers);
104 }
105 }
106
107 if (!gpu_channel_request_callback_.is_null()) {
108 if (!gpu_channel_host)
109 gpu_channel_host = EnsureGpuChannelEstablished();
110
111 if (!gpu_channel_host)
112 return;
113
114 GpuChannelRequestCallback gpu_request_callback =
115 gpu_channel_request_callback_;
116 gpu_channel_request_callback_ = GpuChannelRequestCallback();
117 gpu_request_callback.Run(gpu_channel_host);
118 }
119 }
120
121 if (!gpu_channel_request_callback_.is_null() ||
122 !render_context_request_callbacks_.empty())
123 HandlePendingRequests();
124 }
125
126 void ContextProviderFactoryImpl::CreateRenderCompositorContexts(
127 ContextProviders& context_providers,
128 scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
129 DCHECK(gpu_channel_host);
130
131 // TODO(khushalsagar): Figure out if we can share this code with the
132 // renderer compositor.
133 scoped_refptr<ContextProviderCommandBuffer> worker_context_provider =
134 SharedCompositorWorkerContextProvider(gpu_channel_host);
135 if (!worker_context_provider) {
136 // Cause the compositor to wait and try again.
137 return;
138 }
139
140 // The renderer compositor context doesn't do a lot of stuff, so we don't
141 // expect it to need a lot of space for commands or transfer. Raster and
142 // uploads happen on the worker context instead.
143 gpu::SharedMemoryLimits limits = gpu::SharedMemoryLimits::ForMailboxContext();
144
145 // This is for an offscreen context for the compositor. So the default
146 // framebuffer doesn't need alpha, depth, stencil, antialiasing.
147 gpu::gles2::ContextCreationAttribHelper attributes;
148 attributes.alpha_size = -1;
149 attributes.depth_size = 0;
150 attributes.stencil_size = 0;
151 attributes.samples = 0;
152 attributes.sample_buffers = 0;
153 attributes.bind_generates_resource = false;
154 attributes.lose_context_when_out_of_memory = true;
155
156 constexpr bool automatic_flushes = false;
157 constexpr bool support_locking = false;
158
159 // The compositor context shares resources with the worker context unless
160 // the worker is async.
161 ContextProviderCommandBuffer* share_context = worker_context_provider.get();
162 if (IsAsyncWorkerContextEnabled())
163 share_context = nullptr;
164
165 scoped_refptr<ContextProviderCommandBuffer> context_provider(
166 new ContextProviderCommandBuffer(
167 gpu_channel_host, gpu::GPU_STREAM_DEFAULT,
168 gpu::GpuStreamPriority::NORMAL, gpu::kNullSurfaceHandle,
169 GURL(std::string("chrome://gpu/ContextProviderFactoryImpl::") +
170 std::string("CompositorContextProvider")),
171 automatic_flushes, support_locking, limits, attributes, share_context,
172 command_buffer_metrics::RENDER_COMPOSITOR_CONTEXT));
173
174 context_providers.compositor_context_provider = std::move(context_provider);
175 context_providers.worker_context_provider =
176 std::move(worker_context_provider);
177 }
178
179 scoped_refptr<ContextProviderCommandBuffer>
180 ContextProviderFactoryImpl::SharedCompositorWorkerContextProvider(
181 scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
182 // Try to reuse existing shared worker context provider.
183 if (shared_worker_context_provider_) {
184 // Note: If context is lost, delete reference after releasing the lock.
185 cc::ContextProvider::ScopedContextLock lock(
186 shared_worker_context_provider_.get());
187 if (shared_worker_context_provider_->ContextGL()
188 ->GetGraphicsResetStatusKHR() == GL_NO_ERROR)
189 return shared_worker_context_provider_;
190 }
191
192 int32_t stream_id = gpu::GPU_STREAM_DEFAULT;
193 gpu::GpuStreamPriority stream_priority = gpu::GpuStreamPriority::NORMAL;
194 if (IsAsyncWorkerContextEnabled()) {
195 stream_id = gpu_channel_host->GenerateStreamID();
196 stream_priority = gpu::GpuStreamPriority::LOW;
197 }
198
199 bool support_locking = true;
200 gpu::gles2::ContextCreationAttribHelper attributes;
201 attributes.alpha_size = -1;
202 attributes.depth_size = 0;
203 attributes.stencil_size = 0;
204 attributes.samples = 0;
205 attributes.sample_buffers = 0;
206 attributes.bind_generates_resource = false;
207 attributes.lose_context_when_out_of_memory = true;
208 const bool automatic_flushes = false;
209
210 shared_worker_context_provider_ = new ContextProviderCommandBuffer(
211 std::move(gpu_channel_host), stream_id, stream_priority,
212 gpu::kNullSurfaceHandle,
213 GURL(std::string("chrome://gpu/ContextProviderFactoryImpl::") +
214 std::string("SharedCompositorWorkerContextProvider")),
215 automatic_flushes, support_locking, gpu::SharedMemoryLimits(), attributes,
216 nullptr, command_buffer_metrics::RENDER_WORKER_CONTEXT);
217
218 if (!shared_worker_context_provider_->BindToCurrentThread())
Khushal 2016/07/28 18:12:31 Does this look correct? We do it on the main threa
219 shared_worker_context_provider_ = nullptr;
220 return shared_worker_context_provider_;
221 }
222
223 gpu::GpuChannelHost* ContextProviderFactoryImpl::EnsureGpuChannelEstablished() {
224 #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
225 defined(SYZYASAN) || defined(CYGPROFILE_INSTRUMENTATION)
226 const int64_t kGpuChannelTimeoutInSeconds = 40;
227 #else
228 const int64_t kGpuChannelTimeoutInSeconds = 10;
229 #endif
230
231 BrowserGpuChannelHostFactory* factory =
232 BrowserGpuChannelHostFactory::instance();
233
234 if (factory->GetGpuChannel())
235 return factory->GetGpuChannel();
236
237 factory->EstablishGpuChannel(
238 CAUSE_FOR_GPU_LAUNCH_DISPLAY_COMPOSITOR_CONTEXT,
239 base::Bind(&ContextProviderFactoryImpl::OnGpuChannelEstablished,
240 weak_factory_.GetWeakPtr()));
241 establish_gpu_channel_timeout_.Start(
242 FROM_HERE, base::TimeDelta::FromSeconds(kGpuChannelTimeoutInSeconds),
243 this, &ContextProviderFactoryImpl::OnGpuChannelTimeout);
244
245 return nullptr;
246 }
247
248 void ContextProviderFactoryImpl::OnGpuChannelEstablished() {
249 establish_gpu_channel_timeout_.Stop();
250 HandlePendingRequests();
251 }
252
253 void ContextProviderFactoryImpl::OnGpuChannelTimeout() {
254 LOG(FATAL) << "Timed out waiting for GPU channel.";
255 }
256
257 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/context_provider_factory_impl_android.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698