Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / compositor / gpu_process_transport_factory.cc
bloba5b14336ab766d262cf57c47b317d497ab7b1980
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
3 // found in the LICENSE file.
5 #include "content/browser/compositor/gpu_process_transport_factory.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/location.h"
12 #include "base/metrics/histogram.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/threading/simple_thread.h"
16 #include "base/threading/thread.h"
17 #include "cc/base/histograms.h"
18 #include "cc/output/compositor_frame.h"
19 #include "cc/output/output_surface.h"
20 #include "cc/raster/task_graph_runner.h"
21 #include "cc/surfaces/onscreen_display_client.h"
22 #include "cc/surfaces/surface_display_output_surface.h"
23 #include "cc/surfaces/surface_manager.h"
24 #include "content/browser/compositor/browser_compositor_output_surface.h"
25 #include "content/browser/compositor/browser_compositor_overlay_candidate_validator.h"
26 #include "content/browser/compositor/gpu_browser_compositor_output_surface.h"
27 #include "content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h"
28 #include "content/browser/compositor/offscreen_browser_compositor_output_surface.h"
29 #include "content/browser/compositor/reflector_impl.h"
30 #include "content/browser/compositor/software_browser_compositor_output_surface.h"
31 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
32 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
33 #include "content/browser/gpu/compositor_util.h"
34 #include "content/browser/gpu/gpu_data_manager_impl.h"
35 #include "content/browser/gpu/gpu_surface_tracker.h"
36 #include "content/browser/renderer_host/render_widget_host_impl.h"
37 #include "content/common/gpu/client/context_provider_command_buffer.h"
38 #include "content/common/gpu/client/gl_helper.h"
39 #include "content/common/gpu/client/gpu_channel_host.h"
40 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
41 #include "content/common/gpu/gpu_process_launch_causes.h"
42 #include "content/common/host_shared_bitmap_manager.h"
43 #include "content/public/common/content_switches.h"
44 #include "gpu/GLES2/gl2extchromium.h"
45 #include "gpu/command_buffer/client/gles2_interface.h"
46 #include "gpu/command_buffer/common/mailbox.h"
47 #include "third_party/khronos/GLES2/gl2.h"
48 #include "ui/compositor/compositor.h"
49 #include "ui/compositor/compositor_constants.h"
50 #include "ui/compositor/compositor_switches.h"
51 #include "ui/compositor/layer.h"
52 #include "ui/gfx/geometry/size.h"
53 #include "ui/gfx/native_widget_types.h"
55 #if defined(OS_WIN)
56 #include "content/browser/compositor/software_output_device_win.h"
57 #elif defined(USE_OZONE)
58 #include "content/browser/compositor/browser_compositor_overlay_candidate_validator_ozone.h"
59 #include "content/browser/compositor/software_output_device_ozone.h"
60 #include "ui/ozone/public/overlay_candidates_ozone.h"
61 #include "ui/ozone/public/overlay_manager_ozone.h"
62 #include "ui/ozone/public/ozone_platform.h"
63 #include "ui/ozone/public/ozone_switches.h"
64 #elif defined(USE_X11)
65 #include "content/browser/compositor/software_output_device_x11.h"
66 #elif defined(OS_MACOSX)
67 #include "content/browser/compositor/browser_compositor_overlay_candidate_validator_mac.h"
68 #include "content/browser/compositor/software_output_device_mac.h"
69 #endif
71 using cc::ContextProvider;
72 using gpu::gles2::GLES2Interface;
74 static const int kNumRetriesBeforeSoftwareFallback = 4;
76 namespace content {
77 namespace {
79 class RasterThread : public base::SimpleThread {
80 public:
81 RasterThread(cc::TaskGraphRunner* task_graph_runner)
82 : base::SimpleThread("CompositorTileWorker1"),
83 task_graph_runner_(task_graph_runner) {}
85 // Overridden from base::SimpleThread:
86 void Run() override { task_graph_runner_->Run(); }
88 private:
89 cc::TaskGraphRunner* task_graph_runner_;
91 DISALLOW_COPY_AND_ASSIGN(RasterThread);
94 } // namespace
96 struct GpuProcessTransportFactory::PerCompositorData {
97 int surface_id;
98 BrowserCompositorOutputSurface* surface;
99 ReflectorImpl* reflector;
100 scoped_ptr<cc::OnscreenDisplayClient> display_client;
102 PerCompositorData() : surface_id(0), surface(nullptr), reflector(nullptr) {}
105 GpuProcessTransportFactory::GpuProcessTransportFactory()
106 : next_surface_id_namespace_(1u),
107 task_graph_runner_(new cc::TaskGraphRunner),
108 callback_factory_(this) {
109 ui::Layer::InitializeUILayerSettings();
110 cc::SetClientNameForMetrics("Browser");
112 if (UseSurfacesEnabled())
113 surface_manager_ = make_scoped_ptr(new cc::SurfaceManager);
115 raster_thread_.reset(new RasterThread(task_graph_runner_.get()));
116 raster_thread_->Start();
117 #if defined(OS_WIN)
118 software_backing_.reset(new OutputDeviceBacking);
119 #endif
122 GpuProcessTransportFactory::~GpuProcessTransportFactory() {
123 DCHECK(per_compositor_data_.empty());
125 // Make sure the lost context callback doesn't try to run during destruction.
126 callback_factory_.InvalidateWeakPtrs();
128 task_graph_runner_->Shutdown();
129 if (raster_thread_)
130 raster_thread_->Join();
133 scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
134 GpuProcessTransportFactory::CreateOffscreenCommandBufferContext() {
135 CauseForGpuLaunch cause =
136 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
137 scoped_refptr<GpuChannelHost> gpu_channel_host(
138 BrowserGpuChannelHostFactory::instance()->EstablishGpuChannelSync(cause));
139 return CreateContextCommon(gpu_channel_host, 0);
142 scoped_ptr<cc::SoftwareOutputDevice>
143 GpuProcessTransportFactory::CreateSoftwareOutputDevice(
144 ui::Compositor* compositor) {
145 #if defined(OS_WIN)
146 return scoped_ptr<cc::SoftwareOutputDevice>(
147 new SoftwareOutputDeviceWin(software_backing_.get(), compositor));
148 #elif defined(USE_OZONE)
149 return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceOzone(
150 compositor));
151 #elif defined(USE_X11)
152 return scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareOutputDeviceX11(
153 compositor));
154 #elif defined(OS_MACOSX)
155 return scoped_ptr<cc::SoftwareOutputDevice>(
156 new SoftwareOutputDeviceMac(compositor));
157 #else
158 NOTREACHED();
159 return scoped_ptr<cc::SoftwareOutputDevice>();
160 #endif
163 scoped_ptr<BrowserCompositorOverlayCandidateValidator>
164 CreateOverlayCandidateValidator(gfx::AcceleratedWidget widget) {
165 #if defined(USE_OZONE)
166 scoped_ptr<ui::OverlayCandidatesOzone> overlay_candidates =
167 ui::OzonePlatform::GetInstance()
168 ->GetOverlayManager()
169 ->CreateOverlayCandidates(widget);
170 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
171 if (overlay_candidates &&
172 (command_line->HasSwitch(switches::kEnableHardwareOverlays) ||
173 command_line->HasSwitch(switches::kOzoneTestSingleOverlaySupport))) {
174 return scoped_ptr<BrowserCompositorOverlayCandidateValidator>(
175 new BrowserCompositorOverlayCandidateValidatorOzone(
176 widget, overlay_candidates.Pass()));
178 #elif defined(OS_MACOSX)
179 return make_scoped_ptr(
180 new BrowserCompositorOverlayCandidateValidatorMac(widget));
181 #endif
182 return scoped_ptr<BrowserCompositorOverlayCandidateValidator>();
185 static bool ShouldCreateGpuOutputSurface(ui::Compositor* compositor) {
186 #if defined(OS_CHROMEOS)
187 // Software fallback does not happen on Chrome OS.
188 return true;
189 #endif
191 #if defined(OS_WIN)
192 if (::GetProp(compositor->widget(), kForceSoftwareCompositor) &&
193 ::RemoveProp(compositor->widget(), kForceSoftwareCompositor))
194 return false;
195 #endif
197 return GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor();
200 void GpuProcessTransportFactory::CreateOutputSurface(
201 base::WeakPtr<ui::Compositor> compositor) {
202 DCHECK(!!compositor);
203 PerCompositorData* data = per_compositor_data_[compositor.get()];
204 if (!data) {
205 data = CreatePerCompositorData(compositor.get());
206 } else {
207 // TODO(piman): Use GpuSurfaceTracker to map ids to surfaces instead of an
208 // output_surface_map_ here.
209 output_surface_map_.Remove(data->surface_id);
210 data->surface = nullptr;
213 bool create_gpu_output_surface =
214 ShouldCreateGpuOutputSurface(compositor.get());
215 if (create_gpu_output_surface) {
216 CauseForGpuLaunch cause =
217 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
218 BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel(
219 cause, base::Bind(&GpuProcessTransportFactory::EstablishedGpuChannel,
220 callback_factory_.GetWeakPtr(), compositor,
221 create_gpu_output_surface, 0));
222 } else {
223 EstablishedGpuChannel(compositor, create_gpu_output_surface, 0);
227 void GpuProcessTransportFactory::EstablishedGpuChannel(
228 base::WeakPtr<ui::Compositor> compositor,
229 bool create_gpu_output_surface,
230 int num_attempts) {
231 if (!compositor)
232 return;
233 PerCompositorData* data = per_compositor_data_[compositor.get()];
234 DCHECK(data);
236 if (num_attempts > kNumRetriesBeforeSoftwareFallback) {
237 #if defined(OS_CHROMEOS)
238 LOG(FATAL) << "Unable to create a UI graphics context, and cannot use "
239 << "software compositing on ChromeOS.";
240 #endif
241 create_gpu_output_surface = false;
244 scoped_refptr<ContextProviderCommandBuffer> context_provider;
245 if (create_gpu_output_surface) {
246 // Try to reuse existing worker context provider.
247 if (shared_worker_context_provider_) {
248 base::AutoLock lock(*shared_worker_context_provider_->GetLock());
249 if (shared_worker_context_provider_->ContextGL()
250 ->GetGraphicsResetStatusKHR() != GL_NO_ERROR)
251 shared_worker_context_provider_ = nullptr;
253 scoped_refptr<GpuChannelHost> gpu_channel_host =
254 BrowserGpuChannelHostFactory::instance()->GetGpuChannel();
255 if (gpu_channel_host.get()) {
256 context_provider = ContextProviderCommandBuffer::Create(
257 GpuProcessTransportFactory::CreateContextCommon(gpu_channel_host,
258 data->surface_id),
259 BROWSER_COMPOSITOR_ONSCREEN_CONTEXT);
260 if (context_provider && !context_provider->BindToCurrentThread())
261 context_provider = nullptr;
262 if (!shared_worker_context_provider_) {
263 shared_worker_context_provider_ = ContextProviderCommandBuffer::Create(
264 GpuProcessTransportFactory::CreateContextCommon(gpu_channel_host,
266 BROWSER_WORKER_CONTEXT);
267 if (shared_worker_context_provider_ &&
268 !shared_worker_context_provider_->BindToCurrentThread())
269 shared_worker_context_provider_ = nullptr;
273 bool created_gpu_browser_compositor =
274 !!context_provider && !!shared_worker_context_provider_;
276 UMA_HISTOGRAM_BOOLEAN("Aura.CreatedGpuBrowserCompositor",
277 created_gpu_browser_compositor);
279 if (!created_gpu_browser_compositor) {
280 // Try again.
281 CauseForGpuLaunch cause =
282 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
283 BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel(
284 cause, base::Bind(&GpuProcessTransportFactory::EstablishedGpuChannel,
285 callback_factory_.GetWeakPtr(), compositor,
286 create_gpu_output_surface, num_attempts + 1));
287 return;
291 scoped_ptr<BrowserCompositorOutputSurface> surface;
292 if (!create_gpu_output_surface) {
293 surface = make_scoped_ptr(new SoftwareBrowserCompositorOutputSurface(
294 CreateSoftwareOutputDevice(compositor.get()),
295 compositor->vsync_manager()));
296 } else {
297 DCHECK(context_provider);
298 ContextProvider::Capabilities capabilities =
299 context_provider->ContextCapabilities();
300 if (!data->surface_id) {
301 surface = make_scoped_ptr(new OffscreenBrowserCompositorOutputSurface(
302 context_provider, shared_worker_context_provider_,
303 compositor->vsync_manager(),
304 scoped_ptr<BrowserCompositorOverlayCandidateValidator>()));
305 } else if (capabilities.gpu.surfaceless) {
306 GLenum target = GL_TEXTURE_2D;
307 GLenum format = GL_RGB;
308 #if defined(OS_MACOSX)
309 target = GL_TEXTURE_RECTANGLE_ARB;
310 format = GL_BGRA_EXT;
311 #endif
312 surface =
313 make_scoped_ptr(new GpuSurfacelessBrowserCompositorOutputSurface(
314 context_provider, shared_worker_context_provider_,
315 data->surface_id, compositor->vsync_manager(),
316 CreateOverlayCandidateValidator(compositor->widget()), target,
317 format, BrowserGpuMemoryBufferManager::current()));
318 } else {
319 scoped_ptr<BrowserCompositorOverlayCandidateValidator> validator;
320 #if !defined(OS_MACOSX)
321 // Overlays are only supported on surfaceless output surfaces on Mac.
322 validator = CreateOverlayCandidateValidator(compositor->widget());
323 #endif
324 surface = make_scoped_ptr(new GpuBrowserCompositorOutputSurface(
325 context_provider, shared_worker_context_provider_,
326 compositor->vsync_manager(), validator.Pass()));
330 // TODO(piman): Use GpuSurfaceTracker to map ids to surfaces instead of an
331 // output_surface_map_ here.
332 output_surface_map_.AddWithID(surface.get(), data->surface_id);
333 data->surface = surface.get();
334 if (data->reflector)
335 data->reflector->OnSourceSurfaceReady(data->surface);
337 if (!UseSurfacesEnabled()) {
338 compositor->SetOutputSurface(surface.Pass());
339 return;
342 // This gets a bit confusing. Here we have a ContextProvider in the |surface|
343 // configured to render directly to this widget. We need to make an
344 // OnscreenDisplayClient associated with that context, then return a
345 // SurfaceDisplayOutputSurface set up to draw to the display's surface.
346 cc::SurfaceManager* manager = surface_manager_.get();
347 scoped_ptr<cc::OnscreenDisplayClient> display_client(
348 new cc::OnscreenDisplayClient(
349 surface.Pass(), manager, HostSharedBitmapManager::current(),
350 BrowserGpuMemoryBufferManager::current(),
351 compositor->GetRendererSettings(), compositor->task_runner()));
353 scoped_ptr<cc::SurfaceDisplayOutputSurface> output_surface(
354 new cc::SurfaceDisplayOutputSurface(
355 manager, compositor->surface_id_allocator(), context_provider,
356 shared_worker_context_provider_));
357 display_client->set_surface_output_surface(output_surface.get());
358 output_surface->set_display_client(display_client.get());
359 display_client->display()->Resize(compositor->size());
360 data->display_client = display_client.Pass();
361 compositor->SetOutputSurface(output_surface.Pass());
364 scoped_ptr<ui::Reflector> GpuProcessTransportFactory::CreateReflector(
365 ui::Compositor* source_compositor,
366 ui::Layer* target_layer) {
367 PerCompositorData* source_data = per_compositor_data_[source_compositor];
368 DCHECK(source_data);
370 scoped_ptr<ReflectorImpl> reflector(
371 new ReflectorImpl(source_compositor, target_layer));
372 source_data->reflector = reflector.get();
373 if (BrowserCompositorOutputSurface* source_surface = source_data->surface)
374 reflector->OnSourceSurfaceReady(source_surface);
375 return reflector.Pass();
378 void GpuProcessTransportFactory::RemoveReflector(ui::Reflector* reflector) {
379 ReflectorImpl* reflector_impl = static_cast<ReflectorImpl*>(reflector);
380 PerCompositorData* data =
381 per_compositor_data_[reflector_impl->mirrored_compositor()];
382 DCHECK(data);
383 data->reflector->Shutdown();
384 data->reflector = nullptr;
387 void GpuProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
388 PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
389 if (it == per_compositor_data_.end())
390 return;
391 PerCompositorData* data = it->second;
392 DCHECK(data);
393 // TODO(piman): Use GpuSurfaceTracker to map ids to surfaces instead of an
394 // output_surface_map_ here.
395 if (data->surface)
396 output_surface_map_.Remove(data->surface_id);
397 if (data->surface_id)
398 GpuSurfaceTracker::Get()->RemoveSurface(data->surface_id);
399 delete data;
400 per_compositor_data_.erase(it);
401 if (per_compositor_data_.empty()) {
402 // Destroying the GLHelper may cause some async actions to be cancelled,
403 // causing things to request a new GLHelper. Due to crbug.com/176091 the
404 // GLHelper created in this case would be lost/leaked if we just reset()
405 // on the |gl_helper_| variable directly. So instead we call reset() on a
406 // local scoped_ptr.
407 scoped_ptr<GLHelper> helper = gl_helper_.Pass();
409 // If there are any observer left at this point, make sure they clean up
410 // before we destroy the GLHelper.
411 FOR_EACH_OBSERVER(
412 ImageTransportFactoryObserver, observer_list_, OnLostResources());
414 helper.reset();
415 DCHECK(!gl_helper_) << "Destroying the GLHelper should not cause a new "
416 "GLHelper to be created.";
420 bool GpuProcessTransportFactory::DoesCreateTestContexts() { return false; }
422 uint32 GpuProcessTransportFactory::GetImageTextureTarget(
423 gfx::BufferFormat format,
424 gfx::BufferUsage usage) {
425 return BrowserGpuMemoryBufferManager::GetImageTextureTarget(format, usage);
428 cc::SharedBitmapManager* GpuProcessTransportFactory::GetSharedBitmapManager() {
429 return HostSharedBitmapManager::current();
432 gpu::GpuMemoryBufferManager*
433 GpuProcessTransportFactory::GetGpuMemoryBufferManager() {
434 return BrowserGpuMemoryBufferManager::current();
437 cc::TaskGraphRunner* GpuProcessTransportFactory::GetTaskGraphRunner() {
438 return task_graph_runner_.get();
441 ui::ContextFactory* GpuProcessTransportFactory::GetContextFactory() {
442 return this;
445 gfx::GLSurfaceHandle GpuProcessTransportFactory::GetSharedSurfaceHandle() {
446 gfx::GLSurfaceHandle handle = gfx::GLSurfaceHandle(
447 gfx::kNullPluginWindow, gfx::NULL_TRANSPORT);
448 handle.parent_client_id =
449 BrowserGpuChannelHostFactory::instance()->GetGpuChannelId();
450 return handle;
453 scoped_ptr<cc::SurfaceIdAllocator>
454 GpuProcessTransportFactory::CreateSurfaceIdAllocator() {
455 scoped_ptr<cc::SurfaceIdAllocator> allocator =
456 make_scoped_ptr(new cc::SurfaceIdAllocator(next_surface_id_namespace_++));
457 if (GetSurfaceManager())
458 allocator->RegisterSurfaceIdNamespace(GetSurfaceManager());
459 return allocator;
462 void GpuProcessTransportFactory::ResizeDisplay(ui::Compositor* compositor,
463 const gfx::Size& size) {
464 PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
465 if (it == per_compositor_data_.end())
466 return;
467 PerCompositorData* data = it->second;
468 DCHECK(data);
469 if (data->display_client)
470 data->display_client->display()->Resize(size);
473 cc::SurfaceManager* GpuProcessTransportFactory::GetSurfaceManager() {
474 return surface_manager_.get();
477 GLHelper* GpuProcessTransportFactory::GetGLHelper() {
478 if (!gl_helper_ && !per_compositor_data_.empty()) {
479 scoped_refptr<cc::ContextProvider> provider =
480 SharedMainThreadContextProvider();
481 if (provider.get())
482 gl_helper_.reset(new GLHelper(provider->ContextGL(),
483 provider->ContextSupport()));
485 return gl_helper_.get();
488 void GpuProcessTransportFactory::AddObserver(
489 ImageTransportFactoryObserver* observer) {
490 observer_list_.AddObserver(observer);
493 void GpuProcessTransportFactory::RemoveObserver(
494 ImageTransportFactoryObserver* observer) {
495 observer_list_.RemoveObserver(observer);
498 #if defined(OS_MACOSX)
499 void GpuProcessTransportFactory::OnSurfaceDisplayed(int surface_id) {
500 BrowserCompositorOutputSurface* surface = output_surface_map_.Lookup(
501 surface_id);
502 if (surface)
503 surface->OnSurfaceDisplayed();
506 void GpuProcessTransportFactory::SetCompositorSuspendedForRecycle(
507 ui::Compositor* compositor,
508 bool suspended) {
509 PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
510 if (it == per_compositor_data_.end())
511 return;
512 PerCompositorData* data = it->second;
513 DCHECK(data);
514 BrowserCompositorOutputSurface* surface =
515 output_surface_map_.Lookup(data->surface_id);
516 if (surface)
517 surface->SetSurfaceSuspendedForRecycle(suspended);
520 bool GpuProcessTransportFactory::
521 SurfaceShouldNotShowFramesAfterSuspendForRecycle(int surface_id) const {
522 BrowserCompositorOutputSurface* surface =
523 output_surface_map_.Lookup(surface_id);
524 if (surface)
525 return surface->SurfaceShouldNotShowFramesAfterSuspendForRecycle();
526 return false;
528 #endif
530 scoped_refptr<cc::ContextProvider>
531 GpuProcessTransportFactory::SharedMainThreadContextProvider() {
532 if (shared_main_thread_contexts_.get())
533 return shared_main_thread_contexts_;
535 // In threaded compositing mode, we have to create our own context for the
536 // main thread since the compositor's context will be bound to the
537 // compositor thread. When not in threaded mode, we still need a separate
538 // context so that skia and gl_helper don't step on each other.
539 shared_main_thread_contexts_ = ContextProviderCommandBuffer::Create(
540 GpuProcessTransportFactory::CreateOffscreenCommandBufferContext(),
541 BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT);
543 if (shared_main_thread_contexts_.get()) {
544 shared_main_thread_contexts_->SetLostContextCallback(
545 base::Bind(&GpuProcessTransportFactory::
546 OnLostMainThreadSharedContextInsideCallback,
547 callback_factory_.GetWeakPtr()));
548 if (!shared_main_thread_contexts_->BindToCurrentThread())
549 shared_main_thread_contexts_ = NULL;
551 return shared_main_thread_contexts_;
554 GpuProcessTransportFactory::PerCompositorData*
555 GpuProcessTransportFactory::CreatePerCompositorData(
556 ui::Compositor* compositor) {
557 DCHECK(!per_compositor_data_[compositor]);
559 gfx::AcceleratedWidget widget = compositor->widget();
560 GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
562 PerCompositorData* data = new PerCompositorData;
563 if (compositor->widget() == gfx::kNullAcceleratedWidget) {
564 data->surface_id = 0;
565 } else {
566 data->surface_id = tracker->AddSurfaceForNativeWidget(widget);
567 tracker->SetSurfaceHandle(data->surface_id,
568 gfx::GLSurfaceHandle(widget, gfx::NATIVE_DIRECT));
571 per_compositor_data_[compositor] = data;
573 return data;
576 scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
577 GpuProcessTransportFactory::CreateContextCommon(
578 scoped_refptr<GpuChannelHost> gpu_channel_host,
579 int surface_id) {
580 if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor())
581 return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
582 blink::WebGraphicsContext3D::Attributes attrs;
583 attrs.shareResources = true;
584 attrs.depth = false;
585 attrs.stencil = false;
586 attrs.antialias = false;
587 attrs.noAutomaticFlushes = true;
588 bool lose_context_when_out_of_memory = true;
589 if (!gpu_channel_host.get()) {
590 LOG(ERROR) << "Failed to establish GPU channel.";
591 return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
593 GURL url("chrome://gpu/GpuProcessTransportFactory::CreateContextCommon");
594 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
595 new WebGraphicsContext3DCommandBufferImpl(
596 surface_id,
597 url,
598 gpu_channel_host.get(),
599 attrs,
600 lose_context_when_out_of_memory,
601 WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(),
602 NULL));
603 return context.Pass();
606 void GpuProcessTransportFactory::OnLostMainThreadSharedContextInsideCallback() {
607 base::ThreadTaskRunnerHandle::Get()->PostTask(
608 FROM_HERE,
609 base::Bind(&GpuProcessTransportFactory::OnLostMainThreadSharedContext,
610 callback_factory_.GetWeakPtr()));
613 void GpuProcessTransportFactory::OnLostMainThreadSharedContext() {
614 LOG(ERROR) << "Lost UI shared context.";
616 // Keep old resources around while we call the observers, but ensure that
617 // new resources are created if needed.
618 // Kill shared contexts for both threads in tandem so they are always in
619 // the same share group.
620 scoped_refptr<cc::ContextProvider> lost_shared_main_thread_contexts =
621 shared_main_thread_contexts_;
622 shared_main_thread_contexts_ = NULL;
624 scoped_ptr<GLHelper> lost_gl_helper = gl_helper_.Pass();
626 FOR_EACH_OBSERVER(ImageTransportFactoryObserver,
627 observer_list_,
628 OnLostResources());
630 // Kill things that use the shared context before killing the shared context.
631 lost_gl_helper.reset();
632 lost_shared_main_thread_contexts = NULL;
635 } // namespace content