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; |
| 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 ShouldCreateGpuOutputSurface(ui::Compositor* compositor) { |
| 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 = |
138 #if defined(OS_CHROMEOS) | 154 ShouldCreateGpuOutputSurface(compositor.get()); |
139 // Software fallback does not happen on Chrome OS. | 155 if (create_gpu_output_surface) { |
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 = | 156 CauseForGpuLaunch cause = |
152 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; | 157 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; |
153 BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel( | 158 BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel( |
154 cause, | 159 cause, base::Bind(&GpuProcessTransportFactory::EstablishedGpuChannel, |
155 base::Bind(&GpuProcessTransportFactory::EstablishedGpuChannel, | 160 callback_factory_.GetWeakPtr(), compositor, |
156 callback_factory_.GetWeakPtr(), | 161 create_gpu_output_surface, 0)); |
157 compositor, | |
158 create_software_renderer)); | |
159 } else { | 162 } else { |
160 EstablishedGpuChannel(compositor, create_software_renderer); | 163 EstablishedGpuChannel(compositor, create_gpu_output_surface, 0); |
161 } | 164 } |
162 } | 165 } |
163 | 166 |
164 void GpuProcessTransportFactory::EstablishedGpuChannel( | 167 void GpuProcessTransportFactory::EstablishedGpuChannel( |
165 base::WeakPtr<ui::Compositor> compositor, | 168 base::WeakPtr<ui::Compositor> compositor, |
166 bool create_software_renderer) { | 169 bool create_gpu_output_surface, |
| 170 int num_attempts) { |
167 if (!compositor) | 171 if (!compositor) |
168 return; | 172 return; |
169 PerCompositorData* data = per_compositor_data_[compositor.get()]; | 173 PerCompositorData* data = per_compositor_data_[compositor.get()]; |
170 DCHECK(data); | 174 DCHECK(data); |
171 scoped_refptr<GpuChannelHost> gpu_channel_host = | 175 |
172 BrowserGpuChannelHostFactory::instance()->GetGpuChannel(); | 176 if (num_attempts > kNumRetriesBeforeSoftwareFallback) { |
173 scoped_refptr<ContextProviderCommandBuffer> context_provider; | 177 #if defined(OS_CHROMEOS) |
174 if (gpu_channel_host.get() && !create_software_renderer) { | 178 LOG(FATAL) << "Unable to create a UI graphics context, and cannot use " |
175 context_provider = ContextProviderCommandBuffer::Create( | 179 << "software compositing on ChromeOS."; |
176 GpuProcessTransportFactory::CreateContextCommon(gpu_channel_host, | 180 #endif |
177 data->surface_id), | 181 create_gpu_output_surface = false; |
178 "Compositor"); | |
179 if (!context_provider->BindToCurrentThread()) | |
180 context_provider = nullptr; | |
181 } | 182 } |
182 | 183 |
183 UMA_HISTOGRAM_BOOLEAN("Aura.CreatedGpuBrowserCompositor", | 184 scoped_refptr<ContextProviderCommandBuffer> context_provider; |
184 !!context_provider.get()); | 185 if (create_gpu_output_surface) { |
| 186 scoped_refptr<GpuChannelHost> gpu_channel_host = |
| 187 BrowserGpuChannelHostFactory::instance()->GetGpuChannel(); |
| 188 if (gpu_channel_host.get()) { |
| 189 context_provider = ContextProviderCommandBuffer::Create( |
| 190 GpuProcessTransportFactory::CreateContextCommon(gpu_channel_host, |
| 191 data->surface_id), |
| 192 "Compositor"); |
| 193 if (context_provider && !context_provider->BindToCurrentThread()) |
| 194 context_provider = nullptr; |
| 195 } |
185 | 196 |
186 if (UseSurfacesEnabled()) { | 197 UMA_HISTOGRAM_BOOLEAN("Aura.CreatedGpuBrowserCompositor", |
187 // This gets a bit confusing. Here we have a ContextProvider configured to | 198 !!context_provider.get()); |
188 // render directly to this widget. We need to make an OnscreenDisplayClient | 199 |
189 // associated with this context, then return a SurfaceDisplayOutputSurface | 200 if (!context_provider) { |
190 // set up to draw to the display's surface. | 201 // Try again. |
191 cc::SurfaceManager* manager = surface_manager_.get(); | 202 CauseForGpuLaunch cause = |
192 scoped_ptr<cc::OutputSurface> display_surface; | 203 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; |
193 if (!context_provider.get()) { | 204 BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel( |
194 display_surface = | 205 cause, base::Bind(&GpuProcessTransportFactory::EstablishedGpuChannel, |
195 make_scoped_ptr(new SoftwareBrowserCompositorOutputSurface( | 206 callback_factory_.GetWeakPtr(), compositor, |
196 CreateSoftwareOutputDevice(compositor.get()), | 207 create_gpu_output_surface, num_attempts + 1)); |
197 data->surface_id, | 208 return; |
198 &output_surface_map_, | 209 } |
199 compositor->vsync_manager())); | 210 } |
200 } else { | 211 |
201 display_surface = make_scoped_ptr(new GpuBrowserCompositorOutputSurface( | 212 scoped_ptr<BrowserCompositorOutputSurface> surface; |
202 context_provider, | 213 if (!create_gpu_output_surface) { |
203 data->surface_id, | 214 surface = make_scoped_ptr(new SoftwareBrowserCompositorOutputSurface( |
204 &output_surface_map_, | 215 CreateSoftwareOutputDevice(compositor.get()), data->surface_id, |
| 216 &output_surface_map_, compositor->vsync_manager())); |
| 217 } else { |
| 218 DCHECK(context_provider); |
| 219 #if defined(USE_OZONE) |
| 220 if (ui::SurfaceFactoryOzone::GetInstance() |
| 221 ->CanShowPrimaryPlaneAsOverlay()) { |
| 222 surface = |
| 223 make_scoped_ptr(new GpuSurfacelessBrowserCompositorOutputSurface( |
| 224 context_provider, data->surface_id, &output_surface_map_, |
| 225 compositor->vsync_manager(), |
| 226 CreateOverlayCandidateValidator(compositor->widget()), GL_RGB, |
| 227 BrowserGpuMemoryBufferManager::current())); |
| 228 } else |
| 229 #endif |
| 230 { |
| 231 surface = make_scoped_ptr(new GpuBrowserCompositorOutputSurface( |
| 232 context_provider, data->surface_id, &output_surface_map_, |
205 compositor->vsync_manager(), | 233 compositor->vsync_manager(), |
206 CreateOverlayCandidateValidator(compositor->widget()))); | 234 CreateOverlayCandidateValidator(compositor->widget()))); |
207 } | 235 } |
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 } | 236 } |
224 | 237 |
225 if (!context_provider.get()) { | 238 if (data->reflector) |
226 #if defined(OS_CHROMEOS) | 239 data->reflector->OnSourceSurfaceReady(surface.get()); |
227 LOG(FATAL) << "Shouldn't use software compositing on ChromeOS."; | |
228 #endif | |
229 | 240 |
230 scoped_ptr<SoftwareBrowserCompositorOutputSurface> surface( | 241 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()); | 242 compositor->SetOutputSurface(surface.Pass()); |
237 return; | 243 return; |
238 } | 244 } |
239 | 245 |
240 scoped_ptr<BrowserCompositorOutputSurface> surface; | 246 // This gets a bit confusing. Here we have a ContextProvider in the |surface| |
241 #if defined(USE_OZONE) | 247 // configured to render directly to this widget. We need to make an |
242 if (ui::SurfaceFactoryOzone::GetInstance()->CanShowPrimaryPlaneAsOverlay()) { | 248 // OnscreenDisplayClient associated with that context, then return a |
243 surface.reset(new GpuSurfacelessBrowserCompositorOutputSurface( | 249 // SurfaceDisplayOutputSurface set up to draw to the display's surface. |
244 context_provider, data->surface_id, &output_surface_map_, | 250 cc::SurfaceManager* manager = surface_manager_.get(); |
245 compositor->vsync_manager(), | 251 scoped_ptr<cc::OnscreenDisplayClient> display_client( |
246 CreateOverlayCandidateValidator(compositor->widget()), GL_RGB, | 252 new cc::OnscreenDisplayClient( |
247 BrowserGpuMemoryBufferManager::current())); | 253 surface.Pass(), manager, HostSharedBitmapManager::current(), |
248 } | 254 BrowserGpuMemoryBufferManager::current(), |
249 #endif | 255 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 | 256 |
258 if (data->reflector.get()) | 257 scoped_ptr<cc::SurfaceDisplayOutputSurface> output_surface( |
259 data->reflector->OnSourceSurfaceReady(surface.get()); | 258 new cc::SurfaceDisplayOutputSurface( |
260 | 259 manager, compositor->surface_id_allocator(), context_provider)); |
261 compositor->SetOutputSurface(surface.Pass()); | 260 display_client->set_surface_output_surface(output_surface.get()); |
| 261 output_surface->set_display_client(display_client.get()); |
| 262 display_client->display()->Resize(compositor->size()); |
| 263 data->display_client = display_client.Pass(); |
| 264 compositor->SetOutputSurface(output_surface.Pass()); |
262 } | 265 } |
263 | 266 |
264 scoped_refptr<ui::Reflector> GpuProcessTransportFactory::CreateReflector( | 267 scoped_refptr<ui::Reflector> GpuProcessTransportFactory::CreateReflector( |
265 ui::Compositor* source_compositor, | 268 ui::Compositor* source_compositor, |
266 ui::Layer* target_layer) { | 269 ui::Layer* target_layer) { |
267 PerCompositorData* source_data = per_compositor_data_[source_compositor]; | 270 PerCompositorData* source_data = per_compositor_data_[source_compositor]; |
268 DCHECK(source_data); | 271 DCHECK(source_data); |
269 | 272 |
270 source_data->reflector = new ReflectorImpl(source_compositor, target_layer); | 273 source_data->reflector = new ReflectorImpl(source_compositor, target_layer); |
271 // Use the |output_surface_map_| to check if the output surface has been bound | 274 // 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, | 511 FOR_EACH_OBSERVER(ImageTransportFactoryObserver, |
509 observer_list_, | 512 observer_list_, |
510 OnLostResources()); | 513 OnLostResources()); |
511 | 514 |
512 // Kill things that use the shared context before killing the shared context. | 515 // Kill things that use the shared context before killing the shared context. |
513 lost_gl_helper.reset(); | 516 lost_gl_helper.reset(); |
514 lost_shared_main_thread_contexts = NULL; | 517 lost_shared_main_thread_contexts = NULL; |
515 } | 518 } |
516 | 519 |
517 } // namespace content | 520 } // namespace content |
OLD | NEW |