Chromium Code Reviews| 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 |