| 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 |