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