OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/browser/compositor/gpu_process_transport_factory.h" | 5 #include "content/browser/compositor/gpu_process_transport_factory.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
53 #include "ui/ozone/public/surface_factory_ozone.h" | 53 #include "ui/ozone/public/surface_factory_ozone.h" |
54 #elif defined(USE_X11) | 54 #elif defined(USE_X11) |
55 #include "content/browser/compositor/software_output_device_x11.h" | 55 #include "content/browser/compositor/software_output_device_x11.h" |
56 #elif defined(OS_MACOSX) | 56 #elif defined(OS_MACOSX) |
57 #include "content/browser/compositor/software_output_device_mac.h" | 57 #include "content/browser/compositor/software_output_device_mac.h" |
58 #endif | 58 #endif |
59 | 59 |
60 using cc::ContextProvider; | 60 using cc::ContextProvider; |
61 using gpu::gles2::GLES2Interface; | 61 using gpu::gles2::GLES2Interface; |
62 | 62 |
63 static const int kNumRetriesBeforeSoftwareFallback = 4; | |
no sievers
2015/02/25 01:51:00
nit: use anonymous namespace, drop static
| |
64 | |
63 namespace content { | 65 namespace content { |
64 | 66 |
65 struct GpuProcessTransportFactory::PerCompositorData { | 67 struct GpuProcessTransportFactory::PerCompositorData { |
66 int surface_id; | 68 int surface_id; |
67 scoped_refptr<ReflectorImpl> reflector; | 69 scoped_refptr<ReflectorImpl> reflector; |
68 scoped_ptr<cc::OnscreenDisplayClient> display_client; | 70 scoped_ptr<cc::OnscreenDisplayClient> display_client; |
69 }; | 71 }; |
70 | 72 |
71 GpuProcessTransportFactory::GpuProcessTransportFactory() | 73 GpuProcessTransportFactory::GpuProcessTransportFactory() |
72 : next_surface_id_namespace_(1u), | 74 : next_surface_id_namespace_(1u), |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
119 if (overlay_candidates && | 121 if (overlay_candidates && |
120 base::CommandLine::ForCurrentProcess()->HasSwitch( | 122 base::CommandLine::ForCurrentProcess()->HasSwitch( |
121 switches::kEnableHardwareOverlays)) { | 123 switches::kEnableHardwareOverlays)) { |
122 return scoped_ptr<cc::OverlayCandidateValidator>( | 124 return scoped_ptr<cc::OverlayCandidateValidator>( |
123 new OverlayCandidateValidatorOzone(widget, overlay_candidates)); | 125 new OverlayCandidateValidatorOzone(widget, overlay_candidates)); |
124 } | 126 } |
125 #endif | 127 #endif |
126 return scoped_ptr<cc::OverlayCandidateValidator>(); | 128 return scoped_ptr<cc::OverlayCandidateValidator>(); |
127 } | 129 } |
128 | 130 |
131 static bool CreateGpuOutputSurface() { | |
piman
2015/02/25 01:44:47
nit: ShouldCreateGpuOuputSurface? (this doesn't cr
no sievers
2015/02/25 01:51:00
nit: ShouldCreateGpuOutputSurface() or ShouldUseGp
danakj
2015/02/25 21:25:38
+1
| |
132 #if defined(OS_CHROMEOS) | |
133 // Software fallback does not happen on Chrome OS. | |
134 return true; | |
135 #endif | |
136 | |
137 #if defined(OS_WIN) | |
138 if (::GetProp(compositor->widget(), kForceSoftwareCompositor) && | |
139 ::RemoveProp(compositor->widget(), kForceSoftwareCompositor)) | |
140 return false; | |
141 #endif | |
142 | |
143 return GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor(); | |
144 } | |
145 | |
129 void GpuProcessTransportFactory::CreateOutputSurface( | 146 void GpuProcessTransportFactory::CreateOutputSurface( |
130 base::WeakPtr<ui::Compositor> compositor, | 147 base::WeakPtr<ui::Compositor> compositor) { |
131 bool software_fallback) { | |
132 DCHECK(!!compositor); | 148 DCHECK(!!compositor); |
133 PerCompositorData* data = per_compositor_data_[compositor.get()]; | 149 PerCompositorData* data = per_compositor_data_[compositor.get()]; |
134 if (!data) | 150 if (!data) |
135 data = CreatePerCompositorData(compositor.get()); | 151 data = CreatePerCompositorData(compositor.get()); |
136 | 152 |
137 bool create_software_renderer = software_fallback; | 153 bool create_gpu_output_surface = CreateGpuOutputSurface(); |
138 #if defined(OS_CHROMEOS) | 154 if (create_gpu_output_surface) { |
139 // Software fallback does not happen on Chrome OS. | |
140 create_software_renderer = false; | |
141 #elif defined(OS_WIN) | |
142 if (::GetProp(compositor->widget(), kForceSoftwareCompositor)) { | |
143 if (::RemoveProp(compositor->widget(), kForceSoftwareCompositor)) | |
144 create_software_renderer = true; | |
145 } | |
146 #endif | |
147 if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) | |
148 create_software_renderer = true; | |
149 | |
150 if (!create_software_renderer) { | |
151 CauseForGpuLaunch cause = | 155 CauseForGpuLaunch cause = |
152 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; | 156 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; |
153 BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel( | 157 BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel( |
154 cause, | 158 cause, base::Bind(&GpuProcessTransportFactory::EstablishedGpuChannel, |
155 base::Bind(&GpuProcessTransportFactory::EstablishedGpuChannel, | 159 callback_factory_.GetWeakPtr(), compositor, |
156 callback_factory_.GetWeakPtr(), | 160 create_gpu_output_surface, 0)); |
157 compositor, | |
158 create_software_renderer)); | |
159 } else { | 161 } else { |
160 EstablishedGpuChannel(compositor, create_software_renderer); | 162 EstablishedGpuChannel(compositor, create_gpu_output_surface, 0); |
161 } | 163 } |
162 } | 164 } |
163 | 165 |
164 void GpuProcessTransportFactory::EstablishedGpuChannel( | 166 void GpuProcessTransportFactory::EstablishedGpuChannel( |
165 base::WeakPtr<ui::Compositor> compositor, | 167 base::WeakPtr<ui::Compositor> compositor, |
166 bool create_software_renderer) { | 168 bool create_gpu_output_surface, |
169 int num_attempts) { | |
167 if (!compositor) | 170 if (!compositor) |
168 return; | 171 return; |
169 PerCompositorData* data = per_compositor_data_[compositor.get()]; | 172 PerCompositorData* data = per_compositor_data_[compositor.get()]; |
170 DCHECK(data); | 173 DCHECK(data); |
171 scoped_refptr<GpuChannelHost> gpu_channel_host = | 174 |
172 BrowserGpuChannelHostFactory::instance()->GetGpuChannel(); | 175 if (num_attempts > kNumRetriesBeforeSoftwareFallback) { |
173 scoped_refptr<ContextProviderCommandBuffer> context_provider; | 176 #if defined(OS_CHROMEOS) |
174 if (gpu_channel_host.get() && !create_software_renderer) { | 177 LOG(FATAL) << "Unable to create a UI graphics context, and cannot use " |
175 context_provider = ContextProviderCommandBuffer::Create( | 178 << "software compositing on ChromeOS."; |
176 GpuProcessTransportFactory::CreateContextCommon(gpu_channel_host, | 179 #endif |
177 data->surface_id), | 180 create_gpu_output_surface = false; |
178 "Compositor"); | |
179 if (!context_provider->BindToCurrentThread()) | |
180 context_provider = nullptr; | |
181 } | 181 } |
182 | 182 |
183 UMA_HISTOGRAM_BOOLEAN("Aura.CreatedGpuBrowserCompositor", | 183 scoped_refptr<ContextProviderCommandBuffer> context_provider; |
184 !!context_provider.get()); | 184 if (create_gpu_output_surface) { |
185 scoped_refptr<GpuChannelHost> gpu_channel_host = | |
186 BrowserGpuChannelHostFactory::instance()->GetGpuChannel(); | |
187 if (gpu_channel_host.get()) { | |
188 context_provider = ContextProviderCommandBuffer::Create( | |
189 GpuProcessTransportFactory::CreateContextCommon(gpu_channel_host, | |
190 data->surface_id), | |
191 "Compositor"); | |
192 if (context_provider && !context_provider->BindToCurrentThread()) | |
193 context_provider = nullptr; | |
194 } | |
185 | 195 |
186 if (UseSurfacesEnabled()) { | 196 UMA_HISTOGRAM_BOOLEAN("Aura.CreatedGpuBrowserCompositor", |
187 // This gets a bit confusing. Here we have a ContextProvider configured to | 197 !!context_provider.get()); |
188 // render directly to this widget. We need to make an OnscreenDisplayClient | 198 |
189 // associated with this context, then return a SurfaceDisplayOutputSurface | 199 if (!context_provider) { |
190 // set up to draw to the display's surface. | 200 // Try again. |
191 cc::SurfaceManager* manager = surface_manager_.get(); | 201 CauseForGpuLaunch cause = |
192 scoped_ptr<cc::OutputSurface> display_surface; | 202 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; |
193 if (!context_provider.get()) { | 203 BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel( |
194 display_surface = | 204 cause, base::Bind(&GpuProcessTransportFactory::EstablishedGpuChannel, |
195 make_scoped_ptr(new SoftwareBrowserCompositorOutputSurface( | 205 callback_factory_.GetWeakPtr(), compositor, |
196 CreateSoftwareOutputDevice(compositor.get()), | 206 create_gpu_output_surface, num_attempts + 1)); |
197 data->surface_id, | 207 return; |
198 &output_surface_map_, | 208 } |
199 compositor->vsync_manager())); | 209 } |
200 } else { | 210 |
201 display_surface = make_scoped_ptr(new GpuBrowserCompositorOutputSurface( | 211 scoped_ptr<BrowserCompositorOutputSurface> surface; |
202 context_provider, | 212 if (!create_gpu_output_surface) { |
203 data->surface_id, | 213 surface = make_scoped_ptr(new SoftwareBrowserCompositorOutputSurface( |
204 &output_surface_map_, | 214 CreateSoftwareOutputDevice(compositor.get()), data->surface_id, |
215 &output_surface_map_, compositor->vsync_manager())); | |
216 } else { | |
217 DCHECK(context_provider); | |
218 #if defined(USE_OZONE) | |
219 if (ui::SurfaceFactoryOzone::GetInstance() | |
220 ->CanShowPrimaryPlaneAsOverlay()) { | |
221 surface = | |
222 make_scoped_ptr(new GpuSurfacelessBrowserCompositorOutputSurface( | |
223 context_provider, data->surface_id, &output_surface_map_, | |
224 compositor->vsync_manager(), | |
225 CreateOverlayCandidateValidator(compositor->widget()), GL_RGB, | |
226 BrowserGpuMemoryBufferManager::current())); | |
227 } else | |
228 #endif | |
229 { | |
230 surface = make_scoped_ptr(new GpuBrowserCompositorOutputSurface( | |
231 context_provider, data->surface_id, &output_surface_map_, | |
205 compositor->vsync_manager(), | 232 compositor->vsync_manager(), |
206 CreateOverlayCandidateValidator(compositor->widget()))); | 233 CreateOverlayCandidateValidator(compositor->widget()))); |
207 } | 234 } |
208 scoped_ptr<cc::OnscreenDisplayClient> display_client( | |
209 new cc::OnscreenDisplayClient( | |
210 display_surface.Pass(), manager, HostSharedBitmapManager::current(), | |
211 BrowserGpuMemoryBufferManager::current(), | |
212 compositor->GetRendererSettings(), compositor->task_runner())); | |
213 | |
214 scoped_ptr<cc::SurfaceDisplayOutputSurface> output_surface( | |
215 new cc::SurfaceDisplayOutputSurface( | |
216 manager, compositor->surface_id_allocator(), context_provider)); | |
217 display_client->set_surface_output_surface(output_surface.get()); | |
218 output_surface->set_display_client(display_client.get()); | |
219 display_client->display()->Resize(compositor->size()); | |
220 data->display_client = display_client.Pass(); | |
221 compositor->SetOutputSurface(output_surface.Pass()); | |
222 return; | |
223 } | 235 } |
224 | 236 |
225 if (!context_provider.get()) { | 237 if (data->reflector) |
226 #if defined(OS_CHROMEOS) | 238 data->reflector->OnSourceSurfaceReady(surface.get()); |
227 LOG(FATAL) << "Shouldn't use software compositing on ChromeOS."; | |
228 #endif | |
229 | 239 |
230 scoped_ptr<SoftwareBrowserCompositorOutputSurface> surface( | 240 if (!UseSurfacesEnabled()) { |
231 new SoftwareBrowserCompositorOutputSurface( | |
232 CreateSoftwareOutputDevice(compositor.get()), | |
233 data->surface_id, | |
234 &output_surface_map_, | |
235 compositor->vsync_manager())); | |
236 compositor->SetOutputSurface(surface.Pass()); | 241 compositor->SetOutputSurface(surface.Pass()); |
237 return; | 242 return; |
238 } | 243 } |
239 | 244 |
240 scoped_ptr<BrowserCompositorOutputSurface> surface; | 245 // This gets a bit confusing. Here we have a ContextProvider in the |surface| |
241 #if defined(USE_OZONE) | 246 // configured to render directly to this widget. We need to make an |
242 if (ui::SurfaceFactoryOzone::GetInstance()->CanShowPrimaryPlaneAsOverlay()) { | 247 // OnscreenDisplayClient associated with that context, then return a |
243 surface.reset(new GpuSurfacelessBrowserCompositorOutputSurface( | 248 // SurfaceDisplayOutputSurface set up to draw to the display's surface. |
244 context_provider, data->surface_id, &output_surface_map_, | 249 cc::SurfaceManager* manager = surface_manager_.get(); |
245 compositor->vsync_manager(), | 250 scoped_ptr<cc::OnscreenDisplayClient> display_client( |
246 CreateOverlayCandidateValidator(compositor->widget()), GL_RGB, | 251 new cc::OnscreenDisplayClient( |
247 BrowserGpuMemoryBufferManager::current())); | 252 surface.Pass(), manager, HostSharedBitmapManager::current(), |
248 } | 253 BrowserGpuMemoryBufferManager::current(), |
249 #endif | 254 compositor->GetRendererSettings(), compositor->task_runner())); |
250 if (!surface) | |
251 surface.reset(new GpuBrowserCompositorOutputSurface( | |
252 context_provider, | |
253 data->surface_id, | |
254 &output_surface_map_, | |
255 compositor->vsync_manager(), | |
256 CreateOverlayCandidateValidator(compositor->widget()))); | |
257 | 255 |
258 if (data->reflector.get()) | 256 scoped_ptr<cc::SurfaceDisplayOutputSurface> output_surface( |
259 data->reflector->OnSourceSurfaceReady(surface.get()); | 257 new cc::SurfaceDisplayOutputSurface( |
260 | 258 manager, compositor->surface_id_allocator(), context_provider)); |
261 compositor->SetOutputSurface(surface.Pass()); | 259 display_client->set_surface_output_surface(output_surface.get()); |
260 output_surface->set_display_client(display_client.get()); | |
261 display_client->display()->Resize(compositor->size()); | |
262 data->display_client = display_client.Pass(); | |
263 compositor->SetOutputSurface(output_surface.Pass()); | |
262 } | 264 } |
263 | 265 |
264 scoped_refptr<ui::Reflector> GpuProcessTransportFactory::CreateReflector( | 266 scoped_refptr<ui::Reflector> GpuProcessTransportFactory::CreateReflector( |
265 ui::Compositor* source_compositor, | 267 ui::Compositor* source_compositor, |
266 ui::Layer* target_layer) { | 268 ui::Layer* target_layer) { |
267 PerCompositorData* source_data = per_compositor_data_[source_compositor]; | 269 PerCompositorData* source_data = per_compositor_data_[source_compositor]; |
268 DCHECK(source_data); | 270 DCHECK(source_data); |
269 | 271 |
270 source_data->reflector = new ReflectorImpl(source_compositor, target_layer); | 272 source_data->reflector = new ReflectorImpl(source_compositor, target_layer); |
271 // Use the |output_surface_map_| to check if the output surface has been bound | 273 // Use the |output_surface_map_| to check if the output surface has been bound |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
508 FOR_EACH_OBSERVER(ImageTransportFactoryObserver, | 510 FOR_EACH_OBSERVER(ImageTransportFactoryObserver, |
509 observer_list_, | 511 observer_list_, |
510 OnLostResources()); | 512 OnLostResources()); |
511 | 513 |
512 // Kill things that use the shared context before killing the shared context. | 514 // Kill things that use the shared context before killing the shared context. |
513 lost_gl_helper.reset(); | 515 lost_gl_helper.reset(); |
514 lost_shared_main_thread_contexts = NULL; | 516 lost_shared_main_thread_contexts = NULL; |
515 } | 517 } |
516 | 518 |
517 } // namespace content | 519 } // namespace content |
OLD | NEW |