gpu_process_transport_factory.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// found in the LICENSE file.
4558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/compositor/gpu_process_transport_factory.h"
6558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
7558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include <string>
8558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
9558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "base/bind.h"
10558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "base/command_line.h"
11558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "base/location.h"
12558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "base/message_loop/message_loop.h"
13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/metrics/histogram.h"
14558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "cc/output/compositor_frame.h"
15558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "cc/output/output_surface.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/compositor/browser_compositor_output_surface.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/compositor/browser_compositor_output_surface_proxy.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/compositor/gpu_browser_compositor_output_surface.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/compositor/reflector_impl.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/compositor/software_browser_compositor_output_surface.h"
21558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
22558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/browser/gpu/gpu_data_manager_impl.h"
23558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/browser/gpu/gpu_surface_tracker.h"
24558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/browser/renderer_host/render_widget_host_impl.h"
25fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch#include "content/common/gpu/client/context_provider_command_buffer.h"
26558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/common/gpu/client/gl_helper.h"
27558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/common/gpu/client/gpu_channel_host.h"
28558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
29558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/common/gpu/gpu_process_launch_causes.h"
30558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "gpu/GLES2/gl2extchromium.h"
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gpu/command_buffer/client/gles2_interface.h"
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gpu/command_buffer/common/mailbox.h"
33558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "third_party/khronos/GLES2/gl2.h"
34558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "ui/compositor/compositor.h"
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/compositor/compositor_constants.h"
36558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "ui/compositor/compositor_switches.h"
37558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "ui/gfx/native_widget_types.h"
38558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "ui/gfx/size.h"
39558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
40558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#if defined(OS_WIN)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/compositor/software_output_device_win.h"
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#elif defined(USE_OZONE)
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/browser/compositor/overlay_candidate_validator_ozone.h"
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/compositor/software_output_device_ozone.h"
45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/gfx/ozone/surface_factory_ozone.h"
46558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#elif defined(USE_X11)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/compositor/software_output_device_x11.h"
48558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#endif
49558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using cc::ContextProvider;
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using gpu::gles2::GLES2Interface;
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
53558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochnamespace content {
54558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
55558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochstruct GpuProcessTransportFactory::PerCompositorData {
56558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  int surface_id;
57558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  scoped_refptr<ReflectorImpl> reflector;
58558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch};
59558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
60558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochGpuProcessTransportFactory::GpuProcessTransportFactory()
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : callback_factory_(this) {
62558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  output_surface_proxy_ = new BrowserCompositorOutputSurfaceProxy(
63d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      &output_surface_map_);
64558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
65558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
66558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochGpuProcessTransportFactory::~GpuProcessTransportFactory() {
67558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(per_compositor_data_.empty());
68fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch
69fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch  // Make sure the lost context callback doesn't try to run during destruction.
70fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch  callback_factory_.InvalidateWeakPtrs();
71558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
72558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
73558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochscoped_ptr<WebGraphicsContext3DCommandBufferImpl>
74558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochGpuProcessTransportFactory::CreateOffscreenCommandBufferContext() {
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return CreateContextCommon(0);
76558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
77558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
78bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochscoped_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
79bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    ui::Compositor* compositor) {
80bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#if defined(OS_WIN)
81bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceWin(
82bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      compositor));
831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#elif defined(USE_OZONE)
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceOzone(
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      compositor));
86bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#elif defined(USE_X11)
87bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceX11(
88bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      compositor));
8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#else
90bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  NOTREACHED();
91bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return scoped_ptr<cc::SoftwareOutputDevice>();
9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#endif
93bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
94bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochscoped_ptr<cc::OverlayCandidateValidator> CreateOverlayCandidateValidator(
96c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gfx::AcceleratedWidget widget) {
97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if defined(USE_OZONE)
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::OverlayCandidatesOzone* overlay_candidates =
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      gfx::SurfaceFactoryOzone::GetInstance()->GetOverlayCandidates(widget);
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (overlay_candidates && CommandLine::ForCurrentProcess()->HasSwitch(
101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                switches::kEnableHardwareOverlays)) {
102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return scoped_ptr<cc::OverlayCandidateValidator>(
103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        new OverlayCandidateValidatorOzone(widget, overlay_candidates));
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif
106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return scoped_ptr<cc::OverlayCandidateValidator>();
107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
109558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochscoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ui::Compositor* compositor, bool software_fallback) {
111558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  PerCompositorData* data = per_compositor_data_[compositor];
112558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!data)
113558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    data = CreatePerCompositorData(compositor);
114558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool create_software_renderer = software_fallback;
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_CHROMEOS)
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Software fallback does not happen on Chrome OS.
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  create_software_renderer = false;
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_WIN)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (::GetProp(compositor->widget(), kForceSoftwareCompositor)) {
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (::RemoveProp(compositor->widget(), kForceSoftwareCompositor))
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      create_software_renderer = true;
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<ContextProviderCommandBuffer> context_provider;
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!create_software_renderer) {
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    context_provider = ContextProviderCommandBuffer::Create(
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        GpuProcessTransportFactory::CreateContextCommon(data->surface_id),
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        "Compositor");
131558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN("Aura.CreatedGpuBrowserCompositor", !!context_provider);
134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!context_provider.get()) {
136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (ui::Compositor::WasInitializedWithThread()) {
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      LOG(FATAL) << "Failed to create UI context, but can't use software"
138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 " compositing with browser threaded compositing. Aborting.";
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<SoftwareBrowserCompositorOutputSurface> surface(
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        new SoftwareBrowserCompositorOutputSurface(
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            output_surface_proxy_,
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            CreateSoftwareOutputDevice(compositor),
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            per_compositor_data_[compositor]->surface_id,
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            &output_surface_map_,
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            compositor->vsync_manager()));
148bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return surface.PassAs<cc::OutputSurface>();
149bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
150558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
151558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  scoped_refptr<base::SingleThreadTaskRunner> compositor_thread_task_runner =
152558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      ui::Compositor::GetCompositorMessageLoop();
153558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!compositor_thread_task_runner.get())
154558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    compositor_thread_task_runner = base::MessageLoopProxy::current();
155558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
156558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Here we know the GpuProcessHost has been set up, because we created a
157558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // context.
158558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  output_surface_proxy_->ConnectToGpuProcessHost(
159558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      compositor_thread_task_runner.get());
160558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
161558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  scoped_ptr<BrowserCompositorOutputSurface> surface(
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new GpuBrowserCompositorOutputSurface(
1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          context_provider,
164558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch          per_compositor_data_[compositor]->surface_id,
165d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          &output_surface_map_,
166c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          compositor->vsync_manager(),
167c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          CreateOverlayCandidateValidator(compositor->widget())));
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (data->reflector.get())
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    data->reflector->ReattachToOutputSurfaceFromMainThread(surface.get());
170558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
171558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return surface.PassAs<cc::OutputSurface>();
172558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
173558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
174558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochscoped_refptr<ui::Reflector> GpuProcessTransportFactory::CreateReflector(
175558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    ui::Compositor* source,
176558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    ui::Layer* target) {
177558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  PerCompositorData* data = per_compositor_data_[source];
178558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(data);
179558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
180558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  data->reflector = new ReflectorImpl(
181d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      source, target, &output_surface_map_, data->surface_id);
182558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return data->reflector;
183558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
184558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
185558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid GpuProcessTransportFactory::RemoveReflector(
186558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    scoped_refptr<ui::Reflector> reflector) {
187558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  ReflectorImpl* reflector_impl =
188558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      static_cast<ReflectorImpl*>(reflector.get());
189558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  PerCompositorData* data =
190558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      per_compositor_data_[reflector_impl->mirrored_compositor()];
191558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(data);
192558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  data->reflector->Shutdown();
193558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  data->reflector = NULL;
194558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
195558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
196558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid GpuProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
197558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
198558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (it == per_compositor_data_.end())
199558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return;
200558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  PerCompositorData* data = it->second;
201558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(data);
202558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  GpuSurfaceTracker::Get()->RemoveSurface(data->surface_id);
203558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  delete data;
204558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  per_compositor_data_.erase(it);
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (per_compositor_data_.empty()) {
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Destroying the GLHelper may cause some async actions to be cancelled,
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // causing things to request a new GLHelper. Due to crbug.com/176091 the
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // GLHelper created in this case would be lost/leaked if we just reset()
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // on the |gl_helper_| variable directly. So instead we call reset() on a
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // local scoped_ptr.
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<GLHelper> helper = gl_helper_.Pass();
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    helper.reset();
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(!gl_helper_) << "Destroying the GLHelper should not cause a new "
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           "GLHelper to be created.";
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
216558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
217558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
218c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochbool GpuProcessTransportFactory::DoesCreateTestContexts() { return false; }
219c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch
220558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochui::ContextFactory* GpuProcessTransportFactory::AsContextFactory() {
221558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return this;
222558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
223558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gfx::GLSurfaceHandle GpuProcessTransportFactory::GetSharedSurfaceHandle() {
225558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  gfx::GLSurfaceHandle handle = gfx::GLSurfaceHandle(
226558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      gfx::kNullPluginWindow, gfx::TEXTURE_TRANSPORT);
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  handle.parent_client_id =
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      BrowserGpuChannelHostFactory::instance()->GetGpuChannelId();
229558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return handle;
230558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
231558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
232558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochGLHelper* GpuProcessTransportFactory::GetGLHelper() {
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!gl_helper_ && !per_compositor_data_.empty()) {
2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    scoped_refptr<cc::ContextProvider> provider =
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        SharedMainThreadContextProvider();
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (provider.get())
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gl_helper_.reset(new GLHelper(provider->ContextGL(),
2388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                    provider->ContextSupport()));
239558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
240558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return gl_helper_.get();
241558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
242558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
243558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid GpuProcessTransportFactory::AddObserver(
244558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    ImageTransportFactoryObserver* observer) {
245558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  observer_list_.AddObserver(observer);
246558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
247558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
248558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid GpuProcessTransportFactory::RemoveObserver(
249558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    ImageTransportFactoryObserver* observer) {
250558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  observer_list_.RemoveObserver(observer);
251558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
252558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
253558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochscoped_refptr<cc::ContextProvider>
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)GpuProcessTransportFactory::SharedMainThreadContextProvider() {
2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (shared_main_thread_contexts_.get())
2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return shared_main_thread_contexts_;
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // In threaded compositing mode, we have to create our own context for the
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // main thread since the compositor's context will be bound to the
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // compositor thread. When not in threaded mode, we still need a separate
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // context so that skia and gl_helper don't step on each other.
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  shared_main_thread_contexts_ = ContextProviderCommandBuffer::Create(
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GpuProcessTransportFactory::CreateOffscreenCommandBufferContext(),
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "Offscreen-MainThread");
2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (shared_main_thread_contexts_) {
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    shared_main_thread_contexts_->SetLostContextCallback(
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::Bind(&GpuProcessTransportFactory::
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                        OnLostMainThreadSharedContextInsideCallback,
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                   callback_factory_.GetWeakPtr()));
2715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (!shared_main_thread_contexts_->BindToCurrentThread())
2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      shared_main_thread_contexts_ = NULL;
273558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return shared_main_thread_contexts_;
275558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
276558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
277558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochGpuProcessTransportFactory::PerCompositorData*
278558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochGpuProcessTransportFactory::CreatePerCompositorData(
279558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    ui::Compositor* compositor) {
280558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(!per_compositor_data_[compositor]);
281558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
282558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  gfx::AcceleratedWidget widget = compositor->widget();
283558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
284558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
285558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  PerCompositorData* data = new PerCompositorData;
286558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  data->surface_id = tracker->AddSurfaceForNativeWidget(widget);
287558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  tracker->SetSurfaceHandle(
288558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      data->surface_id,
289558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      gfx::GLSurfaceHandle(widget, gfx::NATIVE_DIRECT));
290558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
291558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  per_compositor_data_[compositor] = data;
292558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
293558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return data;
294558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
295558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
296558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochscoped_ptr<WebGraphicsContext3DCommandBufferImpl>
297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)GpuProcessTransportFactory::CreateContextCommon(int surface_id) {
298558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor())
299558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  blink::WebGraphicsContext3D::Attributes attrs;
301558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  attrs.shareResources = true;
302558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  attrs.depth = false;
303558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  attrs.stencil = false;
304558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  attrs.antialias = false;
305558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  attrs.noAutomaticFlushes = true;
306e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  bool lose_context_when_out_of_memory = true;
307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  CauseForGpuLaunch cause =
308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
3091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<GpuChannelHost> gpu_channel_host(
310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      BrowserGpuChannelHostFactory::instance()->EstablishGpuChannelSync(cause));
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!gpu_channel_host) {
312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    LOG(ERROR) << "Failed to establish GPU channel.";
3131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
315558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  GURL url("chrome://gpu/GpuProcessTransportFactory::CreateContextCommon");
316558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
317558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      new WebGraphicsContext3DCommandBufferImpl(
318558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch          surface_id,
319558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch          url,
3201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          gpu_channel_host.get(),
3211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          attrs,
322e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          lose_context_when_out_of_memory,
323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(),
324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          NULL));
325558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return context.Pass();
326558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
327558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
328fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid GpuProcessTransportFactory::OnLostMainThreadSharedContextInsideCallback() {
329558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  base::MessageLoop::current()->PostTask(
330558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      FROM_HERE,
331558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      base::Bind(&GpuProcessTransportFactory::OnLostMainThreadSharedContext,
332fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch                 callback_factory_.GetWeakPtr()));
333558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
334558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
335558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid GpuProcessTransportFactory::OnLostMainThreadSharedContext() {
336558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  LOG(ERROR) << "Lost UI shared context.";
3373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
338558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Keep old resources around while we call the observers, but ensure that
339558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // new resources are created if needed.
3403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Kill shared contexts for both threads in tandem so they are always in
3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // the same share group.
3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_refptr<cc::ContextProvider> lost_shared_main_thread_contexts =
3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      shared_main_thread_contexts_;
3444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  shared_main_thread_contexts_  = NULL;
345558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<GLHelper> lost_gl_helper = gl_helper_.Pass();
347558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
348558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  FOR_EACH_OBSERVER(ImageTransportFactoryObserver,
349558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                    observer_list_,
350558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                    OnLostResources());
3513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Kill things that use the shared context before killing the shared context.
3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  lost_gl_helper.reset();
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  lost_shared_main_thread_contexts  = NULL;
355558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
356558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
357558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}  // namespace content
358