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

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

Powered by Google App Engine
This is Rietveld 408576698